Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/3] ARM: dts: rockchip: Enable build of rk3066 MK808 dts
From: Heiko Stuebner @ 2016-10-06 16:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <84d4bc0b733cb9776f03ad54bb946fd1c4be4049.1475764778.git.paweljarosz3691@gmail.com>

Hi Pawe?,

Am Donnerstag, 6. Oktober 2016, 18:22:40 CEST schrieb =?UTF-8?q?
Pawe=C5=82=20Jarosz?=:
> MK808 is rockchip rk3066 based board made by Rickomagic. It has two usb
> ports, sdmmc, wifi and uart onboard.
> 
> Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
> ---
>  arch/arm/boot/dts/Makefile | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index befcd26..f19cc1d 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -639,6 +639,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
>  	rk3036-kylin.dtb \
>  	rk3066a-bqcurie2.dtb \
>  	rk3066a-marsboard.dtb \
> +	rk3066a-mk808.dtb \
>  	rk3066a-rayeager.dtb \
>  	rk3188-radxarock.dtb \
>  	rk3228-evb.dtb \

This patch breaks bisectability, as it adds a dtb to the makefile that you only 
add in patch3 which makes builds fail. Please fold your patches 1 and 3 into 
one patch and also add and entry to Documentation/devicetree/bindings/arm/
rockchip.txt for the board.


Heiko

^ permalink raw reply

* [PATCH 1/3] ARM: dts: rockchip: Enable build of rk3066 MK808 dts
From: Paweł Jarosz @ 2016-10-06 17:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <46121446.zsYkG9qnut@phil>

Hi Heiko



> This patch breaks bisectability, as it adds a dtb to the makefile that you only
> add in patch3 which makes builds fail. Please fold your patches 1 and 3 into
> one patch and also add and entry to Documentation/devicetree/bindings/arm/
> rockchip.txt for the board.
>
>
> Heiko

Should i squash all patches in one?

I saw now in logs that it's common practise.


Pawe?

^ permalink raw reply

* [PATCH 1/3] ARM: dts: rockchip: Enable build of rk3066 MK808 dts
From: Heiko Stuebner @ 2016-10-06 17:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <c6d58e9b-8d36-61c5-5af1-59b1c293d969@gmail.com>

Am Donnerstag, 6. Oktober 2016, 19:05:15 CEST schrieb Pawe? Jarosz:
> Hi Heiko
> 
> > This patch breaks bisectability, as it adds a dtb to the makefile that you
> > only add in patch3 which makes builds fail. Please fold your patches 1
> > and 3 into one patch and also add and entry to
> > Documentation/devicetree/bindings/arm/ rockchip.txt for the board.
> > 
> > 
> > Heiko
> 
> Should i squash all patches in one?
> 
> I saw now in logs that it's common practise.

Nope ... vendor-prefix should stay separate, everything else can be in one 
patch.

^ permalink raw reply

* [PATCH v5 2/5] drm/bridge: Add RGB to VGA bridge support
From: Laurent Pinchart @ 2016-10-06 17:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <96cef428-19e5-ff98-1de1-fa31dd8d4142@codeaurora.org>

Hello,

On Thursday 06 Oct 2016 17:09:57 Archit Taneja wrote:
> On 10/06/2016 12:51 PM, Maxime Ripard wrote:
> > On Mon, Oct 03, 2016 at 04:40:57PM +0530, Archit Taneja wrote:
> >> On 09/30/2016 08:07 PM, Maxime Ripard wrote:
> >>> Some boards have an entirely passive RGB to VGA bridge, based on either
> >>> DACs or resistor ladders.
> >>> 
> >>> Those might or might not have an i2c bus routed to the VGA connector in
> >>> order to access the screen EDIDs.
> >>> 
> >>> Add a bridge that doesn't do anything but expose the modes available on
> >>> the screen, either based on the EDIDs if available, or based on the XGA
> >>> standards.
> >>> 
> >>> Acked-by: Rob Herring <robh@kernel.org>
> >>> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> >>> ---
> >>> .../bindings/display/bridge/rgb-to-vga-bridge.txt  |  48 +++++
> >>> drivers/gpu/drm/bridge/Kconfig                     |   7 +
> >>> drivers/gpu/drm/bridge/Makefile                    |   1 +
> >>> drivers/gpu/drm/bridge/rgb-to-vga.c                | 229 +++++++++++++++
> >>> 4 files changed, 285 insertions(+)
> >>> create mode 100644
> >>> Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
> >>> create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
> >>> 
> >>> diff --git
> >>> a/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.tx
> >>> t
> >>> b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.tx
> >>> t new file mode 100644
> >>> index 000000000000..a8375bc1f9cb
> >>> --- /dev/null
> >>> +++
> >>> b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.tx
> >>> t @@ -0,0 +1,48 @@
> >>> +Dumb RGB to VGA bridge
> >>> +----------------------
> >>> +
> >>> +This binding is aimed for dumb RGB to VGA bridges that do not require
> >>> +any configuration.
> >>> +
> >>> +Required properties:
> >>> +
> >>> +- compatible: Must be "rgb-to-vga-bridge"
> >> 
> >> I'd talked to Laurent on IRC if he's okay with this. And I guess you to
> >> had discussed it during XDC too. He's suggested that it'd be better to
> >> have the compatible string as "simple-vga-dac".
> > 
> > I just wished this bikeshedding had taken place publicly and be
> > actually part of that discussion, but yeah, ok.
> 
> Sorry about that. I'd pinged him for an Ack, the discussion went
> more than that :)
> 
> >> Some of the reasons behind having this:
> >> 
> >> - We don't need to specify "rgb" in the compatible string since most
> >> simple VGA DACs can only work with an RGB input.
> > 
> > Ok.
> > 
> >> - Also, with "dac" specified in the string, we don't need to
> >> specifically mention "bridge" in the string. Also, bridge is a drm
> >> specific term.
> >> 
> >> - "simple" is considered because it's an unconfigurable bridge, and it
> >> might be misleading for other VGA DACs to not use "vga-dac".
> > 
> > All those "simple" bindings are just the biggest lie we ever
> > told. It's simple when you introduce it, and then grows into something
> > much more complicated than a non-simple implementation.
> 
> "simple" here is supposed to mean that it's an unconfigurable RGB to
> VGA DAC. This isn't supposed to follow the simple-panel model, where
> you add the "simple-panel" string in the compatible node, along with
> you chip specific compatible string.

I agree with Maxime, I don't like the word "simple". My preference would be 
"vga-dac" for a lack of a better qualifier than "simple" to describe the fact 
that the device requires no configuration. My only concern with "vga-dac" is 
that we would restrict usage of that compatible string for a subset of VGA 
DACs, with more complex devices not being compatible with "vga-dac" even 
though they are VGA DACs. That's a problem I can live with though.

> In other words, this driver shouldn't be touched again in the future :)
> If someone wants to write a RGB to VGA driver which is even
> slightly configurable, they'll need to write a new bridge driver.

I'm sure that won't be true. I can certainly foresee the addition of 
regulators support for instance. It's unfortunately never black and white.

> >> What do you think about this? If you think it's good, would it be
> >> possible for you to change this? I guess it's okay for the rest of
> >> the patch to stay the same.
> > 
> > I'll update and respin the serie.

-- 
Regards,

Laurent Pinchart

^ permalink raw reply

* [PATCH v2 0/2] Add MK808 RK3066 device
From: Paweł Jarosz @ 2016-10-06 17:37 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset adds support for Rikomagic MK808 v1 device with RK901 wifi.

It is hdmi stick with two usb ports(host and otg), sdmmc, wifi and uart
onboard.

It is RK3066 based.

Pawe? Jarosz (2):
  devicetree: Add vendor prefix for Rikomagic
  ARM: dts: rockchip: Add rk3066 MK808 board

 Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
 .../devicetree/bindings/vendor-prefixes.txt        |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/rk3066a-mk808.dts                | 184 +++++++++++++++++++++
 4 files changed, 190 insertions(+)
 create mode 100644 arch/arm/boot/dts/rk3066a-mk808.dts

-- 
2.7.4

^ permalink raw reply

* [PATCH v2 1/2] devicetree: Add vendor prefix for Rikomagic
From: Paweł Jarosz @ 2016-10-06 17:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1475774981.git.paweljarosz3691@gmail.com>

Add Rikomagic to vendor-prefixes.txt

Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
---
Changes in v2:
- none
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 69caf14..3edfa08 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -224,6 +224,7 @@ realtek Realtek Semiconductor Corp.
 renesas	Renesas Electronics Corporation
 richtek	Richtek Technology Corporation
 ricoh	Ricoh Co. Ltd.
+rikomagic	Rikomagic
 rockchip	Fuzhou Rockchip Electronics Co., Ltd
 samsung	Samsung Semiconductor
 sandisk	Sandisk Corporation
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: rockchip: Add rk3066 MK808 board
From: Paweł Jarosz @ 2016-10-06 17:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1475774981.git.paweljarosz3691@gmail.com>

MK808 is a tv stick which has rockchip rk3066 CPU inside, two usb ports
- host and otg, micro sd card slot and onboard wifi RK901.

Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
---

Changes in v2:
- included Heiko sugestion.

 Documentation/devicetree/bindings/arm/rockchip.txt |   4 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/rk3066a-mk808.dts                | 184 +++++++++++++++++++++
 3 files changed, 189 insertions(+)
 create mode 100644 arch/arm/boot/dts/rk3066a-mk808.dts

diff --git a/Documentation/devicetree/bindings/arm/rockchip.txt b/Documentation/devicetree/bindings/arm/rockchip.txt
index 55f388f..c09595b 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.txt
+++ b/Documentation/devicetree/bindings/arm/rockchip.txt
@@ -17,6 +17,10 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "chipspark,rayeager-px2", "rockchip,rk3066a";
 
+- Rikomagic MK808 v1 board:
+    Required root node properties:
+      - compatible = "rikomagic,mk808", "rockchip,rk3066a";
+
 - Radxa Rock board:
     Required root node properties:
       - compatible = "radxa,rock", "rockchip,rk3188";
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index befcd26..f19cc1d 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -639,6 +639,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
 	rk3036-kylin.dtb \
 	rk3066a-bqcurie2.dtb \
 	rk3066a-marsboard.dtb \
+	rk3066a-mk808.dtb \
 	rk3066a-rayeager.dtb \
 	rk3188-radxarock.dtb \
 	rk3228-evb.dtb \
diff --git a/arch/arm/boot/dts/rk3066a-mk808.dts b/arch/arm/boot/dts/rk3066a-mk808.dts
new file mode 100644
index 0000000..2878562
--- /dev/null
+++ b/arch/arm/boot/dts/rk3066a-mk808.dts
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016 Pawe? Jarosz <paweljarosz3691@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "rk3066a.dtsi"
+
+/ {
+	model = "Rikomagic MK808";
+	compatible = "rikomagic,mk808", "rockchip,rk3066a";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	memory at 60000000 {
+		device_type = "memory";
+		reg = <0x60000000 0x40000000>;
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		blue {
+			label = "mk808:blue:power";
+			gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+			linux,default-trigger = "default-on";
+		};
+	};
+
+	mmc_pwrseq: mmc-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sdmmc_pwr>;
+		reset-gpios = <&gpio3 7 GPIO_ACTIVE_HIGH>;
+	};
+
+	sdio_pwrseq: sdio-pwrseq {
+		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_pwr>;
+		reset-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+	};
+
+	vcc_io: vcc-io {
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_io";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+	};
+
+	vcc_host: usb-host-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&host_drv>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-name = "host-pwr";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+
+	vcc_otg: usb-otg-regulator {
+		compatible = "regulator-fixed";
+		gpio = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+		pinctrl-0 = <&otg_drv>;
+		pinctrl-names = "default";
+		regulator-always-on;
+		regulator-name = "vcc_otg";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		startup-delay-us = <100000>;
+		vin-supply = <&vcc_io>;
+	};
+};
+
+&mmc0 {
+	bus-width = <4>;
+	cap-mmc-highspeed;
+	cap-sd-highspeed;
+	mmc-pwrseq = <&mmc_pwrseq>;
+	num-slots = <1>;
+	status = "okay";
+	vmmc-supply = <&vcc_io>;
+};
+
+&mmc1 {
+	bus-width = <4>;
+	disable-wp;
+	mmc-pwrseq = <&sdio_pwrseq>;
+	non-removable;
+	num-slots = <1>;
+	status = "okay";
+	vmmc-supply = <&vcc_io>;
+};
+
+&pinctrl {
+	usb-host {
+		host_drv: host-drv {
+			rockchip,pins = <RK_GPIO0 6 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	usb-otg {
+		otg_drv: otg-drv {
+			rockchip,pins = <RK_GPIO0 5 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	sdmmc {
+		sdmmc_pwr: sdmmc-pwr {
+			rockchip,pins = <RK_GPIO3 7 RK_FUNC_GPIO &pcfg_pull_default>;
+		};
+	};
+
+	sdio {
+		wifi_pwr: wifi-pwr {
+			rockchip,pins = <RK_GPIO3 24 RK_FUNC_GPIO &pcfg_pull_none>;
+		};
+	};
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usb_host {
+	status = "okay";
+};
+
+&usb_otg {
+	status = "okay";
+};
+
+&usbphy {
+	status = "okay";
+};
+
+&wdt {
+	status = "okay";
+};
+
-- 
2.7.4

^ permalink raw reply related

* [PATCH 6/6] ARM: da850: adjust memory settings for tilcdc
From: Sekhar Nori @ 2016-10-06 17:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <eff0e150-e8d2-3859-1abe-c5f70f576fad@ti.com>

On Wednesday 05 October 2016 01:52 PM, Peter Ujfalusi wrote:
> On 10/04/16 16:02, Kevin Hilman wrote:
>> Peter Ujfalusi <peter.ujfalusi@ti.com> writes:
>>
>>> On 10/01/16 12:24, Sekhar Nori wrote:
>>
>> [...]
>>
>>>> In any case, to configure the PBBR, you will have to introduce a driver
>>>> for it in drivers/memory. Then you can set it up per board using a DT
>>>> parameter.
>>>
>>> and we can reuse the introduced bindings for am335x and OMAP1/2 as well. On
>>> OMAP the legacy DMA API provided a call to raise the priority of the sDMA in
>>> EMIF :o That needs to be removed and replaced.
>>
>> Can you point us to the bindings you're referring to?
> 
> We don't have one atm.
> 
> And the DMA priority hack in legacy sDMA code is for OMAP1:
> omap_set_dma_priority(). Basically it can change the sDMA priority in
> OCPT1_PRIOR, OCPT2_PRIOR, EMIFF_PRIOR and EMIFS_PRIOR registers.
> 
>> Also, a new driver in drivers/memory is fine for setting the PBBR, but
>> what about the SYSCFG0 registers.  Are you OK with leaving those in the
>> init code as proposed in $SUBJECT patch?
> 
> My problem is - as I described it in reply to Bartosz - is that for example I
> don't want the LCDC to get high priority on OMAP-L138 EVM from Logic as it
> does not have LCD/VGA by default. ifdef for LCDC is not good either since my
> kernel have LCDC compiled in, but it is disabled.
> 
> The easiest way would be to have pdata quirk to handle the LCDK until we have
> proper handling of the priority configuration.

We don't have pdata quirks handling in mach-davinci. And I think instead
of investing time in adding pdata quirks which are anyway a short term
solution, it is better to work on a drivers/bus/ based driver which can
help adjust master priorities via DT.

Although as Peter asked, it is indeed intriguing as to why LCDC priority
has to be raised even in supposed absence of any competing traffic.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v2 0/5] Add runtime PM support for clocks (on Exynos SoC example)
From: Tobias Jakobi @ 2016-10-06 18:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474282525-30441-1-git-send-email-m.szyprowski@samsung.com>

Hello Marek,

I'm using the patches from the v4.8-clocks-pm-v2 branch plus the ones
from the v4.8-clocks-pm-v2 branch on top of 4.8.0.

I see some warnings on boot coming from driver core. It appears that the
warnings are actually meaningful, since IOMMUs stop working completly.
E.g. if I modprobe s5p-mfc later, firmware loading fails because
apparantly the IOMMU domain isn't online.

> WARNING: CPU: 0 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c

I added some debug printk() to device_links_driver_bound(), to show the
link status. Apparantly it is always DEVICE_LINK_AVAILABLE.

Here's the (semi) full log:
> [    0.000000] Booting Linux on physical CPU 0xa00
> [    0.000000] Linux version 4.8.0-vanilla+ (liquid at chidori) (gcc version 4.9.3 (Gentoo 4.9.3 p1.5, pie-0.6.4) ) #3 SMP PREEMPT Thu Oct 6 19:14:15 CEST 2016
> [    0.000000] CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
> [    0.000000] OF: fdt:Machine model: Hardkernel ODROID-X2 board based on Exynos4412
> [    0.000000] Reserved memory: created DMA memory pool at 0xbf700000, size 8 MiB
> [    0.000000] OF: reserved mem: initialized node region_mfc_right, compatible id shared-dma-pool
> [    0.000000] Reserved memory: created DMA memory pool at 0xbe700000, size 16 MiB
> [    0.000000] OF: reserved mem: initialized node region_mfc_left, compatible id shared-dma-pool
> [    0.000000] cma: Reserved 128 MiB at 0xb6400000
> [    0.000000] Memory policy: Data cache writealloc
> [    0.000000] Samsung CPU ID: 0xe4412220
> [    0.000000] Running under secure firmware.
> [    0.000000] percpu: Embedded 14 pages/cpu @eefb3000 s26176 r8192 d22976 u57344
> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 516352
> [    0.000000] Kernel command line: video=HDMI-A-1:1280x720M at 60 console=ttySAC1,115200n8 root=PARTUUID=8c900d97-367f-47a9-bd66-6eced1a29836 rootfstype=f2fs rootwait ro earlyprintk console=tty1 console=ttySAC1,115200
> [    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
> [    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
> [    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
> [    0.000000] Memory: 1913244K/2071552K available (6144K kernel code, 223K rwdata, 1432K rodata, 1024K init, 246K bss, 27236K reserved, 131072K cma-reserved, 1154048K highmem)
> [    0.000000] Virtual kernel memory layout:
> [    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
> [    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
> [    0.000000]     vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
> [    0.000000]     lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
> [    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
> [    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
> [    0.000000]       .text : 0xc0008000 - 0xc0700000   (7136 kB)
> [    0.000000]       .init : 0xc0900000 - 0xc0a00000   (1024 kB)
> [    0.000000]       .data : 0xc0a00000 - 0xc0a37fc0   ( 224 kB)
> [    0.000000]        .bss : 0xc0a39000 - 0xc0a76a08   ( 247 kB)
> [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
> [    0.000000] Preemptible hierarchical RCU implementation.
> [    0.000000]  Build-time adjustment of leaf fanout to 32.
> [    0.000000] NR_IRQS:16 nr_irqs:16 16
> [    0.000000] L2C: platform modifies aux control register: 0x02070000 -> 0x3e470001
> [    0.000000] L2C: platform provided aux values permit register corruption.
> [    0.000000] L2C: DT/platform modifies aux control register: 0x02070000 -> 0x3e470001
> [    0.000000] L2C-310 enabling early BRESP for Cortex-A9
> [    0.000000] L2C-310: enabling full line of zeros but not enabled in Cortex-A9
> [    0.000000] L2C-310 ID prefetch enabled, offset 8 lines
> [    0.000000] L2C-310 dynamic clock gating enabled, standby mode enabled
> [    0.000000] L2C-310 cache controller enabled, 16 ways, 1024 kB
> [    0.000000] L2C-310: CACHE_ID 0x4100c4c8, AUX_CTRL 0x7e470001
> [    0.000000] Exynos4x12 clocks: sclk_apll = 1000000000, sclk_mpll = 800000000
> [    0.000000]  sclk_epll = 96000000, sclk_vpll = 350000000, arm_clk = 1000000000
> [    0.000000] Switching to timer-based delay loop, resolution 41ns
> [    0.000000] clocksource: mct-frc: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635851949 ns
> [    0.000004] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
> [    0.000263] Console: colour dummy device 80x30
> [    0.000978] console [tty1] enabled
> [    0.001003] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=120000)
> [    0.001039] pid_max: default: 32768 minimum: 301
> [    0.001118] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
> [    0.001142] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
> [    0.001577] CPU: Testing write buffer coherency: ok
> [    0.001875] CPU0: thread -1, cpu 0, socket 10, mpidr 80000a00
> [    0.002240] Setting up static identity map for 0x40100000 - 0x40100058
> [    0.055360] CPU1: thread -1, cpu 1, socket 10, mpidr 80000a01
> [    0.075335] CPU2: thread -1, cpu 2, socket 10, mpidr 80000a02
> [    0.095316] CPU3: thread -1, cpu 3, socket 10, mpidr 80000a03
> [    0.095374] Brought up 4 CPUs
> [    0.095445] SMP: Total of 4 processors activated (192.00 BogoMIPS).
> [    0.095464] CPU: All CPU(s) started in SVC mode.
> [    0.096280] devtmpfs: initialized
> [    0.110373] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
> [    0.110612] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302231375000 ns
> [    0.114190] pinctrl core: initialized pinctrl subsystem
> [    0.114738] lcd0-power-domain at 10023C80 has as child subdomain: tv-power-domain at 10023C20.
> [    0.115573] NET: Registered protocol family 16
> [    0.117150] DMA: preallocated 256 KiB pool for atomic coherent allocations
> [    0.134991] cpuidle: using governor ladder
> [    0.154989] cpuidle: using governor menu
> [    0.155398] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
> [    0.155434] hw-breakpoint: maximum watchpoint size is 4 bytes.
> [    0.197368] SCSI subsystem initialized
> [    0.197498] usbcore: registered new interface driver usbfs
> [    0.197568] usbcore: registered new interface driver hub
> [    0.197664] usbcore: registered new device driver usb
> [    0.198081] s3c-i2c 13860000.i2c: slave address 0x10
> [    0.198111] s3c-i2c 13860000.i2c: bus frequency set to 390 KHz
> [    0.198570] s3c-i2c 13860000.i2c: i2c-0: S3C I2C adapter
> [    0.198763] s3c-i2c 13870000.i2c: slave address 0x10
> [    0.198791] s3c-i2c 13870000.i2c: bus frequency set to 390 KHz
> [    0.199046] s3c-i2c 13870000.i2c: i2c-1: S3C I2C adapter
> [    0.199192] s3c-i2c 13880000.i2c: slave address 0x00
> [    0.199218] s3c-i2c 13880000.i2c: bus frequency set to 97 KHz
> [    0.199375] s3c-i2c 13880000.i2c: i2c-2: S3C I2C adapter
> [    0.199481] s3c-i2c 138e0000.i2c: slave address 0x00
> [    0.199506] s3c-i2c 138e0000.i2c: bus frequency set to 97 KHz
> [    0.199758] s3c-i2c 138e0000.i2c: i2c-8: S3C I2C adapter
> [    0.200052] Linux video capture interface: v2.00
> [    0.205439] Advanced Linux Sound Architecture Driver Initialized.
> [    0.205901] Bluetooth: Core ver 2.21
> [    0.205947] NET: Registered protocol family 31
> [    0.205966] Bluetooth: HCI device and connection manager initialized
> [    0.205992] Bluetooth: HCI socket layer initialized
> [    0.206014] Bluetooth: L2CAP socket layer initialized
> [    0.206036] Bluetooth: SCO socket layer initialized
> [    0.206567] clocksource: Switched to clocksource mct-frc
> [    0.214799] NET: Registered protocol family 2
> [    0.215264] TCP established hash table entries: 8192 (order: 3, 32768 bytes)
> [    0.215352] TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
> [    0.215463] TCP: Hash tables configured (established 8192 bind 8192)
> [    0.215531] UDP hash table entries: 512 (order: 2, 16384 bytes)
> [    0.215573] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
> [    0.215717] NET: Registered protocol family 1
> [    0.216073] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
> [    0.217474] futex hash table entries: 1024 (order: 4, 65536 bytes)
> [    0.217587] audit: initializing netlink subsys (disabled)
> [    0.217641] audit: type=2000 audit(0.215:1): initialized
> [    0.218191] workingset: timestamp_bits=30 max_order=19 bucket_order=0
> [    0.230957] bounce: pool size: 64 pages
> [    0.231124] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
> [    0.231157] io scheduler noop registered
> [    0.231175] io scheduler deadline registered
> [    0.231306] io scheduler cfq registered (default)
> [    0.231963] 125b0000.exynos-usbphy supply vbus not found, using dummy regulator
> [    0.235681] dma-pl330 12680000.pdma: Loaded driver for PL330 DMAC-141330
> [    0.235717] dma-pl330 12680000.pdma:         DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
> [    0.238256] dma-pl330 12690000.pdma: Loaded driver for PL330 DMAC-141330
> [    0.238291] dma-pl330 12690000.pdma:         DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
> [    0.239110] dma-pl330 12850000.mdma: Loaded driver for PL330 DMAC-141330
> [    0.239141] dma-pl330 12850000.mdma:         DBUFF-64x8bytes Num_Chans-8 Num_Peri-1 Num_Events-32
> [    0.239800] 13800000.serial: ttySAC0 at MMIO 0x13800000 (irq = 53, base_baud = 0) is a S3C6400/10
> [    0.240144] 13810000.serial: ttySAC1 at MMIO 0x13810000 (irq = 54, base_baud = 0) is a S3C6400/10
> [    1.015731] console [ttySAC1] enabled
> [    1.019770] 13820000.serial: ttySAC2 at MMIO 0x13820000 (irq = 55, base_baud = 0) is a S3C6400/10
> [    1.028570] 13830000.serial: ttySAC3 at MMIO 0x13830000 (irq = 56, base_baud = 0) is a S3C6400/10
> [    1.038157] [drm] Initialized drm 1.1.0 20060810
> [    1.042093] exynos-mixer 12c10000.mixer: Linked as a consumer to 12e20000.sysmmu
> [    1.049118] iommu: Adding device 12c10000.mixer to group 0
> [    1.055403] DEBUG: device_links_driver_bound(): 1
> [    1.059238] ------------[ cut here ]------------
> [    1.063826] WARNING: CPU: 0 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
> [    1.072851] Modules linked in:
> [    1.075859] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.8.0-vanilla+ #3
> [    1.082458] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [    1.088533] Backtrace: 
> [    1.090970] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
> [    1.098524]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
> [    1.104161] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
> [    1.111376] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
> [    1.118306]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
> [    1.123946] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
> [    1.131506]  r9:00000000 r8:c0a258d8 r7:ee3114e4 r6:eeafa874 r5:00000000 r4:ee3114c0
> [    1.139231] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
> [    1.148615] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
> [    1.157287]  r9:00000000 r8:c0a258d8 r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eeafa810
> [    1.165011] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
> [    1.173345]  r4:eeafa810 r3:600000d3
> [    1.176894] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
> [    1.185323]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eeafa844 r5:c0a258d8
> [    1.193128]  r4:eeafa810 r3:00000000
> [    1.196685] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
> [    1.204853]  r6:c0407eb0 r5:c0a258d8 r4:00000000 r3:c0407eb0
> [    1.210485] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
> [    1.218480]  r6:c0a26758 r5:ee27f780 r4:c0a258d8
> [    1.223072] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
> [    1.231072] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
> [    1.239139]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a258d8
> [    1.244773] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
> [    1.253809]  r5:00000000 r4:00000004
> [    1.257364] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
> [    1.266402] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
> [    1.274554]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
> [    1.281232] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
> [    1.289917]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
> [    1.297722]  r4:c093a520
> [    1.300243] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
> [    1.308493]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
> [    1.316297]  r4:00000000
> [    1.318815] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
> [    1.326373]  r4:00000000 r3:ee880000
> [    1.329952] ---[ end trace 402e0b75dfe2947b ]---
> [    1.336115] exynos-hdmi 12d00000.hdmi: Failed to get supply 'vdd': -517
> [    1.341761] s5p-g2d 10800000.g2d: Linked as a consumer to 10a40000.sysmmu
> [    1.347960] iommu: Adding device 10800000.g2d to group 1
> [    1.353512] s5p-g2d 10800000.g2d: The Exynos G2D (ver 4.1) successfully probed.
> [    1.360510] DEBUG: device_links_driver_bound(): 1
> [    1.365183] ------------[ cut here ]------------
> [    1.369786] WARNING: CPU: 1 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
> [    1.378819] Modules linked in:
> [    1.381829] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-vanilla+ #3
> [    1.389651] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [    1.395718] Backtrace: 
> [    1.398154] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
> [    1.405709]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
> [    1.411344] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
> [    1.418560] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
> [    1.425491]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
> [    1.431132] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
> [    1.438691]  r9:00000000 r8:c0a2621c r7:ee910ae4 r6:eeac4a74 r5:00000000 r4:ee910ac0
> [    1.446416] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
> [    1.455800] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
> [    1.464472]  r9:00000000 r8:c0a2621c r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eeac4a10
> [    1.472196] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
> [    1.480530]  r4:eeac4a10 r3:00000000
> [    1.484080] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
> [    1.492508]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eeac4a44 r5:c0a2621c
> [    1.500313]  r4:eeac4a10 r3:00000000
> [    1.503870] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
> [    1.512038]  r6:c0407eb0 r5:c0a2621c r4:00000000 r3:c0407eb0
> [    1.517671] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
> [    1.525665]  r6:c0a26758 r5:ee932b80 r4:c0a2621c
> [    1.530257] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
> [    1.538257] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
> [    1.546324]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a2621c
> [    1.551959] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
> [    1.560994]  r5:00000000 r4:0000000a
> [    1.564548] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
> [    1.573587] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
> [    1.581739]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
> [    1.588415] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
> [    1.597103]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
> [    1.604907]  r4:c093a520
> [    1.607427] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
> [    1.615678]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
> [    1.623482]  r4:00000000
> [    1.625999] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
> [    1.633558]  r4:00000000 r3:ee880000
> [    1.637133] ---[ end trace 402e0b75dfe2947c ]---
> [    1.642227] exynos-drm-fimc 11800000.fimc: Linked as a consumer to 11a20000.sysmmu
> [    1.649335] iommu: Adding device 11800000.fimc to group 2
> [    1.655529] exynos-drm-fimc 11810000.fimc: Linked as a consumer to 11a30000.sysmmu
> [    1.662263] iommu: Adding device 11810000.fimc to group 3
> [    1.668447] exynos-drm-fimc 11820000.fimc: Linked as a consumer to 11a40000.sysmmu
> [    1.675196] iommu: Adding device 11820000.fimc to group 4
> [    1.681278] exynos-drm-fimc 11820000.fimc: drm fimc registered successfully.
> [    1.687589] DEBUG: device_links_driver_bound(): 1
> [    1.692264] ------------[ cut here ]------------
> [    1.696852] WARNING: CPU: 0 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
> [    1.705880] Modules linked in:
> [    1.708891] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-vanilla+ #3
> [    1.716713] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [    1.722780] Backtrace: 
> [    1.725216] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
> [    1.732771]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
> [    1.738407] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
> [    1.745624] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
> [    1.752553]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
> [    1.758194] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
> [    1.765754]  r9:00000000 r8:c0a26330 r7:ee311d24 r6:eea83074 r5:00000000 r4:ee311d00
> [    1.773479] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
> [    1.782862] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
> [    1.791534]  r9:00000000 r8:c0a26330 r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eea83010
> [    1.799258] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
> [    1.807592]  r4:eea83010 r3:600000d3
> [    1.811142] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
> [    1.819571]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eea83044 r5:c0a26330
> [    1.827376]  r4:eea83010 r3:00000000
> [    1.830932] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
> [    1.839100]  r6:c0407eb0 r5:c0a26330 r4:00000000 r3:c0407eb0
> [    1.844733] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
> [    1.852728]  r6:c0a26758 r5:ee27fa00 r4:c0a26330
> [    1.857319] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
> [    1.865320] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
> [    1.873386]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a26330
> [    1.879021] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
> [    1.888057]  r5:00000000 r4:0000000b
> [    1.891610] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
> [    1.900649] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
> [    1.908801]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
> [    1.915478] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
> [    1.924165]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
> [    1.931969]  r4:c093a520
> [    1.934489] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
> [    1.942740]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
> [    1.950545]  r4:00000000
> [    1.953062] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
> [    1.960620]  r4:00000000 r3:ee880000
> [    1.964193] ---[ end trace 402e0b75dfe2947d ]---
> [    1.969039] exynos-drm-fimc 11830000.fimc: Linked as a consumer to 11a50000.sysmmu
> [    1.976392] iommu: Adding device 11830000.fimc to group 5
> [    1.982437] exynos-drm-fimc 11830000.fimc: drm fimc registered successfully.
> [    1.988799] DEBUG: device_links_driver_bound(): 1
> [    1.993464] ------------[ cut here ]------------
> [    1.998056] WARNING: CPU: 2 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
> [    2.007076] Modules linked in:
> [    2.010087] CPU: 2 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-vanilla+ #3
> [    2.017909] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [    2.023975] Backtrace: 
> [    2.026412] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
> [    2.033967]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
> [    2.039603] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
> [    2.046819] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
> [    2.053750]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
> [    2.059390] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
> [    2.066950]  r9:00000000 r8:c0a26330 r7:ee313264 r6:eea83274 r5:00000000 r4:ee313240
> [    2.074675] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
> [    2.084058] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
> [    2.092731]  r9:00000000 r8:c0a26330 r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eea83210
> [    2.100454] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
> [    2.108788]  r4:eea83210 r3:600000d3
> [    2.112338] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
> [    2.120767]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eea83244 r5:c0a26330
> [    2.128571]  r4:eea83210 r3:00000000
> [    2.132128] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
> [    2.140296]  r6:c0407eb0 r5:c0a26330 r4:00000000 r3:c0407eb0
> [    2.145929] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
> [    2.153924]  r6:c0a26758 r5:ee27fa00 r4:c0a26330
> [    2.158516] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
> [    2.166516] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
> [    2.174582]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a26330
> [    2.180217] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
> [    2.189252]  r5:00000000 r4:0000000b
> [    2.192806] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
> [    2.201845] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
> [    2.209997]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
> [    2.216674] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
> [    2.225361]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
> [    2.233165]  r4:c093a520
> [    2.235685] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
> [    2.243936]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
> [    2.251740]  r4:00000000
> [    2.254258] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
> [    2.261816]  r4:00000000 r3:ee880000
> [    2.265388] ---[ end trace 402e0b75dfe2947e ]---
> [    2.270457] exynos-drm-ipp exynos-drm-ipp: drm ipp registered successfully.
> [    2.280368] loop: module loaded
> [    2.293185] random: fast init done
> [    2.303857] usbcore: registered new interface driver smsc95xx
> [    2.491598] dwc2 12480000.hsotg: Specified GNPTXFDEP=1024 > 768
> [    2.491906] dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM
> [    2.499801] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> [    2.505798] ehci-exynos: EHCI EXYNOS driver
> [    2.510438] exynos-ehci 12580000.ehci: EHCI Host Controller
> [    2.515535] exynos-ehci 12580000.ehci: new USB bus registered, assigned bus number 1
> [    2.523434] exynos-ehci 12580000.ehci: irq 51, io mem 0x12580000
> [    2.541596] exynos-ehci 12580000.ehci: USB 2.0 started, EHCI 1.00
> <snip>

I'll try to do another test with just the 5 patches from this set
applied (without the IOMMU probe deferral).

With best wishes,
Tobias



Marek Szyprowski wrote:
> Dear All,
> 
> This patchset adds runtime PM support to common clock framework. This is an
> attempt to implement support for clock controllers, which belongs to a power
> domain. This approach works surprisingly well on Exynos 4412 and 5433 SoCs,
> what allowed us to solve various freeze/crash issues related to power
> management.
> 
> The main idea behind this patchset is to keep clock's controller power domain
> enabled every time when at least one of its clock is enabled or access to its
> registers is being made. Clock controller driver (clock provider) can
> supply a struct device pointer, which is the used by clock core for tracking and
> managing clock's controller runtime pm state. Each clk_prepare() operation will
> first call pm_runtime_get_sync() on the supplied device, while clk_unprepare()
> will do pm_runtime_put() at the end.
> 
> This runtime PM feature has been tested with Exynos4412 and Exynos5433 clocks
> drivers. Both have some clocks, which belongs to respective power domains and
> need special handling during power on/off procedures. Till now it wasn't handled
> at all, what caused various problems.
> 
> Patches for exynos 4412 and 5433 clocks drivers change the way the clock
> provider is initialized. Instead of CLK_OF_DECLARE based initialization, a
> complete platform device driver infrastructure is being used. This is needed to
> let driver to use runtime pm feature and integrate with generic power domains.
> The side-effect of this change is a delay in clock provider registeration
> during system boot, so early initialized drivers might get EPROBEDEFER error
> when requesting their clocks. This is an issue for IOMMU drivers, so
> this patchset will be fully functional once the deferred probe for IOMMU
> will be merged.
> 
> The side-effect of this patchset is the one can finally read
> /sys/kernel/debug/clk/clk_summary on all Exynos4412 boards without any freeze.
> 
> If one wants to test this patchset (on Exynos4412 Trats2 device with FIMC-IS
> driver), I've provided a branch with all needed patches (fixes for Exynos,
> FIMC-IS driver and IOMMU deferred probe):
> https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.8-clocks-pm-v2
> 
> Patches are based on vanilla v4.8-rc7 kernel.
> 
> Best regards
> Marek Szyprowski
> Samsung R&D Institute Poland
> 
> Changelog:
> v2:
> - Simplified clk_pm_runtime_get/put functions, removed workaround for devices
>   with disabled runtime pm. Such workaround is no longer needed since commit
>   4d23a5e84806b202d9231929c9507ef7cf7a0185 ("PM / Domains: Allow runtime PM
>   during system PM phases").
> - Added CLK_RUNTIME_PM flag to indicate clocks, for which clock core should
>   call runtime pm functions. This solves problem with clocks, for which struct
>   device is already registered, but no runtime pm is enabled.
> - Extended commit messages according to Ulf suggestions.
> - Fixed some style issues pointed by Barlomiej.
> 
> v1: http://www.spinics.net/lists/arm-kernel/msg528128.html
> - initial version
> 
> Marek Szyprowski (5):
>   clk: add support for runtime pm
>   clock: samsung: add support for runtime pm
>   clocks: exynos4x12: add runtime pm support for ISP clocks
>   ARM: dts: exynos: add support for ISP power domain to exynos4x12
>     clocks device
>   clocks: exynos5433: add runtime pm support
> 
>  .../devicetree/bindings/clock/exynos4-clock.txt    |  22 ++
>  arch/arm/boot/dts/exynos4x12.dtsi                  |   5 +
>  drivers/clk/clk.c                                  | 107 +++++-
>  drivers/clk/samsung/clk-exynos4.c                  | 227 ++++++++----
>  drivers/clk/samsung/clk-exynos5433.c               | 385 ++++++++++++++++-----
>  drivers/clk/samsung/clk-pll.c                      |   4 +-
>  drivers/clk/samsung/clk.c                          |  36 +-
>  drivers/clk/samsung/clk.h                          |   7 +
>  include/linux/clk-provider.h                       |   1 +
>  9 files changed, 632 insertions(+), 162 deletions(-)
> 

^ permalink raw reply

* [PATCH v2 0/5] Add runtime PM support for clocks (on Exynos SoC example)
From: Tobias Jakobi @ 2016-10-06 18:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <57F6926F.1070707@math.uni-bielefeld.de>

For reference, the build was done with this config:
https://github.com/tobiasjakobi/odroid-environment/blob/master/sourcecode/system/vanilla-4.8.conf

- Tobias


Tobias Jakobi wrote:
> Hello Marek,
> 
> I'm using the patches from the v4.8-clocks-pm-v2 branch plus the ones
> from the v4.8-clocks-pm-v2 branch on top of 4.8.0.
> 
> I see some warnings on boot coming from driver core. It appears that the
> warnings are actually meaningful, since IOMMUs stop working completly.
> E.g. if I modprobe s5p-mfc later, firmware loading fails because
> apparantly the IOMMU domain isn't online.
> 
>> WARNING: CPU: 0 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
> 
> I added some debug printk() to device_links_driver_bound(), to show the
> link status. Apparantly it is always DEVICE_LINK_AVAILABLE.
> 
> Here's the (semi) full log:
>> [    0.000000] Booting Linux on physical CPU 0xa00
>> [    0.000000] Linux version 4.8.0-vanilla+ (liquid at chidori) (gcc version 4.9.3 (Gentoo 4.9.3 p1.5, pie-0.6.4) ) #3 SMP PREEMPT Thu Oct 6 19:14:15 CEST 2016
>> [    0.000000] CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=10c5387d
>> [    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
>> [    0.000000] OF: fdt:Machine model: Hardkernel ODROID-X2 board based on Exynos4412
>> [    0.000000] Reserved memory: created DMA memory pool at 0xbf700000, size 8 MiB
>> [    0.000000] OF: reserved mem: initialized node region_mfc_right, compatible id shared-dma-pool
>> [    0.000000] Reserved memory: created DMA memory pool at 0xbe700000, size 16 MiB
>> [    0.000000] OF: reserved mem: initialized node region_mfc_left, compatible id shared-dma-pool
>> [    0.000000] cma: Reserved 128 MiB at 0xb6400000
>> [    0.000000] Memory policy: Data cache writealloc
>> [    0.000000] Samsung CPU ID: 0xe4412220
>> [    0.000000] Running under secure firmware.
>> [    0.000000] percpu: Embedded 14 pages/cpu @eefb3000 s26176 r8192 d22976 u57344
>> [    0.000000] Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 516352
>> [    0.000000] Kernel command line: video=HDMI-A-1:1280x720M at 60 console=ttySAC1,115200n8 root=PARTUUID=8c900d97-367f-47a9-bd66-6eced1a29836 rootfstype=f2fs rootwait ro earlyprintk console=tty1 console=ttySAC1,115200
>> [    0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes)
>> [    0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
>> [    0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
>> [    0.000000] Memory: 1913244K/2071552K available (6144K kernel code, 223K rwdata, 1432K rodata, 1024K init, 246K bss, 27236K reserved, 131072K cma-reserved, 1154048K highmem)
>> [    0.000000] Virtual kernel memory layout:
>> [    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
>> [    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
>> [    0.000000]     vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
>> [    0.000000]     lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
>> [    0.000000]     pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
>> [    0.000000]     modules : 0xbf000000 - 0xbfe00000   (  14 MB)
>> [    0.000000]       .text : 0xc0008000 - 0xc0700000   (7136 kB)
>> [    0.000000]       .init : 0xc0900000 - 0xc0a00000   (1024 kB)
>> [    0.000000]       .data : 0xc0a00000 - 0xc0a37fc0   ( 224 kB)
>> [    0.000000]        .bss : 0xc0a39000 - 0xc0a76a08   ( 247 kB)
>> [    0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
>> [    0.000000] Preemptible hierarchical RCU implementation.
>> [    0.000000]  Build-time adjustment of leaf fanout to 32.
>> [    0.000000] NR_IRQS:16 nr_irqs:16 16
>> [    0.000000] L2C: platform modifies aux control register: 0x02070000 -> 0x3e470001
>> [    0.000000] L2C: platform provided aux values permit register corruption.
>> [    0.000000] L2C: DT/platform modifies aux control register: 0x02070000 -> 0x3e470001
>> [    0.000000] L2C-310 enabling early BRESP for Cortex-A9
>> [    0.000000] L2C-310: enabling full line of zeros but not enabled in Cortex-A9
>> [    0.000000] L2C-310 ID prefetch enabled, offset 8 lines
>> [    0.000000] L2C-310 dynamic clock gating enabled, standby mode enabled
>> [    0.000000] L2C-310 cache controller enabled, 16 ways, 1024 kB
>> [    0.000000] L2C-310: CACHE_ID 0x4100c4c8, AUX_CTRL 0x7e470001
>> [    0.000000] Exynos4x12 clocks: sclk_apll = 1000000000, sclk_mpll = 800000000
>> [    0.000000]  sclk_epll = 96000000, sclk_vpll = 350000000, arm_clk = 1000000000
>> [    0.000000] Switching to timer-based delay loop, resolution 41ns
>> [    0.000000] clocksource: mct-frc: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 79635851949 ns
>> [    0.000004] sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
>> [    0.000263] Console: colour dummy device 80x30
>> [    0.000978] console [tty1] enabled
>> [    0.001003] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=120000)
>> [    0.001039] pid_max: default: 32768 minimum: 301
>> [    0.001118] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
>> [    0.001142] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
>> [    0.001577] CPU: Testing write buffer coherency: ok
>> [    0.001875] CPU0: thread -1, cpu 0, socket 10, mpidr 80000a00
>> [    0.002240] Setting up static identity map for 0x40100000 - 0x40100058
>> [    0.055360] CPU1: thread -1, cpu 1, socket 10, mpidr 80000a01
>> [    0.075335] CPU2: thread -1, cpu 2, socket 10, mpidr 80000a02
>> [    0.095316] CPU3: thread -1, cpu 3, socket 10, mpidr 80000a03
>> [    0.095374] Brought up 4 CPUs
>> [    0.095445] SMP: Total of 4 processors activated (192.00 BogoMIPS).
>> [    0.095464] CPU: All CPU(s) started in SVC mode.
>> [    0.096280] devtmpfs: initialized
>> [    0.110373] VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
>> [    0.110612] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 9556302231375000 ns
>> [    0.114190] pinctrl core: initialized pinctrl subsystem
>> [    0.114738] lcd0-power-domain at 10023C80 has as child subdomain: tv-power-domain at 10023C20.
>> [    0.115573] NET: Registered protocol family 16
>> [    0.117150] DMA: preallocated 256 KiB pool for atomic coherent allocations
>> [    0.134991] cpuidle: using governor ladder
>> [    0.154989] cpuidle: using governor menu
>> [    0.155398] hw-breakpoint: found 5 (+1 reserved) breakpoint and 1 watchpoint registers.
>> [    0.155434] hw-breakpoint: maximum watchpoint size is 4 bytes.
>> [    0.197368] SCSI subsystem initialized
>> [    0.197498] usbcore: registered new interface driver usbfs
>> [    0.197568] usbcore: registered new interface driver hub
>> [    0.197664] usbcore: registered new device driver usb
>> [    0.198081] s3c-i2c 13860000.i2c: slave address 0x10
>> [    0.198111] s3c-i2c 13860000.i2c: bus frequency set to 390 KHz
>> [    0.198570] s3c-i2c 13860000.i2c: i2c-0: S3C I2C adapter
>> [    0.198763] s3c-i2c 13870000.i2c: slave address 0x10
>> [    0.198791] s3c-i2c 13870000.i2c: bus frequency set to 390 KHz
>> [    0.199046] s3c-i2c 13870000.i2c: i2c-1: S3C I2C adapter
>> [    0.199192] s3c-i2c 13880000.i2c: slave address 0x00
>> [    0.199218] s3c-i2c 13880000.i2c: bus frequency set to 97 KHz
>> [    0.199375] s3c-i2c 13880000.i2c: i2c-2: S3C I2C adapter
>> [    0.199481] s3c-i2c 138e0000.i2c: slave address 0x00
>> [    0.199506] s3c-i2c 138e0000.i2c: bus frequency set to 97 KHz
>> [    0.199758] s3c-i2c 138e0000.i2c: i2c-8: S3C I2C adapter
>> [    0.200052] Linux video capture interface: v2.00
>> [    0.205439] Advanced Linux Sound Architecture Driver Initialized.
>> [    0.205901] Bluetooth: Core ver 2.21
>> [    0.205947] NET: Registered protocol family 31
>> [    0.205966] Bluetooth: HCI device and connection manager initialized
>> [    0.205992] Bluetooth: HCI socket layer initialized
>> [    0.206014] Bluetooth: L2CAP socket layer initialized
>> [    0.206036] Bluetooth: SCO socket layer initialized
>> [    0.206567] clocksource: Switched to clocksource mct-frc
>> [    0.214799] NET: Registered protocol family 2
>> [    0.215264] TCP established hash table entries: 8192 (order: 3, 32768 bytes)
>> [    0.215352] TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
>> [    0.215463] TCP: Hash tables configured (established 8192 bind 8192)
>> [    0.215531] UDP hash table entries: 512 (order: 2, 16384 bytes)
>> [    0.215573] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
>> [    0.215717] NET: Registered protocol family 1
>> [    0.216073] hw perfevents: enabled with armv7_cortex_a9 PMU driver, 7 counters available
>> [    0.217474] futex hash table entries: 1024 (order: 4, 65536 bytes)
>> [    0.217587] audit: initializing netlink subsys (disabled)
>> [    0.217641] audit: type=2000 audit(0.215:1): initialized
>> [    0.218191] workingset: timestamp_bits=30 max_order=19 bucket_order=0
>> [    0.230957] bounce: pool size: 64 pages
>> [    0.231124] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251)
>> [    0.231157] io scheduler noop registered
>> [    0.231175] io scheduler deadline registered
>> [    0.231306] io scheduler cfq registered (default)
>> [    0.231963] 125b0000.exynos-usbphy supply vbus not found, using dummy regulator
>> [    0.235681] dma-pl330 12680000.pdma: Loaded driver for PL330 DMAC-141330
>> [    0.235717] dma-pl330 12680000.pdma:         DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
>> [    0.238256] dma-pl330 12690000.pdma: Loaded driver for PL330 DMAC-141330
>> [    0.238291] dma-pl330 12690000.pdma:         DBUFF-32x4bytes Num_Chans-8 Num_Peri-32 Num_Events-32
>> [    0.239110] dma-pl330 12850000.mdma: Loaded driver for PL330 DMAC-141330
>> [    0.239141] dma-pl330 12850000.mdma:         DBUFF-64x8bytes Num_Chans-8 Num_Peri-1 Num_Events-32
>> [    0.239800] 13800000.serial: ttySAC0 at MMIO 0x13800000 (irq = 53, base_baud = 0) is a S3C6400/10
>> [    0.240144] 13810000.serial: ttySAC1 at MMIO 0x13810000 (irq = 54, base_baud = 0) is a S3C6400/10
>> [    1.015731] console [ttySAC1] enabled
>> [    1.019770] 13820000.serial: ttySAC2 at MMIO 0x13820000 (irq = 55, base_baud = 0) is a S3C6400/10
>> [    1.028570] 13830000.serial: ttySAC3 at MMIO 0x13830000 (irq = 56, base_baud = 0) is a S3C6400/10
>> [    1.038157] [drm] Initialized drm 1.1.0 20060810
>> [    1.042093] exynos-mixer 12c10000.mixer: Linked as a consumer to 12e20000.sysmmu
>> [    1.049118] iommu: Adding device 12c10000.mixer to group 0
>> [    1.055403] DEBUG: device_links_driver_bound(): 1
>> [    1.059238] ------------[ cut here ]------------
>> [    1.063826] WARNING: CPU: 0 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
>> [    1.072851] Modules linked in:
>> [    1.075859] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.8.0-vanilla+ #3
>> [    1.082458] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [    1.088533] Backtrace: 
>> [    1.090970] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
>> [    1.098524]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
>> [    1.104161] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
>> [    1.111376] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
>> [    1.118306]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
>> [    1.123946] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
>> [    1.131506]  r9:00000000 r8:c0a258d8 r7:ee3114e4 r6:eeafa874 r5:00000000 r4:ee3114c0
>> [    1.139231] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
>> [    1.148615] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
>> [    1.157287]  r9:00000000 r8:c0a258d8 r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eeafa810
>> [    1.165011] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
>> [    1.173345]  r4:eeafa810 r3:600000d3
>> [    1.176894] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
>> [    1.185323]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eeafa844 r5:c0a258d8
>> [    1.193128]  r4:eeafa810 r3:00000000
>> [    1.196685] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
>> [    1.204853]  r6:c0407eb0 r5:c0a258d8 r4:00000000 r3:c0407eb0
>> [    1.210485] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
>> [    1.218480]  r6:c0a26758 r5:ee27f780 r4:c0a258d8
>> [    1.223072] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
>> [    1.231072] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
>> [    1.239139]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a258d8
>> [    1.244773] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
>> [    1.253809]  r5:00000000 r4:00000004
>> [    1.257364] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
>> [    1.266402] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
>> [    1.274554]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
>> [    1.281232] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
>> [    1.289917]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
>> [    1.297722]  r4:c093a520
>> [    1.300243] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
>> [    1.308493]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
>> [    1.316297]  r4:00000000
>> [    1.318815] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
>> [    1.326373]  r4:00000000 r3:ee880000
>> [    1.329952] ---[ end trace 402e0b75dfe2947b ]---
>> [    1.336115] exynos-hdmi 12d00000.hdmi: Failed to get supply 'vdd': -517
>> [    1.341761] s5p-g2d 10800000.g2d: Linked as a consumer to 10a40000.sysmmu
>> [    1.347960] iommu: Adding device 10800000.g2d to group 1
>> [    1.353512] s5p-g2d 10800000.g2d: The Exynos G2D (ver 4.1) successfully probed.
>> [    1.360510] DEBUG: device_links_driver_bound(): 1
>> [    1.365183] ------------[ cut here ]------------
>> [    1.369786] WARNING: CPU: 1 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
>> [    1.378819] Modules linked in:
>> [    1.381829] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-vanilla+ #3
>> [    1.389651] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [    1.395718] Backtrace: 
>> [    1.398154] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
>> [    1.405709]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
>> [    1.411344] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
>> [    1.418560] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
>> [    1.425491]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
>> [    1.431132] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
>> [    1.438691]  r9:00000000 r8:c0a2621c r7:ee910ae4 r6:eeac4a74 r5:00000000 r4:ee910ac0
>> [    1.446416] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
>> [    1.455800] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
>> [    1.464472]  r9:00000000 r8:c0a2621c r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eeac4a10
>> [    1.472196] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
>> [    1.480530]  r4:eeac4a10 r3:00000000
>> [    1.484080] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
>> [    1.492508]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eeac4a44 r5:c0a2621c
>> [    1.500313]  r4:eeac4a10 r3:00000000
>> [    1.503870] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
>> [    1.512038]  r6:c0407eb0 r5:c0a2621c r4:00000000 r3:c0407eb0
>> [    1.517671] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
>> [    1.525665]  r6:c0a26758 r5:ee932b80 r4:c0a2621c
>> [    1.530257] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
>> [    1.538257] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
>> [    1.546324]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a2621c
>> [    1.551959] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
>> [    1.560994]  r5:00000000 r4:0000000a
>> [    1.564548] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
>> [    1.573587] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
>> [    1.581739]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
>> [    1.588415] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
>> [    1.597103]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
>> [    1.604907]  r4:c093a520
>> [    1.607427] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
>> [    1.615678]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
>> [    1.623482]  r4:00000000
>> [    1.625999] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
>> [    1.633558]  r4:00000000 r3:ee880000
>> [    1.637133] ---[ end trace 402e0b75dfe2947c ]---
>> [    1.642227] exynos-drm-fimc 11800000.fimc: Linked as a consumer to 11a20000.sysmmu
>> [    1.649335] iommu: Adding device 11800000.fimc to group 2
>> [    1.655529] exynos-drm-fimc 11810000.fimc: Linked as a consumer to 11a30000.sysmmu
>> [    1.662263] iommu: Adding device 11810000.fimc to group 3
>> [    1.668447] exynos-drm-fimc 11820000.fimc: Linked as a consumer to 11a40000.sysmmu
>> [    1.675196] iommu: Adding device 11820000.fimc to group 4
>> [    1.681278] exynos-drm-fimc 11820000.fimc: drm fimc registered successfully.
>> [    1.687589] DEBUG: device_links_driver_bound(): 1
>> [    1.692264] ------------[ cut here ]------------
>> [    1.696852] WARNING: CPU: 0 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
>> [    1.705880] Modules linked in:
>> [    1.708891] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-vanilla+ #3
>> [    1.716713] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [    1.722780] Backtrace: 
>> [    1.725216] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
>> [    1.732771]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
>> [    1.738407] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
>> [    1.745624] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
>> [    1.752553]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
>> [    1.758194] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
>> [    1.765754]  r9:00000000 r8:c0a26330 r7:ee311d24 r6:eea83074 r5:00000000 r4:ee311d00
>> [    1.773479] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
>> [    1.782862] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
>> [    1.791534]  r9:00000000 r8:c0a26330 r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eea83010
>> [    1.799258] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
>> [    1.807592]  r4:eea83010 r3:600000d3
>> [    1.811142] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
>> [    1.819571]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eea83044 r5:c0a26330
>> [    1.827376]  r4:eea83010 r3:00000000
>> [    1.830932] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
>> [    1.839100]  r6:c0407eb0 r5:c0a26330 r4:00000000 r3:c0407eb0
>> [    1.844733] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
>> [    1.852728]  r6:c0a26758 r5:ee27fa00 r4:c0a26330
>> [    1.857319] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
>> [    1.865320] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
>> [    1.873386]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a26330
>> [    1.879021] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
>> [    1.888057]  r5:00000000 r4:0000000b
>> [    1.891610] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
>> [    1.900649] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
>> [    1.908801]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
>> [    1.915478] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
>> [    1.924165]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
>> [    1.931969]  r4:c093a520
>> [    1.934489] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
>> [    1.942740]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
>> [    1.950545]  r4:00000000
>> [    1.953062] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
>> [    1.960620]  r4:00000000 r3:ee880000
>> [    1.964193] ---[ end trace 402e0b75dfe2947d ]---
>> [    1.969039] exynos-drm-fimc 11830000.fimc: Linked as a consumer to 11a50000.sysmmu
>> [    1.976392] iommu: Adding device 11830000.fimc to group 5
>> [    1.982437] exynos-drm-fimc 11830000.fimc: drm fimc registered successfully.
>> [    1.988799] DEBUG: device_links_driver_bound(): 1
>> [    1.993464] ------------[ cut here ]------------
>> [    1.998056] WARNING: CPU: 2 PID: 1 at drivers/base/core.c:356 device_links_driver_bound+0x124/0x12c
>> [    2.007076] Modules linked in:
>> [    2.010087] CPU: 2 PID: 1 Comm: swapper/0 Tainted: G        W       4.8.0-vanilla+ #3
>> [    2.017909] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
>> [    2.023975] Backtrace: 
>> [    2.026412] [<c010bb84>] (dump_backtrace) from [<c010bd80>] (show_stack+0x18/0x1c)
>> [    2.033967]  r6:60000053 r5:c0a1ff00 r4:00000000 r3:00040800
>> [    2.039603] [<c010bd68>] (show_stack) from [<c0353640>] (dump_stack+0x9c/0xb0)
>> [    2.046819] [<c03535a4>] (dump_stack) from [<c011fa74>] (__warn+0xec/0x104)
>> [    2.053750]  r6:c08038b0 r5:00000000 r4:00000000 r3:00040800
>> [    2.059390] [<c011f988>] (__warn) from [<c011fb44>] (warn_slowpath_null+0x28/0x30)
>> [    2.066950]  r9:00000000 r8:c0a26330 r7:ee313264 r6:eea83274 r5:00000000 r4:ee313240
>> [    2.074675] [<c011fb1c>] (warn_slowpath_null) from [<c0404114>] (device_links_driver_bound+0x124/0x12c)
>> [    2.084058] [<c0403ff0>] (device_links_driver_bound) from [<c0407950>] (driver_bound+0x68/0xb8)
>> [    2.092731]  r9:00000000 r8:c0a26330 r7:00000001 r6:c0a6d79c r5:c0a6d794 r4:eea83210
>> [    2.100454] [<c04078e8>] (driver_bound) from [<c0407e4c>] (driver_probe_device+0x280/0x2e4)
>> [    2.108788]  r4:eea83210 r3:600000d3
>> [    2.112338] [<c0407bcc>] (driver_probe_device) from [<c0407f64>] (__driver_attach+0xb4/0xb8)
>> [    2.120767]  r10:00000000 r9:c03f1178 r8:ffffffff r7:00000000 r6:eea83244 r5:c0a26330
>> [    2.128571]  r4:eea83210 r3:00000000
>> [    2.132128] [<c0407eb0>] (__driver_attach) from [<c0405f1c>] (bus_for_each_dev+0x74/0xa8)
>> [    2.140296]  r6:c0407eb0 r5:c0a26330 r4:00000000 r3:c0407eb0
>> [    2.145929] [<c0405ea8>] (bus_for_each_dev) from [<c0407760>] (driver_attach+0x24/0x28)
>> [    2.153924]  r6:c0a26758 r5:ee27fa00 r4:c0a26330
>> [    2.158516] [<c040773c>] (driver_attach) from [<c0407320>] (bus_add_driver+0x1a8/0x220)
>> [    2.166516] [<c0407178>] (bus_add_driver) from [<c0408894>] (driver_register+0x80/0x100)
>> [    2.174582]  r7:c0744e38 r6:c0744dc0 r5:00000000 r4:c0a26330
>> [    2.180217] [<c0408814>] (driver_register) from [<c0409920>] (__platform_driver_register+0x48/0x50)
>> [    2.189252]  r5:00000000 r4:0000000b
>> [    2.192806] [<c04098d8>] (__platform_driver_register) from [<c03f1240>] (exynos_drm_init+0xc8/0xfc)
>> [    2.201845] [<c03f1178>] (exynos_drm_init) from [<c01017c4>] (do_one_initcall+0x58/0x19c)
>> [    2.209997]  r8:c0a02448 r7:c0a39000 r6:c0a39000 r5:00000006 r4:c093a520
>> [    2.216674] [<c010176c>] (do_one_initcall) from [<c0900edc>] (kernel_init_freeable+0x1e4/0x288)
>> [    2.225361]  r10:c0926834 r9:c090060c r8:0000008e r7:c0a39000 r6:c0a39000 r5:00000006
>> [    2.233165]  r4:c093a520
>> [    2.235685] [<c0900cf8>] (kernel_init_freeable) from [<c06dc2dc>] (kernel_init+0x10/0x11c)
>> [    2.243936]  r10:00000000 r9:00000000 r8:00000000 r7:00000000 r6:00000000 r5:c06dc2cc
>> [    2.251740]  r4:00000000
>> [    2.254258] [<c06dc2cc>] (kernel_init) from [<c0107dd8>] (ret_from_fork+0x14/0x3c)
>> [    2.261816]  r4:00000000 r3:ee880000
>> [    2.265388] ---[ end trace 402e0b75dfe2947e ]---
>> [    2.270457] exynos-drm-ipp exynos-drm-ipp: drm ipp registered successfully.
>> [    2.280368] loop: module loaded
>> [    2.293185] random: fast init done
>> [    2.303857] usbcore: registered new interface driver smsc95xx
>> [    2.491598] dwc2 12480000.hsotg: Specified GNPTXFDEP=1024 > 768
>> [    2.491906] dwc2 12480000.hsotg: EPs: 16, dedicated fifos, 7808 entries in SPRAM
>> [    2.499801] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
>> [    2.505798] ehci-exynos: EHCI EXYNOS driver
>> [    2.510438] exynos-ehci 12580000.ehci: EHCI Host Controller
>> [    2.515535] exynos-ehci 12580000.ehci: new USB bus registered, assigned bus number 1
>> [    2.523434] exynos-ehci 12580000.ehci: irq 51, io mem 0x12580000
>> [    2.541596] exynos-ehci 12580000.ehci: USB 2.0 started, EHCI 1.00
>> <snip>
> 
> I'll try to do another test with just the 5 patches from this set
> applied (without the IOMMU probe deferral).
> 
> With best wishes,
> Tobias
> 
> 
> 
> Marek Szyprowski wrote:
>> Dear All,
>>
>> This patchset adds runtime PM support to common clock framework. This is an
>> attempt to implement support for clock controllers, which belongs to a power
>> domain. This approach works surprisingly well on Exynos 4412 and 5433 SoCs,
>> what allowed us to solve various freeze/crash issues related to power
>> management.
>>
>> The main idea behind this patchset is to keep clock's controller power domain
>> enabled every time when at least one of its clock is enabled or access to its
>> registers is being made. Clock controller driver (clock provider) can
>> supply a struct device pointer, which is the used by clock core for tracking and
>> managing clock's controller runtime pm state. Each clk_prepare() operation will
>> first call pm_runtime_get_sync() on the supplied device, while clk_unprepare()
>> will do pm_runtime_put() at the end.
>>
>> This runtime PM feature has been tested with Exynos4412 and Exynos5433 clocks
>> drivers. Both have some clocks, which belongs to respective power domains and
>> need special handling during power on/off procedures. Till now it wasn't handled
>> at all, what caused various problems.
>>
>> Patches for exynos 4412 and 5433 clocks drivers change the way the clock
>> provider is initialized. Instead of CLK_OF_DECLARE based initialization, a
>> complete platform device driver infrastructure is being used. This is needed to
>> let driver to use runtime pm feature and integrate with generic power domains.
>> The side-effect of this change is a delay in clock provider registeration
>> during system boot, so early initialized drivers might get EPROBEDEFER error
>> when requesting their clocks. This is an issue for IOMMU drivers, so
>> this patchset will be fully functional once the deferred probe for IOMMU
>> will be merged.
>>
>> The side-effect of this patchset is the one can finally read
>> /sys/kernel/debug/clk/clk_summary on all Exynos4412 boards without any freeze.
>>
>> If one wants to test this patchset (on Exynos4412 Trats2 device with FIMC-IS
>> driver), I've provided a branch with all needed patches (fixes for Exynos,
>> FIMC-IS driver and IOMMU deferred probe):
>> https://git.linaro.org/people/marek.szyprowski/linux-srpol.git v4.8-clocks-pm-v2
>>
>> Patches are based on vanilla v4.8-rc7 kernel.
>>
>> Best regards
>> Marek Szyprowski
>> Samsung R&D Institute Poland
>>
>> Changelog:
>> v2:
>> - Simplified clk_pm_runtime_get/put functions, removed workaround for devices
>>   with disabled runtime pm. Such workaround is no longer needed since commit
>>   4d23a5e84806b202d9231929c9507ef7cf7a0185 ("PM / Domains: Allow runtime PM
>>   during system PM phases").
>> - Added CLK_RUNTIME_PM flag to indicate clocks, for which clock core should
>>   call runtime pm functions. This solves problem with clocks, for which struct
>>   device is already registered, but no runtime pm is enabled.
>> - Extended commit messages according to Ulf suggestions.
>> - Fixed some style issues pointed by Barlomiej.
>>
>> v1: http://www.spinics.net/lists/arm-kernel/msg528128.html
>> - initial version
>>
>> Marek Szyprowski (5):
>>   clk: add support for runtime pm
>>   clock: samsung: add support for runtime pm
>>   clocks: exynos4x12: add runtime pm support for ISP clocks
>>   ARM: dts: exynos: add support for ISP power domain to exynos4x12
>>     clocks device
>>   clocks: exynos5433: add runtime pm support
>>
>>  .../devicetree/bindings/clock/exynos4-clock.txt    |  22 ++
>>  arch/arm/boot/dts/exynos4x12.dtsi                  |   5 +
>>  drivers/clk/clk.c                                  | 107 +++++-
>>  drivers/clk/samsung/clk-exynos4.c                  | 227 ++++++++----
>>  drivers/clk/samsung/clk-exynos5433.c               | 385 ++++++++++++++++-----
>>  drivers/clk/samsung/clk-pll.c                      |   4 +-
>>  drivers/clk/samsung/clk.c                          |  36 +-
>>  drivers/clk/samsung/clk.h                          |   7 +
>>  include/linux/clk-provider.h                       |   1 +
>>  9 files changed, 632 insertions(+), 162 deletions(-)
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* [PATCH 06/14] ASoC: Add sun8i digital audio codec
From: Alexandre Belloni @ 2016-10-06 18:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <901741475770017@web21g.yandex.ru>

On 07/10/2016 at 00:06:57 +0800, Icenowy Zheng wrote :
> 05.10.2016, 00:20, "Maxime Ripard" <maxime.ripard@free-electrons.com>:
> > Hi,
> >
> >> ?+static const struct of_device_id sun8i_codec_of_match[] = {
> >> ?+ { .compatible = "allwinner,sun8i-a33-codec" },
> >> ?+ { .compatible = "allwinner,sun8i-a23-codec" },
> >
> > I thought that the A23 and A33 had different codecs? In that case, it
> > wouldn't be a good assumption to make
> 
> Yes.
> 
> >
> >> ?+ {}
> >> ?+};
> >> ?+MODULE_DEVICE_TABLE(of, sun8i_codec_of_match);
> >> ?+
> >> ?+static struct platform_driver sun8i_codec_driver = {
> >> ?+ .driver = {
> >> ?+ .name = "sun8i-codec",
> >> ?+ .owner = THIS_MODULE,
> >> ?+ .of_match_table = sun8i_codec_of_match,
> >> ?+ },
> >> ?+ .probe = sun8i_codec_probe,
> >> ?+ .remove = sun8i_codec_remove,
> >> ?+};
> >> ?+module_platform_driver(sun8i_codec_driver);
> >> ?+
> >> ?+MODULE_DESCRIPTION("Allwinner A33 (sun8i) codec driver");
> >> ?+MODULE_AUTHOR("huanxin<huanxin@reuuimllatech.com>");
> >
> > Those obfuscated email adresses are not really helpful :)
> 
> This kind of email addresses  are kept in many places in mainline kernel.
> 
> e.g. drivers/mmc/host/sunxi-mmc.c have 'Aaron Maoye <leafy.myeh@reuuimllatech.com>'
> 

Well, that is only one place and it is a comment, not in the
MODULE_AUTHOR macro. I would agree that it is not useful to have a stale
email address in MODULE_AUTHOR.

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [PATCH v4 0/1] Armada 7k/8k CP110 system controller fixes
From: Marcin Wojtas @ 2016-10-06 19:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1474789673-3837-1-git-send-email-mw@semihalf.com>

Hi Stephen,

Do you have any further comments on the remaining patch?

Best regards,
Marcin

2016-09-25 9:47 GMT+02:00 Marcin Wojtas <mw@semihalf.com>:
> Hi,
>
> Two patches from the third version of the patchset have already been
> applied, so I re-send the last one with corrected allocation of
> clock data, which was pointed in the review.
>
> Any feedback would be very welcome.
>
> Best regards,
> Marcin
>
> Changelog:
> v4 <- v3
> * fix allocation of clock data
>
> v3 <- v2
> * return -ENOMEM on alloc failures
>
> v1 <- v2
> * replace setting CLK_IS_BASIC flag with clearing init structure fields
>   with memset
> * minor improvements of allocation and error checking
> * add migration to clk_hw
>
>
> Marcin Wojtas (1):
>   clk: mvebu: migrate CP110 system controller to clk_hw API and
>     registration
>
>  drivers/clk/mvebu/cp110-system-controller.c | 150 +++++++++++++---------------
>  1 file changed, 72 insertions(+), 78 deletions(-)
>
> --
> 1.8.3.1
>

^ permalink raw reply

* [PATCH] dmaengine: qcom_hidma: prevent disable in error
From: Sinan Kaya @ 2016-10-06 19:33 UTC (permalink / raw)
  To: linux-arm-kernel

When an error is observed, we try to disable the channel and prevent
further accesses from the client.

Depending on the type of error, transitioning into disabled state might
not be possible. Adding a check to make sure that HW is in enabled/running
state before the disable transition happens.

Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
---
 drivers/dma/qcom/hidma_ll.c | 15 ++-------------
 1 file changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/qcom/hidma_ll.c b/drivers/dma/qcom/hidma_ll.c
index 3224f24..c3a66c9 100644
--- a/drivers/dma/qcom/hidma_ll.c
+++ b/drivers/dma/qcom/hidma_ll.c
@@ -564,19 +564,8 @@ int hidma_ll_disable(struct hidma_lldev *lldev)
 	u32 val;
 	int ret;
 
-	val = readl(lldev->evca + HIDMA_EVCA_CTRLSTS_REG);
-	lldev->evch_state = HIDMA_CH_STATE(val);
-	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
-	lldev->trch_state = HIDMA_CH_STATE(val);
-
-	/* already suspended by this OS */
-	if ((lldev->trch_state == HIDMA_CH_SUSPENDED) ||
-	    (lldev->evch_state == HIDMA_CH_SUSPENDED))
-		return 0;
-
-	/* already stopped by the manager */
-	if ((lldev->trch_state == HIDMA_CH_STOPPED) ||
-	    (lldev->evch_state == HIDMA_CH_STOPPED))
+	/* The channel needs to be in working state */
+	if (!hidma_ll_isenabled(lldev))
 		return 0;
 
 	val = readl(lldev->trca + HIDMA_TRCA_CTRLSTS_REG);
-- 
1.9.1

^ permalink raw reply related

* [PATCH] ARM: dts: rockchip: initialize rk3066 PLL clock rate
From: Paweł Jarosz @ 2016-10-06 19:42 UTC (permalink / raw)
  To: linux-arm-kernel

Initialize PLL rate while kernel init. No other module does than.
Clock rates are taken from rk3066 TRM. Assigned values are for 125 degrees
celcius operating point.
This gives us performance boost observable for example in mmc transfers.

Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
---
 arch/arm/boot/dts/rk3066a.dtsi | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
index 0d0dae3..cf215e8 100644
--- a/arch/arm/boot/dts/rk3066a.dtsi
+++ b/arch/arm/boot/dts/rk3066a.dtsi
@@ -151,6 +151,10 @@
 
 		#clock-cells = <1>;
 		#reset-cells = <1>;
+		assigned-clocks = <&cru PLL_DPLL>, <&cru PLL_APLL>,
+				  <&cru PLL_CPLL>, <&cru PLL_GPLL>;
+		assigned-clock-rates = <533000000>, <600000000>,
+				       <600000000>, <600000000>;
 	};
 
 	timer at 2000e000 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH v6 1/5] drm/sun4i: rgb: Remove the bridge enable/disable functions
From: Sean Paul @ 2016-10-06 19:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5100ee37c9bbb53f8227bd38f1d3160e507c489d.1475740611.git-series.maxime.ripard@free-electrons.com>

On Thu, Oct 6, 2016 at 3:57 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The atomic helpers already call the drm_bridge_enable on our behalf,
> there's no need to do it a second time.
>
> Reported-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Sean Paul <seanpaul@chromium.org>

> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  drivers/gpu/drm/sun4i/sun4i_rgb.c | 6 ------
>  1 file changed, 0 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> index 4e4bea6f395c..d198ad7e5323 100644
> --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
> +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
> @@ -155,9 +155,6 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
>         if (!IS_ERR(tcon->panel))
>                 drm_panel_prepare(tcon->panel);
>
> -       /* encoder->bridge can be NULL; drm_bridge_enable checks for it */
> -       drm_bridge_enable(encoder->bridge);
> -
>         sun4i_tcon_channel_enable(tcon, 0);
>
>         if (!IS_ERR(tcon->panel))
> @@ -177,9 +174,6 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
>
>         sun4i_tcon_channel_disable(tcon, 0);
>
> -       /* encoder->bridge can be NULL; drm_bridge_disable checks for it */
> -       drm_bridge_disable(encoder->bridge);
> -
>         if (!IS_ERR(tcon->panel))
>                 drm_panel_unprepare(tcon->panel);
>  }
> --
> git-series 0.8.10
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH 1/8] PM / Domains: Make genpd state allocation dynamic
From: Ulf Hansson @ 2016-10-06 19:45 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20161006154052.GB28930@linaro.org>

On 6 October 2016 at 17:40, Lina Iyer <lina.iyer@linaro.org> wrote:
> On Thu, Oct 06 2016 at 02:37 -0600, Ulf Hansson wrote:
>>
>> On 5 October 2016 at 22:31, Lina Iyer <lina.iyer@linaro.org> wrote:
>>>
>>> Allow PM Domain states to be defined dynamically by the drivers. This
>>> removes the limitation on the maximum number of states possible for a
>>> domain.
>>>
>>> Cc: Axel Haslam <ahaslam+renesas@baylibre.com>
>>> Suggested-by: Ulf Hansson <ulf.hansson@linaro.org>
>>> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
>
> <...>
>>>
>>> -#define GENPD_MAX_NUM_STATES   8 /* Number of possible low power states
>>> */
>>> -
>>>  enum gpd_status {
>>>         GPD_STATE_ACTIVE = 0,   /* PM domain is active */
>>>         GPD_STATE_POWER_OFF,    /* PM domain is off */
>>> @@ -70,7 +68,7 @@ struct generic_pm_domain {
>>>         void (*detach_dev)(struct generic_pm_domain *domain,
>>>                            struct device *dev);
>>>         unsigned int flags;             /* Bit field of configs for genpd
>>> */
>>> -       struct genpd_power_state states[GENPD_MAX_NUM_STATES];
>>> +       struct genpd_power_state *states;
>>>         unsigned int state_count; /* number of states */
>>>         unsigned int state_idx; /* state that genpd will go to when off
>>> */
>>>
>>> --
>>> 2.7.4
>>>
>>
>> In general I like the improvement, but..
>>
>> This change implies that ->states may very well be NULL. This isn't
>> validated by genpd's internal logic when power off/on the domain
>> (genpd_power_on|off(), __default_power_down_ok()). You need to fix
>> this, somehow.
>>
> Good point.
>
>> Perhaps the easiest solutions is, when pm_genpd_init() finds that
>> ->state is NULL, that we allocate a struct genpd_power_state with
>> array size of 1 and assign it to ->states. Although, doing this also
>> means you need to track that genpd was responsible for the the
>> allocation, so it must also free the data from within genpd_remove().
>>
>> Unless you have other ideas!?
>>
> I can think of some hacks, but they are uglier than the problem we are
> trying to solve. We could drop this patch. Real world situations would
> not have more than 8 states and if there is one, we can think about it
> then.

The problem with the current approach is that we waste some memory as
we always have an array of 8 states per genpd. In the worst case,
which currently is the most common case, only 1 out of 8 states is
being used.

So, let's not be lazy here and instead take the opportunity to fix
this, and especially I think this makes sense, before we go on and add
the DT parsing of the domain-idle-states.

The more sophisticated method would probably be to use kobject/kref,
but let's not go there for now. Instead let's try an easy method of
just tracking whether the allocations had been made internally by
genpd, via adding a "bool state_allocated to the struct
generic_pm_domain. Would that work?

Kind regards
Uffe

^ permalink raw reply

* [PATCH v5 2/5] drm/bridge: Add RGB to VGA bridge support
From: Sean Paul @ 2016-10-06 19:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5319260.UeCnJXKVPe@avalon>

On Thu, Oct 6, 2016 at 1:27 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> Hello,
>
> On Thursday 06 Oct 2016 17:09:57 Archit Taneja wrote:
>> On 10/06/2016 12:51 PM, Maxime Ripard wrote:
>> > On Mon, Oct 03, 2016 at 04:40:57PM +0530, Archit Taneja wrote:
>> >> On 09/30/2016 08:07 PM, Maxime Ripard wrote:
>> >>> Some boards have an entirely passive RGB to VGA bridge, based on either
>> >>> DACs or resistor ladders.
>> >>>
>> >>> Those might or might not have an i2c bus routed to the VGA connector in
>> >>> order to access the screen EDIDs.
>> >>>
>> >>> Add a bridge that doesn't do anything but expose the modes available on
>> >>> the screen, either based on the EDIDs if available, or based on the XGA
>> >>> standards.
>> >>>
>> >>> Acked-by: Rob Herring <robh@kernel.org>
>> >>> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>> >>> ---
>> >>> .../bindings/display/bridge/rgb-to-vga-bridge.txt  |  48 +++++
>> >>> drivers/gpu/drm/bridge/Kconfig                     |   7 +
>> >>> drivers/gpu/drm/bridge/Makefile                    |   1 +
>> >>> drivers/gpu/drm/bridge/rgb-to-vga.c                | 229 +++++++++++++++
>> >>> 4 files changed, 285 insertions(+)
>> >>> create mode 100644
>> >>> Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
>> >>> create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
>> >>>
>> >>> diff --git
>> >>> a/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.tx
>> >>> t
>> >>> b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.tx
>> >>> t new file mode 100644
>> >>> index 000000000000..a8375bc1f9cb
>> >>> --- /dev/null
>> >>> +++
>> >>> b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.tx
>> >>> t @@ -0,0 +1,48 @@
>> >>> +Dumb RGB to VGA bridge
>> >>> +----------------------
>> >>> +
>> >>> +This binding is aimed for dumb RGB to VGA bridges that do not require
>> >>> +any configuration.
>> >>> +
>> >>> +Required properties:
>> >>> +
>> >>> +- compatible: Must be "rgb-to-vga-bridge"
>> >>
>> >> I'd talked to Laurent on IRC if he's okay with this. And I guess you to
>> >> had discussed it during XDC too. He's suggested that it'd be better to
>> >> have the compatible string as "simple-vga-dac".
>> >
>> > I just wished this bikeshedding had taken place publicly and be
>> > actually part of that discussion, but yeah, ok.
>>
>> Sorry about that. I'd pinged him for an Ack, the discussion went
>> more than that :)
>>
>> >> Some of the reasons behind having this:
>> >>
>> >> - We don't need to specify "rgb" in the compatible string since most
>> >> simple VGA DACs can only work with an RGB input.
>> >
>> > Ok.
>> >
>> >> - Also, with "dac" specified in the string, we don't need to
>> >> specifically mention "bridge" in the string. Also, bridge is a drm
>> >> specific term.
>> >>
>> >> - "simple" is considered because it's an unconfigurable bridge, and it
>> >> might be misleading for other VGA DACs to not use "vga-dac".
>> >
>> > All those "simple" bindings are just the biggest lie we ever
>> > told. It's simple when you introduce it, and then grows into something
>> > much more complicated than a non-simple implementation.
>>
>> "simple" here is supposed to mean that it's an unconfigurable RGB to
>> VGA DAC. This isn't supposed to follow the simple-panel model, where
>> you add the "simple-panel" string in the compatible node, along with
>> you chip specific compatible string.
>
> I agree with Maxime, I don't like the word "simple". My preference would be
> "vga-dac" for a lack of a better qualifier than "simple" to describe the fact
> that the device requires no configuration. My only concern with "vga-dac" is
> that we would restrict usage of that compatible string for a subset of VGA
> DACs, with more complex devices not being compatible with "vga-dac" even
> though they are VGA DACs. That's a problem I can live with though.

While we're bikeshedding (feel free to ignore my input on this), I
think Maxime's initial "dumb" qualifier was better than "simple". I
think "passive" also gets the point across better than "simple", which
we've already established as something else in drm.

Now that I've gotten that out of the way, this patch looks good to me
regardless of the name.

Reviewed-by: Sean Paul <seanpaul@chromium.org>

Sean

>
>> In other words, this driver shouldn't be touched again in the future :)
>> If someone wants to write a RGB to VGA driver which is even
>> slightly configurable, they'll need to write a new bridge driver.
>
> I'm sure that won't be true. I can certainly foresee the addition of
> regulators support for instance. It's unfortunately never black and white.
>
>> >> What do you think about this? If you think it's good, would it be
>> >> possible for you to change this? I guess it's okay for the rest of
>> >> the patch to stay the same.
>> >
>> > I'll update and respin the serie.
>
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH] coresight: tmc: implementing TMC-ETR AUX space API
From: Mathieu Poirier @ 2016-10-06 20:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <3aba2b4f-72b1-297b-bc0a-2a08aa8845e8@arm.com>

On 3 October 2016 at 08:32, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 19/09/16 22:14, Mathieu Poirier wrote:
>>
>> This patch implements the AUX area interfaces required to
>> use the TMC-ETR (configured to work in scatter-gather mode)
>> from the Perf sub-system.
>>
>> Some of this work was inspired from the original implementation
>> done by Pratik Patel at CodeAurora.
>>
>
> Hi Mathieu,
>
> Thanks for nailing the monster. I have a few comments below on the
> implementation.
>
>> Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
>> ---
>>  drivers/hwtracing/coresight/coresight-tmc-etr.c | 629
>> +++++++++++++++++++++++-
>>  drivers/hwtracing/coresight/coresight-tmc.h     |   1 +
>>  2 files changed, 621 insertions(+), 9 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> index 6d7de0309e94..581d6393bb5d 100644
>> --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
>> @@ -17,10 +17,60 @@
>>
>>  #include <linux/coresight.h>
>>  #include <linux/dma-mapping.h>
>> +#include <linux/slab.h>
>> +
>>  #include "coresight-priv.h"
>>  #include "coresight-tmc.h"
>>
>> -void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
>> +/**
>> + * struct etr_page - DMA'able and virtual address representation for a
>> page
>> + * @daddr:             DMA'able page address returned by dma_map_page()
>> + * @vaddr:             Virtual address returned by page_address()
>> + */
>> +struct etr_page {
>> +       dma_addr_t      daddr;
>> +       u64             vaddr;
>> +};
>> +
>> +/**
>> + * struct cs_etr_buffer - keep track of a recording session' specifics
>> + * @dev:               device reference to be used with the DMA API
>> + * @tmc:               generic portion of the TMC buffers
>> + * @etr_nr_pages:      number of memory pages for the ETR-SG trace
>> storage
>> + * @pt_vaddr:          the virtual address of the first page table entry
>> + * @page_addr:         quick access to all the pages held in the page
>> table
>> + */
>> +struct cs_etr_buffers {
>> +       struct device           *dev;
>> +       struct cs_buffers       tmc;
>> +       unsigned int            etr_nr_pages;
>> +       void __iomem            *pt_vaddr;
>> +       struct etr_page         page_addr[0];
>> +};
>> +
>> +#define TMC_ETR_ENTRIES_PER_PT (PAGE_SIZE / sizeof(u32))
>> +
>> +/*
>> + * Helpers for scatter-gather descriptors.  Descriptors are defined as
>> follow:
>> + *
>> + * ---Bit31------------Bit4-------Bit1-----Bit0--
>> + * |     Address[39:12]    | SBZ |  Entry Type  |
>> + * ----------------------------------------------
>> + *
>> + * Address: Bits [39:12] of a physical page address. Bits [11:0] are
>> + *         always zero.
>> + *
>> + * Entry type: b10 - Normal entry
>> + *             b11 - Last entry in a page table
>> + *             b01 - Last entry
>> + */
>> +#define TMC_ETR_SG_LST_ENT(phys_pte)   (((phys_pte >> PAGE_SHIFT) << 4) |
>> 0x1)
>> +#define TMC_ETR_SG_ENT(phys_pte)       (((phys_pte >> PAGE_SHIFT) << 4) |
>> 0x2)
>> +#define TMC_ETR_SG_NXT_TBL(phys_pte)   (((phys_pte >> PAGE_SHIFT) << 4) |
>> 0x3)
>> +
>
>
> Please be aware that on arm64, the PAGE_SIZE can be 16K or 64K. So hard
> coding
> PAGE_SHIFT here might be problematic on those configurations as the ETR page
> size
> is always 4K.

You are correct.  This driver will not work with page sizes bigger than 4K.

>
>> +#define TMC_ETR_SG_ENT_TO_PG(entry)    ((entry >> 4) << PAGE_SHIFT)
>> +
>> +void tmc_etr_enable_hw_cnt_mem(struct tmc_drvdata *drvdata)
>>  {
>>         u32 axictl;
>>
>> @@ -57,7 +107,47 @@ void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
>>         CS_LOCK(drvdata->base);
>>  }
>>
>> -static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
>> +void tmc_etr_enable_hw_sg_mem(struct tmc_drvdata *drvdata)
>
>
>
>> +        * DBAHI Holds the upper eight bits of the 40-bit address used to
>> +        * locate the trace buffer in system memory.
>> +        */
>> +       writel_relaxed((drvdata->paddr >> 32) & 0xFF,
>> +                       drvdata->base + TMC_DBAHI);
>
>
> I think we should do the same for tmc_etr_enable_hw_cnt_mem().

Totally.

>
>> @@ -199,7 +290,7 @@ static int tmc_enable_etr_sink_perf(struct
>> coresight_device *csdev, u32 mode)
>>                 goto out;
>>         }
>>
>> -       tmc_etr_enable_hw(drvdata);
>> +       tmc_etr_enable_hw_sg_mem(drvdata);
>>  out:
>>         spin_unlock_irqrestore(&drvdata->spinlock, flags);
>>
>> @@ -241,9 +332,528 @@ static void tmc_disable_etr_sink(struct
>> coresight_device *csdev)
>>         dev_info(drvdata->dev, "TMC-ETR disabled\n");
>>  }
>>
>> +/*
>> + * The default perf ring buffer size is 32 and 1024 pages for user and
>> kernel
>> + * space respectively.  The size of the intermediate SG list is allowed
>> + * to match the size of the perf ring buffer but cap it to the default
>> + * kernel size.
>> + */
>> +#define DEFAULT_NR_KERNEL_PAGES        1024
>> +static int tmc_get_etr_pages(int nr_pages)
>
>
> The name could be confusing, as it kind of implies it allocates nr_pages.
> It might be worth renaming it to tmc_get_etr_pages_nr ?

I see your point, though "tmc_get_etr_nr_pages" would likely be
better.  A comment wouldn't be armful either.

>
>> +{
>> +       if (nr_pages <= DEFAULT_NR_KERNEL_PAGES)
>> +               return nr_pages;
>> +
>> +       return DEFAULT_NR_KERNEL_PAGES;
>> +}
>> +
>> +/*
>> + * Go through all the pages in the SG list and check if @phys_addr
>> + * falls within one of those.  If so record the information in
>> + * @page and @offset.
>> + */
>> +static int
>> +tmc_get_sg_page_index(struct cs_etr_buffers *etr_buffer,
>> +                     u64 phys_addr, u32 *page, u32 *offset)
>> +{
>> +       int i = 0, pte = 0, nr_pages = etr_buffer->etr_nr_pages;
>> +       u32 *page_table_itr = etr_buffer->pt_vaddr;
>> +       phys_addr_t phys_page_addr;
>> +
>> +       /* Circle through all the pages in the SG list */
>> +       while (pte < nr_pages) {
>> +               phys_page_addr =
>> TMC_ETR_SG_ENT_TO_PG((u64)*page_table_itr);
>
>
> Could we not find the phys_addr by scanning the etr_pages[].daddr and use
> the
> index to hope through the PageTable links to reach the entry which could
> have it
> and return the offset within that page ?

Yes, that is another way of proceeding.  I simply decided to keep the
table walktrough similar in all the function.

>
>> +
>> +               /* Does @phys_addr falls within this page? */
>> +               if (phys_addr >= phys_page_addr &&
>> +                   phys_addr < (phys_page_addr + PAGE_SIZE)) {
>> +                       *page = pte;
>> +                       *offset = phys_addr - phys_page_addr;
>> +                       return 0;
>> +               }
>> +
>> +               if (pte == nr_pages - 1) {
>> +                       /* The last page in the SG list */
>> +                       pte++;
>> +               } else if (i == TMC_ETR_ENTRIES_PER_PT - 1) {
>> +                       /*
>> +                        * The last entry in this page table - get a
>> reference
>> +                        * on the next page table and do _not_ increment
>> @pte
>> +                        */
>> +                       page_table_itr = phys_to_virt(phys_page_addr);
>> +                       i = 0;
>> +               } else {
>> +                       /* A normal page in the SG list */
>> +                       page_table_itr++;
>> +                       pte++;
>> +                       i++;
>> +               }
>> +       }
>> +
>> +       return -EINVAL;
>> +}
>> +
>> +static void tmc_sg_page_sync(struct cs_etr_buffers *etr_buffer,
>> +                            int start_page, u64 to_sync)
>
>
> nit: to_sync doesn't give a clue on what the unit is ? pages ? bytes ?
> could it be u64 size ?

It sure could.

>
>> +{
>> +       int i, index;
>> +       int pages_to_sync = DIV_ROUND_UP_ULL(to_sync, PAGE_SIZE);
>> +       dma_addr_t daddr;
>> +       struct device *dev = etr_buffer->dev;
>> +
>> +       for (i = start_page; i < (start_page + pages_to_sync); i++) {
>> +               /* Wrap around the etr page list if need be */
>> +               index = i % etr_buffer->etr_nr_pages;
>> +               daddr = etr_buffer->page_addr[index].daddr;
>> +               dma_sync_single_for_cpu(dev, daddr, PAGE_SIZE,
>> DMA_FROM_DEVICE);
>> +       }
>> +}
>> +
>
>
>> +static void tmc_free_sg_buffer(struct cs_etr_buffers *etr_buffer, int
>> nr_pages)
>> +{
>> +       int i = 0, pte = 0;
>> +       u32 *page_addr, *page_table_itr;
>> +       u32 *page_table_addr = etr_buffer->pt_vaddr;
>> +       phys_addr_t phys_page_addr;
>> +       dma_addr_t daddr;
>> +       struct device *dev = etr_buffer->dev;
>> +
>> +       if (!page_table_addr)
>> +               return;
>> +
>
>
> Please check comments on tmc_alloc_sg_buffer().
>
>> +
>> +static int
>> +tmc_alloc_sg_buffer(struct cs_etr_buffers *etr_buffer, int cpu, int
>> nr_pages)
>> +{
>> +       int i = 0, node, pte = 0, ret = 0;
>> +       dma_addr_t dma_page_addr;
>> +       u32 *page_table_addr, *page_addr;
>> +       struct page *page;
>> +       struct device *dev = etr_buffer->dev;
>> +
>> +       if (cpu == -1)
>> +               cpu = smp_processor_id();
>> +       node = cpu_to_node(cpu);
>> +
>> +       /* Allocate the first page table */
>> +       page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0);
>> +       if (!page)
>> +               return -ENOMEM;
>> +
>> +       page_table_addr = page_address(page);
>
>
> Would it be simpler to allocate the pages required for the PageTables and
> track them
> separately ? i.e for a given nr_pages, we could easily calculate the number
> of Table
> entries required.
>
> nr_table_pages = (nr_pages << (PAGE_SHIFT - 12)) / (TMC_ETR_ENTRIES_PER_PT -
> 1);

This would have to be rounded up.

> table_pages = alloc_pages_exact_nid(node, GFP_KERNEL|__GFP_ZERO,
> nr_table_pages * PAGE_SIZE);

Not sure about this part.  A request like this may be hard to fulfil
on a busy system.  Allocating non-contiguous page tables is, in my
opinion, a better way to go.

>
> where, PAGE_SHIFT - 12 ( = PAGE_SHIFT_4K) gives the log2 number 4K pages in
> a system
> page.
>
> That way, we can link the pages easily and also free them easily in
> tmc_free_sg_buffer() without
> traversing the page table once again, since we track the ETR pages and the
> pages for the tables now.
> Also the page table initialisation below could be much simpler as we could
> link the table entries
> at one shot.

Right, that is another way of doing things and I toyed with the idea a
while back.  It would involve keeping references to the page tables in
a linked list, which isn't the end of the world.  But my logic was
that:

1) We need to walk the page tables to find each ETR pages so why bother?
2) The HW already maintains the linked list for us, no need to
maintain the same information in SW.

I added plenty of comments especially to help people with the
algorithm.  I can try to see if the code is simpler by proceeding your
way but I have doubts the benefits will be worth the cost (and we
still maintain the same information twice).

>
>>
>> +       /*
>> +        * Keep track of the first page table, the rest will be chained
>> +        * in the last page table entry.
>> +        */
>> +       etr_buffer->pt_vaddr = page_table_addr;
>> +
>> +       while (pte < nr_pages) {
>> +               page = alloc_pages_node(node,
>> +                                       GFP_KERNEL | __GFP_ZERO, 0);
>> +               if (!page) {
>> +                       ret = -ENOMEM;
>> +                       goto err;
>> +               }
>> +
>> +               page_addr = page_address(page);
>> +
>> +               if (pte == nr_pages - 1) {
>> +                       /* The last page in the list */
>> +                       dma_page_addr = tmc_setup_dma_page(dev, page);
>> +                       if (dma_page_addr == -EINVAL) {
>> +                               ret = -EINVAL;
>> +                               goto err;
>> +                       }
>> +
>> +                       *page_table_addr =
>> TMC_ETR_SG_LST_ENT(dma_page_addr);
>> +
>> +                       etr_buffer->page_addr[pte].vaddr = (u64)page_addr;
>> +                       etr_buffer->page_addr[pte].daddr = dma_page_addr;
>> +
>> +                       pte++;
>> +               } else if (i == TMC_ETR_ENTRIES_PER_PT - 1) {
>> +                       /* The last entry in this page table */
>> +                       *page_table_addr =
>> +
>> TMC_ETR_SG_NXT_TBL(virt_to_phys(page_addr));
>
>
> Shouldn't this also be a dma_addr_t of the page ? The TMC ETR would use the
> address in the table to "read" the page table in this case, while the other
> pte entries are used to "write" data to the addresses (for which you
> correctly
> set up the dma address). I don't see why the "read" address should be any
> different.
> The TMC TRM uses PTn_BaseAddr for the page table base, which can be
> confusing.
> But if you see the DBALO which points to the PT0_BaseAddr, it should be
> clear.

You are correct - looking at this again I'm probably just lucky that
it worked.  The page table entries need to be read by the HW and there
is no guarantee the setup we've just did in virtual memory has been
pushed to the physical memory.  This will need a
dma_sync_single_for_device().

>
>> +                       /* Move on to the next page table */
>> +                       page_table_addr = page_addr;
>> +
>> +                       i = 0;
>> +               } else {
>> +                       /* A normal page in the SG list */
>> +                       dma_page_addr = tmc_setup_dma_page(dev, page);
>> +                       if (dma_page_addr == -EINVAL) {
>> +                               ret = -EINVAL;
>> +                               goto err;
>> +                       }
>> +
>> +                       *page_table_addr = TMC_ETR_SG_ENT(dma_page_addr);
>> +
>> +                       etr_buffer->page_addr[pte].vaddr = (u64)page_addr;
>> +                       etr_buffer->page_addr[pte].daddr = dma_page_addr;
>> +
>> +                       page_table_addr++;
>
>
> As mentioned above, with a page size other than 4K, we are wasting space
> here.
>

Definitely - see my comment at the end on that.

>> +                       pte++;
>> +                       i++;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +
>> +err:
>> +       tmc_free_sg_buffer(etr_buffer, pte);
>> +       etr_buffer->pt_vaddr = NULL;
>> +       return ret;
>> +}
>> +
>> +static void *tmc_alloc_etr_buffer(struct coresight_device *csdev, int
>> cpu,
>> +                                 void **pages, int nr_pages, bool
>> overwrite)
>> +{
>> +       int etr_pages, node;
>> +       struct device *dev = csdev->dev.parent;
>> +       struct cs_etr_buffers *buf;
>> +
>> +       if (cpu == -1)
>> +               cpu = smp_processor_id();
>> +       node = cpu_to_node(cpu);
>> +
>> +       /* Register DBALO and DBAHI form a 40-bit address range */
>> +       if (dma_set_mask(dev, DMA_BIT_MASK(40)))
>> +               return NULL;
>> +
>> +       /*
>> +        * The HW can't start collecting data in the middle of the SG
>> list,
>> +        * it must start at the beginning.  As such we can't use the ring
>> +        * buffer provided by perf as entries into the page tables since
>> +        * it is not guaranteed that user space will have the chance to
>> +        * consume the data before the next trace run begins.
>> +        *
>> +        * To work around this reserve a set of pages that will be used as
>> +        * and intermediate (SG) buffer.  This isn't optimal but the best
>> we
>> +        * can do with the current HW revision.
>
>
> Just for my understanding, is this because we don't get a notification from
> the hardware when the buffers are (getting) full ?

The ideal solution would be to use the pages given to us by perf.
That way we wouldn't have to copy the content of the buffer for each
run to the perf ring buffer.  But we can't use the perf ring buffer
because we aren't guaranteed user space will have time to consume the
latest information.  As such if a process is scheduled more than once
before user space can consume the data we'd have to tell the HW to
start on the next available address, something that isn't supported.

>
>> +        */
>> +       etr_pages = tmc_get_etr_pages(nr_pages);
>
>
> nit: As mentioned above the function name and the variable name etr_pages
> could be
> confusing. How about renaming the variable to nr_etr_pages ?

I'm good with that.

>
>> +static int tmc_set_etr_buffer(struct coresight_device *csdev,
>> +                             struct perf_output_handle *handle,
>> +                             void *sink_config)
>> +{
>> +       unsigned long head;
>> +       struct cs_etr_buffers *buf = sink_config;
>> +       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       /* wrap head around to the amount of space we have */
>> +       head = handle->head & ((buf->tmc.nr_pages << PAGE_SHIFT) - 1);
>> +
>> +       /* find the page to write to */
>> +       buf->tmc.cur = head / PAGE_SIZE;
>> +
>> +       /* and offset within that page */
>> +       buf->tmc.offset = head % PAGE_SIZE;
>> +
>> +       local_set(&buf->tmc.data_size, 0);
>> +
>> +       /* Keep track of how big the internal SG list is */
>> +       drvdata->size = buf->etr_nr_pages << PAGE_SHIFT;
>> +
>> +       /* Tell the HW where to put the trace data */
>> +       drvdata->paddr = virt_to_phys(buf->pt_vaddr);
>
>
> Shouldn't this be a dma_addr as we used to program in the normal mode ?

Yes.  As I mentioned above I'm pretty sure it is sheer luck that it works.

>
>> +
>> +       return 0;
>> +}
>> +
>> +static unsigned long tmc_reset_etr_buffer(struct coresight_device *csdev,
>> +                                         struct perf_output_handle
>> *handle,
>> +                                         void *sink_config, bool *lost)
>> +{
>> +       long size = 0;
>> +       struct cs_etr_buffers *buf = sink_config;
>> +       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       if (buf) {
>> +               /*
>> +                * In snapshot mode ->data_size holds the new address of
>> the
>> +                * ring buffer's head.  The size itself is the whole
>> address
>> +                * range since we want the latest information.
>> +                */
>> +               if (buf->tmc.snapshot) {
>> +                       size = buf->tmc.nr_pages << PAGE_SHIFT;
>> +                       handle->head = local_xchg(&buf->tmc.data_size,
>> size);
>> +               }
>> +
>> +               /*
>> +                * Tell the tracer PMU how much we got in this run and if
>> +                * something went wrong along the way.  Nobody else can
>> use
>> +                * this cs_etr_buffers instance until we are done.  As
>> such
>> +                * resetting parameters here and squaring off with the
>> ring
>> +                * buffer API in the tracer PMU is fine.
>> +                */
>> +               *lost = !!local_xchg(&buf->tmc.lost, 0);
>> +               size = local_xchg(&buf->tmc.data_size, 0);
>
>
> I don't fully understand the cs_buffer API, but we set the data_size to 0,
> unconditionally here.
> Whats the point of setting the data_size above for snapshot mode ?

In snapshot mode data_size is overloaded and holds current head.  As
such once that information has been recorded we need to set data_size
to the current size of the buffer (since we've been around many
times).  Later on that size is recorded before data_size gets reset in
preparation for another run.

>
>> +       }
>> +
>> +       /* Get ready for another run */
>> +       drvdata->vaddr = NULL;
>> +       drvdata->paddr = 0;
>> +
>> +       return size;
>> +}
>> +
>> +static void tmc_update_etr_buffer(struct coresight_device *csdev,
>> +                                 struct perf_output_handle *handle,
>> +                                 void *sink_config)
>> +{
>> +       bool full;
>> +       int i, rb_index, sg_index = 0;
>> +       u32 rwplo, rwphi, rb_offset, sg_offset = 0;
>> +       u32 stop_index, stop_offset, to_copy, sg_size;
>> +       u32 *rb_ptr, *sg_ptr;
>> +       u64 rwp, to_read;
>> +       struct cs_etr_buffers *etr_buf = sink_config;
>> +       struct cs_buffers *cs_buf = &etr_buf->tmc;
>> +       struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
>> +
>> +       if (!etr_buf)
>> +               return;
>> +
>> +       /* This shouldn't happen */
>> +       if (WARN_ON_ONCE(local_read(&drvdata->mode) != CS_MODE_PERF))
>> +               return;
>> +
>> +       CS_UNLOCK(drvdata->base);
>> +
>> +       tmc_flush_and_stop(drvdata);
>> +
>> +       rwplo = readl_relaxed(drvdata->base + TMC_RWP);
>> +       rwphi = readl_relaxed(drvdata->base + TMC_RWPHI);
>> +       full = (readl_relaxed(drvdata->base + TMC_STS) & TMC_STS_FULL);
>
>
> nitpick: you don't need the brackets above.

Ok.

>
>> +
>> +       /* Combine the high and low part of the rwp to make a full address
>> */
>> +       rwp = (u64)rwphi << 32;
>> +       rwp |= rwplo;
>> +
>> +       /* Convert the stop address in RAM to a page and an offset */
>> +       if (tmc_get_sg_page_index(etr_buf, rwp, &stop_index,
>> &stop_offset))
>> +               goto out;
>> +
>> +       if (full) {
>> +               /*
>> +                * The buffer head has wrapped around.  As such the size
>> +                * is the entire buffer length and the index and offset in
>> +                * the scatter-gather list are moved forward.
>> +                */
>> +               local_inc(&cs_buf->lost);
>> +               to_read = drvdata->size;
>> +               sg_index = stop_index;
>> +               sg_offset = stop_offset;
>> +       } else {
>> +               to_read = (stop_index * PAGE_SIZE) + stop_offset;
>> +       }
>> +
>> +       /*
>> +        * The TMC RAM buffer may be bigger than the space available in
>> the
>> +        * perf ring buffer (handle->size).  If so advance the RRP so that
>> we
>> +        * get the latest trace data.
>> +        */
>
>
> A stupid question: Is this something we can tune in the tmc to match the
> handle->size so that we
> don't have to worry about it ?
>

This is because we are dealing with two buffers: an internal one (etr
pages) and the one shared with user space (the perf ring buffer).  On
a busy system there is no guarantee user space can keep up with kernel
space and the size available in the perf ring buffer _may_ end up
being smaller than what has been harvested in the internal buffer.

>> +       if (to_read > handle->size) {
>> +               u64 rrp;
>> +
>> +               /*
>> +                * Compute where we should start reading from
>> +                * relative to rwp.
>> +                */
>> +               rrp = rwp + drvdata->size;
>> +               /* Go back just enough */
>> +               rrp -= handle->size;
>
>
>
> This looks wrong to me. We cannot simply move the rrp pointer back and
> forth, as the buffer
> is not guaranteed to be contiguous.

Yeah, now that I look at it again it is broken.

>
>> +               /* Make sure we are still within our limits */
>> +               rrp %= drvdata->size;
>
>
> And the above step definitely makes it not an address. We may have to find
> the address by looking
> at the page table.
>
>> +
>> +               /* Get a new index and offset based on rrp */
>> +               if (tmc_get_sg_page_index(etr_buf, rrp,
>> +                                         &stop_index, &stop_offset))
>> +                       goto out;
>> +
>> +               /* Tell user space we lost data */
>> +               local_inc(&cs_buf->lost);
>> +               to_read = handle->size;
>> +               /* Adjust start index and offset */
>> +               sg_index = stop_index;
>> +               sg_offset = stop_offset;
>> +       }
>> +
>> +       /* Get a handle on where the Perf ring buffer is */
>> +       rb_index = cs_buf->cur;
>> +       rb_offset = cs_buf->offset;
>> +
>> +       /* Refresh the SG list */
>> +       tmc_sg_page_sync(etr_buf, sg_index, to_read);
>> +
>> +       for (i = to_read; i > 0; ) {
>> +               /* Get current location of the perf ring buffer */
>> +               rb_ptr = cs_buf->data_pages[rb_index] + rb_offset;
>> +               /* Get current location in the ETR SG list */
>> +               sg_ptr = (u32 *)(etr_buf->page_addr[sg_index].vaddr +
>> +                                sg_offset);
>> +
>> +               /*
>> +                * First figure out the maximum amount of data we can get
>> out
>> +                * of the ETR SG list.
>> +                */
>> +               if (i < PAGE_SIZE)
>> +                       sg_size = i;
>> +               else
>> +                       sg_size = PAGE_SIZE - sg_offset;
>
>
> If i < PAGE_SIZE and (PAGE_SIZE - sg_offset) < i, we could crash below
> trying to
> copy from beyond the page.
> I think it should be :
>
>                 sg_size = min(PAGE_SIZE - sg_offset, i);
>
>

So this driver won't work on systems where pages are not 4K.  As such
I suggest to make the Perf API available only if the system has been
configured with 4K pages.  That way we have an ETR driver that works
in SG mode and a foundation for future extension should someone has
the need for support on 16K and 64K pages.  Fixing this to work on 16K
and 64K page size would likely demand a fair amount of time, something
I'm currently don't have.

Opinion?

Thanks,
Mathieu

> Thanks
> Suzuki

^ permalink raw reply

* [PATCH v13 02/15] iommu/arm-smmu: Initialize the msi geometry
From: Alex Williamson @ 2016-10-06 20:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-3-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:18 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> On ARM, MSI write transactions also are translated by the smmu.
> Let's report that specificity by setting the iommu_msi_supported
> field to true. A valid aperture window will need to be provided.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> v12 -> v13:
> - reword the commit message
> 
> v8 -> v9:
> - reword the title and patch description
> 
> v7 -> v8:
> - use DOMAIN_ATTR_MSI_GEOMETRY
> 
> v4 -> v5:
> - don't handle fsl_pamu_domain anymore
> - handle arm-smmu-v3
> ---
>  drivers/iommu/arm-smmu-v3.c | 2 ++
>  drivers/iommu/arm-smmu.c    | 3 +++
>  2 files changed, 5 insertions(+)
> 
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 15c01c3..f82eec3 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -1382,6 +1382,7 @@ static bool arm_smmu_capable(enum iommu_cap cap)
>  static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
>  {
>  	struct arm_smmu_domain *smmu_domain;
> +	struct iommu_domain_msi_geometry msi_geometry = {0, 0, true};

nit, this initialization makes it difficult to search for who sets
iommu_msi_supported, could we perhaps be more explicit in the
initialization, ie.
	{
		.aperture_start = 0,
		.aperture_end = 0,
		.iommu_msi_supported = true
	};

No change to the compiled version, but easier to find in the source.

>  
>  	if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
>  		return NULL;
> @@ -1400,6 +1401,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
>  		kfree(smmu_domain);
>  		return NULL;
>  	}
> +	smmu_domain->domain.msi_geometry = msi_geometry;
>  
>  	mutex_init(&smmu_domain->init_mutex);
>  	spin_lock_init(&smmu_domain->pgtbl_lock);
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index ac4aab9..97ff1b4 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -1002,6 +1002,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>  static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
>  {
>  	struct arm_smmu_domain *smmu_domain;
> +	struct iommu_domain_msi_geometry msi_geometry = {0, 0, true};
>  
>  	if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
>  		return NULL;
> @@ -1020,6 +1021,8 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
>  		return NULL;
>  	}
>  
> +	smmu_domain->domain.msi_geometry = msi_geometry;
> +
>  	mutex_init(&smmu_domain->init_mutex);
>  	spin_lock_init(&smmu_domain->pgtbl_lock);
>  

^ permalink raw reply

* [PATCH v13 03/15] iommu/dma: Allow MSI-only cookies
From: Alex Williamson @ 2016-10-06 20:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-4-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:19 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> From: Robin Murphy <robin.murphy@arm.com>
> 
> IOMMU domain users such as VFIO face a similar problem to DMA API ops
> with regard to mapping MSI messages in systems where the MSI write is
> subject to IOMMU translation. With the relevant infrastructure now in
> place for managed DMA domains, it's actually really simple for other
> users to piggyback off that and reap the benefits without giving up
> their own IOVA management, and without having to reinvent their own
> wheel in the MSI layer.
> 
> Allow such users to opt into automatic MSI remapping by dedicating a
> region of their IOVA space to a managed cookie.
> 
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> 
> v1 -> v2:
> - compared to Robin's version
> - add NULL last param to iommu_dma_init_domain
> - set the msi_geometry aperture
> - I removed
>   if (base < U64_MAX - size)
>      reserve_iova(iovad, iova_pfn(iovad, base + size), ULONG_MAX);
>   don't get why we would reserve something out of the scope of the iova domain?
>   what do I miss?
> ---
>  drivers/iommu/dma-iommu.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  include/linux/dma-iommu.h |  9 +++++++++
>  2 files changed, 49 insertions(+)
> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index c5ab866..11da1a0 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -716,3 +716,43 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  		msg->address_lo += lower_32_bits(msi_page->iova);
>  	}
>  }
> +
> +/**
> + * iommu_get_dma_msi_region_cookie - Configure a domain for MSI remapping only

Should this perhaps be iommu_setup_dma_msi_region_cookie, or something
along those lines.  I'm not sure what we're get'ing.  Thanks,

Alex

> + * @domain: IOMMU domain to prepare
> + * @base: Base address of IOVA region to use as the MSI remapping aperture
> + * @size: Size of the desired MSI aperture
> + *
> + * Users who manage their own IOVA allocation and do not want DMA API support,
> + * but would still like to take advantage of automatic MSI remapping, can use
> + * this to initialise their own domain appropriately.
> + */
> +int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
> +		dma_addr_t base, u64 size)
> +{
> +	struct iommu_dma_cookie *cookie;
> +	struct iova_domain *iovad;
> +	int ret;
> +
> +	if (domain->type == IOMMU_DOMAIN_DMA)
> +		return -EINVAL;
> +
> +	ret = iommu_get_dma_cookie(domain);
> +	if (ret)
> +		return ret;
> +
> +	ret = iommu_dma_init_domain(domain, base, size, NULL);
> +	if (ret) {
> +		iommu_put_dma_cookie(domain);
> +		return ret;
> +	}
> +
> +	domain->msi_geometry.aperture_start = base;
> +	domain->msi_geometry.aperture_end = base + size - 1;
> +
> +	cookie = domain->iova_cookie;
> +	iovad = &cookie->iovad;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(iommu_get_dma_msi_region_cookie);
> diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
> index 32c5890..1c55413 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -67,6 +67,9 @@ int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
>  /* The DMA API isn't _quite_ the whole story, though... */
>  void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
>  
> +int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
> +		dma_addr_t base, u64 size);
> +
>  #else
>  
>  struct iommu_domain;
> @@ -90,6 +93,12 @@ static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
>  {
>  }
>  
> +static inline int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
> +		dma_addr_t base, u64 size)
> +{
> +	return -ENODEV;
> +}
> +
>  #endif	/* CONFIG_IOMMU_DMA */
>  #endif	/* __KERNEL__ */
>  #endif	/* __DMA_IOMMU_H */

^ permalink raw reply

* [PATCH v13 04/15] genirq/msi: Introduce the MSI doorbell API
From: Alex Williamson @ 2016-10-06 20:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-5-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:20 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> We introduce a new msi-doorbell API that allows msi controllers
> to allocate and register their doorbells. This is useful when
> those doorbells are likely to be iommu mapped (typically on ARM).
> The VFIO layer will need to gather information about those doorbells:
> whether they are safe (ie. they implement irq remapping) and how
> many IOMMU pages are requested to map all of them.
> 
> This patch first introduces the dedicated msi_doorbell_info struct
> and the registration/unregistration functions.
> 
> A doorbell region is characterized by its physical address base, size,
> and whether it its safe (ie. it implements IRQ remapping). A doorbell
> can be per-cpu of global. We currently only care about global doorbells.
                 ^^ s/of/or/

> 
> A function returns whether all doorbells are safe.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> v12 -> v13:
> - directly select MSI_DOORBELL in ARM_SMMU and ARM_SMMU_V3 configs
> - remove prot attribute
> - move msi_doorbell_info struct definition in msi-doorbell.c
> - change the commit title
> - change proto of the registration function
> - msi_doorbell_safe now in this patch
> 
> v11 -> v12:
> - rename irqchip_doorbell into msi_doorbell, irqchip_doorbell_list
>   into msi_doorbell_list and irqchip_doorbell_mutex into
>   msi_doorbell_mutex
> - fix style issues: align msi_doorbell struct members, kernel-doc comments
> - use kzalloc
> - use container_of in msi_doorbell_unregister_global
> - compute nb_unsafe_doorbells on registration/unregistration
> - registration simply returns NULL if allocation failed
> 
> v10 -> v11:
> - remove void *chip_data argument from register/unregister function
> - remove lookup funtions since we restored the struct irq_chip
>   msi_doorbell_info ops to realize this function
> - reword commit message and title
> 
> Conflicts:
> 	kernel/irq/Makefile
> 
> Conflicts:
> 	drivers/iommu/Kconfig
> ---
>  drivers/iommu/Kconfig        |  2 +
>  include/linux/msi-doorbell.h | 77 ++++++++++++++++++++++++++++++++++
>  kernel/irq/Kconfig           |  4 ++
>  kernel/irq/Makefile          |  1 +
>  kernel/irq/msi-doorbell.c    | 98 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 182 insertions(+)
>  create mode 100644 include/linux/msi-doorbell.h
>  create mode 100644 kernel/irq/msi-doorbell.c
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index 8ee54d7..0cc7fac 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -297,6 +297,7 @@ config SPAPR_TCE_IOMMU
>  config ARM_SMMU
>  	bool "ARM Ltd. System MMU (SMMU) Support"
>  	depends on (ARM64 || ARM) && MMU
> +	select MSI_DOORBELL
>  	select IOMMU_API
>  	select IOMMU_IO_PGTABLE_LPAE
>  	select ARM_DMA_USE_IOMMU if ARM
> @@ -310,6 +311,7 @@ config ARM_SMMU
>  config ARM_SMMU_V3
>  	bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
>  	depends on ARM64
> +	select MSI_DOORBELL
>  	select IOMMU_API
>  	select IOMMU_IO_PGTABLE_LPAE
>  	select GENERIC_MSI_IRQ_DOMAIN
> diff --git a/include/linux/msi-doorbell.h b/include/linux/msi-doorbell.h
> new file mode 100644
> index 0000000..c18a382
> --- /dev/null
> +++ b/include/linux/msi-doorbell.h
> @@ -0,0 +1,77 @@
> +/*
> + * API to register/query MSI doorbells likely to be IOMMU mapped
> + *
> + * Copyright (C) 2016 Red Hat, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef _LINUX_MSI_DOORBELL_H
> +#define _LINUX_MSI_DOORBELL_H
> +
> +struct msi_doorbell_info;
> +
> +#ifdef CONFIG_MSI_DOORBELL
> +
> +/**
> + * msi_doorbell_register - allocate and register a global doorbell
> + * @base: physical base address of the global doorbell
> + * @size: size of the global doorbell
> + * @prot: protection/memory attributes
> + * @safe: true is irq_remapping implemented for this doorbell
> + * @dbinfo: returned doorbell info
> + *
> + * Return: 0 on success, -ENOMEM on allocation failure
> + */
> +int msi_doorbell_register_global(phys_addr_t base, size_t size,
> +				 bool safe,
> +				 struct msi_doorbell_info **dbinfo);
> +

Seems like alloc/free behavior vs register/unregister.  Also seems
cleaner to just return a struct msi_doorbell_info* and use PTR_ERR for
return codes.  These are of course superficial changes that could be
addressed in the future.

> +/**
> + * msi_doorbell_unregister_global - unregister a global doorbell
> + * @db: doorbell info to unregister
> + *
> + * remove the doorbell descriptor from the list of registered doorbells
> + * and deallocates it
> + */
> +void msi_doorbell_unregister_global(struct msi_doorbell_info *db);
> +
> +/**
> + * msi_doorbell_safe - return whether all registered doorbells are safe
> + *
> + * Safe doorbells are those which implement irq remapping
> + * Return: true if all doorbells are safe, false otherwise
> + */
> +bool msi_doorbell_safe(void);
> +
> +#else
> +
> +static inline int
> +msi_doorbell_register_global(phys_addr_t base, size_t size,
> +			     int prot, bool safe,
> +			     struct msi_doorbell_info **dbinfo)
> +{
> +	*dbinfo = NULL;
> +	return 0;

If we return a struct*

return NULL;

> +}
> +
> +static inline void
> +msi_doorbell_unregister_global(struct msi_doorbell_info *db) {}
> +
> +static inline bool msi_doorbell_safe(void)
> +{
> +	return true;
> +}

Is it?

> +#endif /* CONFIG_MSI_DOORBELL */
> +
> +#endif
> diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
> index 3bbfd6a..d4faaaa 100644
> --- a/kernel/irq/Kconfig
> +++ b/kernel/irq/Kconfig
> @@ -72,6 +72,10 @@ config GENERIC_IRQ_IPI
>  config GENERIC_MSI_IRQ
>  	bool
>  
> +# MSI doorbell support (for doorbell IOMMU mapping)
> +config MSI_DOORBELL
> +	bool
> +
>  # Generic MSI hierarchical interrupt domain support
>  config GENERIC_MSI_IRQ_DOMAIN
>  	bool
> diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
> index 1d3ee31..5b04dd1 100644
> --- a/kernel/irq/Makefile
> +++ b/kernel/irq/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_PM_SLEEP) += pm.o
>  obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o
>  obj-$(CONFIG_GENERIC_IRQ_IPI) += ipi.o
>  obj-$(CONFIG_SMP) += affinity.o
> +obj-$(CONFIG_MSI_DOORBELL) += msi-doorbell.o
> diff --git a/kernel/irq/msi-doorbell.c b/kernel/irq/msi-doorbell.c
> new file mode 100644
> index 0000000..60a262a
> --- /dev/null
> +++ b/kernel/irq/msi-doorbell.c
> @@ -0,0 +1,98 @@
> +/*
> + * API to register/query MSI doorbells likely to be IOMMU mapped
> + *
> + * Copyright (C) 2016 Red Hat, Inc.
> + * Author: Eric Auger <eric.auger@redhat.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/slab.h>
> +#include <linux/irq.h>
> +#include <linux/msi-doorbell.h>
> +
> +/**
> + * struct msi_doorbell_info - MSI doorbell region descriptor
> + * @percpu_doorbells: per cpu doorbell base address
> + * @global_doorbell: base address of the doorbell
> + * @doorbell_is_percpu: is the doorbell per cpu or global?
> + * @safe: true if irq remapping is implemented
> + * @size: size of the doorbell
> + */
> +struct msi_doorbell_info {
> +	union {
> +		phys_addr_t __percpu    *percpu_doorbells;
> +		phys_addr_t             global_doorbell;
> +	};
> +	bool    doorbell_is_percpu;
> +	bool    safe;
> +	size_t  size;
> +};
> +
> +struct msi_doorbell {
> +	struct msi_doorbell_info	info;
> +	struct list_head		next;
> +};
> +
> +/* list of registered MSI doorbells */
> +static LIST_HEAD(msi_doorbell_list);
> +
> +/* counts the number of unsafe registered doorbells */
> +static uint nb_unsafe_doorbells;
> +
> +/* protects the list and nb__unsafe_doorbells */

Extra underscore

> +static DEFINE_MUTEX(msi_doorbell_mutex);
> +
> +int msi_doorbell_register_global(phys_addr_t base, size_t size, bool safe,
> +				 struct msi_doorbell_info **dbinfo)
> +{
> +	struct msi_doorbell *db;
> +
> +	db = kzalloc(sizeof(*db), GFP_KERNEL);
> +	if (!db)
> +		return -ENOMEM;
> +
> +	db->info.global_doorbell = base;
> +	db->info.size = size;
> +	db->info.safe = safe;
> +
> +	mutex_lock(&msi_doorbell_mutex);
> +	list_add(&db->next, &msi_doorbell_list);
> +	if (!db->info.safe)
> +		nb_unsafe_doorbells++;
> +	mutex_unlock(&msi_doorbell_mutex);
> +	*dbinfo = &db->info;
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(msi_doorbell_register_global);
> +
> +void msi_doorbell_unregister_global(struct msi_doorbell_info *dbinfo)
> +{
> +	struct msi_doorbell *db;
> +
> +	db = container_of(dbinfo, struct msi_doorbell, info);
> +
> +	mutex_lock(&msi_doorbell_mutex);
> +	list_del(&db->next);
> +	if (!db->info.safe)
> +		nb_unsafe_doorbells--;
> +	mutex_unlock(&msi_doorbell_mutex);
> +	kfree(db);
> +}
> +EXPORT_SYMBOL_GPL(msi_doorbell_unregister_global);
> +
> +bool msi_doorbell_safe(void)
> +{
> +	return !nb_unsafe_doorbells;
> +}
> +EXPORT_SYMBOL_GPL(msi_doorbell_safe);

^ permalink raw reply

* [PATCH v13 08/15] vfio: Introduce a vfio_dma type field
From: Alex Williamson @ 2016-10-06 20:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-9-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:24 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> We introduce a vfio_dma type since we will need to discriminate
> different types of dma slots:
> - VFIO_IOVA_USER: IOVA region used to map user vaddr
> - VFIO_IOVA_RESERVED_MSI: IOVA region reserved to map MSI doorbells
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Alex Williamson <alex.williamson@redhat.com>

> 
> ---
> v9 -> v10:
> - renamed VFIO_IOVA_RESERVED into VFIO_IOVA_RESERVED_MSI
> - explicitly set type to VFIO_IOVA_USER on dma_map
> 
> v6 -> v7:
> - add VFIO_IOVA_ANY
> - do not introduce yet any VFIO_IOVA_RESERVED handling
> ---
>  drivers/vfio/vfio_iommu_type1.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 2ba1942..a9f8b93 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -53,6 +53,12 @@ module_param_named(disable_hugepages,
>  MODULE_PARM_DESC(disable_hugepages,
>  		 "Disable VFIO IOMMU support for IOMMU hugepages.");
>  
> +enum vfio_iova_type {
> +	VFIO_IOVA_USER = 0,	/* standard IOVA used to map user vaddr */
> +	VFIO_IOVA_RESERVED_MSI,	/* reserved to map MSI doorbells */
> +	VFIO_IOVA_ANY,		/* matches any IOVA type */
> +};
> +
>  struct vfio_iommu {
>  	struct list_head	domain_list;
>  	struct mutex		lock;
> @@ -75,6 +81,7 @@ struct vfio_dma {
>  	unsigned long		vaddr;		/* Process virtual addr */
>  	size_t			size;		/* Map size (bytes) */
>  	int			prot;		/* IOMMU_READ/WRITE */
> +	enum vfio_iova_type	type;		/* type of IOVA */
>  };
>  
>  struct vfio_group {
> @@ -607,6 +614,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>  	dma->iova = iova;
>  	dma->vaddr = vaddr;
>  	dma->prot = prot;
> +	dma->type = VFIO_IOVA_USER;
>  
>  	/* Insert zero-sized and grow as we map chunks of it */
>  	vfio_link_dma(iommu, dma);

^ permalink raw reply

* [PATCH v13 09/15] vfio/type1: vfio_find_dma accepting a type argument
From: Alex Williamson @ 2016-10-06 20:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-10-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:25 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> In our RB-tree we get prepared to insert slots of different types
> (USER and RESERVED). It becomes useful to be able to search for dma
> slots of a specific type or any type.
> 
> This patch introduces vfio_find_dma_from_node which starts the
> search from a given node and stops on the first node that matches
> the @start and @size parameters. If this node also matches the
> @type parameter, the node is returned else NULL is returned.
> 
> At the moment we only have USER SLOTS so the type will always match.
> 
> In a separate patch, this function will be enhanced to pursue the
> search recursively in case a node with a different type is
> encountered.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  drivers/vfio/vfio_iommu_type1.c | 53 +++++++++++++++++++++++++++++++++--------
>  1 file changed, 43 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index a9f8b93..cb7267a 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -94,25 +94,56 @@ struct vfio_group {
>   * into DMA'ble space using the IOMMU
>   */
>  
> -static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
> -				      dma_addr_t start, size_t size)
> +/**
> + * vfio_find_dma_from_node: looks for a dma slot intersecting a window
> + * from a given rb tree node
> + * @top: top rb tree node where the search starts (including this node)
> + * @start: window start
> + * @size: window size
> + * @type: window type
> + */
> +static struct vfio_dma *vfio_find_dma_from_node(struct rb_node *top,
> +						dma_addr_t start, size_t size,
> +						enum vfio_iova_type type)
>  {
> -	struct rb_node *node = iommu->dma_list.rb_node;
> +	struct rb_node *node = top;
> +	struct vfio_dma *dma;
>  
>  	while (node) {
> -		struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
> -
> +		dma = rb_entry(node, struct vfio_dma, node);
>  		if (start + size <= dma->iova)
>  			node = node->rb_left;
>  		else if (start >= dma->iova + dma->size)
>  			node = node->rb_right;
>  		else
> -			return dma;
> +			break;
>  	}
> +	if (!node)
> +		return NULL;
> +
> +	/* a dma slot intersects our window, check the type also matches */
> +	if (type == VFIO_IOVA_ANY || dma->type == type)
> +		return dma;
>  
>  	return NULL;
>  }
>  
> +/**
> + * vfio_find_dma: find a dma slot intersecting a given window
> + * @iommu: vfio iommu handle
> + * @start: window base iova
> + * @size: window size
> + * @type: window type
> + */
> +static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
> +				      dma_addr_t start, size_t size,
> +				      enum vfio_iova_type type)
> +{
> +	struct rb_node *top_node = iommu->dma_list.rb_node;
> +
> +	return vfio_find_dma_from_node(top_node, start, size, type);

nit, we could do without the top_node variable.

> +}
> +
>  static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
>  {
>  	struct rb_node **link = &iommu->dma_list.rb_node, *parent = NULL;
> @@ -484,19 +515,21 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
>  	 * mappings within the range.
>  	 */
>  	if (iommu->v2) {
> -		dma = vfio_find_dma(iommu, unmap->iova, 0);
> +		dma = vfio_find_dma(iommu, unmap->iova, 0, VFIO_IOVA_USER);
>  		if (dma && dma->iova != unmap->iova) {
>  			ret = -EINVAL;
>  			goto unlock;
>  		}
> -		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0);
> +		dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0,
> +				    VFIO_IOVA_USER);
>  		if (dma && dma->iova + dma->size != unmap->iova + unmap->size) {
>  			ret = -EINVAL;
>  			goto unlock;
>  		}
>  	}
>  
> -	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
> +	while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size,
> +				    VFIO_IOVA_USER))) {
>  		if (!iommu->v2 && unmap->iova > dma->iova)
>  			break;
>  		unmapped += dma->size;
> @@ -600,7 +633,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>  
>  	mutex_lock(&iommu->lock);
>  
> -	if (vfio_find_dma(iommu, iova, size)) {
> +	if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>  		mutex_unlock(&iommu->lock);
>  		return -EEXIST;
>  	}

^ permalink raw reply

* [PATCH v13 10/15] vfio/type1: Implement recursive vfio_find_dma_from_node
From: Alex Williamson @ 2016-10-06 20:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-11-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:26 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> This patch handles the case where a node is encountered, matching
> @start and @size arguments but not matching the @type argument.
> In that case, we need to skip that node and pursue the search in the
> node's leaves. In case @start is inferior to the node's base, we
> resume the search on the left leaf. If the recursive search on the left
> leaves did not produce any match, we search the right leaves recursively.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>

Acked-by: Alex Williamson <alex.williamson@redhat.com>
 
> ---
> 
> v10: creation
> ---
>  drivers/vfio/vfio_iommu_type1.c | 12 +++++++++++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index cb7267a..65a4038 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -125,7 +125,17 @@ static struct vfio_dma *vfio_find_dma_from_node(struct rb_node *top,
>  	if (type == VFIO_IOVA_ANY || dma->type == type)
>  		return dma;
>  
> -	return NULL;
> +	/* restart 2 searches skipping the current node */
> +	if (start < dma->iova) {
> +		dma = vfio_find_dma_from_node(node->rb_left, start,
> +					      size, type);
> +		if (dma)
> +			return dma;
> +	}
> +	if (start + size > dma->iova + dma->size)
> +		dma = vfio_find_dma_from_node(node->rb_right, start,
> +					      size, type);
> +	return dma;
>  }
>  
>  /**

^ permalink raw reply

* [PATCH v13 11/15] vfio/type1: Handle unmap/unpin and replay for VFIO_IOVA_RESERVED slots
From: Alex Williamson @ 2016-10-06 20:19 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1475743531-4780-12-git-send-email-eric.auger@redhat.com>

On Thu,  6 Oct 2016 08:45:27 +0000
Eric Auger <eric.auger@redhat.com> wrote:

> Before allowing the end-user to create VFIO_IOVA_RESERVED dma slots,
> let's implement the expected behavior for removal and replay.
> 
> As opposed to user dma slots, reserved IOVAs are not systematically bound
> to PAs and PAs are not pinned. VFIO just initializes the IOVA "aperture".
> IOVAs are allocated outside of the VFIO framework, by the MSI layer which
> is responsible to free and unmap them. The MSI mapping resources are freeed

nit, extra 'e', "freed"

> by the IOMMU driver on domain destruction.
> 
> On the creation of a new domain, the "replay" of a reserved slot simply
> needs to set the MSI aperture on the new domain.
> 
> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> 
> ---
> v12 -> v13:
> - use dma-iommu iommu_get_dma_msi_region_cookie
> 
> v9 -> v10:
> - replay of a reserved slot sets the MSI aperture on the new domain
> - use VFIO_IOVA_RESERVED_MSI enum value instead of VFIO_IOVA_RESERVED
> 
> v7 -> v8:
> - do no destroy anything anymore, just bypass unmap/unpin and iommu_map
>   on replay
> ---
>  drivers/vfio/Kconfig            |  1 +
>  drivers/vfio/vfio_iommu_type1.c | 10 +++++++++-
>  2 files changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> index da6e2ce..673ec79 100644
> --- a/drivers/vfio/Kconfig
> +++ b/drivers/vfio/Kconfig
> @@ -1,6 +1,7 @@
>  config VFIO_IOMMU_TYPE1
>  	tristate
>  	depends on VFIO
> +	select IOMMU_DMA
>  	default n
>  
>  config VFIO_IOMMU_SPAPR_TCE
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 65a4038..5bc5fc9 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -36,6 +36,7 @@
>  #include <linux/uaccess.h>
>  #include <linux/vfio.h>
>  #include <linux/workqueue.h>
> +#include <linux/dma-iommu.h>
>  
>  #define DRIVER_VERSION  "0.2"
>  #define DRIVER_AUTHOR   "Alex Williamson <alex.williamson@redhat.com>"
> @@ -387,7 +388,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma)
>  	struct vfio_domain *domain, *d;
>  	long unlocked = 0;
>  
> -	if (!dma->size)
> +	if (!dma->size || dma->type != VFIO_IOVA_USER)
>  		return;
>  	/*
>  	 * We use the IOMMU to track the physical addresses, otherwise we'd
> @@ -724,6 +725,13 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
>  		dma = rb_entry(n, struct vfio_dma, node);
>  		iova = dma->iova;
>  
> +		if (dma->type == VFIO_IOVA_RESERVED_MSI) {
> +			ret = iommu_get_dma_msi_region_cookie(domain->domain,
> +						     dma->iova, dma->size);
> +			WARN_ON(ret);
> +			continue;
> +		}

Why is this a passable error?  We consider an iommu_map() error on any
entry a failure.

> +
>  		while (iova < dma->iova + dma->size) {
>  			phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
>  			size_t size;

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox