linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
@ 2014-08-05 10:47 Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 01/29] pm: Add PM domain notifications Marek Szyprowski
                   ` (29 more replies)
  0 siblings, 30 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hello Everyone,

A lot of things has happened in the area of improving Exynos IOMMU
driver and discussion about generic IOMMU bindings, which finally
motivated me to get back to IOMMU related tasks. Just to remind, here
are those 2 important threads:

1. [PATCH v13 00/19] iommu/exynos: Fixes and Enhancements of System MMU
driver with DT: https://lkml.org/lkml/2014/5/12/34

2. [PATCH v4] devicetree: Add generic IOMMU device tree bindings:
https://lkml.org/lkml/2014/7/4/349

As a follow up of those discussions I've decided to finish our internal
code, which adapts Exynos SYSMMU driver to meet generic IOMMU bindings
requirements and implement all needed glue code to finally demonstare
seemless integration IOMMU controller with DMA-mapping subsystem for
the drivers available on Exynos SoCs.


1. Introduction - a few words for those who are not fully aware of the
Exynos SoC hardware

Exynos SoC consists of various devices integrated directly into SoCs.
Most of them are multimedia devices, which usually process large
buffers. Some of them (like i.e. MFC - a multimedia codec or FIMD - a
multi-window framebuffer device & lcd panel controller) are equipped
with more than one memory interface for higher processing performance.
There are also really complex subsystems (like ISP, the camera sensor
interface & processor), which consist of many sub-blocks, each having
its own memory interface/channel/bus (different names are used for the
same thing).

Each such memory controller might be equipped with SYSMMU device, which
acts as IOMMU controller for the parent device (called master device, a
device which that memory interface belongs to). Each SYSMMU controller
has its own register set and clock, belongs to the same power domain as
master device. There is also some non-direct relation from master's
device gate clock - SYSMMU registers can be accessed only when master's
gate clock is enabled.

Basically we have following dependencies between hardware and drivers:
- each multimedia device might have 1 or more SYSMMU controller
- each SYSMMU controller belongs only to 1 master device
- all SYSMMU controllers are independent of each other, there is no
  global hardware ID that must be assigned to enable given SYSMMU
  controller
- multimedia devices are modeled usually by a separate node in device
  tree with it's own compatible string and separate driver for them
- sub-blocks of complex devices right now are not modeled by a separate
  device tree nodes, but this might be changed in the future
- some multimedia devices have limited address space per each memory
  controller/channel (i.e. codec might access buffers only in a 256MiB
  window for each of it's memory channels)
- some drivers for independent device are used together to provide a
  more complex subsystem, i.e. FIMD, HDMI-mixer and others form together
  Exynos DRM subsystem; it is highly welcome to let them to operate in
  the same, shared DMA address space to simplify buffer sharing


2. Introduction part 2 - a few word of summary of the discussions about
generic IOMMU DT bindings

There have been a lot of discussions on the method of modeling IOMMU
controllers in device tree. The approach which has been selected as the
generic IOMMU binding candidate has been described in the '[PATCH v4]
devicetree: Add generic IOMMU device tree bindings' thread.

Those bindings describe how to link an IOMMU controller with its master
device. Basically an 'iommus' property placed in the master's device
node has been introduced. This property contains phandle to IOMMU
controller node. Optional properties of the particular binding can also
be specified after the phandle, assuming that IOMMU controller node
contains '#iommu-cells' property, which defines number of cells used for
those parameters. Those parameters are then interpreted by particular
IOMMU controller driver. Those parameters might be some hw channel id
required for correct hardware setup, base address and size pair for
limited IO address space window or others hardware dependant properties.


3. IOMMU integration to DMA-mapping subsystem

By default we assume that each master device, which has been equipped
with IOMMU controller gets its own DMA (IO) address space. This is
created automatically and transparently without any changes in the
device driver code. All DMA-mapping functions are replaced with the
IOMMU aware versions. This has to be done somewhere by the architecture
or SoC startup code, so when master's driver probe() function is called,
everything is in place.

However some device drivers might need (for various reasons) to manually
manage DMA (IO) address space. For this case a driver need to notify
kernel about that and do the management of DMA address space on its own.
This has been achieved by introducing DRIVER_HAS_OWN_IOMMU_MANAGER flag,
which can be set in struct device_driver. This way the startup code can
easily determine if creating the default per-device separate DMA
address space is required for a given driver or not without any unneeded
alloc/free call sequences.


4. Linux DMA-mapping subsystem and more than one DMA address space

DMA-mapping subsystem assumes that there is only one DMA (IO) address
space associated with the given struct device entity. Usually struct
device is mapped in one-to-one relation to a node describing given
device in device tree. To let driver to access other DMA (IO) address
spaces a sub-device has been introduced. This approach has been already
used by s5p-mfc driver (drivers/media/platform/s5p-mfc/s5p_mfc.c). The
only question is how and when sub-devices are created.

In the proposed approach, such additional address spaces are named with
the names of the respective IOMMU controllers (iommu-names property in
master's DT node). To let driver to access an address space, a
sub-device named 'parent_device_name:address_space_name' need to be
created and added as a child to master's struct device. A good example
is codec device, which on Exynos4412 SoC is instantiated as
'13400000.codec' device. It has 2 memory interfaces ('left' and
'right'), so the sub-devices called '13400000.codec:left' and
'13400000.codec:right' must be created by a driver and added as children
of '13400000.codec' device. Once then the driver is allowed to allocate
2 separate dma-mapping address spaces by calling
arm_iommu_create_mapping() and arm_iommu_detach_device() functions or
newly introduced helper arm_iommu_create_default_mapping(). For more
details, please refer to the last patch in this series.

Exactly the same approach is planned to be done for memory regions and
DMA-mapping implemented on top of CMA or DMA-coherent memory allocators.

When driver doesn't specify that it wants to manage its DMA (IO) address
spaces, a default DMA (IO) address space will be created and all SYSMMU
controllers will be bound to it, so this space will be shared across
master's device IO channels / memory interfaces. This way IOMMU support
might be added only to drivers which really benefit from having
separate IO address space per memory interface without a need to alter
the other drivers.

Why driver might need to manage the IO address space on its own? Once
again the codec device on Exynos4 series is a good example. Memory
interfaces found in the mentioned codec device are limited and can
address only 256MiB window. If we bind both interfaces to common address
space, driver is able only to access memory buffers, which fits into
256MiB window. If we use separate spaces for each memory interface,
codec device will be able to access buffers of total 2*256MiB=512MiB,
which is a significant advantage over the default case of shared address
space.


5. Power management (runtime)

Runtime power management is the most tricky part of the proposed
solution. I assumed that it is a sane requirement that from the
master's device driver the operation without IOMMU and with IOMMU (with
default, per-device mapping) should be exactly the same. The runtime
power management, which is now mainly limited to enabling and disabling
hardware power domains is done by the master's device driver. However
from the hardware perspective, there is also a need to save SYSMMU
context before switch pm domain off and restore it after switching pm
domain on.

To achieve this way of SYSMMU operation, a notifiers for power domains
have been introduces. With such an approach no changes are needed in
master's device driver and SYSMMU driver seamlessly integrates with
master's device runtime pm operations.


6. Proposed patches and changes

Patch 0001 "pm: Add PM domain notifications" adds support for power
domain notifiers (see chapter 5 above).

Patch 0002 "ARM: Exynos: bind power domains earlier, on device creation"
changes the time, when Exynos power domains are bound to the device. Now
this happens on DEVICE_ADD event instead of DRIVER_BIND, so when SYSMMU
driver is being initialized, the power domains are already bound and
notifiers can be added.

Patch 0003 "clk: exynos: add missing smmu_g2d clock and update comments"
simply simply adds missing sysmmu related entities to Exynos clock
driver.

Patch 0004 "drivers: base: add notifier for failed driver bind" add
event for failed driver bind, so things prepared in DRIVER_BIND event
can be cleaned up, similar to DRIVER_UNBOUND.

Patch 0005 "drivers: convert suppress_bind_attrs parameter into flags"
is preparation for adding new flags to struct device_driver.

Patch 0006 "drivers: iommu: add notify about failed bind" adds support
for recently introduced failed driver bind event to IOMMU subsystem.

Patch 0007 "ARM: dma-mapping: arm_iommu_attach_device: automatically set
max_seg_size" moves common operation of setting dma max_seg_size
directly to arm_iommu_attach_device function.

Patch 0008 "ARM: dma-mapping: add helpers for managing default
per-device dma mappings" adds convenient helpers for the most common
case of setting up per-device, separate DMA (IO) address space.

Patch 0009 "ARM: dma-mapping: provide stubs if no ARM_DMA_USE_IOMMU has
been selected" fixes usage of IOMMU related ARM DMA-mapping functions in
common code.

Patch 0010 "drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag" adds a flag
described in chapter 3.

Patch 0011 "DRM: exynos: add DRIVER_HAS_OWN_IOMMU_MANAGER flag to all
sub-drivers" marks all Exynos DRM sub-drivers with a flag notifying that
they perform own management of DMA (IO) address space. All the code to
setup dma-mapping and attach all devices is realy there.

Patch 0012 "DRM: Exynos: fix window clear code" is a simple bugfix of
broken init code, which triggers issues when used with IOMMU (page fault
happens on systems, where bootloader has left framebuffer enabled).

Patch 0013 "temporary: media: s5p-mfc: remove DT hacks & initialization
custom memory init code" removes all custom memory region handling, to
let later demonstrate how to use separate DMA (IO) address spaces from
master's device driver.

Patch 0014 "devicetree: Update Exynos SYSMMU device tree bindings" adds
a few words about proposed solution to SYSMMU device tree bindings
documentation.

Patch 0015 "ARM: DTS: Exynos4: add System MMU nodes" adds device tree
nodes for all SYSMMU controllers found in Exynos 4210 and 4x12 SoC and
respective properties to their master devices.

Patch 0016-0021 are simple bugfixes and code refactoring to simplify
the driver: 
	"iommu: exynos: make driver multiarch friendly",
	"iommu: exynos: don't read version register on every tlb",
	"iommu: exynos: remove unused functions",
	"iommu: exynos: remove useless spinlock",
	"iommu: exynos: refactor function parameters to simplify code",
	"iommu: exynos: remove unused functions, part 2".

Patch 0022 "iommu: exynos: add support for binding more than one sysmmu
to master device" adds support for storing a list of SYSMMU controllers
in the master's iommu arch data structure.

Patch 0023 "iommu: exynos: init iommu controllers from device tree"
finally implements bindings described in patch 0015 and access to
particular DMA address space managed by SYSMMU controller via sub-device
of predefined name (see chapter 4).

Patch 0024 "iommu: exynos: create default iommu-based dma-mapping for
master devices" does what patch title says.

Patch 0025 "iommu: exynos: add support for runtime_pm" implements power
management scheme described in chapter 5.

Patch 0026-0028 are cleanup and refactoring to make the code easier to
understand:
	"iommu: exynos: rename variables to reflect their purpose",
	"iommu: exynos: document internal structures",
	"iommu: exynos: remove excessive includes and sort others
	 alphabetically".

Patch 0029 "temporary: media: s5p-mfc: add support for IOMMU"
demonstrates how to use sub-devices to get access to separate DMA (IO)
address spaces. The driver is able to work both with and without this
patch. Without this patch a common shared address space is created for
both SYSMMU controllers (so only 256MiB of total address space is
available, see end of chapter 4).


7. Summary

All the development of those patches have been done on Exynos4412-based
OdroidU3 board and Exynos4210-based UniversalC210, on top of v3.16
kernel with some additional patches to enable HDMI support on Odroid
board. This version is available in the following GIT repository:
http://git.linaro.org/git/people/marek.szyprowski/linux-dma-mapping.git
on branch v3.16-odroid-iommu.

However, the version posted here has been rebased on top of linux-next
kernel (next-20140804 tag), to make marging the easier once v3.17-rc1 is
out.


8. Diffstat

 .../devicetree/bindings/iommu/samsung,sysmmu.txt   |  93 ++-
 Documentation/power/notifiers.txt                  |  14 +
 arch/arm/boot/dts/exynos4.dtsi                     | 118 ++++
 arch/arm/boot/dts/exynos4210.dtsi                  |  23 +
 arch/arm/boot/dts/exynos4x12.dtsi                  |  82 +++
 arch/arm/include/asm/dma-iommu.h                   |  36 ++
 arch/arm/mach-exynos/pm_domains.c                  |  12 +-
 arch/arm/mach-integrator/impd1.c                   |   2 +-
 arch/arm/mm/dma-mapping.c                          |  47 ++
 drivers/base/bus.c                                 |   4 +-
 drivers/base/dd.c                                  |  10 +-
 drivers/base/platform.c                            |   2 +-
 drivers/base/power/domain.c                        |  70 ++-
 drivers/clk/samsung/clk-exynos4.c                  |   1 +
 drivers/gpu/drm/exynos/exynos_drm_fimc.c           |   1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  26 +-
 drivers/gpu/drm/exynos/exynos_drm_g2d.c            |   1 +
 drivers/gpu/drm/exynos/exynos_drm_gsc.c            |   1 +
 drivers/gpu/drm/exynos/exynos_drm_rotator.c        |   1 +
 drivers/gpu/drm/exynos/exynos_mixer.c              |   1 +
 drivers/iommu/exynos-iommu.c                       | 663 +++++++++++++--------
 drivers/iommu/iommu.c                              |   3 +
 drivers/media/platform/s5p-mfc/s5p_mfc.c           | 107 ++--
 drivers/pci/host/pci-mvebu.c                       |   2 +-
 drivers/pci/host/pci-rcar-gen2.c                   |   2 +-
 drivers/pci/host/pci-tegra.c                       |   2 +-
 drivers/pci/host/pcie-rcar.c                       |   2 +-
 drivers/soc/tegra/pmc.c                            |   2 +-
 include/dt-bindings/clock/exynos4.h                |  10 +-
 include/linux/device.h                             |  12 +-
 include/linux/iommu.h                              |   1 +
 include/linux/pm.h                                 |   2 +
 include/linux/pm_domain.h                          |  19 +
 33 files changed, 1016 insertions(+), 356 deletions(-)


Best regards
Marek Szyprowski
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* [PATCH 01/29] pm: Add PM domain notifications
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 02/29] ARM: Exynos: bind power domains earlier, on device creation Marek Szyprowski
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

From: Sylwester Nawrocki <s.nawrocki@samsung.com>

This patch adds notifiers to the runtime PM/genpd subsystem. It is now
possible to register a notifier, which will be called before and after
the generic power domain subsystem calls the power domain's power_on
and power_off callbacks.

Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
 Documentation/power/notifiers.txt | 14 ++++++++
 drivers/base/power/domain.c       | 70 ++++++++++++++++++++++++++++++++++++---
 include/linux/pm.h                |  2 ++
 include/linux/pm_domain.h         | 19 +++++++++++
 4 files changed, 101 insertions(+), 4 deletions(-)

diff --git a/Documentation/power/notifiers.txt b/Documentation/power/notifiers.txt
index a81fa25..62303f6 100644
--- a/Documentation/power/notifiers.txt
+++ b/Documentation/power/notifiers.txt
@@ -53,3 +53,17 @@ NULL).  To register and/or unregister a suspend notifier use the functions
 register_pm_notifier() and unregister_pm_notifier(), respectively, defined in
 include/linux/suspend.h .  If you don't need to unregister the notifier, you can
 also use the pm_notifier() macro defined in include/linux/suspend.h .
+
+Power Domain notifiers
+----------------------
+
+The power domain notifiers allow subsystems or drivers to register for power
+domain on/off notifications, should they need to perform any actions right
+before or right after the power domain on/off.  The device must be already
+added to a power domain before its subsystem or driver registers the notifier.
+Following events are supported:
+
+PM_GENPD_POWER_ON_PREPARE	The power domain is about to turn on.
+PM_GENPD_POST_POWER_ON		The power domain has just turned on.
+PM_GENPD_POWER_OFF_PREPARE	The power domain is about to turn off.
+PM_GENPD_POST_POWER_OFF		The power domain has just turned off.
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index eee55c1..5fe0966 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -70,6 +70,45 @@ static struct generic_pm_domain *pm_genpd_lookup_name(const char *domain_name)
 	return genpd;
 }
 
+int pm_genpd_register_notifier(struct device *dev, struct notifier_block *nb)
+{
+	struct pm_domain_data *pdd;
+	int ret = -EINVAL;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.subsys_data) {
+		pdd = dev->power.subsys_data->domain_data;
+		ret = blocking_notifier_chain_register(&pdd->notify_chain_head,
+						       nb);
+	}
+	spin_unlock_irq(&dev->power.lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm_genpd_register_notifier);
+
+void pm_genpd_unregister_notifier(struct device *dev, struct notifier_block *nb)
+{
+	struct pm_domain_data *pdd;
+
+	spin_lock_irq(&dev->power.lock);
+	if (dev->power.subsys_data) {
+		pdd = dev->power.subsys_data->domain_data;
+		blocking_notifier_chain_unregister(&pdd->notify_chain_head, nb);
+	}
+	spin_unlock_irq(&dev->power.lock);
+}
+EXPORT_SYMBOL_GPL(pm_genpd_unregister_notifier);
+
+static void pm_genpd_notifier_call(unsigned long event,
+				   struct generic_pm_domain *genpd)
+{
+	struct pm_domain_data *pdd;
+
+	list_for_each_entry(pdd, &genpd->dev_list, list_node)
+		blocking_notifier_call_chain(&pdd->notify_chain_head,
+					     event, pdd->dev);
+}
+
 #ifdef CONFIG_PM
 
 struct generic_pm_domain *dev_to_genpd(struct device *dev)
@@ -231,10 +270,14 @@ static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
 		ktime_t time_start = ktime_get();
 		s64 elapsed_ns;
 
+		pm_genpd_notifier_call(PM_GENPD_POWER_ON_PREPARE, genpd);
+
 		ret = genpd->power_on(genpd);
 		if (ret)
 			goto err;
 
+		pm_genpd_notifier_call(PM_GENPD_POST_POWER_ON, genpd);
+
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
 		if (elapsed_ns > genpd->power_on_latency_ns) {
 			genpd->power_on_latency_ns = elapsed_ns;
@@ -554,13 +597,17 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 		 * the pm_genpd_poweron() restore power for us (this shouldn't
 		 * happen very often).
 		 */
+		pm_genpd_notifier_call(PM_GENPD_POWER_OFF_PREPARE, genpd);
+
 		ret = genpd->power_off(genpd);
 		if (ret == -EBUSY) {
 			genpd_set_active(genpd);
 			goto out;
 		}
-
 		elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+
+		pm_genpd_notifier_call(PM_GENPD_POST_POWER_OFF, genpd);
+
 		if (elapsed_ns > genpd->power_off_latency_ns) {
 			genpd->power_off_latency_ns = elapsed_ns;
 			genpd->max_off_time_changed = true;
@@ -837,9 +884,13 @@ static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
 	    || atomic_read(&genpd->sd_count) > 0)
 		return;
 
-	if (genpd->power_off)
+	if (genpd->power_off) {
+		pm_genpd_notifier_call(PM_GENPD_POWER_OFF_PREPARE, genpd);
 		genpd->power_off(genpd);
 
+		pm_genpd_notifier_call(PM_GENPD_POST_POWER_OFF, genpd);
+	}
+
 	genpd->status = GPD_STATE_POWER_OFF;
 
 	list_for_each_entry(link, &genpd->slave_links, slave_node) {
@@ -869,8 +920,11 @@ static void pm_genpd_sync_poweron(struct generic_pm_domain *genpd)
 		genpd_sd_counter_inc(link->master);
 	}
 
-	if (genpd->power_on)
+	if (genpd->power_on) {
+		pm_genpd_notifier_call(PM_GENPD_POWER_ON_PREPARE, genpd);
 		genpd->power_on(genpd);
+		pm_genpd_notifier_call(PM_GENPD_POST_POWER_ON, genpd);
+	}
 
 	genpd->status = GPD_STATE_ACTIVE;
 }
@@ -1292,9 +1346,16 @@ static int pm_genpd_restore_noirq(struct device *dev)
 			 * If the domain was off before the hibernation, make
 			 * sure it will be off going forward.
 			 */
-			if (genpd->power_off)
+			if (genpd->power_off) {
+				pm_genpd_notifier_call(PM_GENPD_POWER_OFF_PREPARE,
+						       genpd);
+
 				genpd->power_off(genpd);
 
+				pm_genpd_notifier_call(PM_GENPD_POST_POWER_OFF,
+						       genpd);
+			}
+
 			return 0;
 		}
 	}
@@ -1467,6 +1528,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
 	spin_unlock_irq(&dev->power.lock);
 
 	mutex_lock(&gpd_data->lock);
+	BLOCKING_INIT_NOTIFIER_HEAD(&gpd_data->base.notify_chain_head);
 	gpd_data->base.dev = dev;
 	list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
 	gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 72c0fe0..bfc55d4 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -22,6 +22,7 @@
 #define _LINUX_PM_H
 
 #include <linux/list.h>
+#include <linux/notifier.h>
 #include <linux/workqueue.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
@@ -542,6 +543,7 @@ struct wakeup_source;
 struct pm_domain_data {
 	struct list_head list_node;
 	struct device *dev;
+	struct blocking_notifier_head notify_chain_head;
 };
 
 struct pm_subsys_data {
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 7c1d252..569ab16 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -17,6 +17,12 @@
 #include <linux/notifier.h>
 #include <linux/cpuidle.h>
 
+/* PM domain state transition notifications */
+#define PM_GENPD_POWER_ON_PREPARE	0x01
+#define PM_GENPD_POST_POWER_ON		0x02
+#define PM_GENPD_POWER_OFF_PREPARE	0x03
+#define PM_GENPD_POST_POWER_OFF		0x04
+
 enum gpd_status {
 	GPD_STATE_ACTIVE = 0,	/* PM domain is active */
 	GPD_STATE_WAIT_MASTER,	/* PM domain's master is being waited for */
@@ -167,6 +173,11 @@ extern int pm_genpd_name_poweron(const char *domain_name);
 
 extern bool default_stop_ok(struct device *dev);
 
+extern int pm_genpd_register_notifier(struct device *dev,
+				      struct notifier_block *nb);
+extern void pm_genpd_unregister_notifier(struct device *dev,
+					struct notifier_block *nb);
+
 extern struct dev_power_governor pm_domain_always_on_gov;
 #else
 
@@ -259,6 +270,14 @@ static inline bool default_stop_ok(struct device *dev)
 {
 	return false;
 }
+static inline int pm_genpd_register_notifier(struct device *dev,
+					struct notifier_block *nb)
+{
+	return -ENOSYS;
+}
+static inline void pm_genpd_unregister_notifier(struct device *dev,
+					 struct notifier_block *nb) {}
+
 #define simple_qos_governor NULL
 #define pm_domain_always_on_gov NULL
 #endif
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 02/29] ARM: Exynos: bind power domains earlier, on device creation
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 01/29] pm: Add PM domain notifications Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments Marek Szyprowski
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patches change initialization time of power domain driver from client
device driver bind to device creation. This lets other core drivers to
register power domain notifiers before client driver is bound.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-exynos/pm_domains.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index fd76e1b..1d368a2 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -159,13 +159,13 @@ static int exynos_pm_notifier_call(struct notifier_block *nb,
 	struct device *dev = data;
 
 	switch (event) {
-	case BUS_NOTIFY_BIND_DRIVER:
+	case BUS_NOTIFY_ADD_DEVICE:
 		if (dev->of_node)
 			exynos_read_domain_from_dt(dev);
 
 		break;
 
-	case BUS_NOTIFY_UNBOUND_DRIVER:
+	case BUS_NOTIFY_DEL_DEVICE:
 		exynos_remove_device_from_domain(dev);
 
 		break;
@@ -177,6 +177,13 @@ static struct notifier_block platform_nb = {
 	.notifier_call = exynos_pm_notifier_call,
 };
 
+static int exynos_pm_domain_add(struct device *dev, void *priv)
+{
+	if (dev->of_node)
+		exynos_read_domain_from_dt(dev);
+	return 0;
+}
+
 static __init int exynos4_pm_init_power_domain(void)
 {
 	struct platform_device *pdev;
@@ -236,6 +243,7 @@ no_clk:
 	}
 
 	bus_register_notifier(&platform_bus_type, &platform_nb);
+	bus_for_each_dev(&platform_bus_type, NULL, NULL, exynos_pm_domain_add);
 
 	return 0;
 }
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 01/29] pm: Add PM domain notifications Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 02/29] ARM: Exynos: bind power domains earlier, on device creation Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-18 11:26   ` Tomasz Figa
  2014-08-05 10:47 ` [PATCH 04/29] drivers: base: add notifier for failed driver bind Marek Szyprowski
                   ` (26 subsequent siblings)
  29 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds missing smmu_g2d clock implementation and updates
comment about Exynos4 clocks from 278-282 range. Those clocks are
available on all Exynos4 SoC series, so the misleading comment has been
removed.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/clk/samsung/clk-exynos4.c   |  1 +
 include/dt-bindings/clock/exynos4.h | 10 +++++-----
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
index ac163d7..12a7cc3 100644
--- a/drivers/clk/samsung/clk-exynos4.c
+++ b/drivers/clk/samsung/clk-exynos4.c
@@ -1183,6 +1183,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
 	GATE(CLK_SPI1_ISP, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
 			CLK_IGNORE_UNUSED | CLK_GET_RATE_NOCACHE, 0),
 	GATE(CLK_G2D, "g2d", "aclk200", GATE_IP_DMC, 23, 0, 0),
+	GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk200", GATE_IP_DMC, 24, 0, 0),
 	GATE(CLK_TMU_APBIF, "tmu_apbif", "aclk100", E4X12_GATE_IP_PERIR, 17, 0,
 		0),
 };
diff --git a/include/dt-bindings/clock/exynos4.h b/include/dt-bindings/clock/exynos4.h
index 459bd2b..fb981635 100644
--- a/include/dt-bindings/clock/exynos4.h
+++ b/include/dt-bindings/clock/exynos4.h
@@ -115,11 +115,11 @@
 #define CLK_SMMU_MFCR		275
 #define CLK_G3D			276
 #define CLK_G2D			277
-#define CLK_ROTATOR		278 /* Exynos4210 only */
-#define CLK_MDMA		279 /* Exynos4210 only */
-#define CLK_SMMU_G2D		280 /* Exynos4210 only */
-#define CLK_SMMU_ROTATOR	281 /* Exynos4210 only */
-#define CLK_SMMU_MDMA		282 /* Exynos4210 only */
+#define CLK_ROTATOR		278
+#define CLK_MDMA		279
+#define CLK_SMMU_G2D		280
+#define CLK_SMMU_ROTATOR	281
+#define CLK_SMMU_MDMA		282
 #define CLK_FIMD0		283
 #define CLK_MIE0		284
 #define CLK_MDNIE0		285 /* Exynos4412 only */
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 04/29] drivers: base: add notifier for failed driver bind
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (2 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-21 19:46   ` Laurent Pinchart
                     ` (2 more replies)
  2014-08-05 10:47 ` [PATCH 05/29] drivers: convert suppress_bind_attrs parameter into flags Marek Szyprowski
                   ` (25 subsequent siblings)
  29 siblings, 3 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds support for getting a notify for failed device driver
bind, so all the items done in BUS_NOTIFY_BIND_DRIVER event can be
cleaned if the driver fails to bind.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/base/dd.c      | 10 +++++++---
 include/linux/device.h |  4 +++-
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index e4ffbcf..541a41f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -237,10 +237,14 @@ static int driver_sysfs_add(struct device *dev)
 	return ret;
 }
 
-static void driver_sysfs_remove(struct device *dev)
+static void driver_sysfs_remove(struct device *dev, int failed)
 {
 	struct device_driver *drv = dev->driver;
 
+	if (failed && dev->bus)
+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+					     BUS_NOTIFY_DRVBIND_FAILED, dev);
+
 	if (drv) {
 		sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
 		sysfs_remove_link(&dev->kobj, "driver");
@@ -316,7 +320,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 
 probe_failed:
 	devres_release_all(dev);
-	driver_sysfs_remove(dev);
+	driver_sysfs_remove(dev, true);
 	dev->driver = NULL;
 	dev_set_drvdata(dev, NULL);
 
@@ -509,7 +513,7 @@ static void __device_release_driver(struct device *dev)
 	if (drv) {
 		pm_runtime_get_sync(dev);
 
-		driver_sysfs_remove(dev);
+		driver_sysfs_remove(dev, false);
 
 		if (dev->bus)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
diff --git a/include/linux/device.h b/include/linux/device.h
index b387710..92daded 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -176,7 +176,7 @@ extern int bus_register_notifier(struct bus_type *bus,
 extern int bus_unregister_notifier(struct bus_type *bus,
 				   struct notifier_block *nb);
 
-/* All 4 notifers below get called with the target struct device *
+/* All 7 notifers below get called with the target struct device *
  * as an argument. Note that those functions are likely to be called
  * with the device lock held in the core, so be careful.
  */
@@ -189,6 +189,8 @@ extern int bus_unregister_notifier(struct bus_type *bus,
 						      unbound */
 #define BUS_NOTIFY_UNBOUND_DRIVER	0x00000006 /* driver is unbound
 						      from the device */
+#define BUS_NOTIFY_DRVBIND_FAILED	0x00000007 /* driver failed to bind
+						      to device */
 
 extern struct kset *bus_get_kset(struct bus_type *bus);
 extern struct klist *bus_get_device_klist(struct bus_type *bus);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 05/29] drivers: convert suppress_bind_attrs parameter into flags
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (3 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 04/29] drivers: base: add notifier for failed driver bind Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 06/29] drivers: iommu: add notify about failed bind Marek Szyprowski
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch extends struct device_driver with a flags member and converts
existing suppress_bind_attrs bool field to a flag. This way new flags
can be easily added in the future without changing the structure itself.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mach-integrator/impd1.c | 2 +-
 drivers/base/bus.c               | 4 ++--
 drivers/base/platform.c          | 2 +-
 drivers/pci/host/pci-mvebu.c     | 2 +-
 drivers/pci/host/pci-rcar-gen2.c | 2 +-
 drivers/pci/host/pci-tegra.c     | 2 +-
 drivers/pci/host/pcie-rcar.c     | 2 +-
 drivers/soc/tegra/pmc.c          | 2 +-
 include/linux/device.h           | 6 ++++--
 9 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c
index 3ce8807..a7e7330 100644
--- a/arch/arm/mach-integrator/impd1.c
+++ b/arch/arm/mach-integrator/impd1.c
@@ -406,7 +406,7 @@ static struct lm_driver impd1_driver = {
 		 * As we're dropping the probe() function, suppress driver
 		 * binding from sysfs.
 		 */
-		.suppress_bind_attrs = true,
+		.flags = DRIVER_SUPPRESS_BIND_ATTRS,
 	},
 	.probe		= impd1_probe,
 	.remove		= impd1_remove,
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 83e910a..f223f26 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -707,7 +707,7 @@ int bus_add_driver(struct device_driver *drv)
 			__func__, drv->name);
 	}
 
-	if (!drv->suppress_bind_attrs) {
+	if (!(drv->flags & DRIVER_SUPPRESS_BIND_ATTRS)) {
 		error = add_bind_files(drv);
 		if (error) {
 			/* Ditto */
@@ -740,7 +740,7 @@ void bus_remove_driver(struct device_driver *drv)
 	if (!drv->bus)
 		return;
 
-	if (!drv->suppress_bind_attrs)
+	if (!(drv->flags & DRIVER_SUPPRESS_BIND_ATTRS))
 		remove_bind_files(drv);
 	driver_remove_groups(drv, drv->bus->drv_groups);
 	driver_remove_file(drv, &driver_attr_uevent);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 68a8b77..c696058 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -608,7 +608,7 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
 	drv->prevent_deferred_probe = true;
 
 	/* make sure driver won't have bind/unbind attributes */
-	drv->driver.suppress_bind_attrs = true;
+	drv->driver.flags = DRIVER_SUPPRESS_BIND_ATTRS;
 
 	/* temporary section violation during probe() */
 	drv->probe = probe;
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index a8c6f1a..6815c50 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -1086,7 +1086,7 @@ static struct platform_driver mvebu_pcie_driver = {
 		.name = "mvebu-pcie",
 		.of_match_table = mvebu_pcie_of_match_table,
 		/* driver unloading/unbinding currently not supported */
-		.suppress_bind_attrs = true,
+		.flags = DRIVER_SUPPRESS_BIND_ATTRS,
 	},
 	.probe = mvebu_pcie_probe,
 };
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index 3ef854f..6f1b890 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -413,7 +413,7 @@ static struct platform_driver rcar_pci_driver = {
 	.driver = {
 		.name = "pci-rcar-gen2",
 		.owner = THIS_MODULE,
-		.suppress_bind_attrs = true,
+		.flags = DRIVER_SUPPRESS_BIND_ATTRS,
 		.of_match_table = rcar_pci_of_match,
 	},
 	.probe = rcar_pci_probe,
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 0fb0fdb..2e1698d 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1927,7 +1927,7 @@ static struct platform_driver tegra_pcie_driver = {
 		.name = "tegra-pcie",
 		.owner = THIS_MODULE,
 		.of_match_table = tegra_pcie_of_match,
-		.suppress_bind_attrs = true,
+		.flags = DRIVER_SUPPRESS_BIND_ATTRS,
 	},
 	.probe = tegra_pcie_probe,
 };
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index 4884ee5..9a1936e 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -981,7 +981,7 @@ static struct platform_driver rcar_pcie_driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = rcar_pcie_of_match,
-		.suppress_bind_attrs = true,
+		.flags = DRIVER_SUPPRESS_BIND_ATTRS,
 	},
 	.probe = rcar_pcie_probe,
 };
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index a2c0ceb..77c3eb3 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -892,7 +892,7 @@ static const struct of_device_id tegra_pmc_match[] = {
 static struct platform_driver tegra_pmc_driver = {
 	.driver = {
 		.name = "tegra-pmc",
-		.suppress_bind_attrs = true,
+		.flags = DRIVER_SUPPRESS_BIND_ATTRS,
 		.of_match_table = tegra_pmc_match,
 		.pm = &tegra_pmc_pm_ops,
 	},
diff --git a/include/linux/device.h b/include/linux/device.h
index 92daded..5f4ff02 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -201,7 +201,7 @@ extern struct klist *bus_get_device_klist(struct bus_type *bus);
  * @bus:	The bus which the device of this driver belongs to.
  * @owner:	The module owner.
  * @mod_name:	Used for built-in modules.
- * @suppress_bind_attrs: Disables bind/unbind via sysfs.
+ * @flags:	Flags defining driver behaviour, see below.
  * @of_match_table: The open firmware table.
  * @acpi_match_table: The ACPI match table.
  * @probe:	Called to query the existence of a specific device,
@@ -234,7 +234,7 @@ struct device_driver {
 	struct module		*owner;
 	const char		*mod_name;	/* used for built-in modules */
 
-	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */
+	unsigned long		flags;
 
 	const struct of_device_id	*of_match_table;
 	const struct acpi_device_id	*acpi_match_table;
@@ -251,6 +251,8 @@ struct device_driver {
 	struct driver_private *p;
 };
 
+/* disables bind/unbind via sysfs */
+#define DRIVER_SUPPRESS_BIND_ATTRS	(1 << 0)
 
 extern int __must_check driver_register(struct device_driver *drv);
 extern void driver_unregister(struct device_driver *drv);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 06/29] drivers: iommu: add notify about failed bind
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (4 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 05/29] drivers: convert suppress_bind_attrs parameter into flags Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 07/29] ARM: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size Marek Szyprowski
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds support for forwarding recently introduced
BUS_NOTIFY_DRVBIND_FAILED event to iommu groups. This lets us getting a
notify for failed device driver bind, so all the items done in
IOMMU_GROUP_NOTIFY_BIND_DRIVER event can be cleaned if the driver fails
to bind.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/iommu.c | 3 +++
 include/linux/iommu.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 1698360..516e93a 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -758,6 +758,9 @@ static int iommu_bus_notifier(struct notifier_block *nb,
 	case BUS_NOTIFY_UNBOUND_DRIVER:
 		group_action = IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER;
 		break;
+	case BUS_NOTIFY_DRVBIND_FAILED:
+		group_action = IOMMU_GROUP_NOTIFY_DRVBIND_FAILED;
+		break;
 	}
 
 	if (group_action)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 20f9a52..f9fdae5 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -139,6 +139,7 @@ struct iommu_ops {
 #define IOMMU_GROUP_NOTIFY_BOUND_DRIVER		4 /* Post Driver bind */
 #define IOMMU_GROUP_NOTIFY_UNBIND_DRIVER	5 /* Pre Driver unbind */
 #define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER	6 /* Post Driver unbind */
+#define IOMMU_GROUP_NOTIFY_DRVBIND_FAILED	7 /* Driver failed to bind */
 
 extern int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops);
 extern bool iommu_present(struct bus_type *bus);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 07/29] ARM: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (5 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 06/29] drivers: iommu: add notify about failed bind Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 08/29] ARM: dma-mapping: add helpers for managing default per-device dma mappings Marek Szyprowski
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

If device has no max_seg_size set, we assume that there is no limit and
force it to DMA_BIT_MASK(32) to always use contiguous mappings in DMA
address space.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/mm/dma-mapping.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 7a996aa..8161102 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2051,6 +2051,22 @@ int arm_iommu_attach_device(struct device *dev,
 {
 	int err;
 
+	/*
+	 * if device has no max_seg_size set, we assume that there is no limit
+	 * and force it to DMA_BIT_MASK(32) to always use contiguous mappings
+	 * in DMA address space
+	 */
+	if (!dev->dma_parms) {
+		dev->dma_parms = kzalloc(sizeof(*dev->dma_parms), GFP_KERNEL);
+		if (!dev->dma_parms)
+			return -ENOMEM;
+	}
+	if (!dev->dma_parms->max_segment_size) {
+		err = dma_set_max_seg_size(dev, DMA_BIT_MASK(32));
+		if (err)
+			return err;
+	}
+
 	err = iommu_attach_device(mapping->domain, dev);
 	if (err)
 		return err;
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 08/29] ARM: dma-mapping: add helpers for managing default per-device dma mappings
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (6 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 07/29] ARM: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 09/29] ARM: dma-mapping: provide stubs if no ARM_DMA_USE_IOMMU has been selected Marek Szyprowski
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds 2 helpers: arm_iommu_create_default_mapping and
arm_iommu_release_default_mapping for managing default iommu-based
dma-mapping address space, created for exlusive use only by the given
device. Those helpers are convenient for setting up iommu-based
dma-mapping for most typical devices in the system.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/include/asm/dma-iommu.h |  5 +++++
 arch/arm/mm/dma-mapping.c        | 31 +++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index 8e3fcb9..ae3dac0 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -33,5 +33,10 @@ int arm_iommu_attach_device(struct device *dev,
 					struct dma_iommu_mapping *mapping);
 void arm_iommu_detach_device(struct device *dev);
 
+int arm_iommu_create_default_mapping(struct device *dev, dma_addr_t base,
+				     size_t size);
+
+void arm_iommu_release_default_mapping(struct device *dev);
+
 #endif /* __KERNEL__ */
 #endif
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 8161102..233a8cf 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2106,4 +2106,35 @@ void arm_iommu_detach_device(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
 
+int arm_iommu_create_default_mapping(struct device *dev, dma_addr_t base,
+				     size_t size)
+{
+	struct dma_iommu_mapping *mapping;
+	int ret;
+
+	mapping = arm_iommu_create_mapping(dev->bus, base, size);
+	if (IS_ERR(mapping))
+		return PTR_ERR(mapping);
+
+	ret = arm_iommu_attach_device(dev, mapping);
+	if (ret) {
+		arm_iommu_release_mapping(mapping);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arm_iommu_create_default_mapping);
+
+void arm_iommu_release_default_mapping(struct device *dev)
+{
+	struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+	if (!mapping)
+		return;
+
+	arm_iommu_detach_device(dev);
+	arm_iommu_release_mapping(mapping);
+}
+EXPORT_SYMBOL_GPL(arm_iommu_release_default_mapping);
+
 #endif
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 09/29] ARM: dma-mapping: provide stubs if no ARM_DMA_USE_IOMMU has been selected
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (7 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 08/29] ARM: dma-mapping: add helpers for managing default per-device dma mappings Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag Marek Szyprowski
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch provides stubs returing errors for all iommu related arm
dma-mapping functions, which are used when CONFIG_ARM_DMA_USE_IOMMU is
not set. This let drivers to use common code for iommu and non-iommu
cases without additional ifdefs.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/include/asm/dma-iommu.h | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
index ae3dac0..1e57569 100644
--- a/arch/arm/include/asm/dma-iommu.h
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -9,6 +9,8 @@
 #include <linux/kmemcheck.h>
 #include <linux/kref.h>
 
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+
 struct dma_iommu_mapping {
 	/* iommu specific data */
 	struct iommu_domain	*domain;
@@ -38,5 +40,34 @@ int arm_iommu_create_default_mapping(struct device *dev, dma_addr_t base,
 
 void arm_iommu_release_default_mapping(struct device *dev);
 
+#else
+
+static inline struct dma_iommu_mapping *
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
+static inline void
+arm_iommu_release_mapping(struct dma_iommu_mapping *mapping) { }
+
+static inline int arm_iommu_attach_device(struct device *dev,
+					struct dma_iommu_mapping *mapping)
+{
+	return -ENOSYS;
+}
+
+static inline void arm_iommu_detach_device(struct device *dev) { }
+
+static inline int arm_iommu_create_default_mapping(struct device *dev,
+						dma_addr_t base, size_t size)
+{
+	return -ENOSYS;
+}
+
+static inline void arm_iommu_release_default_mapping(struct device *dev) { }
+
+#endif
+
 #endif /* __KERNEL__ */
 #endif
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (8 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 09/29] ARM: dma-mapping: provide stubs if no ARM_DMA_USE_IOMMU has been selected Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-09-01  5:22   ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 11/29] DRM: exynos: add DRIVER_HAS_OWN_IOMMU_MANAGER flag to all sub-drivers Marek Szyprowski
                   ` (19 subsequent siblings)
  29 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds a new flags for device drivers. This flag instructs
kernel that the device driver does it own management of IOMMU assisted
IO address space translations, so no default dma-mapping structures
should be initialized.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 include/linux/device.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/device.h b/include/linux/device.h
index 5f4ff02..2e62371 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -253,6 +253,8 @@ struct device_driver {
 
 /* disables bind/unbind via sysfs */
 #define DRIVER_SUPPRESS_BIND_ATTRS	(1 << 0)
+/* driver uses own methods to manage IO address space */
+#define DRIVER_HAS_OWN_IOMMU_MANAGER	(1 << 1)
 
 extern int __must_check driver_register(struct device_driver *drv);
 extern void driver_unregister(struct device_driver *drv);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 11/29] DRM: exynos: add DRIVER_HAS_OWN_IOMMU_MANAGER flag to all sub-drivers
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (9 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 12/29] DRM: Exynos: fix window clear code Marek Szyprowski
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Exynos DRM drivers do their own management of IO address space of all
controlled devices, so set DRIVER_HAS_OWN_IOMMU_MANAGER flag to instruct
IOMMU subsystem not to create any defaults for them.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimc.c    | 1 +
 drivers/gpu/drm/exynos/exynos_drm_fimd.c    | 1 +
 drivers/gpu/drm/exynos/exynos_drm_g2d.c     | 1 +
 drivers/gpu/drm/exynos/exynos_drm_gsc.c     | 1 +
 drivers/gpu/drm/exynos/exynos_drm_rotator.c | 1 +
 drivers/gpu/drm/exynos/exynos_mixer.c       | 1 +
 6 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 831dde9..fe84215 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1896,6 +1896,7 @@ struct platform_driver fimc_driver = {
 		.name	= "exynos-drm-fimc",
 		.owner	= THIS_MODULE,
 		.pm	= &fimc_pm_ops,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 33161ad..41904df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -1031,5 +1031,6 @@ struct platform_driver fimd_driver = {
 		.name	= "exynos4-fb",
 		.owner	= THIS_MODULE,
 		.of_match_table = fimd_driver_dt_match,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 8001587..dddeae3 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1555,5 +1555,6 @@ struct platform_driver g2d_driver = {
 		.owner	= THIS_MODULE,
 		.pm	= &g2d_pm_ops,
 		.of_match_table = exynos_g2d_match,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 9e3ff16..76e8b1e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1797,6 +1797,7 @@ struct platform_driver gsc_driver = {
 		.name	= "exynos-drm-gsc",
 		.owner	= THIS_MODULE,
 		.pm	= &gsc_pm_ops,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 };
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index f01fbb6..2da91c4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -852,5 +852,6 @@ struct platform_driver rotator_driver = {
 		.owner	= THIS_MODULE,
 		.pm	= &rotator_pm_ops,
 		.of_match_table = exynos_rotator_match,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 };
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7529946..79b1309a 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1320,6 +1320,7 @@ struct platform_driver mixer_driver = {
 		.name = "exynos-mixer",
 		.owner = THIS_MODULE,
 		.of_match_table = mixer_match_types,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 	.probe = mixer_probe,
 	.remove = mixer_remove,
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 12/29] DRM: Exynos: fix window clear code
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (10 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 11/29] DRM: exynos: add DRIVER_HAS_OWN_IOMMU_MANAGER flag to all sub-drivers Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-09-01 13:37   ` Inki Dae
  2014-08-05 10:47 ` [PATCH 13/29] temporary: media: s5p-mfc: remove DT hacks & initialization custom memory init code Marek Szyprowski
                   ` (17 subsequent siblings)
  29 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

To correctly disable hardware window during driver init, both enable bits
(WINCONx_ENWIN in WINCON and SHADOWCON_CHx_ENABLE in SHADOWCON) must be
cleared, otherwise hardware fails to re-enable such window later.

While touching this function, also temporarily disable ctx->suspended flag
to let fimd_wait_for_vblank function really to do its job.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_fimd.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 41904df..7a363d2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -165,27 +165,38 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
 		DRM_DEBUG_KMS("vblank wait timed out.\n");
 }
 
-
 static void fimd_clear_channel(struct exynos_drm_manager *mgr)
 {
 	struct fimd_context *ctx = mgr->ctx;
-	int win, ch_enabled = 0;
+	int state, win, ch_enabled = 0;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
 	/* Check if any channel is enabled. */
 	for (win = 0; win < WINDOWS_NR; win++) {
-		u32 val = readl(ctx->regs + SHADOWCON);
-		if (val & SHADOWCON_CHx_ENABLE(win)) {
-			val &= ~SHADOWCON_CHx_ENABLE(win);
-			writel(val, ctx->regs + SHADOWCON);
+		u32 val = readl(ctx->regs + WINCON(win));
+		if (val & WINCONx_ENWIN) {
+			/* wincon */
+			val &= ~WINCONx_ENWIN;
+			writel(val, ctx->regs + WINCON(win));
+
+			/* unprotect windows */
+			if (ctx->driver_data->has_shadowcon) {
+				val = readl(ctx->regs + SHADOWCON);
+				val &= ~SHADOWCON_CHx_ENABLE(win);
+				writel(val, ctx->regs + SHADOWCON);
+			}
 			ch_enabled = 1;
 		}
 	}
 
 	/* Wait for vsync, as disable channel takes effect at next vsync */
-	if (ch_enabled)
+	if (ch_enabled) {
+		state = ctx->suspended;
+		ctx->suspended = 0;
 		fimd_wait_for_vblank(mgr);
+		ctx->suspended = state;
+	}
 }
 
 static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 13/29] temporary: media: s5p-mfc: remove DT hacks & initialization custom memory init code
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (11 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 12/29] DRM: Exynos: fix window clear code Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 14/29] devicetree: Update Exynos SYSMMU device tree bindings Marek Szyprowski
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch removes custom initialization of reserved memory regions from
s5p-mfc driver. Driver will use main device pointer for all memory allocations.

This patch is temporary, do not merge it yet.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 73 +-------------------------------
 1 file changed, 2 insertions(+), 71 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index d35b041..77b99ae 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -996,55 +996,8 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
 	.mmap = s5p_mfc_mmap,
 };
 
-static int match_child(struct device *dev, void *data)
-{
-	if (!dev_name(dev))
-		return 0;
-	return !strcmp(dev_name(dev), (char *)data);
-}
-
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
-static int s5p_mfc_alloc_memdevs(struct s5p_mfc_dev *dev)
-{
-	unsigned int mem_info[2] = { };
-
-	dev->mem_dev_l = devm_kzalloc(&dev->plat_dev->dev,
-			sizeof(struct device), GFP_KERNEL);
-	if (!dev->mem_dev_l) {
-		mfc_err("Not enough memory\n");
-		return -ENOMEM;
-	}
-	device_initialize(dev->mem_dev_l);
-	of_property_read_u32_array(dev->plat_dev->dev.of_node,
-			"samsung,mfc-l", mem_info, 2);
-	if (dma_declare_coherent_memory(dev->mem_dev_l, mem_info[0],
-				mem_info[0], mem_info[1],
-				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) {
-		mfc_err("Failed to declare coherent memory for\n"
-		"MFC device\n");
-		return -ENOMEM;
-	}
-
-	dev->mem_dev_r = devm_kzalloc(&dev->plat_dev->dev,
-			sizeof(struct device), GFP_KERNEL);
-	if (!dev->mem_dev_r) {
-		mfc_err("Not enough memory\n");
-		return -ENOMEM;
-	}
-	device_initialize(dev->mem_dev_r);
-	of_property_read_u32_array(dev->plat_dev->dev.of_node,
-			"samsung,mfc-r", mem_info, 2);
-	if (dma_declare_coherent_memory(dev->mem_dev_r, mem_info[0],
-				mem_info[0], mem_info[1],
-				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE) == 0) {
-		pr_err("Failed to declare coherent memory for\n"
-		"MFC device\n");
-		return -ENOMEM;
-	}
-	return 0;
-}
-
 /* MFC probe function */
 static int s5p_mfc_probe(struct platform_device *pdev)
 {
@@ -1096,26 +1049,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 		goto err_res;
 	}
 
-	if (pdev->dev.of_node) {
-		ret = s5p_mfc_alloc_memdevs(dev);
-		if (ret < 0)
-			goto err_res;
-	} else {
-		dev->mem_dev_l = device_find_child(&dev->plat_dev->dev,
-				"s5p-mfc-l", match_child);
-		if (!dev->mem_dev_l) {
-			mfc_err("Mem child (L) device get failed\n");
-			ret = -ENODEV;
-			goto err_res;
-		}
-		dev->mem_dev_r = device_find_child(&dev->plat_dev->dev,
-				"s5p-mfc-r", match_child);
-		if (!dev->mem_dev_r) {
-			mfc_err("Mem child (R) device get failed\n");
-			ret = -ENODEV;
-			goto err_res;
-		}
-	}
+	dev->mem_dev_l = &dev->plat_dev->dev;
+	dev->mem_dev_r = &dev->plat_dev->dev;
 
 	dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
 	if (IS_ERR(dev->alloc_ctx[0])) {
@@ -1246,10 +1181,6 @@ static int s5p_mfc_remove(struct platform_device *pdev)
 	s5p_mfc_release_firmware(dev);
 	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
 	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
-	if (pdev->dev.of_node) {
-		put_device(dev->mem_dev_l);
-		put_device(dev->mem_dev_r);
-	}
 
 	s5p_mfc_final_pm(dev);
 	return 0;
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 14/29] devicetree: Update Exynos SYSMMU device tree bindings
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (12 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 13/29] temporary: media: s5p-mfc: remove DT hacks & initialization custom memory init code Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 15/29] ARM: DTS: Exynos4: add System MMU nodes Marek Szyprowski
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch describes how generic iommu bindings are implemented by
Exynos SYSMMU driver.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 .../devicetree/bindings/iommu/samsung,sysmmu.txt   | 93 +++++++++++++++++++---
 1 file changed, 84 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
index 6fa4c73..999ba6d 100644
--- a/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
+++ b/Documentation/devicetree/bindings/iommu/samsung,sysmmu.txt
@@ -23,16 +23,33 @@ MMUs.
   for window 1, 2 and 3.
 * M2M Scalers and G2D in Exynos5420 has one System MMU on the read channel and
   the other System MMU on the write channel.
-The drivers must consider how to handle those System MMUs. One of the idea is
-to implement child devices or sub-devices which are the client devices of the
-System MMU.
 
-Note:
-The current DT binding for the Exynos System MMU is incomplete.
-The following properties can be removed or changed, if found incompatible with
-the "Generic IOMMU Binding" support for attaching devices to the IOMMU.
+The drivers must consider how to handle those System MMUs. When device
+have more than one SYSMMU controller it is neccessary to add
+"iommu-names" property, which specifies which SYSMMU controller operates
+on which bus or memory channel.
 
-Required properties:
+It is up to the master device driver to decide how such case will be
+handled. It is possible to create separate IO address spaces for each
+SYSMMU or to bind them together to one common IO address space. It is
+also possible to bind more than one device to one IO address space. All
+this has to be handled by master device driver in its initialization
+procedure or flags and no changes to device tree nodes are needed.
+
+In Linux kernel, the general idea is that presence of the SYSMMU
+controllers is transparent to master drivers if they use standard DMA
+API. When driver wants to use IO separate address spaces for each bus or
+memory channel (each SYSMMU) or to bind more than one device to one IO
+address space, it has to specify this to SYSMMU driver by
+DRIVER_HAS_OWN_IOMMU_MANAGER flag. To get access to each SYSMMU bound to
+the given device, additional child devices with special names (matching
+"parent:bus" scheme) have to be registered. Once then, all standard
+IOMMU operations can be performed on such child devices, what will
+result in respective operations done on IO address space managed by
+SYSMMU of the given name. Other operating systems might implement those
+features differently.
+
+Required properties for SYSMMU controller node:
 - compatible: Should be "samsung,exynos-sysmmu"
 - reg: A tuple of base address and size of System MMU registers.
 - interrupt-parent: The phandle of the interrupt controller of System MMU
@@ -45,11 +62,27 @@ Required properties:
 	       Exynos4 SoCs, there needs no "master" clock.
 	       Exynos5 SoCs, some System MMUs must have "master" clocks.
 - clocks: Required if the System MMU is needed to gate its clock.
+- #iommu-cells: Specify number of cells describing IO address space parameters,
+		can be: 0 (zero), meaning all 32bit address space is available,
+		or 2, if address space is limited, first cell then stores
+		base IO address, second cell contains IO window size in bytes.
 - samsung,power-domain: Required if the System MMU is needed to gate its power.
 	  Please refer to the following document:
 	  Documentation/devicetree/bindings/arm/exynos/power_domain.txt
 
-Examples:
+Required properties for master device:
+- iommus: one or more phandles to the SYSMMU controller node, with optionally
+	  specified IO address space (see #iommu-cells property above)
+- iommu-names: if more than one SYSMMU controller is specified, this property
+	       must contain names for each of them. Those names are defined by
+	       the bindings for a particular master device.
+
+For more information, please refer to generic iommu bindings defined in
+iommu.txt file.
+
+Example 1:
+GScaller device with one SYSMMU controller
+
 	gsc_0: gsc@13e00000 {
 		compatible = "samsung,exynos5-gsc";
 		reg = <0x13e00000 0x1000>;
@@ -57,6 +90,7 @@ Examples:
 		samsung,power-domain = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL0>;
 		clock-names = "gscl";
+		iommus = <&sysmmu_gsc0>;
 	};
 
 	sysmmu_gsc0: sysmmu@13E80000 {
@@ -67,4 +101,45 @@ Examples:
 		clock-names = "sysmmu", "master";
 		clocks = <&clock CLK_SMMU_GSCL0>, <&clock CLK_GSCL0>;
 		samsung,power-domain = <&pd_gsc>;
+		#iommu-cells = <0>;
+	};
+
+Example 2:
+MFC Codec with two SYSMMU controllers (on "left" and "right" bus), with address
+space limited to 256MiB each, left bus starts IO address space at 0x20000000,
+while right bus at 0x30000000
+
+	mfc: codec@13400000 {
+		compatible = "samsung,mfc-v5";
+		reg = <0x13400000 0x10000>;
+		interrupts = <0 94 0>;
+		samsung,power-domain = <&pd_mfc>;
+		clocks = <&clock CLK_MFC>;
+		clock-names = "mfc";
+		status = "disabled";
+		iommus = <&sysmmu_mfc_l 0x20000000 0x10000000>,
+			 <&sysmmu_mfc_r 0x30000000 0x10000000>;
+		iommu-names = "left", "right";
+	};
+
+	sysmmu_mfc_l: sysmmu@13620000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13620000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+		samsung,power-domain = <&pd_mfc>;
+		#iommu-cells = <2>;
+	};
+
+	sysmmu_mfc_r: sysmmu@13630000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13630000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+		samsung,power-domain = <&pd_mfc>;
+		#iommu-cells = <2>;
 	};
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 15/29] ARM: DTS: Exynos4: add System MMU nodes
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (13 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 14/29] devicetree: Update Exynos SYSMMU device tree bindings Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 16/29] iommu: exynos: make driver multiarch friendly Marek Szyprowski
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds System MMU nodes that are specific to Exynos4210/4x12 series.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 arch/arm/boot/dts/exynos4.dtsi    | 118 ++++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/exynos4210.dtsi |  23 ++++++++
 arch/arm/boot/dts/exynos4x12.dtsi |  82 ++++++++++++++++++++++++++
 3 files changed, 223 insertions(+)

diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 3385b17..a76b4e5 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -174,6 +174,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			samsung,power-domain = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc0>;
 			status = "disabled";
 		};
 
@@ -185,6 +186,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			samsung,power-domain = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc1>;
 			status = "disabled";
 		};
 
@@ -196,6 +198,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			samsung,power-domain = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc2>;
 			status = "disabled";
 		};
 
@@ -207,6 +210,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			samsung,power-domain = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc3>;
 			status = "disabled";
 		};
 
@@ -395,6 +399,9 @@
 		clocks = <&clock CLK_MFC>;
 		clock-names = "mfc";
 		status = "disabled";
+		iommus = <&sysmmu_mfc_l 0x20000000 0x10000000>,
+			 <&sysmmu_mfc_r 0x30000000 0x10000000>;
+		iommu-names = "left", "right";
 	};
 
 	serial_0: serial@13800000 {
@@ -642,6 +649,117 @@
 		clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
 		clock-names = "sclk_fimd", "fimd";
 		samsung,power-domain = <&pd_lcd0>;
+		iommus = <&sysmmu_fimd0>;
 		status = "disabled";
 	};
+
+	sysmmu_mfc_l: sysmmu@13620000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13620000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+		samsung,power-domain = <&pd_mfc>;
+		#iommu-cells = <2>;
+	};
+
+	sysmmu_mfc_r: sysmmu@13630000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13630000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+		samsung,power-domain = <&pd_mfc>;
+		#iommu-cells = <2>;
+	};
+
+	sysmmu_tv: sysmmu@12E20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12E20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 4>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_TV>, <&clock CLK_MIXER>;
+		samsung,power-domain = <&pd_tv>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc0: sysmmu@11A20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC0>, <&clock CLK_FIMC0>;
+		samsung,power-domain = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc1: sysmmu@11A30000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A30000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 3>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC1>, <&clock CLK_FIMC1>;
+		samsung,power-domain = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc2: sysmmu@11A40000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 4>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC2>, <&clock CLK_FIMC2>;
+		samsung,power-domain = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc3: sysmmu@11A50000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A50000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC3>, <&clock CLK_FIMC3>;
+		samsung,power-domain = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_jpeg: sysmmu@11A60000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A60000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_JPEG>, <&clock CLK_JPEG>;
+		samsung,power-domain = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_rotator: sysmmu@12A30000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12A30000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_ROTATOR>, <&clock CLK_ROTATOR>;
+		samsung,power-domain = <&pd_lcd0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd0: sysmmu@11E20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11E20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD0>, <&clock CLK_FIMD0>;
+		samsung,power-domain = <&pd_lcd0>;
+		#iommu-cells = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 807bb5b..9ae48c2 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -142,6 +142,7 @@
 		interrupts = <0 89 0>;
 		clocks = <&clock CLK_SCLK_FIMG2D>, <&clock CLK_G2D>;
 		clock-names = "sclk_fimg2d", "fimg2d";
+		iommus = <&sysmmu_g2d>;
 		status = "disabled";
 	};
 
@@ -175,4 +176,26 @@
 			samsung,lcd-wb;
 		};
 	};
+
+	sysmmu_g2d: sysmmu@12A20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12A20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 7>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_G2D>, <&clock CLK_G2D>;
+		samsung,power-domain = <&pd_lcd0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd1: sysmmu@12220000 {
+		compatible = "samsung,exynos-sysmmu";
+		interrupt-parent = <&combiner>;
+		reg = <0x12220000 0x1000>;
+		interrupts = <5 3>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD1>, <&clock CLK_FIMD1>;
+		samsung,power-domain = <&pd_lcd1>;
+		#iommu-cells = <0>;
+	};
 };
diff --git a/arch/arm/boot/dts/exynos4x12.dtsi b/arch/arm/boot/dts/exynos4x12.dtsi
index 861bb91..cc97e18 100644
--- a/arch/arm/boot/dts/exynos4x12.dtsi
+++ b/arch/arm/boot/dts/exynos4x12.dtsi
@@ -148,6 +148,7 @@
 		interrupts = <0 89 0>;
 		clocks = <&clock CLK_SCLK_FIMG2D>, <&clock CLK_G2D>;
 		clock-names = "sclk_fimg2d", "fimg2d";
+		iommus = <&sysmmu_g2d>;
 		status = "disabled";
 	};
 
@@ -197,6 +198,7 @@
 			samsung,power-domain = <&pd_isp>;
 			clocks = <&clock CLK_FIMC_LITE0>;
 			clock-names = "flite";
+			iommus = <&sysmmu_fimc_lite0>;
 			status = "disabled";
 		};
 
@@ -207,6 +209,7 @@
 			samsung,power-domain = <&pd_isp>;
 			clocks = <&clock CLK_FIMC_LITE1>;
 			clock-names = "flite";
+			iommus = <&sysmmu_fimc_lite1>;
 			status = "disabled";
 		};
 
@@ -235,6 +238,9 @@
 				      "mcuispdiv1", "uart", "aclk200",
 				      "div_aclk200", "aclk400mcuisp",
 				      "div_aclk400mcuisp";
+			iommus = <&sysmmu_fimc_isp>, <&sysmmu_fimc_drc>,
+				 <&sysmmu_fimc_fd>, <&sysmmu_fimc_mcuctl>;
+			iommu-names = "isp", "drc", "fd", "mcuctl";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges;
@@ -271,4 +277,80 @@
 		compatible = "samsung,exynos4x12-usb2-phy";
 		samsung,sysreg-phandle = <&sys_reg>;
 	};
+
+	sysmmu_g2d: sysmmu@10A40000{
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x10A40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 7>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_G2D>, <&clock CLK_G2D>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_isp: sysmmu@12260000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12260000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <16 2>;
+		samsung,power-domain = <&pd_isp>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_ISP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_drc: sysmmu@12270000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12270000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <16 3>;
+		samsung,power-domain = <&pd_isp>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_DRC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_fd: sysmmu@122A0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x122A0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <16 4>;
+		samsung,power-domain = <&pd_isp>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FD>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_mcuctl: sysmmu@122B0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x122B0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <16 5>;
+		samsung,power-domain = <&pd_isp>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_ISPCX>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_lite0: sysmmu@123B0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x123B0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <16 0>;
+		samsung,power-domain = <&pd_isp>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_LITE0>, <&clock CLK_FIMC_LITE0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_lite1: sysmmu@123C0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x123C0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <16 1>;
+		samsung,power-domain = <&pd_isp>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_LITE1>, <&clock CLK_FIMC_LITE1>;
+		#iommu-cells = <0>;
+	};
 };
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 16/29] iommu: exynos: make driver multiarch friendly
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (14 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 15/29] ARM: DTS: Exynos4: add System MMU nodes Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 17/29] iommu: exynos: don't read version register on every tlb operation Marek Szyprowski
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Initialize all structures and register to iommu subsystem only on Exynos
compatible platforms.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index d037e87..64b3bc8 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/mm.h>
+#include <linux/of.h>
 #include <linux/iommu.h>
 #include <linux/errno.h>
 #include <linux/list.h>
@@ -1187,6 +1188,11 @@ static int __init exynos_iommu_init(void)
 {
 	int ret;
 
+	if (!of_machine_is_compatible("samsung,exynos3") &&
+	    !of_machine_is_compatible("samsung,exynos4") &&
+	    !of_machine_is_compatible("samsung,exynos5"))
+		return -ENODEV;
+
 	lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
 				LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
 	if (!lv2table_kmem_cache) {
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 17/29] iommu: exynos: don't read version register on every tlb operation
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (15 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 16/29] iommu: exynos: make driver multiarch friendly Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 18/29] iommu: exynos: remove unused functions Marek Szyprowski
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch removes reading of REG_MMU_VERSION register on every tlb
operation and caches SYSMMU version in driver's internal data.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 64b3bc8..8927923 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -213,6 +213,7 @@ struct sysmmu_drvdata {
 	spinlock_t lock;
 	struct iommu_domain *domain;
 	phys_addr_t pgtable;
+	int version;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -239,11 +240,6 @@ static void sysmmu_unblock(void __iomem *sfrbase)
 	__raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
 }
 
-static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
-{
-	return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
-}
-
 static bool sysmmu_block(void __iomem *sfrbase)
 {
 	int i = 120;
@@ -403,7 +399,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 	unsigned int cfg = CFG_LRU | CFG_QOS(15);
 	unsigned int ver;
 
-	ver = __raw_sysmmu_version(data);
+	ver = MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
 	if (MMU_MAJ_VER(ver) == 3) {
 		if (MMU_MIN_VER(ver) >= 2) {
 			cfg |= CFG_FLPDCACHE;
@@ -417,6 +413,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 	}
 
 	__raw_writel(cfg, data->sfrbase + REG_MMU_CFG);
+	data->version = ver;
 }
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
@@ -526,7 +523,7 @@ static bool exynos_sysmmu_disable(struct device *dev)
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					      sysmmu_iova_t iova)
 {
-	if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3))
+	if (data->version == MAKE_MMU_VER(3, 3))
 		__raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
@@ -575,7 +572,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
 		 * 1MB page can be cached in one of all sets.
 		 * 64KB page can be one of 16 consecutive sets.
 		 */
-		if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2)
+		if (MMU_MAJ_VER(data->version) == 2)
 			num_inv = min_t(unsigned int, size / PAGE_SIZE, 64);
 
 		if (sysmmu_block(data->sfrbase)) {
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 18/29] iommu: exynos: remove unused functions
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (16 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 17/29] iommu: exynos: don't read version register on every tlb operation Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 19/29] iommu: exynos: remove useless spinlock Marek Szyprowski
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch removes two unneeded functions, which are not a part of
generic IOMMU API and were never used by any other driver.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 31 -------------------------------
 1 file changed, 31 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 8927923..ec3c882 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -491,13 +491,6 @@ static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
 	return ret;
 }
 
-int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable)
-{
-	BUG_ON(!memblock_is_memory(pgtable));
-
-	return __exynos_sysmmu_enable(dev, pgtable, NULL);
-}
-
 static bool exynos_sysmmu_disable(struct device *dev)
 {
 	unsigned long flags;
@@ -589,30 +582,6 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
 	spin_unlock_irqrestore(&data->lock, flags);
 }
 
-void exynos_sysmmu_tlb_invalidate(struct device *dev)
-{
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	unsigned long flags;
-	struct sysmmu_drvdata *data;
-
-	data = dev_get_drvdata(owner->sysmmu);
-
-	spin_lock_irqsave(&data->lock, flags);
-	if (is_sysmmu_active(data)) {
-		if (!IS_ERR(data->clk_master))
-			clk_enable(data->clk_master);
-		if (sysmmu_block(data->sfrbase)) {
-			__sysmmu_tlb_invalidate(data->sfrbase);
-			sysmmu_unblock(data->sfrbase);
-		}
-		if (!IS_ERR(data->clk_master))
-			clk_disable(data->clk_master);
-	} else {
-		dev_dbg(dev, "disabled. Skipping TLB invalidation\n");
-	}
-	spin_unlock_irqrestore(&data->lock, flags);
-}
-
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
 	int irq, ret;
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 19/29] iommu: exynos: remove useless spinlock
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (17 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 18/29] iommu: exynos: remove unused functions Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 20/29] iommu: exynos: refactor function parameters to simplify code Marek Szyprowski
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch removes useless spinlocks and other unused members from
struct exynos_iommu_owner. There is no point is protecting this
structure by spinlock because content of this structure doesn't change
and other structures have their own spinlocks.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 11 -----------
 1 file changed, 11 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index ec3c882..ed8c518 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -190,9 +190,6 @@ struct exynos_iommu_owner {
 	struct list_head client; /* entry of exynos_iommu_domain.clients */
 	struct device *dev;
 	struct device *sysmmu;
-	struct iommu_domain *domain;
-	void *vmm_data;         /* IO virtual memory manager's data */
-	spinlock_t lock;        /* Lock to preserve consistency of System MMU */
 };
 
 struct exynos_iommu_domain {
@@ -478,16 +475,12 @@ static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
 
 	BUG_ON(!has_sysmmu(dev));
 
-	spin_lock_irqsave(&owner->lock, flags);
-
 	data = dev_get_drvdata(owner->sysmmu);
 
 	ret = __sysmmu_enable(data, pgtable, domain);
 	if (ret >= 0)
 		data->master = dev;
 
-	spin_unlock_irqrestore(&owner->lock, flags);
-
 	return ret;
 }
 
@@ -500,16 +493,12 @@ static bool exynos_sysmmu_disable(struct device *dev)
 
 	BUG_ON(!has_sysmmu(dev));
 
-	spin_lock_irqsave(&owner->lock, flags);
-
 	data = dev_get_drvdata(owner->sysmmu);
 
 	disabled = __sysmmu_disable(data);
 	if (disabled)
 		data->master = NULL;
 
-	spin_unlock_irqrestore(&owner->lock, flags);
-
 	return disabled;
 }
 
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 20/29] iommu: exynos: refactor function parameters to simplify code
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (18 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 19/29] iommu: exynos: remove useless spinlock Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 21/29] iommu: exynos: remove unused functions, part 2 Marek Szyprowski
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch simplifies the code by:
- refactoring function parameters from struct device pointer to direct pointer
  to struct sysmmu drvdata
- moving list_head enteries from struct exynos_iommu_owner directly to struct
  sysmmu_drvdata

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 93 ++++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 47 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index ed8c518..018a615 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -187,8 +187,6 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-	struct list_head client; /* entry of exynos_iommu_domain.clients */
-	struct device *dev;
 	struct device *sysmmu;
 };
 
@@ -209,6 +207,7 @@ struct sysmmu_drvdata {
 	int activations;
 	spinlock_t lock;
 	struct iommu_domain *domain;
+	struct list_head domain_node;
 	phys_addr_t pgtable;
 	int version;
 };
@@ -509,12 +508,10 @@ static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 		__raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
-static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
+static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					    sysmmu_iova_t iova)
 {
 	unsigned long flags;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data = dev_get_drvdata(owner->sysmmu);
 
 	if (!IS_ERR(data->clk_master))
 		clk_enable(data->clk_master);
@@ -528,14 +525,10 @@ static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
 		clk_disable(data->clk_master);
 }
 
-static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
-					size_t size)
+static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
+					sysmmu_iova_t iova, size_t size)
 {
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
 	unsigned long flags;
-	struct sysmmu_drvdata *data;
-
-	data = dev_get_drvdata(owner->sysmmu);
 
 	spin_lock_irqsave(&data->lock, flags);
 	if (is_sysmmu_active(data)) {
@@ -565,8 +558,8 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
 		if (!IS_ERR(data->clk_master))
 			clk_disable(data->clk_master);
 	} else {
-		dev_dbg(dev, "disabled. Skipping TLB invalidation @ %#x\n",
-			iova);
+		dev_dbg(data->master,
+			"disabled. Skipping TLB invalidation @ %#x\n", iova);
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
 }
@@ -705,7 +698,7 @@ err_pgtable:
 static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
 {
 	struct exynos_iommu_domain *priv = domain->priv;
-	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
 	unsigned long flags;
 	int i;
 
@@ -713,14 +706,12 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	list_for_each_entry(owner, &priv->clients, client) {
-		while (!exynos_sysmmu_disable(owner->dev))
-			; /* until System MMU is actually disabled */
+	list_for_each_entry(data, &priv->clients, domain_node) {
+		if (__sysmmu_disable(data))
+			data->master = NULL;
+		list_del_init(&data->domain_node);
 	}
 
-	while (!list_empty(&priv->clients))
-		list_del_init(priv->clients.next);
-
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	for (i = 0; i < NUM_LV1ENTRIES; i++)
@@ -739,20 +730,26 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 {
 	struct exynos_iommu_owner *owner = dev->archdata.iommu;
 	struct exynos_iommu_domain *priv = domain->priv;
+	struct sysmmu_drvdata *data;
 	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
 	unsigned long flags;
-	int ret;
+	int ret = -ENODEV;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	if (!has_sysmmu(dev))
+		return -ENODEV;
 
-	ret = __exynos_sysmmu_enable(dev, pagetable, domain);
-	if (ret == 0) {
-		list_add_tail(&owner->client, &priv->clients);
-		owner->domain = domain;
+	data = dev_get_drvdata(owner->sysmmu);
+	if (data) {
+		ret = __sysmmu_enable(data, pagetable, domain);
+		if (ret >= 0) {
+			data->master = dev;
+
+			spin_lock_irqsave(&priv->lock, flags);
+			list_add_tail(&data->domain_node, &priv->clients);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	if (ret < 0) {
 		dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n",
 					__func__, &pagetable);
@@ -768,26 +765,29 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 static void exynos_iommu_detach_device(struct iommu_domain *domain,
 				    struct device *dev)
 {
-	struct exynos_iommu_owner *owner;
 	struct exynos_iommu_domain *priv = domain->priv;
 	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	struct sysmmu_drvdata *data;
 	unsigned long flags;
+	int found = 0;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	if (!has_sysmmu(dev))
+		return;
 
-	list_for_each_entry(owner, &priv->clients, client) {
-		if (owner == dev->archdata.iommu) {
-			if (exynos_sysmmu_disable(dev)) {
-				list_del_init(&owner->client);
-				owner->domain = NULL;
+	spin_lock_irqsave(&priv->lock, flags);
+	list_for_each_entry(data, &priv->clients, domain_node) {
+		if (data->master == dev) {
+			if (__sysmmu_disable(data)) {
+				data->master = NULL;
+				list_del_init(&data->domain_node);
 			}
+			found = true;
 			break;
 		}
 	}
-
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	if (owner == dev->archdata.iommu)
+	if (found)
 		dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
 					__func__, &pagetable);
 	else
@@ -834,12 +834,11 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
 		 * not currently mapped.
 		 */
 		if (need_flush_flpd_cache) {
-			struct exynos_iommu_owner *owner;
+			struct sysmmu_drvdata *data;
 
 			spin_lock(&priv->lock);
-			list_for_each_entry(owner, &priv->clients, client)
-				sysmmu_tlb_invalidate_flpdcache(
-							owner->dev, iova);
+			list_for_each_entry(data, &priv->clients, domain_node)
+				sysmmu_tlb_invalidate_flpdcache(data, iova);
 			spin_unlock(&priv->lock);
 		}
 	}
@@ -874,13 +873,13 @@ static int lv1set_section(struct exynos_iommu_domain *priv,
 
 	spin_lock(&priv->lock);
 	if (lv1ent_page_zero(sent)) {
-		struct exynos_iommu_owner *owner;
+		struct sysmmu_drvdata *data;
 		/*
 		 * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD
 		 * entry by speculative prefetch of SLPD which has no mapping.
 		 */
-		list_for_each_entry(owner, &priv->clients, client)
-			sysmmu_tlb_invalidate_flpdcache(owner->dev, iova);
+		list_for_each_entry(data, &priv->clients, domain_node)
+			sysmmu_tlb_invalidate_flpdcache(data, iova);
 	}
 	spin_unlock(&priv->lock);
 
@@ -985,13 +984,13 @@ static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova,
 static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv,
 						sysmmu_iova_t iova, size_t size)
 {
-	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	list_for_each_entry(owner, &priv->clients, client)
-		sysmmu_tlb_invalidate_entry(owner->dev, iova, size);
+	list_for_each_entry(data, &priv->clients, domain_node)
+		sysmmu_tlb_invalidate_entry(data, iova, size);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 21/29] iommu: exynos: remove unused functions, part 2
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (19 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 20/29] iommu: exynos: refactor function parameters to simplify code Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 22/29] iommu: exynos: add support for binding more than one sysmmu to master device Marek Szyprowski
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

After refactoring functions to use pointer to struct sysmmu_drvdata
directly, some functions became useless and thus never used, so remove
them completely.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 43 -------------------------------------------
 1 file changed, 43 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 018a615..674d1fb 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -458,49 +458,6 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
 	return ret;
 }
 
-/* __exynos_sysmmu_enable: Enables System MMU
- *
- * returns -error if an error occurred and System MMU is not enabled,
- * 0 if the System MMU has been just enabled and 1 if System MMU was already
- * enabled before.
- */
-static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
-				  struct iommu_domain *domain)
-{
-	int ret = 0;
-	unsigned long flags;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data;
-
-	BUG_ON(!has_sysmmu(dev));
-
-	data = dev_get_drvdata(owner->sysmmu);
-
-	ret = __sysmmu_enable(data, pgtable, domain);
-	if (ret >= 0)
-		data->master = dev;
-
-	return ret;
-}
-
-static bool exynos_sysmmu_disable(struct device *dev)
-{
-	unsigned long flags;
-	bool disabled = true;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data;
-
-	BUG_ON(!has_sysmmu(dev));
-
-	data = dev_get_drvdata(owner->sysmmu);
-
-	disabled = __sysmmu_disable(data);
-	if (disabled)
-		data->master = NULL;
-
-	return disabled;
-}
-
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					      sysmmu_iova_t iova)
 {
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 22/29] iommu: exynos: add support for binding more than one sysmmu to master device
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (20 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 21/29] iommu: exynos: remove unused functions, part 2 Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 23/29] iommu: exynos: init iommu controllers from device tree Marek Szyprowski
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds support for assigning more than one SYSMMU controller to
the master device. This has been achieved simply by chaning the struct
device pointer in struct exynos_iommu_owner into the list of struct
sysmmu_drvdata of all controllers assigned to the given master device.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 674d1fb..46e0edc 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -187,7 +187,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-	struct device *sysmmu;
+	struct list_head clients;
 };
 
 struct exynos_iommu_domain {
@@ -208,6 +208,7 @@ struct sysmmu_drvdata {
 	spinlock_t lock;
 	struct iommu_domain *domain;
 	struct list_head domain_node;
+	struct list_head owner_node;
 	phys_addr_t pgtable;
 	int version;
 };
@@ -695,8 +696,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 	if (!has_sysmmu(dev))
 		return -ENODEV;
 
-	data = dev_get_drvdata(owner->sysmmu);
-	if (data) {
+	list_for_each_entry(data, &owner->clients, owner_node) {
 		ret = __sysmmu_enable(data, pagetable, domain);
 		if (ret >= 0) {
 			data->master = dev;
@@ -724,7 +724,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 {
 	struct exynos_iommu_domain *priv = domain->priv;
 	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
-	struct sysmmu_drvdata *data;
+	struct sysmmu_drvdata *data, *next;
 	unsigned long flags;
 	int found = 0;
 
@@ -732,14 +732,13 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 		return;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry(data, &priv->clients, domain_node) {
+	list_for_each_entry_safe(data, next, &priv->clients, domain_node) {
 		if (data->master == dev) {
 			if (__sysmmu_disable(data)) {
 				data->master = NULL;
 				list_del_init(&data->domain_node);
 			}
 			found = true;
-			break;
 		}
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 23/29] iommu: exynos: init iommu controllers from device tree
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (21 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 22/29] iommu: exynos: add support for binding more than one sysmmu to master device Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 24/29] iommu: exynos: create default iommu-based dma-mapping for master devices Marek Szyprowski
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds code to initialize and assign SYSMMU controllers to
their master devices defined in device tree.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 152 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 145 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 46e0edc..845f547 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -21,6 +21,7 @@
 #include <linux/err.h>
 #include <linux/mm.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <linux/iommu.h>
 #include <linux/errno.h>
 #include <linux/list.h>
@@ -211,6 +212,9 @@ struct sysmmu_drvdata {
 	struct list_head owner_node;
 	phys_addr_t pgtable;
 	int version;
+	const char *name;
+	dma_addr_t base;
+	size_t size;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -574,6 +578,11 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 	}
 
 	data->sysmmu = dev;
+
+	/* default io address space parameters */
+	data->base = SZ_1G;
+	data->size = SZ_2G;
+
 	spin_lock_init(&data->lock);
 
 	platform_set_drvdata(pdev, data);
@@ -1055,30 +1064,159 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
 	return phys;
 }
 
+static void __free_owner_struct(struct exynos_iommu_owner *owner,
+				struct device *dev)
+{
+	while (!list_empty(&owner->clients))
+		list_del_init(owner->clients.next);
+
+	kfree(owner);
+	dev->archdata.iommu = NULL;
+}
+
+static int __init_master_sysmmu(struct device *dev)
+{
+	struct of_phandle_args sysmmu_spec;
+	struct exynos_iommu_owner *owner;
+	int i = 0;
+	int ret;
+
+	owner = kzalloc(sizeof(*owner), GFP_KERNEL);
+	if (!owner)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&owner->clients);
+
+	while (!of_parse_phandle_with_args(dev->of_node, "iommus",
+					   "#iommu-cells", i,
+					   &sysmmu_spec)) {
+		struct platform_device *sysmmu;
+		struct sysmmu_drvdata *data;
+
+		sysmmu = of_find_device_by_node(sysmmu_spec.np);
+		if (!sysmmu) {
+			dev_err(dev, "sysmmu node not found\n");
+			ret = -ENODEV;
+			goto err;
+		}
+		data = platform_get_drvdata(sysmmu);
+		if (!data) {
+			ret = -ENODEV;
+			goto err;
+		}
+
+		of_property_read_string_index(dev->of_node, "iommu-names", i,
+					      &data->name);
+
+		if (sysmmu_spec.args_count == 2) {
+			data->base = sysmmu_spec.args[0];
+			data->size = sysmmu_spec.args[1];
+		} else if (sysmmu_spec.args_count != 0) {
+			dev_err(dev, "incorrect iommu property specified\n");
+			ret = -EINVAL;
+			goto err;
+		}
+
+		list_add_tail(&data->owner_node, &owner->clients);
+
+		i++;
+	}
+
+	if (i == 0) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	dev->archdata.iommu = owner;
+	dev_dbg(dev, "registered %d sysmmu controllers\n", i);
+
+	return 0;
+err:
+	__free_owner_struct(owner, dev);
+	return ret;
+}
+
+static int __init_subdevice_sysmmu(struct device *dev)
+{
+	struct device *parent = dev->parent;
+	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
+	char *name;
+
+	name = strrchr(dev_name(dev), ':');
+	if (!name)
+		return -ENODEV;
+	name++;
+
+	owner = parent->archdata.iommu;
+	if (!owner)
+		return -ENODEV;
+
+	list_for_each_entry(data, &owner->clients, owner_node)
+		if (strcmp(name, data->name) == 0)
+			break;
+	if (!data)
+		return -ENODEV;
+
+	owner = kzalloc(sizeof(*owner), GFP_KERNEL);
+	if (!owner)
+		return -ENOMEM;
+	INIT_LIST_HEAD(&owner->clients);
+
+	/* move sysmmu from parent to child device */
+	list_del(&data->owner_node);
+	list_add_tail(&data->owner_node, &owner->clients);
+
+	dev->archdata.iommu = owner;
+	dev_dbg(dev->parent,
+		"registered sysmmu controller for %s subdevice\n", data->name);
+
+	return 0;
+}
+
 static int exynos_iommu_add_device(struct device *dev)
 {
 	struct iommu_group *group;
 	int ret;
 
-	group = iommu_group_get(dev);
+	BUG_ON(dev->archdata.iommu != NULL);
 
-	if (!group) {
-		group = iommu_group_alloc();
-		if (IS_ERR(group)) {
-			dev_err(dev, "Failed to allocate IOMMU group\n");
-			return PTR_ERR(group);
-		}
+	if (of_get_property(dev->of_node, "iommus", NULL))
+		ret = __init_master_sysmmu(dev);
+	else if (dev->parent &&
+		 of_get_property(dev->parent->of_node, "iommus", NULL))
+		ret = __init_subdevice_sysmmu(dev);
+	else
+		return -ENODEV;
+
+	if (ret)
+		return ret;
+
+	group = iommu_group_alloc();
+	if (IS_ERR(group)) {
+		dev_err(dev, "Failed to allocate IOMMU group\n");
+		ret = PTR_ERR(group);
+		goto err;
 	}
 
 	ret = iommu_group_add_device(group, dev);
+	if (ret != 0)
+		goto err;
+
 	iommu_group_put(group);
 
+	return 0;
+err:
+	__free_owner_struct(dev->archdata.iommu, dev);
 	return ret;
 }
 
 static void exynos_iommu_remove_device(struct device *dev)
 {
+	struct exynos_iommu_owner *owner = dev->archdata.iommu;
+
 	iommu_group_remove_device(dev);
+	if (owner)
+		__free_owner_struct(owner, dev);
 }
 
 static const struct iommu_ops exynos_iommu_ops = {
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 24/29] iommu: exynos: create default iommu-based dma-mapping for master devices
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (22 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 23/29] iommu: exynos: init iommu controllers from device tree Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 25/29] iommu: exynos: add support for runtime_pm Marek Szyprowski
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch adds code to create default per-device iommu-based
dma-mapping instance for all master devices, whose driver didn't set
DRIVER_HAS_OWN_IOMMU_MANAGER flag.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 49 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 845f547..336b2f8 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -12,6 +12,7 @@
 #define DEBUG
 #endif
 
+#include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
@@ -29,6 +30,7 @@
 #include <linux/export.h>
 
 #include <asm/cacheflush.h>
+#include <asm/dma-iommu.h>
 #include <asm/pgtable.h>
 
 typedef u32 sysmmu_iova_t;
@@ -1064,6 +1066,43 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
 	return phys;
 }
 
+static int sysmmu_master_device_event(struct notifier_block *nb,
+				      unsigned long val, void *p)
+{
+	struct device *dev = p;
+	struct exynos_iommu_owner *owner = dev->archdata.iommu;
+	struct sysmmu_drvdata *data;
+
+	if (!owner)
+		return 0;
+
+	data = list_first_entry(&owner->clients, struct sysmmu_drvdata,
+				owner_node);
+	if (!data)
+		return 0;
+
+	switch (val) {
+
+	case IOMMU_GROUP_NOTIFY_BIND_DRIVER:
+		if (!(dev->driver->flags & DRIVER_HAS_OWN_IOMMU_MANAGER))
+			arm_iommu_create_default_mapping(dev, data->base,
+							 data->size);
+		break;
+
+	case IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER:
+	case IOMMU_GROUP_NOTIFY_DRVBIND_FAILED:
+		if (!(dev->driver->flags & DRIVER_HAS_OWN_IOMMU_MANAGER))
+			arm_iommu_release_default_mapping(dev);
+		break;
+	}
+
+	return 0;
+}
+
+static struct notifier_block sysmmu_master_device_notifier = {
+	.notifier_call = sysmmu_master_device_event,
+};
+
 static void __free_owner_struct(struct exynos_iommu_owner *owner,
 				struct device *dev)
 {
@@ -1202,6 +1241,7 @@ static int exynos_iommu_add_device(struct device *dev)
 	if (ret != 0)
 		goto err;
 
+	iommu_group_register_notifier(group, &sysmmu_master_device_notifier);
 	iommu_group_put(group);
 
 	return 0;
@@ -1213,8 +1253,15 @@ err:
 static void exynos_iommu_remove_device(struct device *dev)
 {
 	struct exynos_iommu_owner *owner = dev->archdata.iommu;
+	struct iommu_group *group = iommu_group_get(dev);
+
+	if (group) {
+		iommu_group_unregister_notifier(group,
+						&sysmmu_master_device_notifier);
+		iommu_group_remove_device(dev);
+		iommu_group_put(group);
+	}
 
-	iommu_group_remove_device(dev);
 	if (owner)
 		__free_owner_struct(owner, dev);
 }
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 25/29] iommu: exynos: add support for runtime_pm
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (23 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 24/29] iommu: exynos: create default iommu-based dma-mapping for master devices Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 26/29] iommu: exynos: rename variables to reflect their purpose Marek Szyprowski
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch enables support for runtime pm for SYSMMU controllers. State
of each controller is saved before master's device power domain is
turned off and restored after it has been turned on.

exynos_iommu_attach_device() function might be called anytime, even when
power domain for master's device has been turned off, so to let SYSMMU
controllers to access its registers, a call to pm_runtime_get_sync() has
to be done, which turns on the power domain, which SYSMMU belongs to.
Later, once SYSMMU has been enabled, a call to pm_runtime_put() lets
runtime pm to turn off the power domain if there are no other devices
enabled. This way, the SYSMMU drivers get a genpd pm event and save its
state with sysmmu_save_state() function.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 54 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 336b2f8..5cd91b11 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -28,6 +28,7 @@
 #include <linux/list.h>
 #include <linux/memblock.h>
 #include <linux/export.h>
+#include <linux/pm_domain.h>
 
 #include <asm/cacheflush.h>
 #include <asm/dma-iommu.h>
@@ -208,6 +209,7 @@ struct sysmmu_drvdata {
 	struct clk *clk;
 	struct clk *clk_master;
 	int activations;
+	int suspended;
 	spinlock_t lock;
 	struct iommu_domain *domain;
 	struct list_head domain_node;
@@ -217,6 +219,7 @@ struct sysmmu_drvdata {
 	const char *name;
 	dma_addr_t base;
 	size_t size;
+	struct notifier_block pm_notifier;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -235,7 +238,7 @@ static bool set_sysmmu_inactive(struct sysmmu_drvdata *data)
 
 static bool is_sysmmu_active(struct sysmmu_drvdata *data)
 {
-	return data->activations > 0;
+	return (!data->suspended && data->activations > 0);
 }
 
 static void sysmmu_unblock(void __iomem *sfrbase)
@@ -528,6 +531,51 @@ static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
 	spin_unlock_irqrestore(&data->lock, flags);
 }
 
+static void sysmmu_restore_state(struct sysmmu_drvdata *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->lock, flags);
+	if (data->activations > 0) {
+		data->suspended = false;
+		__sysmmu_enable_nocount(data);
+		dev_dbg(data->sysmmu, "restored state\n");
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static void sysmmu_save_state(struct sysmmu_drvdata *data)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&data->lock, flags);
+	if (data->activations > 0) {
+		__sysmmu_disable_nocount(data);
+		data->suspended = true;
+		dev_dbg(data->sysmmu, "saved state\n");
+	}
+	spin_unlock_irqrestore(&data->lock, flags);
+}
+
+static int sysmmu_runtime_genpd_event(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	struct sysmmu_drvdata *data;
+
+	data = container_of(this, struct sysmmu_drvdata, pm_notifier);
+
+	switch (event) {
+	case PM_GENPD_POST_POWER_ON:
+		sysmmu_restore_state(data);
+		break;
+	case PM_GENPD_POWER_OFF_PREPARE:
+		sysmmu_save_state(data);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
 	int irq, ret;
@@ -580,6 +628,7 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 	}
 
 	data->sysmmu = dev;
+	data->pm_notifier.notifier_call = sysmmu_runtime_genpd_event;
 
 	/* default io address space parameters */
 	data->base = SZ_1G;
@@ -708,6 +757,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 		return -ENODEV;
 
 	list_for_each_entry(data, &owner->clients, owner_node) {
+		pm_runtime_get_sync(data->sysmmu);
 		ret = __sysmmu_enable(data, pagetable, domain);
 		if (ret >= 0) {
 			data->master = dev;
@@ -716,6 +766,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 			list_add_tail(&data->domain_node, &priv->clients);
 			spin_unlock_irqrestore(&priv->lock, flags);
 		}
+		pm_runtime_put(data->sysmmu);
 	}
 
 	if (ret < 0) {
@@ -1156,6 +1207,7 @@ static int __init_master_sysmmu(struct device *dev)
 		}
 
 		list_add_tail(&data->owner_node, &owner->clients);
+		pm_genpd_register_notifier(dev, &data->pm_notifier);
 
 		i++;
 	}
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 26/29] iommu: exynos: rename variables to reflect their purpose
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (24 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 25/29] iommu: exynos: add support for runtime_pm Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 27/29] iommu: exynos: document internal structures Marek Szyprowski
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch renames some variables to make the code easier to understand.
'domain' is replaced by 'iommu_domain' (more generic entity) and really
meaning less 'priv' by 'domain' to reflect its purpose.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 191 ++++++++++++++++++++++---------------------
 1 file changed, 97 insertions(+), 94 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 5cd91b11..7600861 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -440,8 +440,8 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
 		clk_disable(data->clk_master);
 }
 
-static int __sysmmu_enable(struct sysmmu_drvdata *data,
-			phys_addr_t pgtable, struct iommu_domain *domain)
+static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
+			   struct iommu_domain *iommu_domain)
 {
 	int ret = 0;
 	unsigned long flags;
@@ -449,7 +449,7 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
 	spin_lock_irqsave(&data->lock, flags);
 	if (set_sysmmu_active(data)) {
 		data->pgtable = pgtable;
-		data->domain = domain;
+		data->domain = iommu_domain;
 
 		__sysmmu_enable_nocount(data);
 
@@ -664,92 +664,93 @@ static inline void pgtable_flush(void *vastart, void *vaend)
 				virt_to_phys(vaend));
 }
 
-static int exynos_iommu_domain_init(struct iommu_domain *domain)
+static int exynos_iommu_domain_init(struct iommu_domain *iommu_domain)
 {
-	struct exynos_iommu_domain *priv;
+	struct exynos_iommu_domain *domain;
 	int i;
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain)
 		return -ENOMEM;
 
-	priv->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
-	if (!priv->pgtable)
+	domain->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
+	if (!domain->pgtable)
 		goto err_pgtable;
 
-	priv->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
-	if (!priv->lv2entcnt)
+	domain->lv2entcnt = (short *)
+			    __get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+	if (!domain->lv2entcnt)
 		goto err_counter;
 
 	/* w/a of System MMU v3.3 to prevent caching 1MiB mapping */
 	for (i = 0; i < NUM_LV1ENTRIES; i += 8) {
-		priv->pgtable[i + 0] = ZERO_LV2LINK;
-		priv->pgtable[i + 1] = ZERO_LV2LINK;
-		priv->pgtable[i + 2] = ZERO_LV2LINK;
-		priv->pgtable[i + 3] = ZERO_LV2LINK;
-		priv->pgtable[i + 4] = ZERO_LV2LINK;
-		priv->pgtable[i + 5] = ZERO_LV2LINK;
-		priv->pgtable[i + 6] = ZERO_LV2LINK;
-		priv->pgtable[i + 7] = ZERO_LV2LINK;
+		domain->pgtable[i + 0] = ZERO_LV2LINK;
+		domain->pgtable[i + 1] = ZERO_LV2LINK;
+		domain->pgtable[i + 2] = ZERO_LV2LINK;
+		domain->pgtable[i + 3] = ZERO_LV2LINK;
+		domain->pgtable[i + 4] = ZERO_LV2LINK;
+		domain->pgtable[i + 5] = ZERO_LV2LINK;
+		domain->pgtable[i + 6] = ZERO_LV2LINK;
+		domain->pgtable[i + 7] = ZERO_LV2LINK;
 	}
 
-	pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES);
+	pgtable_flush(domain->pgtable, domain->pgtable + NUM_LV1ENTRIES);
 
-	spin_lock_init(&priv->lock);
-	spin_lock_init(&priv->pgtablelock);
-	INIT_LIST_HEAD(&priv->clients);
+	spin_lock_init(&domain->lock);
+	spin_lock_init(&domain->pgtablelock);
+	INIT_LIST_HEAD(&domain->clients);
 
-	domain->geometry.aperture_start = 0;
-	domain->geometry.aperture_end   = ~0UL;
-	domain->geometry.force_aperture = true;
+	iommu_domain->geometry.aperture_start = 0;
+	iommu_domain->geometry.aperture_end   = ~0UL;
+	iommu_domain->geometry.force_aperture = true;
 
-	domain->priv = priv;
+	iommu_domain->priv = domain;
 	return 0;
 
 err_counter:
-	free_pages((unsigned long)priv->pgtable, 2);
+	free_pages((unsigned long)domain->pgtable, 2);
 err_pgtable:
-	kfree(priv);
+	kfree(domain);
 	return -ENOMEM;
 }
 
-static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
+static void exynos_iommu_domain_destroy(struct iommu_domain *iommu_domain)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	struct sysmmu_drvdata *data;
 	unsigned long flags;
 	int i;
 
-	WARN_ON(!list_empty(&priv->clients));
+	WARN_ON(!list_empty(&domain->clients));
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&domain->lock, flags);
 
-	list_for_each_entry(data, &priv->clients, domain_node) {
+	list_for_each_entry(data, &domain->clients, domain_node) {
 		if (__sysmmu_disable(data))
 			data->master = NULL;
 		list_del_init(&data->domain_node);
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&domain->lock, flags);
 
 	for (i = 0; i < NUM_LV1ENTRIES; i++)
-		if (lv1ent_page(priv->pgtable + i))
+		if (lv1ent_page(domain->pgtable + i))
 			kmem_cache_free(lv2table_kmem_cache,
-				phys_to_virt(lv2table_base(priv->pgtable + i)));
+			      phys_to_virt(lv2table_base(domain->pgtable + i)));
 
-	free_pages((unsigned long)priv->pgtable, 2);
-	free_pages((unsigned long)priv->lv2entcnt, 1);
-	kfree(domain->priv);
-	domain->priv = NULL;
+	free_pages((unsigned long)domain->pgtable, 2);
+	free_pages((unsigned long)domain->lv2entcnt, 1);
+	kfree(iommu_domain->priv);
+	iommu_domain->priv = NULL;
 }
 
-static int exynos_iommu_attach_device(struct iommu_domain *domain,
+static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
 				   struct device *dev)
 {
 	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	struct sysmmu_drvdata *data;
-	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	phys_addr_t pagetable = virt_to_phys(domain->pgtable);
 	unsigned long flags;
 	int ret = -ENODEV;
 
@@ -758,13 +759,13 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 
 	list_for_each_entry(data, &owner->clients, owner_node) {
 		pm_runtime_get_sync(data->sysmmu);
-		ret = __sysmmu_enable(data, pagetable, domain);
+		ret = __sysmmu_enable(data, pagetable, iommu_domain);
 		if (ret >= 0) {
 			data->master = dev;
 
-			spin_lock_irqsave(&priv->lock, flags);
-			list_add_tail(&data->domain_node, &priv->clients);
-			spin_unlock_irqrestore(&priv->lock, flags);
+			spin_lock_irqsave(&domain->lock, flags);
+			list_add_tail(&data->domain_node, &domain->clients);
+			spin_unlock_irqrestore(&domain->lock, flags);
 		}
 		pm_runtime_put(data->sysmmu);
 	}
@@ -781,11 +782,11 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 	return ret;
 }
 
-static void exynos_iommu_detach_device(struct iommu_domain *domain,
+static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
 				    struct device *dev)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
-	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
+	phys_addr_t pagetable = virt_to_phys(domain->pgtable);
 	struct sysmmu_drvdata *data, *next;
 	unsigned long flags;
 	int found = 0;
@@ -793,8 +794,8 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 	if (!has_sysmmu(dev))
 		return;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry_safe(data, next, &priv->clients, domain_node) {
+	spin_lock_irqsave(&domain->lock, flags);
+	list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
 		if (data->master == dev) {
 			if (__sysmmu_disable(data)) {
 				data->master = NULL;
@@ -803,7 +804,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 			found = true;
 		}
 	}
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&domain->lock, flags);
 
 	if (found)
 		dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
@@ -812,7 +813,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 		dev_err(dev, "%s: No IOMMU is attached\n", __func__);
 }
 
-static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
+static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain,
 		sysmmu_pte_t *sent, sysmmu_iova_t iova, short *pgcounter)
 {
 	if (lv1ent_section(sent)) {
@@ -854,17 +855,17 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
 		if (need_flush_flpd_cache) {
 			struct sysmmu_drvdata *data;
 
-			spin_lock(&priv->lock);
-			list_for_each_entry(data, &priv->clients, domain_node)
+			spin_lock(&domain->lock);
+			list_for_each_entry(data, &domain->clients, domain_node)
 				sysmmu_tlb_invalidate_flpdcache(data, iova);
-			spin_unlock(&priv->lock);
+			spin_unlock(&domain->lock);
 		}
 	}
 
 	return page_entry(sent, iova);
 }
 
-static int lv1set_section(struct exynos_iommu_domain *priv,
+static int lv1set_section(struct exynos_iommu_domain *domain,
 			  sysmmu_pte_t *sent, sysmmu_iova_t iova,
 			  phys_addr_t paddr, short *pgcnt)
 {
@@ -889,17 +890,17 @@ static int lv1set_section(struct exynos_iommu_domain *priv,
 
 	pgtable_flush(sent, sent + 1);
 
-	spin_lock(&priv->lock);
+	spin_lock(&domain->lock);
 	if (lv1ent_page_zero(sent)) {
 		struct sysmmu_drvdata *data;
 		/*
 		 * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD
 		 * entry by speculative prefetch of SLPD which has no mapping.
 		 */
-		list_for_each_entry(data, &priv->clients, domain_node)
+		list_for_each_entry(data, &domain->clients, domain_node)
 			sysmmu_tlb_invalidate_flpdcache(data, iova);
 	}
-	spin_unlock(&priv->lock);
+	spin_unlock(&domain->lock);
 
 	return 0;
 }
@@ -959,74 +960,76 @@ static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size,
  *   than or equal size to 128KiB.
  * - Start address of an I/O virtual region must be aligned by 128KiB.
  */
-static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova,
-			 phys_addr_t paddr, size_t size, int prot)
+static int exynos_iommu_map(struct iommu_domain *iommu_domain,
+			unsigned long l_iova, phys_addr_t paddr, size_t size,
+			int prot)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	sysmmu_pte_t *entry;
 	sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
 	unsigned long flags;
 	int ret = -ENOMEM;
 
-	BUG_ON(priv->pgtable == NULL);
+	BUG_ON(domain->pgtable == NULL);
 
-	spin_lock_irqsave(&priv->pgtablelock, flags);
+	spin_lock_irqsave(&domain->pgtablelock, flags);
 
-	entry = section_entry(priv->pgtable, iova);
+	entry = section_entry(domain->pgtable, iova);
 
 	if (size == SECT_SIZE) {
-		ret = lv1set_section(priv, entry, iova, paddr,
-					&priv->lv2entcnt[lv1ent_offset(iova)]);
+		ret = lv1set_section(domain, entry, iova, paddr,
+				     &domain->lv2entcnt[lv1ent_offset(iova)]);
 	} else {
 		sysmmu_pte_t *pent;
 
-		pent = alloc_lv2entry(priv, entry, iova,
-					&priv->lv2entcnt[lv1ent_offset(iova)]);
+		pent = alloc_lv2entry(domain, entry, iova,
+				      &domain->lv2entcnt[lv1ent_offset(iova)]);
 
 		if (IS_ERR(pent))
 			ret = PTR_ERR(pent);
 		else
 			ret = lv2set_page(pent, paddr, size,
-					&priv->lv2entcnt[lv1ent_offset(iova)]);
+				       &domain->lv2entcnt[lv1ent_offset(iova)]);
 	}
 
 	if (ret)
 		pr_err("%s: Failed(%d) to map %#zx bytes @ %#x\n",
 			__func__, ret, size, iova);
 
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
 	return ret;
 }
 
-static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv,
-						sysmmu_iova_t iova, size_t size)
+static
+void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *domain,
+					sysmmu_iova_t iova, size_t size)
 {
 	struct sysmmu_drvdata *data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&domain->lock, flags);
 
-	list_for_each_entry(data, &priv->clients, domain_node)
+	list_for_each_entry(data, &domain->clients, domain_node)
 		sysmmu_tlb_invalidate_entry(data, iova, size);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&domain->lock, flags);
 }
 
-static size_t exynos_iommu_unmap(struct iommu_domain *domain,
+static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain,
 					unsigned long l_iova, size_t size)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
 	sysmmu_pte_t *ent;
 	size_t err_pgsize;
 	unsigned long flags;
 
-	BUG_ON(priv->pgtable == NULL);
+	BUG_ON(domain->pgtable == NULL);
 
-	spin_lock_irqsave(&priv->pgtablelock, flags);
+	spin_lock_irqsave(&domain->pgtablelock, flags);
 
-	ent = section_entry(priv->pgtable, iova);
+	ent = section_entry(domain->pgtable, iova);
 
 	if (lv1ent_section(ent)) {
 		if (WARN_ON(size < SECT_SIZE)) {
@@ -1059,7 +1062,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain,
 		*ent = 0;
 		size = SPAGE_SIZE;
 		pgtable_flush(ent, ent + 1);
-		priv->lv2entcnt[lv1ent_offset(iova)] += 1;
+		domain->lv2entcnt[lv1ent_offset(iova)] += 1;
 		goto done;
 	}
 
@@ -1073,15 +1076,15 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain,
 	pgtable_flush(ent, ent + SPAGES_PER_LPAGE);
 
 	size = LPAGE_SIZE;
-	priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE;
+	domain->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE;
 done:
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
-	exynos_iommu_tlb_invalidate_entry(priv, iova, size);
+	exynos_iommu_tlb_invalidate_entry(domain, iova, size);
 
 	return size;
 err:
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
 	pr_err("%s: Failed: size(%#zx) @ %#x is smaller than page size %#zx\n",
 		__func__, size, iova, err_pgsize);
@@ -1089,17 +1092,17 @@ err:
 	return 0;
 }
 
-static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
+static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
 					  dma_addr_t iova)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	sysmmu_pte_t *entry;
 	unsigned long flags;
 	phys_addr_t phys = 0;
 
-	spin_lock_irqsave(&priv->pgtablelock, flags);
+	spin_lock_irqsave(&domain->pgtablelock, flags);
 
-	entry = section_entry(priv->pgtable, iova);
+	entry = section_entry(domain->pgtable, iova);
 
 	if (lv1ent_section(entry)) {
 		phys = section_phys(entry) + section_offs(iova);
@@ -1112,7 +1115,7 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
 			phys = spage_phys(entry) + spage_offs(iova);
 	}
 
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
 	return phys;
 }
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 27/29] iommu: exynos: document internal structures
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (25 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 26/29] iommu: exynos: rename variables to reflect their purpose Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 28/29] iommu: exynos: remove excessive includes and sort others alphabetically Marek Szyprowski
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Add a few words of comment to all internal structures used by the driver.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 59 ++++++++++++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 7600861..78ce618 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -189,37 +189,54 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 	"UNKNOWN FAULT"
 };
 
-/* attached to dev.archdata.iommu of the master device */
+/*
+ * This structure is attached to dev.archdata.iommu of the master device
+ * on device add, contains a list of SYSMMU controllers defined by device tree,
+ * which are bound to given master device. It is usually referenced by 'owner'
+ * pointer.
+ */
 struct exynos_iommu_owner {
-	struct list_head clients;
+	struct list_head clients; /* list of sysmmu_drvdata.owner_node */
 };
 
+/*
+ * This structure is stored in ->priv field of generic struct iommu_domain,
+ * contains list of SYSMMU controllers from all master devices, which has been
+ * attached to this domain and page tables of IO address space defined by this
+ * domain. It is usually referenced by 'domain' pointer.
+ */
 struct exynos_iommu_domain {
-	struct list_head clients; /* list of sysmmu_drvdata.node */
+	struct list_head clients; /* list of sysmmu_drvdata.domain_node */
 	sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */
 	short *lv2entcnt; /* free lv2 entry counter for each section */
-	spinlock_t lock; /* lock for this structure */
+	spinlock_t lock; /* lock for modyfying list of clients */
 	spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */
 };
 
+/*
+ * This structure hold all data of a single SYSMMU controller, this includes
+ * hw resources like registers and clocks, pointers and list nodes to connect
+ * it to all other structures, internal state and parameters read from device
+ * tree. It is usually referenced by 'data' pointer.
+ */
 struct sysmmu_drvdata {
-	struct device *sysmmu;	/* System MMU's device descriptor */
-	struct device *master;	/* Owner of system MMU */
-	void __iomem *sfrbase;
-	struct clk *clk;
-	struct clk *clk_master;
-	int activations;
-	int suspended;
-	spinlock_t lock;
-	struct iommu_domain *domain;
-	struct list_head domain_node;
-	struct list_head owner_node;
-	phys_addr_t pgtable;
-	int version;
-	const char *name;
-	dma_addr_t base;
-	size_t size;
-	struct notifier_block pm_notifier;
+	struct device *sysmmu; /* SYSMMU controller device */
+	struct device *master; /* master device (owner of given SYSMMU) */
+	void __iomem *sfrbase; /* our registers */
+	struct clk *clk; /* SYSMMU's clock */
+	struct clk *clk_master; /* master's device clock */
+	int activations; /* number of calls to sysmmu_enable */
+	int suspended; /* status of the controller (managed by runtime pm) */
+	spinlock_t lock; /* lock for modyfying enable/disable state */
+	struct iommu_domain *domain; /* domain we belong to */
+	struct list_head domain_node; /* node for domain clients list */
+	struct list_head owner_node; /* node for owner clients list */
+	phys_addr_t pgtable; /* assigned page table structure */
+	int version; /* our version */
+	const char *name; /* our name from device tree */
+	dma_addr_t base; /* base addres of IO address space define in DT */
+	size_t size; /* size of IO address space define in DT */
+	struct notifier_block pm_notifier; /* notifier for pm domain on/off */
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 28/29] iommu: exynos: remove excessive includes and sort others alphabetically
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (26 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 27/29] iommu: exynos: document internal structures Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-05 10:47 ` [PATCH 29/29] temporary: media: s5p-mfc: add support for IOMMU Marek Szyprowski
  2014-08-18 23:32 ` [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Joerg Roedel
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Removed following unused includes: <linux/mm.h>, <linux/errno.h>,
<linux/memblock.h> and <linux/export.h>.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/iommu/exynos-iommu.c | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 78ce618..1bbb100 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -12,23 +12,19 @@
 #define DEBUG
 #endif
 
+#include <linux/clk.h>
 #include <linux/dma-mapping.h>
+#include <linux/err.h>
 #include <linux/io.h>
+#include <linux/iommu.h>
 #include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/mm.h>
+#include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/iommu.h>
-#include <linux/errno.h>
-#include <linux/list.h>
-#include <linux/memblock.h>
-#include <linux/export.h>
+#include <linux/platform_device.h>
 #include <linux/pm_domain.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
 
 #include <asm/cacheflush.h>
 #include <asm/dma-iommu.h>
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* [PATCH 29/29] temporary: media: s5p-mfc: add support for IOMMU
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (27 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 28/29] iommu: exynos: remove excessive includes and sort others alphabetically Marek Szyprowski
@ 2014-08-05 10:47 ` Marek Szyprowski
  2014-08-18 23:32 ` [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Joerg Roedel
  29 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-05 10:47 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: Marek Szyprowski, linaro-mm-sig, Arnd Bergmann,
	Shaik Ameer Basha, Cho KyongHo, Joerg Roedel, Thierry Reding,
	Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

This patch is an example how to use more than one IOMMU controller in a
device driver for hardware blocks, which have more then one dma master
(memory interface with iommu controller).

This patch is temporary, do not merge it yet.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
 drivers/media/platform/s5p-mfc/s5p_mfc.c | 46 ++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 77b99ae..c2e95ab 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -22,7 +22,11 @@
 #include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <linux/of.h>
+#include <linux/of_platform.h>
 #include <media/videobuf2-core.h>
+
+#include <asm/dma-iommu.h>
+
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
@@ -996,6 +1000,39 @@ static const struct v4l2_file_operations s5p_mfc_fops = {
 	.mmap = s5p_mfc_mmap,
 };
 
+static struct device *s5p_mfc_alloc_memdev(struct device *dev, const char *name)
+{
+	struct device *child;
+	int ret;
+
+	child = devm_kzalloc(dev, sizeof(struct device), GFP_KERNEL);
+	if (!child)
+		return NULL;
+
+	device_initialize(child);
+	dev_set_name(child, "%s:%s", dev_name(dev), name);
+	child->parent = dev;
+	child->bus = dev->bus;
+	child->coherent_dma_mask = dev->coherent_dma_mask;
+	child->dma_mask = dev->dma_mask;
+
+	if (device_add(child) == 0) {
+		ret = arm_iommu_create_default_mapping(child, 0x20000000,
+						       SZ_256M);
+		if (ret == 0)
+			return child;
+	}
+
+	put_device(child);
+	return NULL;
+}
+
+void s5p_mfc_free_memdev(struct device *dev)
+{
+	arm_iommu_release_default_mapping(dev);
+	put_device(dev);
+}
+
 static void *mfc_get_drv_data(struct platform_device *pdev);
 
 /* MFC probe function */
@@ -1049,8 +1086,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 		goto err_res;
 	}
 
-	dev->mem_dev_l = &dev->plat_dev->dev;
-	dev->mem_dev_r = &dev->plat_dev->dev;
+	dev->mem_dev_l = s5p_mfc_alloc_memdev(&dev->plat_dev->dev, "left");
+	dev->mem_dev_r = s5p_mfc_alloc_memdev(&dev->plat_dev->dev, "right");
 
 	dev->alloc_ctx[0] = vb2_dma_contig_init_ctx(dev->mem_dev_l);
 	if (IS_ERR(dev->alloc_ctx[0])) {
@@ -1181,6 +1218,10 @@ static int s5p_mfc_remove(struct platform_device *pdev)
 	s5p_mfc_release_firmware(dev);
 	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[0]);
 	vb2_dma_contig_cleanup_ctx(dev->alloc_ctx[1]);
+	if (dev->mem_dev_l)
+		s5p_mfc_free_memdev(dev->mem_dev_l);
+	if (dev->mem_dev_r)
+		s5p_mfc_free_memdev(dev->mem_dev_r);
 
 	s5p_mfc_final_pm(dev);
 	return 0;
@@ -1436,6 +1477,7 @@ static struct platform_driver s5p_mfc_driver = {
 		.owner	= THIS_MODULE,
 		.pm	= &s5p_mfc_pm_ops,
 		.of_match_table = exynos_mfc_match,
+		.flags	= DRIVER_HAS_OWN_IOMMU_MANAGER,
 	},
 };
 
-- 
1.9.2


^ permalink raw reply related	[flat|nested] 50+ messages in thread

* Re: [PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments
  2014-08-05 10:47 ` [PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments Marek Szyprowski
@ 2014-08-18 11:26   ` Tomasz Figa
  0 siblings, 0 replies; 50+ messages in thread
From: Tomasz Figa @ 2014-08-18 11:26 UTC (permalink / raw)
  To: Marek Szyprowski, iommu, linux-samsung-soc, linux-arm-kernel,
	linux-kernel
  Cc: linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae,
	Kukjin Kim, Sylwester Nawrocki, Kyungmin Park

On 05.08.2014 12:47, Marek Szyprowski wrote:
> This patch adds missing smmu_g2d clock implementation and updates
> comment about Exynos4 clocks from 278-282 range. Those clocks are
> available on all Exynos4 SoC series, so the misleading comment has been
> removed.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/clk/samsung/clk-exynos4.c   |  1 +
>  include/dt-bindings/clock/exynos4.h | 10 +++++-----
>  2 files changed, 6 insertions(+), 5 deletions(-)

Acked-by: Tomasz Figa <t.figa@samsung.com>

Best regards,
Tomasz

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
  2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
                   ` (28 preceding siblings ...)
  2014-08-05 10:47 ` [PATCH 29/29] temporary: media: s5p-mfc: add support for IOMMU Marek Szyprowski
@ 2014-08-18 23:32 ` Joerg Roedel
  2014-08-19  6:07   ` Marek Szyprowski
  29 siblings, 1 reply; 50+ messages in thread
From: Joerg Roedel @ 2014-08-18 23:32 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Thierry Reding, Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

On Tue, Aug 05, 2014 at 12:47:28PM +0200, Marek Szyprowski wrote:
>  .../devicetree/bindings/iommu/samsung,sysmmu.txt   |  93 ++-
>  Documentation/power/notifiers.txt                  |  14 +
>  arch/arm/boot/dts/exynos4.dtsi                     | 118 ++++
>  arch/arm/boot/dts/exynos4210.dtsi                  |  23 +
>  arch/arm/boot/dts/exynos4x12.dtsi                  |  82 +++
>  arch/arm/include/asm/dma-iommu.h                   |  36 ++
>  arch/arm/mach-exynos/pm_domains.c                  |  12 +-
>  arch/arm/mach-integrator/impd1.c                   |   2 +-
>  arch/arm/mm/dma-mapping.c                          |  47 ++
>  drivers/base/bus.c                                 |   4 +-
>  drivers/base/dd.c                                  |  10 +-
>  drivers/base/platform.c                            |   2 +-
>  drivers/base/power/domain.c                        |  70 ++-
>  drivers/clk/samsung/clk-exynos4.c                  |   1 +
>  drivers/gpu/drm/exynos/exynos_drm_fimc.c           |   1 +
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  26 +-
>  drivers/gpu/drm/exynos/exynos_drm_g2d.c            |   1 +
>  drivers/gpu/drm/exynos/exynos_drm_gsc.c            |   1 +
>  drivers/gpu/drm/exynos/exynos_drm_rotator.c        |   1 +
>  drivers/gpu/drm/exynos/exynos_mixer.c              |   1 +
>  drivers/iommu/exynos-iommu.c                       | 663 +++++++++++++--------
>  drivers/iommu/iommu.c                              |   3 +
>  drivers/media/platform/s5p-mfc/s5p_mfc.c           | 107 ++--
>  drivers/pci/host/pci-mvebu.c                       |   2 +-
>  drivers/pci/host/pci-rcar-gen2.c                   |   2 +-
>  drivers/pci/host/pci-tegra.c                       |   2 +-
>  drivers/pci/host/pcie-rcar.c                       |   2 +-
>  drivers/soc/tegra/pmc.c                            |   2 +-
>  include/dt-bindings/clock/exynos4.h                |  10 +-
>  include/linux/device.h                             |  12 +-
>  include/linux/iommu.h                              |   1 +
>  include/linux/pm.h                                 |   2 +
>  include/linux/pm_domain.h                          |  19 +
>  33 files changed, 1016 insertions(+), 356 deletions(-)

This touches a lot of non-iommu stuff. What is your strategy on getting
this in, do you plan to get the non-iommu changes merged first or do you
want to collect the respective Acks and merge this all through one tree?


	Joerg


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
  2014-08-18 23:32 ` [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Joerg Roedel
@ 2014-08-19  6:07   ` Marek Szyprowski
  2014-08-19 11:39     ` Andreas Färber
  0 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-19  6:07 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Thierry Reding, Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hello,

On 2014-08-19 01:32, Joerg Roedel wrote:
> On Tue, Aug 05, 2014 at 12:47:28PM +0200, Marek Szyprowski wrote:
>>   .../devicetree/bindings/iommu/samsung,sysmmu.txt   |  93 ++-
>>   Documentation/power/notifiers.txt                  |  14 +
>>   arch/arm/boot/dts/exynos4.dtsi                     | 118 ++++
>>   arch/arm/boot/dts/exynos4210.dtsi                  |  23 +
>>   arch/arm/boot/dts/exynos4x12.dtsi                  |  82 +++
>>   arch/arm/include/asm/dma-iommu.h                   |  36 ++
>>   arch/arm/mach-exynos/pm_domains.c                  |  12 +-
>>   arch/arm/mach-integrator/impd1.c                   |   2 +-
>>   arch/arm/mm/dma-mapping.c                          |  47 ++
>>   drivers/base/bus.c                                 |   4 +-
>>   drivers/base/dd.c                                  |  10 +-
>>   drivers/base/platform.c                            |   2 +-
>>   drivers/base/power/domain.c                        |  70 ++-
>>   drivers/clk/samsung/clk-exynos4.c                  |   1 +
>>   drivers/gpu/drm/exynos/exynos_drm_fimc.c           |   1 +
>>   drivers/gpu/drm/exynos/exynos_drm_fimd.c           |  26 +-
>>   drivers/gpu/drm/exynos/exynos_drm_g2d.c            |   1 +
>>   drivers/gpu/drm/exynos/exynos_drm_gsc.c            |   1 +
>>   drivers/gpu/drm/exynos/exynos_drm_rotator.c        |   1 +
>>   drivers/gpu/drm/exynos/exynos_mixer.c              |   1 +
>>   drivers/iommu/exynos-iommu.c                       | 663 +++++++++++++--------
>>   drivers/iommu/iommu.c                              |   3 +
>>   drivers/media/platform/s5p-mfc/s5p_mfc.c           | 107 ++--
>>   drivers/pci/host/pci-mvebu.c                       |   2 +-
>>   drivers/pci/host/pci-rcar-gen2.c                   |   2 +-
>>   drivers/pci/host/pci-tegra.c                       |   2 +-
>>   drivers/pci/host/pcie-rcar.c                       |   2 +-
>>   drivers/soc/tegra/pmc.c                            |   2 +-
>>   include/dt-bindings/clock/exynos4.h                |  10 +-
>>   include/linux/device.h                             |  12 +-
>>   include/linux/iommu.h                              |   1 +
>>   include/linux/pm.h                                 |   2 +
>>   include/linux/pm_domain.h                          |  19 +
>>   33 files changed, 1016 insertions(+), 356 deletions(-)
> This touches a lot of non-iommu stuff. What is your strategy on getting
> this in, do you plan to get the non-iommu changes merged first or do you
> want to collect the respective Acks and merge this all through one tree?

Those patches are posted as one patchset mainly to demonstrate how to get
everything to work together. I also posted this as a single patch series
to get some feedback from other iommu developers, especially all those
involved in the generic iommu dt bindings.

For merging, I will split them into smaller series and try to get
respective acks.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
  2014-08-19  6:07   ` Marek Szyprowski
@ 2014-08-19 11:39     ` Andreas Färber
  2014-08-19 12:01       ` Marek Szyprowski
  0 siblings, 1 reply; 50+ messages in thread
From: Andreas Färber @ 2014-08-19 11:39 UTC (permalink / raw)
  To: Marek Szyprowski, Inki Dae
  Cc: Joerg Roedel, iommu, linux-samsung-soc, linux-arm-kernel,
	linux-kernel, linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha,
	Cho KyongHo, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Greg Kroah-Hartman, Rafael J. Wysocki, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park, Ajay Kumar

Hi Marek and Inki,

Am 19.08.2014 08:07, schrieb Marek Szyprowski:
> On 2014-08-19 01:32, Joerg Roedel wrote:
>> On Tue, Aug 05, 2014 at 12:47:28PM +0200, Marek Szyprowski wrote:
[...]
>>>   33 files changed, 1016 insertions(+), 356 deletions(-)
>> This touches a lot of non-iommu stuff. What is your strategy on getting
>> this in, do you plan to get the non-iommu changes merged first or do you
>> want to collect the respective Acks and merge this all through one tree?
> 
> Those patches are posted as one patchset mainly to demonstrate how to get
> everything to work together. I also posted this as a single patch series
> to get some feedback from other iommu developers, especially all those
> involved in the generic iommu dt bindings.
> 
> For merging, I will split them into smaller series and try to get
> respective acks.

I'm working on 5250 based Spring Chromebook and noticed that v3.17-rc1
got some more iommu support. With the new CONFIG_DRM_EXYNOS_IOMMU=y my
machine stops booting. So I'm wondering, is any of this a fix for 3.17,
or is all of this "unrelated" -next material? Also, are you or someone
working on the respective DT changes for Exynos5?

Regards,
Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
  2014-08-19 11:39     ` Andreas Färber
@ 2014-08-19 12:01       ` Marek Szyprowski
  2014-08-19 12:30         ` Andreas Färber
  0 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-19 12:01 UTC (permalink / raw)
  To: Andreas Färber, Inki Dae
  Cc: Joerg Roedel, iommu, linux-samsung-soc, linux-arm-kernel,
	linux-kernel, linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha,
	Cho KyongHo, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Greg Kroah-Hartman, Rafael J. Wysocki, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park, Ajay Kumar

Hello,

On 2014-08-19 13:39, Andreas Färber wrote:
> Hi Marek and Inki,
>
> Am 19.08.2014 08:07, schrieb Marek Szyprowski:
>> On 2014-08-19 01:32, Joerg Roedel wrote:
>>> On Tue, Aug 05, 2014 at 12:47:28PM +0200, Marek Szyprowski wrote:
> [...]
>>>>    33 files changed, 1016 insertions(+), 356 deletions(-)
>>> This touches a lot of non-iommu stuff. What is your strategy on getting
>>> this in, do you plan to get the non-iommu changes merged first or do you
>>> want to collect the respective Acks and merge this all through one tree?
>> Those patches are posted as one patchset mainly to demonstrate how to get
>> everything to work together. I also posted this as a single patch series
>> to get some feedback from other iommu developers, especially all those
>> involved in the generic iommu dt bindings.
>>
>> For merging, I will split them into smaller series and try to get
>> respective acks.
> I'm working on 5250 based Spring Chromebook and noticed that v3.17-rc1
> got some more iommu support. With the new CONFIG_DRM_EXYNOS_IOMMU=y my
> machine stops booting. So I'm wondering, is any of this a fix for 3.17,
> or is all of this "unrelated" -next material?

This is probably a side effect of patch 
3170447c1f264d51b8d1f3898bf2588588a64fdc
("iommu/exynos: Select ARM_DMA_USE_IOMMU"). It added selection of 
ARM_DMA_USE_IOMMU
symbol, on which IOMMU support in Exynos DRM subsystem depends. However 
selecting
this symbol is all that this patch does, without providing any code code 
which
implements real support for ARM DMA IOMMU integration, which is needed 
by Exynos
DRM driver. Please disable CONFIG_DRM_EXYNOS_IOMMU in kernel .config and 
your
system should be bootable again.

> Also, are you or someone
> working on the respective DT changes for Exynos5?

I can prepare DT changes for Exynos5 as well, but first I wanted to 
clarify if
everyone involved in generic IOMMU bindings and Exynos IOMMU driver 
agrees on my
proposal.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem
  2014-08-19 12:01       ` Marek Szyprowski
@ 2014-08-19 12:30         ` Andreas Färber
  0 siblings, 0 replies; 50+ messages in thread
From: Andreas Färber @ 2014-08-19 12:30 UTC (permalink / raw)
  To: Marek Szyprowski, Inki Dae
  Cc: Joerg Roedel, iommu, linux-samsung-soc, linux-arm-kernel,
	linux-kernel, linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha,
	Cho KyongHo, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Greg Kroah-Hartman, Rafael J. Wysocki, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park, Ajay Kumar

Hi,

Am 19.08.2014 14:01, schrieb Marek Szyprowski:
> On 2014-08-19 13:39, Andreas Färber wrote:
>> I'm working on 5250 based Spring Chromebook and noticed that v3.17-rc1
>> got some more iommu support. With the new CONFIG_DRM_EXYNOS_IOMMU=y my
>> machine stops booting. So I'm wondering, is any of this a fix for 3.17,
>> or is all of this "unrelated" -next material?
> 
> This is probably a side effect of patch
> 3170447c1f264d51b8d1f3898bf2588588a64fdc
> ("iommu/exynos: Select ARM_DMA_USE_IOMMU"). It added selection of
> ARM_DMA_USE_IOMMU
> symbol, on which IOMMU support in Exynos DRM subsystem depends. However
> selecting
> this symbol is all that this patch does, without providing any code code
> which
> implements real support for ARM DMA IOMMU integration, which is needed
> by Exynos
> DRM driver. Please disable CONFIG_DRM_EXYNOS_IOMMU in kernel .config and
> your
> system should be bootable again.

Yes, that's what my report implied. :)

I'm bringing this up for -rc2 though: It sounds as if that option should
remain unavailable until the required code is in? Thanks.

>> Also, are you or someone
>> working on the respective DT changes for Exynos5?
> 
> I can prepare DT changes for Exynos5 as well, but first I wanted to
> clarify if
> everyone involved in generic IOMMU bindings and Exynos IOMMU driver
> agrees on my
> proposal.

Sure. I'm updating my old spring-bridge.v6 branch [1] to 3.17-rc1 [2],
which involves three drm bridge patches rebased onto the new drm panel
prepare/unprepare infrastructure plus two LVDS DT patches in addition to
the IOMMU patches. That old branch included DT changes for 5250 in "ARM:
dts: add System MMU nodes of Exynos SoCs", but that'll probably need
updating for the new bindings.

Regards,
Andreas

[1] https://github.com/afaerber/linux/commits/spring-bridge.v6
[2] https://github.com/afaerber/linux/commits/spring-next

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind
  2014-08-05 10:47 ` [PATCH 04/29] drivers: base: add notifier for failed driver bind Marek Szyprowski
@ 2014-08-21 19:46   ` Laurent Pinchart
  2014-08-25 20:05   ` Greg Kroah-Hartman
  2014-08-25 21:18   ` Joerg Roedel
  2 siblings, 0 replies; 50+ messages in thread
From: Laurent Pinchart @ 2014-08-21 19:46 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Thierry Reding, Olof Johansson, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hi Marek,

Thank you for the patch.

On Tuesday 05 August 2014 12:47:32 Marek Szyprowski wrote:
> This patch adds support for getting a notify for failed device driver
> bind, so all the items done in BUS_NOTIFY_BIND_DRIVER event can be
> cleaned if the driver fails to bind.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/base/dd.c      | 10 +++++++---
>  include/linux/device.h |  4 +++-
>  2 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index e4ffbcf..541a41f 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -237,10 +237,14 @@ static int driver_sysfs_add(struct device *dev)
>  	return ret;
>  }
> 
> -static void driver_sysfs_remove(struct device *dev)
> +static void driver_sysfs_remove(struct device *dev, int failed)
>  {
>  	struct device_driver *drv = dev->driver;
> 
> +	if (failed && dev->bus)
> +		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
> +					     BUS_NOTIFY_DRVBIND_FAILED, dev);

This might be a stupid question, but as you only call driver_sysfs_remove with 
failed set to true in a single location (in the failure path of really_probe), 
how about moving the blocking_notifier_call_chain to that location ? The code 
seems to be a bit out of place here.

> +
>  	if (drv) {
>  		sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
>  		sysfs_remove_link(&dev->kobj, "driver");
> @@ -316,7 +320,7 @@ static int really_probe(struct device *dev, struct
> device_driver *drv)
> 
>  probe_failed:
>  	devres_release_all(dev);
> -	driver_sysfs_remove(dev);
> +	driver_sysfs_remove(dev, true);
>  	dev->driver = NULL;
>  	dev_set_drvdata(dev, NULL);
> 
> @@ -509,7 +513,7 @@ static void __device_release_driver(struct device *dev)
>  	if (drv) {
>  		pm_runtime_get_sync(dev);
> 
> -		driver_sysfs_remove(dev);
> +		driver_sysfs_remove(dev, false);
> 
>  		if (dev->bus)
>  			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
> diff --git a/include/linux/device.h b/include/linux/device.h
> index b387710..92daded 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -176,7 +176,7 @@ extern int bus_register_notifier(struct bus_type *bus,
>  extern int bus_unregister_notifier(struct bus_type *bus,
>  				   struct notifier_block *nb);
> 
> -/* All 4 notifers below get called with the target struct device *
> +/* All 7 notifers below get called with the target struct device *
>   * as an argument. Note that those functions are likely to be called
>   * with the device lock held in the core, so be careful.
>   */
> @@ -189,6 +189,8 @@ extern int bus_unregister_notifier(struct bus_type *bus,
> unbound */
>  #define BUS_NOTIFY_UNBOUND_DRIVER	0x00000006 /* driver is unbound
>  						      from the device */
> +#define BUS_NOTIFY_DRVBIND_FAILED	0x00000007 /* driver failed to bind
> +						      to device */
> 
>  extern struct kset *bus_get_kset(struct bus_type *bus);
>  extern struct klist *bus_get_device_klist(struct bus_type *bus);

-- 
Regards,

Laurent Pinchart


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind
  2014-08-05 10:47 ` [PATCH 04/29] drivers: base: add notifier for failed driver bind Marek Szyprowski
  2014-08-21 19:46   ` Laurent Pinchart
@ 2014-08-25 20:05   ` Greg Kroah-Hartman
  2014-08-26  6:23     ` Marek Szyprowski
  2014-08-25 21:18   ` Joerg Roedel
  2 siblings, 1 reply; 50+ messages in thread
From: Greg Kroah-Hartman @ 2014-08-25 20:05 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

On Tue, Aug 05, 2014 at 12:47:32PM +0200, Marek Szyprowski wrote:
> This patch adds support for getting a notify for failed device driver
> bind, so all the items done in BUS_NOTIFY_BIND_DRIVER event can be
> cleaned if the driver fails to bind.

But doesn't the bus know if the driver fails to bind, so why would a
notifier be needed here?  Can't it unwind any problems then?

> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/base/dd.c      | 10 +++++++---
>  include/linux/device.h |  4 +++-
>  2 files changed, 10 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index e4ffbcf..541a41f 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -237,10 +237,14 @@ static int driver_sysfs_add(struct device *dev)
>  	return ret;
>  }
>  
> -static void driver_sysfs_remove(struct device *dev)
> +static void driver_sysfs_remove(struct device *dev, int failed)

I _hate_ having functions with a flag that does something different
depending on it.  If you _really_ need this, just make the notifier call
before calling this function, which should work just fine, right?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind
  2014-08-05 10:47 ` [PATCH 04/29] drivers: base: add notifier for failed driver bind Marek Szyprowski
  2014-08-21 19:46   ` Laurent Pinchart
  2014-08-25 20:05   ` Greg Kroah-Hartman
@ 2014-08-25 21:18   ` Joerg Roedel
  2014-08-26  6:30     ` Marek Szyprowski
  2 siblings, 1 reply; 50+ messages in thread
From: Joerg Roedel @ 2014-08-25 21:18 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Thierry Reding, Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

On Tue, Aug 05, 2014 at 12:47:32PM +0200, Marek Szyprowski wrote:
> +	if (failed && dev->bus)
> +		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
> +					     BUS_NOTIFY_DRVBIND_FAILED, dev);
> +

Why can't you just use the notifier for BUS_NOTIFY_UNBIND_DRIVER or
BUS_NOTIFY_UNBOUND_DRIVER when something goes wrong in driver
initialization?


	Joerg


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind
  2014-08-25 20:05   ` Greg Kroah-Hartman
@ 2014-08-26  6:23     ` Marek Szyprowski
  0 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-26  6:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hello,

On 2014-08-25 22:05, Greg Kroah-Hartman wrote:
> On Tue, Aug 05, 2014 at 12:47:32PM +0200, Marek Szyprowski wrote:
>> This patch adds support for getting a notify for failed device driver
>> bind, so all the items done in BUS_NOTIFY_BIND_DRIVER event can be
>> cleaned if the driver fails to bind.
> But doesn't the bus know if the driver fails to bind, so why would a
> notifier be needed here?  Can't it unwind any problems then?

Some other subsystems (like IOMMU) might register its own notifiers on
the given bus. Such notifier is called before driver probe
(BUS_NOTIFY_BIND_DRIVER event), so one can allocate some resources there.
However there is no way to do the cleanup if the driver fails to bind,
because no notifier is called in such case.

>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>> ---
>>   drivers/base/dd.c      | 10 +++++++---
>>   include/linux/device.h |  4 +++-
>>   2 files changed, 10 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
>> index e4ffbcf..541a41f 100644
>> --- a/drivers/base/dd.c
>> +++ b/drivers/base/dd.c
>> @@ -237,10 +237,14 @@ static int driver_sysfs_add(struct device *dev)
>>   	return ret;
>>   }
>>   
>> -static void driver_sysfs_remove(struct device *dev)
>> +static void driver_sysfs_remove(struct device *dev, int failed)
> I _hate_ having functions with a flag that does something different
> depending on it.  If you _really_ need this, just make the notifier call
> before calling this function, which should work just fine, right?

Ok, I will fix this. If I remember correctly I followed the 
driver_sysfs_add()
function pattern, which (surprisingly, especially when one considers only
the function name) also calls the bus notifiers.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 04/29] drivers: base: add notifier for failed driver bind
  2014-08-25 21:18   ` Joerg Roedel
@ 2014-08-26  6:30     ` Marek Szyprowski
  0 siblings, 0 replies; 50+ messages in thread
From: Marek Szyprowski @ 2014-08-26  6:30 UTC (permalink / raw)
  To: Joerg Roedel
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Thierry Reding, Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hello,

On 2014-08-25 23:18, Joerg Roedel wrote:
> On Tue, Aug 05, 2014 at 12:47:32PM +0200, Marek Szyprowski wrote:
>> +	if (failed && dev->bus)
>> +		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
>> +					     BUS_NOTIFY_DRVBIND_FAILED, dev);
>> +
> Why can't you just use the notifier for BUS_NOTIFY_UNBIND_DRIVER or
> BUS_NOTIFY_UNBOUND_DRIVER when something goes wrong in driver
> initialization?

Hmmm, you might be right. BUS_NOTIFY_UNBIND_DRIVER event happens before 
unbinding
the driver, but BUS_NOTIFY_UNBOUND_DRIVER is called when driver remove 
has been
finished, so it can be considered as a symmetrical pair for 
BUS_NOTIFY_BIND_DRIVER.
Driver which registered bus notifiers is mainly interested in doing 
right cleanup,
so the code executed for IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER and
IOMMU_GROUP_NOTIFY_DRVBIND_FAILED is same.

I will remove this additional event and simply add a call to
BUS_NOTIFY_UNBOUND_DRIVER event when driver probe fails.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-08-05 10:47 ` [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag Marek Szyprowski
@ 2014-09-01  5:22   ` Marek Szyprowski
  2014-09-01  7:07     ` Thierry Reding
  0 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-09-01  5:22 UTC (permalink / raw)
  To: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel
  Cc: linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae,
	Kukjin Kim, Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hi Greg,

On 2014-08-05 12:47, Marek Szyprowski wrote:
> This patch adds a new flags for device drivers. This flag instructs
> kernel that the device driver does it own management of IOMMU assisted
> IO address space translations, so no default dma-mapping structures
> should be initialized.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>   include/linux/device.h | 2 ++
>   1 file changed, 2 insertions(+)
>
> diff --git a/include/linux/device.h b/include/linux/device.h
> index 5f4ff02..2e62371 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -253,6 +253,8 @@ struct device_driver {
>   
>   /* disables bind/unbind via sysfs */
>   #define DRIVER_SUPPRESS_BIND_ATTRS	(1 << 0)
> +/* driver uses own methods to manage IO address space */
> +#define DRIVER_HAS_OWN_IOMMU_MANAGER	(1 << 1)
>   
>   extern int __must_check driver_register(struct device_driver *drv);
>   extern void driver_unregister(struct device_driver *drv);

Could you comment if the approach of using flags in the struct driver
could be accepted? I've converted suppress_bind_attrs entry to flags to
avoid extending the structure, please see patch "[PATCH 05/29] drivers:
convert suppress_bind_attrs parameter into flags".

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01  5:22   ` Marek Szyprowski
@ 2014-09-01  7:07     ` Thierry Reding
  2014-09-01  7:53       ` Marek Szyprowski
  0 siblings, 1 reply; 50+ messages in thread
From: Thierry Reding @ 2014-09-01  7:07 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

[-- Attachment #1: Type: text/plain, Size: 1855 bytes --]

On Mon, Sep 01, 2014 at 07:22:32AM +0200, Marek Szyprowski wrote:
> Hi Greg,
> 
> On 2014-08-05 12:47, Marek Szyprowski wrote:
> > This patch adds a new flags for device drivers. This flag instructs
> > kernel that the device driver does it own management of IOMMU assisted
> > IO address space translations, so no default dma-mapping structures
> > should be initialized.
> >
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> > ---
> >   include/linux/device.h | 2 ++
> >   1 file changed, 2 insertions(+)
> >
> > diff --git a/include/linux/device.h b/include/linux/device.h
> > index 5f4ff02..2e62371 100644
> > --- a/include/linux/device.h
> > +++ b/include/linux/device.h
> > @@ -253,6 +253,8 @@ struct device_driver {
> >   
> >   /* disables bind/unbind via sysfs */
> >   #define DRIVER_SUPPRESS_BIND_ATTRS	(1 << 0)
> > +/* driver uses own methods to manage IO address space */
> > +#define DRIVER_HAS_OWN_IOMMU_MANAGER	(1 << 1)
> >   
> >   extern int __must_check driver_register(struct device_driver *drv);
> >   extern void driver_unregister(struct device_driver *drv);
> 
> Could you comment if the approach of using flags in the struct driver
> could be accepted? I've converted suppress_bind_attrs entry to flags to
> avoid extending the structure, please see patch "[PATCH 05/29] drivers:
> convert suppress_bind_attrs parameter into flags".

Is this really necessary? What I did as part of an RFC series for Tegra
IOMMU support is keep this knowledge within the IOMMU driver rather than
export it to the driver core.

The idea being that the IOMMU driver wouldn't create an ARM DMA/IOMMU
mapping by default but rather allow individual drivers to be marked as
"kernel-internal" and use the DMA/IOMMU glue in that case. Drivers such
as DRM would use the IOMMU API directly.

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01  7:07     ` Thierry Reding
@ 2014-09-01  7:53       ` Marek Szyprowski
  2014-09-01  9:38         ` Arnd Bergmann
  0 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-09-01  7:53 UTC (permalink / raw)
  To: Thierry Reding
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Olof Johansson, Laurent Pinchart, Rob Herring,
	Greg Kroah-Hartman, Rafael J. Wysocki, Inki Dae, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hello,

On 2014-09-01 09:07, Thierry Reding wrote:
> On Mon, Sep 01, 2014 at 07:22:32AM +0200, Marek Szyprowski wrote:
>> Hi Greg,
>>
>> On 2014-08-05 12:47, Marek Szyprowski wrote:
>>> This patch adds a new flags for device drivers. This flag instructs
>>> kernel that the device driver does it own management of IOMMU assisted
>>> IO address space translations, so no default dma-mapping structures
>>> should be initialized.
>>>
>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>> ---
>>>    include/linux/device.h | 2 ++
>>>    1 file changed, 2 insertions(+)
>>>
>>> diff --git a/include/linux/device.h b/include/linux/device.h
>>> index 5f4ff02..2e62371 100644
>>> --- a/include/linux/device.h
>>> +++ b/include/linux/device.h
>>> @@ -253,6 +253,8 @@ struct device_driver {
>>>    
>>>    /* disables bind/unbind via sysfs */
>>>    #define DRIVER_SUPPRESS_BIND_ATTRS	(1 << 0)
>>> +/* driver uses own methods to manage IO address space */
>>> +#define DRIVER_HAS_OWN_IOMMU_MANAGER	(1 << 1)
>>>    
>>>    extern int __must_check driver_register(struct device_driver *drv);
>>>    extern void driver_unregister(struct device_driver *drv);
>> Could you comment if the approach of using flags in the struct driver
>> could be accepted? I've converted suppress_bind_attrs entry to flags to
>> avoid extending the structure, please see patch "[PATCH 05/29] drivers:
>> convert suppress_bind_attrs parameter into flags".
> Is this really necessary? What I did as part of an RFC series for Tegra
> IOMMU support is keep this knowledge within the IOMMU driver rather than
> export it to the driver core.i

The problem with embedding the list of drivers that you would need to update
it everytime when you modify or extend iommu support in the other drivers.
I've tried also other approach, like adding respective notifiers to 
individual
drivers to initialize custom iommu support (or disable default iommu 
mapping)
before iommu driver gets initialized, but such solution is in my opinion too
complex and hard to understand if one is not familiar will all this stuff.

All in all it turned out that the simplest and most generic way is to simply
add the flag to the driver core. Flags might be also used in the future
to model other kinds of dependencies between device drivers and/or driver
core.

> The idea being that the IOMMU driver wouldn't create an ARM DMA/IOMMU
> mapping by default but rather allow individual drivers to be marked as
> "kernel-internal" and use the DMA/IOMMU glue in that case. Drivers such
> as DRM would use the IOMMU API directly.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01  7:53       ` Marek Szyprowski
@ 2014-09-01  9:38         ` Arnd Bergmann
  2014-09-01 10:47           ` Marek Szyprowski
  0 siblings, 1 reply; 50+ messages in thread
From: Arnd Bergmann @ 2014-09-01  9:38 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Marek Szyprowski, Thierry Reding, Rob Herring, linux-samsung-soc,
	Shaik Ameer Basha, Inki Dae, Greg Kroah-Hartman, Joerg Roedel,
	Rafael J. Wysocki, linux-kernel, Tomasz Figa, linaro-mm-sig,
	iommu, Kukjin Kim, Laurent Pinchart, Sylwester Nawrocki,
	Olof Johansson, Kyungmin Park, Cho KyongHo

On Monday 01 September 2014 09:53:29 Marek Szyprowski wrote:
> On 2014-09-01 09:07, Thierry Reding wrote:
> > On Mon, Sep 01, 2014 at 07:22:32AM +0200, Marek Szyprowski wrote:
> >> Hi Greg,
> >>
> >> On 2014-08-05 12:47, Marek Szyprowski wrote:
> >>> This patch adds a new flags for device drivers. This flag instructs
> >>> kernel that the device driver does it own management of IOMMU assisted
> >>> IO address space translations, so no default dma-mapping structures
> >>> should be initialized.
> >>>
> >>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> >>> ---
> >>>    include/linux/device.h | 2 ++
> >>>    1 file changed, 2 insertions(+)
> >>>
> >>> diff --git a/include/linux/device.h b/include/linux/device.h
> >>> index 5f4ff02..2e62371 100644
> >>> --- a/include/linux/device.h
> >>> +++ b/include/linux/device.h
> >>> @@ -253,6 +253,8 @@ struct device_driver {
> >>>    
> >>>    /* disables bind/unbind via sysfs */
> >>>    #define DRIVER_SUPPRESS_BIND_ATTRS       (1 << 0)
> >>> +/* driver uses own methods to manage IO address space */
> >>> +#define DRIVER_HAS_OWN_IOMMU_MANAGER       (1 << 1)
> >>>    
> >>>    extern int __must_check driver_register(struct device_driver *drv);
> >>>    extern void driver_unregister(struct device_driver *drv);
> >> Could you comment if the approach of using flags in the struct driver
> >> could be accepted? I've converted suppress_bind_attrs entry to flags to
> >> avoid extending the structure, please see patch "[PATCH 05/29] drivers:
> >> convert suppress_bind_attrs parameter into flags".
> > Is this really necessary? What I did as part of an RFC series for Tegra
> > IOMMU support is keep this knowledge within the IOMMU driver rather than
> > export it to the driver core.i
> 
> The problem with embedding the list of drivers that you would need to update
> it everytime when you modify or extend iommu support in the other drivers.
> I've tried also other approach, like adding respective notifiers to 
> individual
> drivers to initialize custom iommu support (or disable default iommu 
> mapping)
> before iommu driver gets initialized, but such solution is in my opinion too
> complex and hard to understand if one is not familiar will all this stuff.
> 
> All in all it turned out that the simplest and most generic way is to simply
> add the flag to the driver core. Flags might be also used in the future
> to model other kinds of dependencies between device drivers and/or driver
> core.

I don't get it yet. I would expect that a driver doing its own management
of the iommu gets to use the linux/iommu.h interfaces, while a driver
using the default iommu setup uses linux/dma-mapping.h. Who do you think
needs to set this flag, and who needs to read it?

	Arnd

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01  9:38         ` Arnd Bergmann
@ 2014-09-01 10:47           ` Marek Szyprowski
  2014-09-01 11:56             ` Arnd Bergmann
  0 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-09-01 10:47 UTC (permalink / raw)
  To: Arnd Bergmann, linux-arm-kernel
  Cc: Thierry Reding, Rob Herring, linux-samsung-soc,
	Shaik Ameer Basha, Inki Dae, Greg Kroah-Hartman, Joerg Roedel,
	Rafael J. Wysocki, linux-kernel, Tomasz Figa, linaro-mm-sig,
	iommu, Kukjin Kim, Laurent Pinchart, Sylwester Nawrocki,
	Olof Johansson, Kyungmin Park, Cho KyongHo

Hello,

On 2014-09-01 11:38, Arnd Bergmann wrote:
> On Monday 01 September 2014 09:53:29 Marek Szyprowski wrote:
>> On 2014-09-01 09:07, Thierry Reding wrote:
>>> On Mon, Sep 01, 2014 at 07:22:32AM +0200, Marek Szyprowski wrote:
>>>> Hi Greg,
>>>>
>>>> On 2014-08-05 12:47, Marek Szyprowski wrote:
>>>>> This patch adds a new flags for device drivers. This flag instructs
>>>>> kernel that the device driver does it own management of IOMMU assisted
>>>>> IO address space translations, so no default dma-mapping structures
>>>>> should be initialized.
>>>>>
>>>>> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>>>>> ---
>>>>>     include/linux/device.h | 2 ++
>>>>>     1 file changed, 2 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/device.h b/include/linux/device.h
>>>>> index 5f4ff02..2e62371 100644
>>>>> --- a/include/linux/device.h
>>>>> +++ b/include/linux/device.h
>>>>> @@ -253,6 +253,8 @@ struct device_driver {
>>>>>     
>>>>>     /* disables bind/unbind via sysfs */
>>>>>     #define DRIVER_SUPPRESS_BIND_ATTRS       (1 << 0)
>>>>> +/* driver uses own methods to manage IO address space */
>>>>> +#define DRIVER_HAS_OWN_IOMMU_MANAGER       (1 << 1)
>>>>>     
>>>>>     extern int __must_check driver_register(struct device_driver *drv);
>>>>>     extern void driver_unregister(struct device_driver *drv);
>>>> Could you comment if the approach of using flags in the struct driver
>>>> could be accepted? I've converted suppress_bind_attrs entry to flags to
>>>> avoid extending the structure, please see patch "[PATCH 05/29] drivers:
>>>> convert suppress_bind_attrs parameter into flags".
>>> Is this really necessary? What I did as part of an RFC series for Tegra
>>> IOMMU support is keep this knowledge within the IOMMU driver rather than
>>> export it to the driver core.i
>> The problem with embedding the list of drivers that you would need to update
>> it everytime when you modify or extend iommu support in the other drivers.
>> I've tried also other approach, like adding respective notifiers to
>> individual
>> drivers to initialize custom iommu support (or disable default iommu
>> mapping)
>> before iommu driver gets initialized, but such solution is in my opinion too
>> complex and hard to understand if one is not familiar will all this stuff.
>>
>> All in all it turned out that the simplest and most generic way is to simply
>> add the flag to the driver core. Flags might be also used in the future
>> to model other kinds of dependencies between device drivers and/or driver
>> core.
> I don't get it yet. I would expect that a driver doing its own management
> of the iommu gets to use the linux/iommu.h interfaces, while a driver
> using the default iommu setup uses linux/dma-mapping.h.

You are right.

> Who do you think needs to set this flag, and who needs to read it?

In the proposed solution Exynos IOMMU driver creates a separate IO 
address space
for every client device in a system and binds it to the default 
dma-mapping space
for the given device. When drivers are doing its own management of IO 
address
space, instead of relying on what is available by default with dma-mapping
interface, this will require releasing of the previously created default
structures and resources. So this flag is set by the driver doing its own
management of io address space. The flags is then checked by Exynos 
IOMMU driver
to avoid creating the default dma-mapping address space for devices 
which driver
does its own management.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01 10:47           ` Marek Szyprowski
@ 2014-09-01 11:56             ` Arnd Bergmann
  2014-09-01 12:07               ` Marek Szyprowski
  0 siblings, 1 reply; 50+ messages in thread
From: Arnd Bergmann @ 2014-09-01 11:56 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: linux-arm-kernel, Thierry Reding, Rob Herring, linux-samsung-soc,
	Shaik Ameer Basha, Inki Dae, Greg Kroah-Hartman, Joerg Roedel,
	Rafael J. Wysocki, linux-kernel, Tomasz Figa, linaro-mm-sig,
	iommu, Kukjin Kim, Laurent Pinchart, Sylwester Nawrocki,
	Olof Johansson, Kyungmin Park, Cho KyongHo

On Monday 01 September 2014 12:47:08 Marek Szyprowski wrote:
> > Who do you think needs to set this flag, and who needs to read it?
> 
> In the proposed solution Exynos IOMMU driver creates a separate IO 
> address space
> for every client device in a system and binds it to the default 
> dma-mapping space
> for the given device. When drivers are doing its own management of IO 
> address
> space, instead of relying on what is available by default with dma-mapping
> interface, this will require releasing of the previously created default
> structures and resources. So this flag is set by the driver doing its own
> management of io address space. The flags is then checked by Exynos 
> IOMMU driver
> to avoid creating the default dma-mapping address space for devices 
> which driver
> does its own management.

I don't completely understand it yet. I would assume the device
to be added to the default domain at device creation time
(of_platform_populate), way before we know which device driver
is going to be used. How can this prevent the iommu driver
from doing the association with the domain?

	Arnd

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01 11:56             ` Arnd Bergmann
@ 2014-09-01 12:07               ` Marek Szyprowski
  2014-09-01 13:14                 ` [Linaro-mm-sig] " Arnd Bergmann
  0 siblings, 1 reply; 50+ messages in thread
From: Marek Szyprowski @ 2014-09-01 12:07 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Thierry Reding, Rob Herring, linux-samsung-soc,
	Shaik Ameer Basha, Inki Dae, Greg Kroah-Hartman, Joerg Roedel,
	Rafael J. Wysocki, linux-kernel, Tomasz Figa, linaro-mm-sig,
	iommu, Kukjin Kim, Laurent Pinchart, Sylwester Nawrocki,
	Olof Johansson, Kyungmin Park, Cho KyongHo

Hello,

On 2014-09-01 13:56, Arnd Bergmann wrote:
> On Monday 01 September 2014 12:47:08 Marek Szyprowski wrote:
>>> Who do you think needs to set this flag, and who needs to read it?
>> In the proposed solution Exynos IOMMU driver creates a separate IO
>> address space
>> for every client device in a system and binds it to the default
>> dma-mapping space
>> for the given device. When drivers are doing its own management of IO
>> address
>> space, instead of relying on what is available by default with dma-mapping
>> interface, this will require releasing of the previously created default
>> structures and resources. So this flag is set by the driver doing its own
>> management of io address space. The flags is then checked by Exynos
>> IOMMU driver
>> to avoid creating the default dma-mapping address space for devices
>> which driver
>> does its own management.
> I don't completely understand it yet. I would assume the device
> to be added to the default domain at device creation time
> (of_platform_populate), way before we know which device driver
> is going to be used. How can this prevent the iommu driver
> from doing the association with the domain?

of_platform_populate() is too early to do the association, because that 
time the
exynos iommu driver is even not yet probed.

The association with default dma-mapping domain is done in
IOMMU_GROUP_NOTIFY_BIND_DRIVER notifier, just before binding the driver 
to the
given device. This way iommu driver can check dev->driver->flags and 
skip creating
default dma-mapping domain if driver announces that it wants to handle it by
itself.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [Linaro-mm-sig] [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag
  2014-09-01 12:07               ` Marek Szyprowski
@ 2014-09-01 13:14                 ` Arnd Bergmann
  0 siblings, 0 replies; 50+ messages in thread
From: Arnd Bergmann @ 2014-09-01 13:14 UTC (permalink / raw)
  To: linaro-mm-sig
  Cc: Marek Szyprowski, Rob Herring, linux-samsung-soc,
	Shaik Ameer Basha, Greg Kroah-Hartman, Joerg Roedel,
	Rafael J. Wysocki, linux-kernel, Cho KyongHo, Tomasz Figa,
	Inki Dae, iommu, Kukjin Kim, Laurent Pinchart,
	Sylwester Nawrocki, Olof Johansson, Kyungmin Park,
	Thierry Reding, linux-arm-kernel, will.deacon

On Monday 01 September 2014 14:07:34 Marek Szyprowski wrote:
> On 2014-09-01 13:56, Arnd Bergmann wrote:
> > On Monday 01 September 2014 12:47:08 Marek Szyprowski wrote:
> >>> Who do you think needs to set this flag, and who needs to read it?
> >> In the proposed solution Exynos IOMMU driver creates a separate IO
> >> address space
> >> for every client device in a system and binds it to the default
> >> dma-mapping space
> >> for the given device. When drivers are doing its own management of IO
> >> address
> >> space, instead of relying on what is available by default with dma-mapping
> >> interface, this will require releasing of the previously created default
> >> structures and resources. So this flag is set by the driver doing its own
> >> management of io address space. The flags is then checked by Exynos
> >> IOMMU driver
> >> to avoid creating the default dma-mapping address space for devices
> >> which driver
> >> does its own management.
> > I don't completely understand it yet. I would assume the device
> > to be added to the default domain at device creation time
> > (of_platform_populate), way before we know which device driver
> > is going to be used. How can this prevent the iommu driver
> > from doing the association with the domain?
> 
> of_platform_populate() is too early to do the association, because that 
> time the
> exynos iommu driver is even not yet probed.

Please have a look at the "Introduce automatic DMA configuration for IOMMU
masters" series that Will Deacon sent out the other day. The idea is that
we are changing the probe order so that the iommu gets initialized early
enough for all IOMMU association to be done there.

> The association with default dma-mapping domain is done in
> IOMMU_GROUP_NOTIFY_BIND_DRIVER notifier, just before binding the driver 
> to the
> given device. This way iommu driver can check dev->driver->flags and 
> skip creating
> default dma-mapping domain if driver announces that it wants to handle it by
> itself.

I really want to kill off those notifiers.

	Arnd

^ permalink raw reply	[flat|nested] 50+ messages in thread

* Re: [PATCH 12/29] DRM: Exynos: fix window clear code
  2014-08-05 10:47 ` [PATCH 12/29] DRM: Exynos: fix window clear code Marek Szyprowski
@ 2014-09-01 13:37   ` Inki Dae
  0 siblings, 0 replies; 50+ messages in thread
From: Inki Dae @ 2014-09-01 13:37 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: iommu, linux-samsung-soc, linux-arm-kernel, linux-kernel,
	linaro-mm-sig, Arnd Bergmann, Shaik Ameer Basha, Cho KyongHo,
	Joerg Roedel, Thierry Reding, Olof Johansson, Laurent Pinchart,
	Rob Herring, Greg Kroah-Hartman, Rafael J. Wysocki, Kukjin Kim,
	Sylwester Nawrocki, Tomasz Figa, Kyungmin Park

Hi Marek,

On 2014년 08월 05일 19:47, Marek Szyprowski wrote:
> To correctly disable hardware window during driver init, both enable bits
> (WINCONx_ENWIN in WINCON and SHADOWCON_CHx_ENABLE in SHADOWCON) must be
> cleared, otherwise hardware fails to re-enable such window later.
> 
> While touching this function, also temporarily disable ctx->suspended flag
> to let fimd_wait_for_vblank function really to do its job.
> 
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
>  drivers/gpu/drm/exynos/exynos_drm_fimd.c | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> index 41904df..7a363d2 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
> @@ -165,27 +165,38 @@ static void fimd_wait_for_vblank(struct exynos_drm_manager *mgr)
>  		DRM_DEBUG_KMS("vblank wait timed out.\n");
>  }
>  
> -
>  static void fimd_clear_channel(struct exynos_drm_manager *mgr)
>  {
>  	struct fimd_context *ctx = mgr->ctx;
> -	int win, ch_enabled = 0;
> +	int state, win, ch_enabled = 0;

It doesn't need to declare state variable here because this variable is
used only when ch_enabled is 1.

>  
>  	DRM_DEBUG_KMS("%s\n", __FILE__);
>  
>  	/* Check if any channel is enabled. */
>  	for (win = 0; win < WINDOWS_NR; win++) {
> -		u32 val = readl(ctx->regs + SHADOWCON);
> -		if (val & SHADOWCON_CHx_ENABLE(win)) {
> -			val &= ~SHADOWCON_CHx_ENABLE(win);
> -			writel(val, ctx->regs + SHADOWCON);
> +		u32 val = readl(ctx->regs + WINCON(win));

WARNING: Missing a blank line after declarations

> +		if (val & WINCONx_ENWIN) {
> +			/* wincon */
> +			val &= ~WINCONx_ENWIN;
> +			writel(val, ctx->regs + WINCON(win));
> +
> +			/* unprotect windows */
> +			if (ctx->driver_data->has_shadowcon) {
> +				val = readl(ctx->regs + SHADOWCON);
> +				val &= ~SHADOWCON_CHx_ENABLE(win);
> +				writel(val, ctx->regs + SHADOWCON);
> +			}
>  			ch_enabled = 1;
>  		}
>  	}
>  
>  	/* Wait for vsync, as disable channel takes effect at next vsync */
> -	if (ch_enabled)
> +	if (ch_enabled) {
> +		state = ctx->suspended;

int state = ctx->suspended;

> +		ctx->suspended = 0;
>  		fimd_wait_for_vblank(mgr);
> +		ctx->suspended = state;
> +	}
>  }
>  
>  static int fimd_mgr_initialize(struct exynos_drm_manager *mgr,
> 

Above is trivial so I fixed them. Picked it up.

Thanks,
Inki Dae




^ permalink raw reply	[flat|nested] 50+ messages in thread

end of thread, other threads:[~2014-09-01 13:37 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-05 10:47 [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Marek Szyprowski
2014-08-05 10:47 ` [PATCH 01/29] pm: Add PM domain notifications Marek Szyprowski
2014-08-05 10:47 ` [PATCH 02/29] ARM: Exynos: bind power domains earlier, on device creation Marek Szyprowski
2014-08-05 10:47 ` [PATCH 03/29] clk: exynos: add missing smmu_g2d clock and update comments Marek Szyprowski
2014-08-18 11:26   ` Tomasz Figa
2014-08-05 10:47 ` [PATCH 04/29] drivers: base: add notifier for failed driver bind Marek Szyprowski
2014-08-21 19:46   ` Laurent Pinchart
2014-08-25 20:05   ` Greg Kroah-Hartman
2014-08-26  6:23     ` Marek Szyprowski
2014-08-25 21:18   ` Joerg Roedel
2014-08-26  6:30     ` Marek Szyprowski
2014-08-05 10:47 ` [PATCH 05/29] drivers: convert suppress_bind_attrs parameter into flags Marek Szyprowski
2014-08-05 10:47 ` [PATCH 06/29] drivers: iommu: add notify about failed bind Marek Szyprowski
2014-08-05 10:47 ` [PATCH 07/29] ARM: dma-mapping: arm_iommu_attach_device: automatically set max_seg_size Marek Szyprowski
2014-08-05 10:47 ` [PATCH 08/29] ARM: dma-mapping: add helpers for managing default per-device dma mappings Marek Szyprowski
2014-08-05 10:47 ` [PATCH 09/29] ARM: dma-mapping: provide stubs if no ARM_DMA_USE_IOMMU has been selected Marek Szyprowski
2014-08-05 10:47 ` [PATCH 10/29] drivers: add DRIVER_HAS_OWN_IOMMU_MANAGER flag Marek Szyprowski
2014-09-01  5:22   ` Marek Szyprowski
2014-09-01  7:07     ` Thierry Reding
2014-09-01  7:53       ` Marek Szyprowski
2014-09-01  9:38         ` Arnd Bergmann
2014-09-01 10:47           ` Marek Szyprowski
2014-09-01 11:56             ` Arnd Bergmann
2014-09-01 12:07               ` Marek Szyprowski
2014-09-01 13:14                 ` [Linaro-mm-sig] " Arnd Bergmann
2014-08-05 10:47 ` [PATCH 11/29] DRM: exynos: add DRIVER_HAS_OWN_IOMMU_MANAGER flag to all sub-drivers Marek Szyprowski
2014-08-05 10:47 ` [PATCH 12/29] DRM: Exynos: fix window clear code Marek Szyprowski
2014-09-01 13:37   ` Inki Dae
2014-08-05 10:47 ` [PATCH 13/29] temporary: media: s5p-mfc: remove DT hacks & initialization custom memory init code Marek Szyprowski
2014-08-05 10:47 ` [PATCH 14/29] devicetree: Update Exynos SYSMMU device tree bindings Marek Szyprowski
2014-08-05 10:47 ` [PATCH 15/29] ARM: DTS: Exynos4: add System MMU nodes Marek Szyprowski
2014-08-05 10:47 ` [PATCH 16/29] iommu: exynos: make driver multiarch friendly Marek Szyprowski
2014-08-05 10:47 ` [PATCH 17/29] iommu: exynos: don't read version register on every tlb operation Marek Szyprowski
2014-08-05 10:47 ` [PATCH 18/29] iommu: exynos: remove unused functions Marek Szyprowski
2014-08-05 10:47 ` [PATCH 19/29] iommu: exynos: remove useless spinlock Marek Szyprowski
2014-08-05 10:47 ` [PATCH 20/29] iommu: exynos: refactor function parameters to simplify code Marek Szyprowski
2014-08-05 10:47 ` [PATCH 21/29] iommu: exynos: remove unused functions, part 2 Marek Szyprowski
2014-08-05 10:47 ` [PATCH 22/29] iommu: exynos: add support for binding more than one sysmmu to master device Marek Szyprowski
2014-08-05 10:47 ` [PATCH 23/29] iommu: exynos: init iommu controllers from device tree Marek Szyprowski
2014-08-05 10:47 ` [PATCH 24/29] iommu: exynos: create default iommu-based dma-mapping for master devices Marek Szyprowski
2014-08-05 10:47 ` [PATCH 25/29] iommu: exynos: add support for runtime_pm Marek Szyprowski
2014-08-05 10:47 ` [PATCH 26/29] iommu: exynos: rename variables to reflect their purpose Marek Szyprowski
2014-08-05 10:47 ` [PATCH 27/29] iommu: exynos: document internal structures Marek Szyprowski
2014-08-05 10:47 ` [PATCH 28/29] iommu: exynos: remove excessive includes and sort others alphabetically Marek Szyprowski
2014-08-05 10:47 ` [PATCH 29/29] temporary: media: s5p-mfc: add support for IOMMU Marek Szyprowski
2014-08-18 23:32 ` [PATCH 00/29] Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem Joerg Roedel
2014-08-19  6:07   ` Marek Szyprowski
2014-08-19 11:39     ` Andreas Färber
2014-08-19 12:01       ` Marek Szyprowski
2014-08-19 12:30         ` Andreas Färber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).