Re: [PATCH V10 00/12] IOMMU probe deferral support

2017-04-04 Thread Rob Herring
On Tue, Apr 4, 2017 at 5:18 AM, Sricharan R  wrote:
> This series calls the dma ops configuration for the devices
> at a generic place so that it works for all busses.
> The dma_configure_ops for a device is now called during
> the device_attach callback just before the probe of the
> bus/driver is called. Similarly dma_deconfigure is called during
> device/driver_detach path.

For patches 3, 4, 6, 7, 8:

Acked-by: Rob Herring 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V3 0/5] iommu/arm-smmu: Add runtime pm/sleep support

2017-04-04 Thread Stephen Boyd
On 04/03, Will Deacon wrote:
> On Fri, Mar 31, 2017 at 10:58:16PM -0400, Rob Clark wrote:
> > On Fri, Mar 31, 2017 at 1:54 PM, Will Deacon  wrote:
> > > On Thu, Mar 09, 2017 at 09:05:43PM +0530, Sricharan R wrote:
> > >> This series provides the support for turning on the arm-smmu's
> > >> clocks/power domains using runtime pm. This is done using the
> > >> recently introduced device links patches, which lets the symmu's
> > >> runtime to follow the master's runtime pm, so the smmu remains
> > >> powered only when the masters use it.
> > >
> > > Do you have any numbers for the power savings you achieve with this?
> > > How often do we actually manage to stop the SMMU clocks on an SoC with
> > > a handful of masters?
> > >
> > > In other words, is this too coarse-grained to be useful, or is it common
> > > that all the devices upstream of the SMMU are suspended?
> > 
> > well, if you think about a phone/tablet with a command mode panel,
> > pretty much all devices will be suspended most of the time ;-)
> 
> Well, that's really what I was asking about. I assumed that periodic
> modem/radio transactions would keep the SMMU clocked, so would like to get a
> rough idea of the power savings achieved with this coarse-grained approach.

Sometimes we distribute SMMUs to each IP block in the system and
let each one of those live in their own clock + power domain. In
these cases, the SMMU can be powered down along with the only IP
block that uses it. Furthermore, sometimes we put the IP block
and the SMMU inside the same power domain to really tie the two
together, so we definitely have cases where all devices (device?)
upstream of the SMMU are suspended. And in the case of
multimedia, it could be very often that something like the camera
app isn't open and thus the SMMU dedicated for the camera can be
powered down.

Other times we have two SMMUs in the system where one is
dedicated to GPU and the other is "everything else". Even in
these cases, we can suspend the GPU one when the GPU is inactive
because it's the only consumer. The other SMMU might not be as
fine grained, but I think we still power it down quite often
because the consumers are mostly multimedia devices that aren't
active when the display is off.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC] PCI ACS Flags Clarification

2017-04-04 Thread Alex Williamson
On Tue, 4 Apr 2017 14:47:58 -0400
Sinan Kaya  wrote:

> I'm looking for a guideline on how Access Control Services (ACS) need to be
> implemented in HW for cases where peer to peer is and isn't supported.
> 
> I see conflicting information in the code. 
> 
> iommu.c calls pci_acs_enabled() from pci_device_group() to determine if
> ACS path is enabled for the following flags.
> 
> This paragraph lays out the requirements. 
> 
>  /*
>   * To consider a PCI device isolated, we require ACS to support Source
>   * Validation, Request Redirection, Completer Redirection, and Upstream
>   * Forwarding.  This effectively means that devices cannot spoof their
>   * requester ID, requests and completions cannot be redirected, and all
>   * transactions are forwarded upstream, even as it passes through a
>   * bridge where the target device is downstream.
>   */
> #define REQ_ACS_FLAGS   (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)
> 
> I also see the following comment in pci_acs_flags_enabled() which gets
> called from pci_acs_enabled()
> 
> /*
>  * Except for egress control, capabilities are either required
>  * or only required if controllable.  Features missing from the
>  * capability field can therefore be assumed as hard-wired enabled.
>  */
> 
> This comment in pci_acs_flags_enabled() is confusing. A capability that reads
> 0 usually means it is not enabled. This code is assuming enabled. 
> Are we trying to say that we'll use the capability bits as a mask while
> verifying the requested ACS flags?

See the language in the PCIe spec:

6.12.1.1. ACS Downstream Ports

- ACS Source Validation: must be implemented.

- ACS Translation Blocking: must be implemented.

- ACS P2P Request Redirect: must be implemented by Root Ports that
  support peer-to-peer traffic with other Root Ports; must be
  implemented by Switch Downstream Ports. 

- ACS P2P Completion Redirect: must be implemented by Root Ports that
  implement ACS P2P Request Redirect; must be implemented by Switch
  Downstream Ports.

- ACS Upstream Forwarding: must be implemented by Root Ports if the RC
  supports Redirected Request Validation; must be implemented by Switch
  Downstream Ports.

- ACS P2P Egress Control: implementation is optional.

Thus for a downstream port, SV and TB must be implemented, period.

RR, CR, and UF must be implemented by switch downstream ports, period.

On a root port, if RR is not implemented, we can assume it does not
support P2P with other root ports.

If the root port supports RR, it must also support CR and UF.

The kernel code takes a bit of a lax approach to this with the items
you've identified above, we assume that if a capability isn't present
then the device is compliant to the spec and not trying to circumvent
it.  It's a generalization trying to also encompass other component
types.


> For systems that don't support P2P, the code will check PCI_ACS_SV
>   only. So, if I summarize this correctly;

For a downstream port or downstream switch port, this would not be spec
compliant.  TB would need to be implemented for either (not that the
kernel cares for isolation) and all except EC would need to be
implemented on a downstream switch port.

> The requirement is to have an 
> 1. ACS capability with PCI_ACS_SV if p2p is not supported
> 2. ACS capability with PCI_ACS_SV|PCI_ACS_RR | PCI_ACS_CR |
>   PCI_ACS_UF if p2p is supported.
> 
> Did I get this right?

I'd suggest following the spec, not the code, that way you always have a
case for how you interpret the spec and the behavior of your hardware.
The code is an attempt to validate the device against the spec, but more
thorough implementations may follow.  REQ_ACS_FLAGS defines the set of
ACS capabilities we think are relevant to device isolation.  In
particular, UF seems like a key feature and our current test for it may
not be fully correct.  Note how RR and CR only specify p2p with other
root ports while UF requires transaction towards to the RC.  Section
6.12.2 further defines Redirected Request Validation as a feature
within the context of RR and CR.  So rather than look at the code,
discuss section 6.12 with the hardware engineers and understand how it
behaves relative to each device and transaction type.  Implement the
capabilities that best match.  Attempting a minimal implementation
based on the current software interpretation may bite later, for
instance if we re-interpret how UF works.  Thanks,

Alex
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[RFC] PCI ACS Flags Clarification

2017-04-04 Thread Sinan Kaya
I'm looking for a guideline on how Access Control Services (ACS) need to be
implemented in HW for cases where peer to peer is and isn't supported.

I see conflicting information in the code. 

iommu.c calls pci_acs_enabled() from pci_device_group() to determine if
ACS path is enabled for the following flags.

This paragraph lays out the requirements. 

 /*
  * To consider a PCI device isolated, we require ACS to support Source
  * Validation, Request Redirection, Completer Redirection, and Upstream
  * Forwarding.  This effectively means that devices cannot spoof their
  * requester ID, requests and completions cannot be redirected, and all
  * transactions are forwarded upstream, even as it passes through a
  * bridge where the target device is downstream.
  */
#define REQ_ACS_FLAGS   (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF)

I also see the following comment in pci_acs_flags_enabled() which gets
called from pci_acs_enabled()

/*
 * Except for egress control, capabilities are either required
 * or only required if controllable.  Features missing from the
 * capability field can therefore be assumed as hard-wired enabled.
 */

This comment in pci_acs_flags_enabled() is confusing. A capability that reads
0 usually means it is not enabled. This code is assuming enabled. 
Are we trying to say that we'll use the capability bits as a mask while
verifying the requested ACS flags?

For systems that don't support P2P, the code will check PCI_ACS_SV only. 
So, if I summarize this correctly;

The requirement is to have an 
1. ACS capability with PCI_ACS_SV if p2p is not supported
2. ACS capability with PCI_ACS_SV|PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF if p2p
is supported.

Did I get this right?

-- 
Sinan Kaya
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 2/2] PCI: quirks: Fix ThunderX2 dma alias handling

2017-04-04 Thread Robin Murphy
On 04/04/17 12:50, Jayachandran C wrote:
> On Mon, Apr 03, 2017 at 04:07:53PM +0100, Robin Murphy wrote:
>> On 03/04/17 14:15, Jayachandran C wrote:
>>> The Cavium ThunderX2 arm64 SoCs (called Broadcom Vulcan earlier), the PCI
>>> topology is slightly unusual. For a multi-node system, it looks like:
>>>
>>> [node level PCI bridges - one per node]
>>> [SoC PCI devices with MSI-X but no IOMMU]
>>> [PCI-PCIe "glue" bridges - upto 14, one per real port below]
>>> [PCIe real root ports associated with IOMMU and GICv3 ITS]
>>> [External PCI devices connected to PCIe links]
>>
>> Since it's not entirely obvious, what does the actual DT - or IORT if
>> you must ;) - topology for this look like? I can't help thinking that
>> either it's inaccurate, or that this is going to expose a shortcoming in
>> pci_dma_configure() which breaks things - unless I'm missing something,
>> isn't find_pci_root_bus() going to go all the way up to the top-level
>> glue bridge and pick up the wrong firmware node (if any) for the
>> appropriate DMA properties?
> 
> I will try to describe the ACPI interface:
> 
> There is just one ECAM area, a single bus range and one set of memory
> windows for the whole system - so there is just one entry in DSDT for
> the PCI controller. This entry also corresponds to the PCI RC node in
> IORT. DMA is coherent and supports 64 bits system-wide, the attributes
> (in DSDT and IORT) reflect this.
> 
> lspci on the system looks like this:
> -[:00]-+-00.0-[01-1e]--+-04.0  14e4:9026
>|   +-04.1  14e4:9026
>|   +-05.0  14e4:9027
>|   +-05.1  14e4:9027
>|   +-0a.0-[02-03]00.0-[03]--
>|   +-0a.1-[04-05]00.0-[05]--
>|   [...etc...]
>|   +-0b.0-[12-14]00.0-[13-14]--+-00.0  8086:1583
>|   |   \-00.1  8086:1583
>|   [...etc...]
>|   \-0b.5-[1d-1e]00.0-[1e]--
>\-00.1-[1f-3b]--+-04.0  14e4:9026
>+-04.1  14e4:9026
>+-05.0  14e4:9027
>+-05.1  14e4:9027
>+-0a.0-[20-21]00.0-[21]--
>[...etc...]
> 
> The devices here are:
>  - 00:00.0 and 00:00.1 are the node (socket) level bridges
>  - 01:[45].x and 1f:[45].x are SoC PCI devices like SATA and USB
>  - 01:[ab].x and 1f:[ab].x are the PCI-PCIe "reverse"/glue bridges
>  - 02:00.0 etc are the "real" PCIe ports connected to external PCIe cards. 
> Each node has a GIC ITS, and a group of 4 PCIe ports have an SMMU.
> 
> The IORT is built by the firmware based on its PCI enumeration. The IORT
> will have multiple entries under the PCI RC node:
>  - one entry per node to map the SoC devices directly to ITS for MSI-X,
>since the SoC devices are not attached to any SMMU.
>  - An entry per "real" PCIe port to map RIDs under it to the corresponding
>SMMU.
> The SMMU nodes will have an entry to map its RID ranges to the node ITS.
> 
> The IORT spec supports this configuration, and the corresponding code is
> already upstream, so the only sticking point right now is
> pci_for_each_dma_alias().

Thanks, that helps a lot. The "single global ECAM space" idea was
eluding me, but in that context it all makes much more sense - I'm
assuming the two quirked device IDs correspond to the 00:00.[01] devices
and the [02-1e]:00.0 ones.

So (at the risk of Jon mooing at me), I guess the DT description would
be a single node looking something like:

pcie {
reg = [global ECAM space for segment ];

msi-map = <0x0100  0x0100 0x1d00>,
  <0x1f00  0x1f00 0x1d00>;
iommu-map = <0x0200  0x0200 0x1c00>,
<0x2000  0x2000 0x1c00>;
};

(note to self: which incidentally also means of_pci_map_rid() probably
wants fixing to not treat gaps in the map as an error)

With only one node like that, rather than having the whole first 3
levels of bridges described, the "stop at the appropriate node in the
callback" approach does become even more impractical in all cases. So,
for $TITLE, based on the above understanding:

Reviewed-by: Robin Murphy 

Cheers,
Robin.

> 
> JC.
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V10 00/12] IOMMU probe deferral support

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> This series calls the dma ops configuration for the devices
> at a generic place so that it works for all busses.
> The dma_configure_ops for a device is now called during
> the device_attach callback just before the probe of the
> bus/driver is called. Similarly dma_deconfigure is called during
> device/driver_detach path.
> 
> pci_bus_add_devices(platform/amba)(_device_create/driver_register)
>| |
> pci_bus_add_device (device_add/driver_register)
>| |
> device_attach   device_initial_probe
>| |
> __device_attach_driver__device_attach_driver
>|
> driver_probe_device
>|
> really_probe
>|
> dma_configure
> 
> Similarly on the device/driver_unregister path __device_release_driver is
> called which inturn calls dma_deconfigure.
> 
> Rebased the series against mainline 4.11-rc5. Applies and builds cleanly
> against mainline and linux-next, iommu-next.
>   
> * Tested with platform and pci devices for probe deferral
>   and reprobe on arm64 based platform.

Sricharan, thanks for keeping this going - I really think we're there now :)

Joerg, I realise that at -rc5 time is getting on a bit already, but even
the non-vintage parts of the series are pretty mature now so it would be
nice to at least give it a spin in -next. If you don't quite share my
confidence for landing it in 4.12, please consider it for early next
cycle to get a full workout.

Thanks,
Robin.

> Previous post of this series [8]. 
> 
> Please note that, i have kept the tested/acked tags intact from V8
> because V9/10 were for more fixes that was added, so the original
> tags that was given for the functional testing remains the same.
> 
>  [V10]
>  * Rebased on top of 4.11-rc5.
>  
>  * Fixed coherent_dma_mask 64bit overflow issue [8]
>for OF. The fix for OF was added as a separate
>patch#6, since the issue is true even without probe deferral,
>but gets reproduced with the probe deferral series.
>Added Lorenzo's ACPI fix for coherent_dma_mask overflow
>and the fix for dma_configure getting called more than
>once for the same device.
> 
>  * Also fixed an build issue caught by kbuild robot for
>m68k arch. The issue was dma_(de)configure was not
>getting defined for !CONFIG_HAS_DMA, so fixed that as well.
> 
>  [V9]
>  * Rebased on top of 4.11-rc1.
> 
>  * Merged Robin's fixes for legacy binding issue,
>pci devices with no iommu-map property and deferencing
>of_iommu_table after init.
>  
>  [V8]
>  * Picked up all the acks and tested tags from Marek and
>Hanjun for DT and ACPI patches respectively, since
>no functional changes was done.
> 
>  * Addressed Minor comments Sinan and Bjorn.
> 
>  * Added Robin's fix for fixing the deferencing NULL for
>of_iommu_table after init in patch #2.
> 
>  * Rebased it on top of linux-next
> 
>  [V7]
>  * Updated the subject and commit log for patch #6 as per
>comments from Lorenzo. No functional changes.
> 
>  [V6]
>  * Fixed a bug in dma_configure function pointed out by
>Robin.
>  * Reordered the patches as per comments from Robin and
>Lorenzo.
>  * Added Tags.
> 
>  [V5]
>  * Reworked the pci configuration code hanging outside and
>pushed it to dma_configure as in PATCH#5,6,7.
>Also added a couple of patches that Lorenzo provided for
>correcting the Probe deferring mechanism in case of
>ACPI devices from here [5].
> 
>  [V4]
>  * Took the reworked patches [2] from Robin's branch and
>rebased on top of Lorenzo's ACPI IORT ARM support series [3].
> 
>  * Added the patches for moving the dma ops configuration of
>acpi based devices to probe time as well.
>  [V3]
>  * Removed the patch to split dma_masks/dma_ops configuration
>separately based on review comments that both masks and ops are
>required only during the device probe time.
> 
>  * Reworked the series based on Generic DT bindings series.
> 
>  * Added call to iommu's remove_device in the cleanup path for arm and
>arm64.
> 
>  * Removed the notifier trick in arm64 to handle early device
>registration.
> 
>  * Added reset of dma_ops in cleanup path for arm based on comments.
> 
>  * Fixed the pci_iommu_configure path and tested with PCI device as
>well.
>  
>  * Fixed a bug to return the correct iommu_ops from patch 7 [4] in
>last post.
> 
>  * Fixed few other cosmetic comments.
>   
>  [V2]
>  * Updated the Initial post to call dma_configure/deconfigure from
>generic code
>  
>  * Added iommu add_device callback from of_iommu_configure path
> 
>  [V1]
>  * Initial post from Laurent Pinchart [1]
> 
> [1] 

Re: [PATCH V10 07/12] of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices

2017-04-04 Thread Sricharan R

Hi Robin,

On 4/4/2017 5:47 PM, Robin Murphy wrote:

On 04/04/17 11:18, Sricharan R wrote:

Configuring DMA ops at probe time will allow deferring device probe when
the IOMMU isn't available yet. The dma_configure for the device is
now called from the generic device_attach callback just before the
bus/driver probe is called. This way, configuring the DMA ops for the
device would be called at the same place for all bus_types, hence the
deferred probing mechanism should work for all buses as well.

pci_bus_add_devices(platform/amba)(_device_create/driver_register)
   | |
pci_bus_add_device (device_add/driver_register)
   | |
device_attach   device_initial_probe
   | |
__device_attach_driver__device_attach_driver
   |
driver_probe_device
   |
really_probe
   |
dma_configure

Similarly on the device/driver_unregister path __device_release_driver is
called which inturn calls dma_deconfigure.

This patch changes the dma ops configuration to probe time for
both OF and ACPI based platform/amba/pci bus devices.


Reviewed-by: Robin Murphy 

It's possible we could subsume {of,acpi}_dma_deconfigure() into
dma_deconfigure() entirely in future if it becomes clear that neither of
them will ever need to do anything firmware-specific, but I think for
now it's probably safer to keep the current symmetry - calling
arch_teardown_dma_ops() twice is benign (and even if it weren't, I'd say
it really should be!)



Ya, calling it twice should cause no harm. If nothing firmware specific
gets added this could simply be put in deconfigure itself in future.
Thanks for all the reviews !!

Regards,
 Sricharan




Robin.


Tested-by: Marek Szyprowski 
Tested-by: Hanjun Guo 
Acked-by: Bjorn Helgaas  (drivers/pci part)
Acked-by: Rafael J. Wysocki 
Signed-off-by: Sricharan R 
---

 [V10] Added dummy dma_(de)configure functions in case
   of !CONFIG_HAS_DMA to avoid build breaks.

 drivers/acpi/glue.c |  5 -
 drivers/base/dd.c   |  9 +
 drivers/base/dma-mapping.c  | 40 
 drivers/of/platform.c   |  5 +
 drivers/pci/probe.c | 28 
 include/linux/dma-mapping.h | 12 
 6 files changed, 62 insertions(+), 37 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index fb19e1c..c05f241 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -176,7 +176,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
struct list_head *physnode_list;
unsigned int node_id;
int retval = -EINVAL;
-   enum dev_dma_attr attr;

if (has_acpi_companion(dev)) {
if (acpi_dev) {
@@ -233,10 +232,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
if (!has_acpi_companion(dev))
ACPI_COMPANION_SET(dev, acpi_dev);

-   attr = acpi_get_dma_attr(acpi_dev);
-   if (attr != DEV_DMA_NOT_SUPPORTED)
-   acpi_dma_configure(dev, attr);
-
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(_dev->dev.kobj, >kobj,
   physical_node_name);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a1fbf55..4882f06 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -19,6 +19,7 @@

 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -356,6 +357,10 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
if (ret)
goto pinctrl_bind_failed;

+   ret = dma_configure(dev);
+   if (ret)
+   goto dma_failed;
+
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
@@ -417,6 +422,8 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
goto done;

 probe_failed:
+   dma_deconfigure(dev);
+dma_failed:
if (dev->bus)
blocking_notifier_call_chain(>bus->p->bus_notifier,
 BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
@@ -826,6 +833,8 @@ static void __device_release_driver(struct device *dev, 
struct device *parent)
drv->remove(dev);

device_links_driver_cleanup(dev);
+   dma_deconfigure(dev);
+
devres_release_all(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index efd71cf..449b948 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -7,9 +7,11 @@
  * This file is released under the GPLv2.
  */

+#include 
 #include 
 #include 

Re: [PATCH V10 07/12] of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> Configuring DMA ops at probe time will allow deferring device probe when
> the IOMMU isn't available yet. The dma_configure for the device is
> now called from the generic device_attach callback just before the
> bus/driver probe is called. This way, configuring the DMA ops for the
> device would be called at the same place for all bus_types, hence the
> deferred probing mechanism should work for all buses as well.
> 
> pci_bus_add_devices(platform/amba)(_device_create/driver_register)
>| |
> pci_bus_add_device (device_add/driver_register)
>| |
> device_attach   device_initial_probe
>| |
> __device_attach_driver__device_attach_driver
>|
> driver_probe_device
>|
> really_probe
>|
> dma_configure
> 
> Similarly on the device/driver_unregister path __device_release_driver is
> called which inturn calls dma_deconfigure.
> 
> This patch changes the dma ops configuration to probe time for
> both OF and ACPI based platform/amba/pci bus devices.

Reviewed-by: Robin Murphy 

It's possible we could subsume {of,acpi}_dma_deconfigure() into
dma_deconfigure() entirely in future if it becomes clear that neither of
them will ever need to do anything firmware-specific, but I think for
now it's probably safer to keep the current symmetry - calling
arch_teardown_dma_ops() twice is benign (and even if it weren't, I'd say
it really should be!)

Robin.

> Tested-by: Marek Szyprowski 
> Tested-by: Hanjun Guo 
> Acked-by: Bjorn Helgaas  (drivers/pci part)
> Acked-by: Rafael J. Wysocki 
> Signed-off-by: Sricharan R 
> ---
> 
>  [V10] Added dummy dma_(de)configure functions in case
>of !CONFIG_HAS_DMA to avoid build breaks.
> 
>  drivers/acpi/glue.c |  5 -
>  drivers/base/dd.c   |  9 +
>  drivers/base/dma-mapping.c  | 40 
>  drivers/of/platform.c   |  5 +
>  drivers/pci/probe.c | 28 
>  include/linux/dma-mapping.h | 12 
>  6 files changed, 62 insertions(+), 37 deletions(-)
> 
> diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
> index fb19e1c..c05f241 100644
> --- a/drivers/acpi/glue.c
> +++ b/drivers/acpi/glue.c
> @@ -176,7 +176,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
> *acpi_dev)
>   struct list_head *physnode_list;
>   unsigned int node_id;
>   int retval = -EINVAL;
> - enum dev_dma_attr attr;
>  
>   if (has_acpi_companion(dev)) {
>   if (acpi_dev) {
> @@ -233,10 +232,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
> *acpi_dev)
>   if (!has_acpi_companion(dev))
>   ACPI_COMPANION_SET(dev, acpi_dev);
>  
> - attr = acpi_get_dma_attr(acpi_dev);
> - if (attr != DEV_DMA_NOT_SUPPORTED)
> - acpi_dma_configure(dev, attr);
> -
>   acpi_physnode_link_name(physical_node_name, node_id);
>   retval = sysfs_create_link(_dev->dev.kobj, >kobj,
>  physical_node_name);
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index a1fbf55..4882f06 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -19,6 +19,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -356,6 +357,10 @@ static int really_probe(struct device *dev, struct 
> device_driver *drv)
>   if (ret)
>   goto pinctrl_bind_failed;
>  
> + ret = dma_configure(dev);
> + if (ret)
> + goto dma_failed;
> +
>   if (driver_sysfs_add(dev)) {
>   printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
>   __func__, dev_name(dev));
> @@ -417,6 +422,8 @@ static int really_probe(struct device *dev, struct 
> device_driver *drv)
>   goto done;
>  
>  probe_failed:
> + dma_deconfigure(dev);
> +dma_failed:
>   if (dev->bus)
>   blocking_notifier_call_chain(>bus->p->bus_notifier,
>BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
> @@ -826,6 +833,8 @@ static void __device_release_driver(struct device *dev, 
> struct device *parent)
>   drv->remove(dev);
>  
>   device_links_driver_cleanup(dev);
> + dma_deconfigure(dev);
> +
>   devres_release_all(dev);
>   dev->driver = NULL;
>   dev_set_drvdata(dev, NULL);
> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
> index efd71cf..449b948 100644
> --- a/drivers/base/dma-mapping.c
> +++ b/drivers/base/dma-mapping.c
> @@ -7,9 +7,11 @@
>   * This file is released under the GPLv2.
>   */
>  
> +#include 
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  
> @@ 

Re: [PATCH v4 2/2] PCI: quirks: Fix ThunderX2 dma alias handling

2017-04-04 Thread Jayachandran C
On Mon, Apr 03, 2017 at 04:07:53PM +0100, Robin Murphy wrote:
> On 03/04/17 14:15, Jayachandran C wrote:
> > The Cavium ThunderX2 arm64 SoCs (called Broadcom Vulcan earlier), the PCI
> > topology is slightly unusual. For a multi-node system, it looks like:
> > 
> > [node level PCI bridges - one per node]
> > [SoC PCI devices with MSI-X but no IOMMU]
> > [PCI-PCIe "glue" bridges - upto 14, one per real port below]
> > [PCIe real root ports associated with IOMMU and GICv3 ITS]
> > [External PCI devices connected to PCIe links]
> 
> Since it's not entirely obvious, what does the actual DT - or IORT if
> you must ;) - topology for this look like? I can't help thinking that
> either it's inaccurate, or that this is going to expose a shortcoming in
> pci_dma_configure() which breaks things - unless I'm missing something,
> isn't find_pci_root_bus() going to go all the way up to the top-level
> glue bridge and pick up the wrong firmware node (if any) for the
> appropriate DMA properties?

I will try to describe the ACPI interface:

There is just one ECAM area, a single bus range and one set of memory
windows for the whole system - so there is just one entry in DSDT for
the PCI controller. This entry also corresponds to the PCI RC node in
IORT. DMA is coherent and supports 64 bits system-wide, the attributes
(in DSDT and IORT) reflect this.

lspci on the system looks like this:
-[:00]-+-00.0-[01-1e]--+-04.0  14e4:9026
   |   +-04.1  14e4:9026
   |   +-05.0  14e4:9027
   |   +-05.1  14e4:9027
   |   +-0a.0-[02-03]00.0-[03]--
   |   +-0a.1-[04-05]00.0-[05]--
   |   [...etc...]
   |   +-0b.0-[12-14]00.0-[13-14]--+-00.0  8086:1583
   |   |   \-00.1  8086:1583
   |   [...etc...]
   |   \-0b.5-[1d-1e]00.0-[1e]--
   \-00.1-[1f-3b]--+-04.0  14e4:9026
   +-04.1  14e4:9026
   +-05.0  14e4:9027
   +-05.1  14e4:9027
   +-0a.0-[20-21]00.0-[21]--
   [...etc...]

The devices here are:
 - 00:00.0 and 00:00.1 are the node (socket) level bridges
 - 01:[45].x and 1f:[45].x are SoC PCI devices like SATA and USB
 - 01:[ab].x and 1f:[ab].x are the PCI-PCIe "reverse"/glue bridges
 - 02:00.0 etc are the "real" PCIe ports connected to external PCIe cards. 
Each node has a GIC ITS, and a group of 4 PCIe ports have an SMMU.

The IORT is built by the firmware based on its PCI enumeration. The IORT
will have multiple entries under the PCI RC node:
 - one entry per node to map the SoC devices directly to ITS for MSI-X,
   since the SoC devices are not attached to any SMMU.
 - An entry per "real" PCIe port to map RIDs under it to the corresponding
   SMMU.
The SMMU nodes will have an entry to map its RID ranges to the node ITS.

The IORT spec supports this configuration, and the corresponding code is
already upstream, so the only sticking point right now is
pci_for_each_dma_alias().

JC.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V10 12/12] ACPI/IORT: Remove linker section for IORT entries probing

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> From: Lorenzo Pieralisi 
> 
> The IORT linker section introduced by commit 34ceea275f62
> ("ACPI/IORT: Introduce linker section for IORT entries probing")
> was needed to make sure SMMU drivers are registered (and therefore
> probed) in the kernel before devices using the SMMU have a chance
> to probe in turn.
> 
> Through the introduction of deferred IOMMU configuration the linker
> section based IORT probing infrastructure is not needed any longer, in
> that device/SMMU probe dependencies are managed through the probe
> deferral mechanism, making the IORT linker section infrastructure
> unused, so that it can be removed.
> 
> Remove the unused IORT linker section probing infrastructure
> from the kernel to complete the ACPI IORT IOMMU configure probe
> deferral mechanism implementation.

Reviewed-by: Robin Murphy 

> Tested-by: Hanjun Guo 
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Robin Murphy 
> Cc: Sricharan R 
> ---
>  drivers/acpi/arm64/iort.c | 2 --
>  include/asm-generic/vmlinux.lds.h | 1 -
>  include/linux/acpi_iort.h | 3 ---
>  3 files changed, 6 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index e323ece..e7b1940 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -1000,6 +1000,4 @@ void __init acpi_iort_init(void)
>   }
>  
>   iort_init_platform_devices();
> -
> - acpi_probe_device_table(iort);
>  }
> diff --git a/include/asm-generic/vmlinux.lds.h 
> b/include/asm-generic/vmlinux.lds.h
> index 0968d13..9faa26c 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -566,7 +566,6 @@
>   IRQCHIP_OF_MATCH_TABLE()\
>   ACPI_PROBE_TABLE(irqchip)   \
>   ACPI_PROBE_TABLE(clksrc)\
> - ACPI_PROBE_TABLE(iort)  \
>   EARLYCON_TABLE()
>  
>  #define INIT_TEXT\
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 77e0809..f167e1d04 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -52,7 +52,4 @@ const struct iommu_ops *iort_iommu_configure(struct device 
> *dev)
>  { return NULL; }
>  #endif
>  
> -#define IORT_ACPI_DECLARE(name, table_id, fn)\
> - ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
> -
>  #endif /* __ACPI_IORT_H__ */
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V10 09/12] drivers: acpi: Handle IOMMU lookup failure with deferred probing or error

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> This is an equivalent to the DT's handling of the iommu master's probe
> with deferred probing when the corrsponding iommu is not probed yet.
> The lack of a registered IOMMU can be caused by the lack of a driver for
> the IOMMU, the IOMMU device probe not having been performed yet, having
> been deferred, or having failed.
> 
> The first case occurs when the firmware describes the bus master and
> IOMMU topology correctly but no device driver exists for the IOMMU yet
> or the device driver has not been compiled in. Return NULL, the caller
> will configure the device without an IOMMU.
> 
> The second and third cases are handled by deferring the probe of the bus
> master device which will eventually get reprobed after the IOMMU.
> 
> The last case is currently handled by deferring the probe of the bus
> master device as well. A mechanism to either configure the bus master
> device without an IOMMU or to fail the bus master device probe depending
> on whether the IOMMU is optional or mandatory would be a good
> enhancement.

I think we really have caught everything now...

Reviewed-by: Robin Murphy 

> Tested-by: Hanjun Guo 
> [Lorenzo: Added fixes for dma_coherent_mask overflow, acpi_dma_configure
>   called multiple times for same device]
> Signed-off-by: Lorenzo Pieralisi 
> Signed-off-by: Sricharan R 
> ---
> 
>  [V10] Added Lorenzo's ACPI fix for coherent_dma_mask overflow
>and the fix for dma_configure getting called more than
>once for the same device.
> 
>  drivers/acpi/arm64/iort.c  | 33 -
>  drivers/acpi/scan.c| 11 ---
>  drivers/base/dma-mapping.c |  2 +-
>  include/acpi/acpi_bus.h|  2 +-
>  include/linux/acpi.h   |  7 +--
>  5 files changed, 47 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 3dd9ec3..e323ece 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -543,6 +543,14 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
> device *dev,
>   const struct iommu_ops *ops = NULL;
>   int ret = -ENODEV;
>   struct fwnode_handle *iort_fwnode;
> + struct iommu_fwspec *fwspec = dev->iommu_fwspec;
> +
> + /*
> +  * If we already translated the fwspec there
> +  * is nothing left to do, return the iommu_ops.
> +  */
> + if (fwspec && fwspec->ops)
> + return fwspec->ops;
>  
>   if (node) {
>   iort_fwnode = iort_get_fwnode(node);
> @@ -550,8 +558,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
> device *dev,
>   return NULL;
>  
>   ops = iommu_ops_from_fwnode(iort_fwnode);
> + /*
> +  * If the ops look-up fails, this means that either
> +  * the SMMU drivers have not been probed yet or that
> +  * the SMMU drivers are not built in the kernel;
> +  * Depending on whether the SMMU drivers are built-in
> +  * in the kernel or not, defer the IOMMU configuration
> +  * or just abort it.
> +  */
>   if (!ops)
> - return NULL;
> + return iort_iommu_driver_enabled(node->type) ?
> +ERR_PTR(-EPROBE_DEFER) : NULL;
>  
>   ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
>   }
> @@ -625,12 +642,26 @@ const struct iommu_ops *iort_iommu_configure(struct 
> device *dev)
>  
>   while (parent) {
>   ops = iort_iommu_xlate(dev, parent, streamid);
> + if (IS_ERR_OR_NULL(ops))
> + return ops;
>  
>   parent = iort_node_get_id(node, ,
> IORT_IOMMU_TYPE, i++);
>   }
>   }
>  
> + /*
> +  * If we have reason to believe the IOMMU driver missed the initial
> +  * add_device callback for dev, replay it to get things in order.
> +  */
> + if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
> + dev->bus && !dev->iommu_group) {
> + int err = ops->add_device(dev);
> +
> + if (err)
> + ops = ERR_PTR(err);
> + }
> +
>   return ops;
>  }
>  
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 1926918..2a513cc 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1373,20 +1373,25 @@ enum dev_dma_attr acpi_get_dma_attr(struct 
> acpi_device *adev)
>   * @dev: The pointer to the device
>   * @attr: device dma attributes
>   */
> -void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
> +int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
>  {
>   const struct iommu_ops *iommu;
> + u64 size;
>  
>   

Re: [PATCH V10 08/12] iommu: of: Handle IOMMU lookup failure with deferred probing or error

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> From: Laurent Pinchart 
> 
> Failures to look up an IOMMU when parsing the DT iommus property need to
> be handled separately from the .of_xlate() failures to support deferred
> probing.
> 
> The lack of a registered IOMMU can be caused by the lack of a driver for
> the IOMMU, the IOMMU device probe not having been performed yet, having
> been deferred, or having failed.
> 
> The first case occurs when the device tree describes the bus master and
> IOMMU topology correctly but no device driver exists for the IOMMU yet
> or the device driver has not been compiled in. Return NULL, the caller
> will configure the device without an IOMMU.
> 
> The second and third cases are handled by deferring the probe of the bus
> master device which will eventually get reprobed after the IOMMU.
> 
> The last case is currently handled by deferring the probe of the bus
> master device as well. A mechanism to either configure the bus master
> device without an IOMMU or to fail the bus master device probe depending
> on whether the IOMMU is optional or mandatory would be a good
> enhancement.

Reviewed-by: Robin Murphy 

> Tested-by: Marek Szyprowski 
> Signed-off-by: Laurent Pichart 
> Signed-off-by: Sricharan R 
> ---
>  drivers/base/dma-mapping.c | 5 +++--
>  drivers/iommu/of_iommu.c   | 4 ++--
>  drivers/of/device.c| 7 ++-
>  include/linux/of_device.h  | 9 ++---
>  4 files changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
> index 449b948..82bd45c 100644
> --- a/drivers/base/dma-mapping.c
> +++ b/drivers/base/dma-mapping.c
> @@ -353,6 +353,7 @@ int dma_configure(struct device *dev)
>  {
>   struct device *bridge = NULL, *dma_dev = dev;
>   enum dev_dma_attr attr;
> + int ret = 0;
>  
>   if (dev_is_pci(dev)) {
>   bridge = pci_get_host_bridge_device(to_pci_dev(dev));
> @@ -363,7 +364,7 @@ int dma_configure(struct device *dev)
>   }
>  
>   if (dma_dev->of_node) {
> - of_dma_configure(dev, dma_dev->of_node);
> + ret = of_dma_configure(dev, dma_dev->of_node);
>   } else if (has_acpi_companion(dma_dev)) {
>   attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
>   if (attr != DEV_DMA_NOT_SUPPORTED)
> @@ -373,7 +374,7 @@ int dma_configure(struct device *dev)
>   if (bridge)
>   pci_put_host_bridge_device(bridge);
>  
> - return 0;
> + return ret;
>  }
>  
>  void dma_deconfigure(struct device *dev)
> diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> index c8be889..9f44ee8 100644
> --- a/drivers/iommu/of_iommu.c
> +++ b/drivers/iommu/of_iommu.c
> @@ -236,7 +236,7 @@ const struct iommu_ops *of_iommu_configure(struct device 
> *dev,
>   ops = ERR_PTR(err);
>   }
>  
> - return IS_ERR(ops) ? NULL : ops;
> + return ops;
>  }
>  
>  static int __init of_iommu_init(void)
> @@ -247,7 +247,7 @@ static int __init of_iommu_init(void)
>   for_each_matching_node_and_match(np, matches, ) {
>   const of_iommu_init_fn init_fn = match->data;
>  
> - if (init_fn(np))
> + if (init_fn && init_fn(np))
>   pr_err("Failed to initialise IOMMU %s\n",
>   of_node_full_name(np));
>   }
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index c2ae6bb..bea8aec 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -82,7 +82,7 @@ int of_device_add(struct platform_device *ofdev)
>   * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
>   * to fix up DMA configuration.
>   */
> -void of_dma_configure(struct device *dev, struct device_node *np)
> +int of_dma_configure(struct device *dev, struct device_node *np)
>  {
>   u64 dma_addr, paddr, size;
>   int ret;
> @@ -129,10 +129,15 @@ void of_dma_configure(struct device *dev, struct 
> device_node *np)
>   coherent ? " " : " not ");
>  
>   iommu = of_iommu_configure(dev, np);
> + if (IS_ERR(iommu))
> + return PTR_ERR(iommu);
> +
>   dev_dbg(dev, "device is%sbehind an iommu\n",
>   iommu ? " " : " not ");
>  
>   arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
> +
> + return 0;
>  }
>  EXPORT_SYMBOL_GPL(of_dma_configure);
>  
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index af98455..2cacdd8 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -55,7 +55,7 @@ static inline struct device_node 
> *of_cpu_device_node_get(int cpu)
>   return of_node_get(cpu_dev->of_node);
>  }
>  
> -void of_dma_configure(struct device *dev, struct device_node *np);
> +int of_dma_configure(struct device *dev, struct 

Re: [PATCH V10 06/12] of: device: Fix overflow of coherent_dma_mask

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> Size of the dma-range is calculated as coherent_dma_mask + 1
> and passed to arch_setup_dma_ops further. It overflows when
> the coherent_dma_mask is set for full 64 bits 0x,
> resulting in size getting passed as 0 wrongly. Fix this by
> passsing in max(mask, mask + 1). Note that in this case
> when the mask is set to full 64bits, we will be passing the mask
> itself to arch_setup_dma_ops instead of the size. The real fix
> for this should be to make arch_setup_dma_ops receive the
> mask and handle it, to be done in the future.

Agreed; in the meantime, this fix is neat and robust enough.

Reviewed-by: Robin Murphy 

> Signed-off-by: Sricharan R 
> ---
>  drivers/of/device.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index c17c19d..c2ae6bb 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -107,7 +107,7 @@ void of_dma_configure(struct device *dev, struct 
> device_node *np)
>   ret = of_dma_get_range(np, _addr, , );
>   if (ret < 0) {
>   dma_addr = offset = 0;
> - size = dev->coherent_dma_mask + 1;
> + size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
>   } else {
>   offset = PFN_DOWN(paddr - dma_addr);
>   dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V10 05/12] ACPI/IORT: Add function to check SMMUs drivers presence

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> From: Lorenzo Pieralisi 
> 
> The IOMMU probe deferral implementation requires a mechanism to detect
> if drivers for SMMU components are built-in in the kernel to detect
> whether IOMMU configuration for a given device should be deferred (ie
> SMMU drivers present but still not probed) or not (drivers not present).
> 
> Add a simple function to IORT to detect if SMMU drivers for SMMU
> components managed by IORT are built-in in the kernel.

Ah, if only DT could be this neat and tidy :D

Reviewed-by: Robin Murphy 

> Tested-by: Hanjun Guo 
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Robin Murphy 
> Cc: Sricharan R 
> ---
>  drivers/acpi/arm64/iort.c | 13 +
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 4a5bb96..3dd9ec3 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -523,6 +523,19 @@ static int arm_smmu_iort_xlate(struct device *dev, u32 
> streamid,
>   return ret;
>  }
>  
> +static inline bool iort_iommu_driver_enabled(u8 type)
> +{
> + switch (type) {
> + case ACPI_IORT_NODE_SMMU_V3:
> + return IS_BUILTIN(CONFIG_ARM_SMMU_V3);
> + case ACPI_IORT_NODE_SMMU:
> + return IS_BUILTIN(CONFIG_ARM_SMMU);
> + default:
> + pr_warn("IORT node type %u does not describe an SMMU\n", type);
> + return false;
> + }
> +}
> +
>  static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
>   struct acpi_iort_node *node,
>   u32 streamid)
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V10 04/12] of: dma: Make of_dma_deconfigure() public

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> From: Laurent Pinchart 
> 
> As part of moving DMA initializing to probe time the
> of_dma_deconfigure() function will need to be called from different
> source files. Make it public and move it to drivers/of/device.c where
> the of_dma_configure() function is.

Reviewed-by: Robin Murphy 

> Tested-by: Marek Szyprowski 
> Signed-off-by: Laurent Pinchart 
> ---
>  drivers/of/device.c   | 12 
>  drivers/of/platform.c |  5 -
>  include/linux/of_device.h |  3 +++
>  3 files changed, 15 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index 09dedd0..c17c19d 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -136,6 +136,18 @@ void of_dma_configure(struct device *dev, struct 
> device_node *np)
>  }
>  EXPORT_SYMBOL_GPL(of_dma_configure);
>  
> +/**
> + * of_dma_deconfigure - Clean up DMA configuration
> + * @dev: Device for which to clean up DMA configuration
> + *
> + * Clean up all configuration performed by of_dma_configure_ops() and free 
> all
> + * resources that have been allocated.
> + */
> +void of_dma_deconfigure(struct device *dev)
> +{
> + arch_teardown_dma_ops(dev);
> +}
> +
>  int of_device_register(struct platform_device *pdev)
>  {
>   device_initialize(>dev);
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 5dfcc96..5344db5 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -158,11 +158,6 @@ struct platform_device *of_device_alloc(struct 
> device_node *np,
>  }
>  EXPORT_SYMBOL(of_device_alloc);
>  
> -static void of_dma_deconfigure(struct device *dev)
> -{
> - arch_teardown_dma_ops(dev);
> -}
> -
>  /**
>   * of_platform_device_create_pdata - Alloc, initialize and register an 
> of_device
>   * @np: pointer to node to create device for
> diff --git a/include/linux/of_device.h b/include/linux/of_device.h
> index c12dace..af98455 100644
> --- a/include/linux/of_device.h
> +++ b/include/linux/of_device.h
> @@ -56,6 +56,7 @@ static inline struct device_node 
> *of_cpu_device_node_get(int cpu)
>  }
>  
>  void of_dma_configure(struct device *dev, struct device_node *np);
> +void of_dma_deconfigure(struct device *dev);
>  #else /* CONFIG_OF */
>  
>  static inline int of_driver_match_device(struct device *dev,
> @@ -105,6 +106,8 @@ static inline struct device_node 
> *of_cpu_device_node_get(int cpu)
>  }
>  static inline void of_dma_configure(struct device *dev, struct device_node 
> *np)
>  {}
> +static inline void of_dma_deconfigure(struct device *dev)
> +{}
>  #endif /* CONFIG_OF */
>  
>  #endif /* _LINUX_OF_DEVICE_H */
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH V10 03/12] of: dma: Move range size workaround to of_dma_get_range()

2017-04-04 Thread Robin Murphy
On 04/04/17 11:18, Sricharan R wrote:
> From: Laurent Pinchart 
> 
> Invalid dma-ranges values should be worked around when retrieving the
> DMA range in of_dma_get_range(), not by all callers of the function.
> This isn't much of a problem now that we have a single caller, but that
> situation will change when moving DMA configuration to device probe
> time.

Just for completeness:

Reviewed-by: Robin Murphy 

> Tested-by: Marek Szyprowski 
> Signed-off-by: Laurent Pinchart 
> ---
>  drivers/of/address.c | 20 ++--
>  drivers/of/device.c  | 15 ---
>  2 files changed, 18 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 02b2903..6aeb816 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -819,8 +819,8 @@ void __iomem *of_io_request_and_map(struct device_node 
> *np, int index,
>   *   CPU addr (phys_addr_t)  : pna cells
>   *   size: nsize cells
>   *
> - * It returns -ENODEV if "dma-ranges" property was not found
> - * for this device in DT.
> + * Return 0 on success, -ENODEV if the "dma-ranges" property was not found 
> for
> + * this device in DT, or -EINVAL if the CPU address or size is invalid.
>   */
>  int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 
> *size)
>  {
> @@ -880,6 +880,22 @@ int of_dma_get_range(struct device_node *np, u64 
> *dma_addr, u64 *paddr, u64 *siz
>   *dma_addr = dmaaddr;
>  
>   *size = of_read_number(ranges + naddr + pna, nsize);
> + /*
> +  * DT nodes sometimes incorrectly set the size as a mask. Work around
> +  * those incorrect DT by computing the size as mask + 1.
> +  */
> + if (*size & 1) {
> + pr_warn("%s: size 0x%llx for dma-range in node(%s) set as 
> mask\n",
> + __func__, *size, np->full_name);
> + *size = *size + 1;
> + }
> +
> + if (!*size) {
> + pr_err("%s: invalid size zero for dma-range in node(%s)\n",
> +__func__, np->full_name);
> + ret = -EINVAL;
> + goto out;
> + }
>  
>   pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
>*dma_addr, *paddr, *size);
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index b1e6beb..09dedd0 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -110,21 +110,6 @@ void of_dma_configure(struct device *dev, struct 
> device_node *np)
>   size = dev->coherent_dma_mask + 1;
>   } else {
>   offset = PFN_DOWN(paddr - dma_addr);
> -
> - /*
> -  * Add a work around to treat the size as mask + 1 in case
> -  * it is defined in DT as a mask.
> -  */
> - if (size & 1) {
> - dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
> -  size);
> - size = size + 1;
> - }
> -
> - if (!size) {
> - dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
> - return;
> - }
>   dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
>   }
>  
> 

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH V10 10/12] arm64: dma-mapping: Remove the notifier trick to handle early setting of dma_ops

2017-04-04 Thread Sricharan R
With arch_setup_dma_ops now being called late during device's probe after
the device's iommu is probed, the notifier trick required to handle the
early setup of dma_ops before the iommu group gets created is not
required. So removing the notifier's here.

Tested-by: Marek Szyprowski 
Tested-by: Hanjun Guo 
Acked-by: Will Deacon 
Signed-off-by: Sricharan R 
[rm: clean up even more]
Signed-off-by: Robin Murphy 
---
 arch/arm64/mm/dma-mapping.c | 142 ++--
 1 file changed, 18 insertions(+), 124 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 81cdb2e..b465759 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -813,34 +813,26 @@ static void __iommu_unmap_sg_attrs(struct device *dev,
.mapping_error = iommu_dma_mapping_error,
 };
 
-/*
- * TODO: Right now __iommu_setup_dma_ops() gets called too early to do
- * everything it needs to - the device is only partially created and the
- * IOMMU driver hasn't seen it yet, so it can't have a group. Thus we
- * need this delayed attachment dance. Once IOMMU probe ordering is sorted
- * to move the arch_setup_dma_ops() call later, all the notifier bits below
- * become unnecessary, and will go away.
- */
-struct iommu_dma_notifier_data {
-   struct list_head list;
-   struct device *dev;
-   const struct iommu_ops *ops;
-   u64 dma_base;
-   u64 size;
-};
-static LIST_HEAD(iommu_dma_masters);
-static DEFINE_MUTEX(iommu_dma_notifier_lock);
+static int __init __iommu_dma_init(void)
+{
+   return iommu_dma_init();
+}
+arch_initcall(__iommu_dma_init);
 
-static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
-  u64 dma_base, u64 size)
+static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+ const struct iommu_ops *ops)
 {
-   struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+   struct iommu_domain *domain;
+
+   if (!ops)
+   return;
 
/*
-* If the IOMMU driver has the DMA domain support that we require,
-* then the IOMMU core will have already configured a group for this
-* device, and allocated the default domain for that group.
+* The IOMMU core code allocates the default DMA domain, which the
+* underlying IOMMU driver needs to support via the dma-iommu layer.
 */
+   domain = iommu_get_domain_for_dev(dev);
+
if (!domain)
goto out_err;
 
@@ -851,109 +843,11 @@ static bool do_iommu_attach(struct device *dev, const 
struct iommu_ops *ops,
dev->dma_ops = _dma_ops;
}
 
-   return true;
+   return;
+
 out_err:
-   pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA 
ops\n",
+pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA 
ops\n",
 dev_name(dev));
-   return false;
-}
-
-static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
- u64 dma_base, u64 size)
-{
-   struct iommu_dma_notifier_data *iommudata;
-
-   iommudata = kzalloc(sizeof(*iommudata), GFP_KERNEL);
-   if (!iommudata)
-   return;
-
-   iommudata->dev = dev;
-   iommudata->ops = ops;
-   iommudata->dma_base = dma_base;
-   iommudata->size = size;
-
-   mutex_lock(_dma_notifier_lock);
-   list_add(>list, _dma_masters);
-   mutex_unlock(_dma_notifier_lock);
-}
-
-static int __iommu_attach_notifier(struct notifier_block *nb,
-  unsigned long action, void *data)
-{
-   struct iommu_dma_notifier_data *master, *tmp;
-
-   if (action != BUS_NOTIFY_BIND_DRIVER)
-   return 0;
-
-   mutex_lock(_dma_notifier_lock);
-   list_for_each_entry_safe(master, tmp, _dma_masters, list) {
-   if (data == master->dev && do_iommu_attach(master->dev,
-   master->ops, master->dma_base, master->size)) {
-   list_del(>list);
-   kfree(master);
-   break;
-   }
-   }
-   mutex_unlock(_dma_notifier_lock);
-   return 0;
-}
-
-static int __init register_iommu_dma_ops_notifier(struct bus_type *bus)
-{
-   struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL);
-   int ret;
-
-   if (!nb)
-   return -ENOMEM;
-
-   nb->notifier_call = __iommu_attach_notifier;
-
-   ret = bus_register_notifier(bus, nb);
-   if (ret) {
-   pr_warn("Failed to register DMA domain notifier; IOMMU DMA ops 
unavailable on bus '%s'\n",
-   bus->name);
-   kfree(nb);
-   }
-   return ret;
-}
-
-static int __init 

[PATCH V10 11/12] iommu/arm-smmu: Clean up early-probing workarounds

2017-04-04 Thread Sricharan R
From: Robin Murphy 

Now that the appropriate ordering is enforced via probe-deferral of
masters in core code, rip it all out and bask in the simplicity.

Tested-by: Hanjun Guo 
Acked-by: Will Deacon 
Signed-off-by: Robin Murphy 
[Sricharan: Rebased on top of ACPI IORT SMMU series]
Signed-off-by: Sricharan R 
---
 drivers/iommu/arm-smmu-v3.c |  46 +-
 drivers/iommu/arm-smmu.c| 110 +++-
 2 files changed, 49 insertions(+), 107 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 591bb96..4362139 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2761,51 +2761,9 @@ static int arm_smmu_device_remove(struct platform_device 
*pdev)
.probe  = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
 };
+module_platform_driver(arm_smmu_driver);
 
-static int __init arm_smmu_init(void)
-{
-   static bool registered;
-   int ret = 0;
-
-   if (!registered) {
-   ret = platform_driver_register(_smmu_driver);
-   registered = !ret;
-   }
-   return ret;
-}
-
-static void __exit arm_smmu_exit(void)
-{
-   return platform_driver_unregister(_smmu_driver);
-}
-
-subsys_initcall(arm_smmu_init);
-module_exit(arm_smmu_exit);
-
-static int __init arm_smmu_of_init(struct device_node *np)
-{
-   int ret = arm_smmu_init();
-
-   if (ret)
-   return ret;
-
-   if (!of_platform_device_create(np, NULL, platform_bus_type.dev_root))
-   return -ENODEV;
-
-   return 0;
-}
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
-
-#ifdef CONFIG_ACPI
-static int __init acpi_smmu_v3_init(struct acpi_table_header *table)
-{
-   if (iort_node_match(ACPI_IORT_NODE_SMMU_V3))
-   return arm_smmu_init();
-
-   return 0;
-}
-IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
-#endif
+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon ");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index b493c99..792fe7d 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2075,6 +2075,23 @@ static int arm_smmu_device_dt_probe(struct 
platform_device *pdev,
return 0;
 }
 
+static void arm_smmu_bus_init(void)
+{
+   /* Oh, for a proper bus abstraction */
+   if (!iommu_present(_bus_type))
+   bus_set_iommu(_bus_type, _smmu_ops);
+#ifdef CONFIG_ARM_AMBA
+   if (!iommu_present(_bustype))
+   bus_set_iommu(_bustype, _smmu_ops);
+#endif
+#ifdef CONFIG_PCI
+   if (!iommu_present(_bus_type)) {
+   pci_request_acs();
+   bus_set_iommu(_bus_type, _smmu_ops);
+   }
+#endif
+}
+
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
struct resource *res;
@@ -2180,21 +2197,30 @@ static int arm_smmu_device_probe(struct platform_device 
*pdev)
arm_smmu_device_reset(smmu);
arm_smmu_test_smr_masks(smmu);
 
-   /* Oh, for a proper bus abstraction */
-   if (!iommu_present(_bus_type))
-   bus_set_iommu(_bus_type, _smmu_ops);
-#ifdef CONFIG_ARM_AMBA
-   if (!iommu_present(_bustype))
-   bus_set_iommu(_bustype, _smmu_ops);
-#endif
-#ifdef CONFIG_PCI
-   if (!iommu_present(_bus_type)) {
-   pci_request_acs();
-   bus_set_iommu(_bus_type, _smmu_ops);
-   }
-#endif
+   /*
+* For ACPI and generic DT bindings, an SMMU will be probed before
+* any device which might need it, so we want the bus ops in place
+* ready to handle default domain setup as soon as any SMMU exists.
+*/
+   if (!using_legacy_binding)
+   arm_smmu_bus_init();
+
+   return 0;
+}
+
+/*
+ * With the legacy DT binding in play, though, we have no guarantees about
+ * probe order, but then we're also not doing default domains, so we can
+ * delay setting bus ops until we're sure every possible SMMU is ready,
+ * and that way ensure that no add_device() calls get missed.
+ */
+static int arm_smmu_legacy_bus_init(void)
+{
+   if (using_legacy_binding)
+   arm_smmu_bus_init();
return 0;
 }
+device_initcall_sync(arm_smmu_legacy_bus_init);
 
 static int arm_smmu_device_remove(struct platform_device *pdev)
 {
@@ -2219,56 +2245,14 @@ static int arm_smmu_device_remove(struct 
platform_device *pdev)
.probe  = arm_smmu_device_probe,
.remove = arm_smmu_device_remove,
 };
-
-static int __init arm_smmu_init(void)
-{
-   static bool registered;
-   int ret = 0;
-
-   if (!registered) {
-   ret = platform_driver_register(_smmu_driver);
-   registered = !ret;
-   }
-   return 

[PATCH V10 12/12] ACPI/IORT: Remove linker section for IORT entries probing

2017-04-04 Thread Sricharan R
From: Lorenzo Pieralisi 

The IORT linker section introduced by commit 34ceea275f62
("ACPI/IORT: Introduce linker section for IORT entries probing")
was needed to make sure SMMU drivers are registered (and therefore
probed) in the kernel before devices using the SMMU have a chance
to probe in turn.

Through the introduction of deferred IOMMU configuration the linker
section based IORT probing infrastructure is not needed any longer, in
that device/SMMU probe dependencies are managed through the probe
deferral mechanism, making the IORT linker section infrastructure
unused, so that it can be removed.

Remove the unused IORT linker section probing infrastructure
from the kernel to complete the ACPI IORT IOMMU configure probe
deferral mechanism implementation.

Tested-by: Hanjun Guo 
Signed-off-by: Lorenzo Pieralisi 
Cc: Robin Murphy 
Cc: Sricharan R 
---
 drivers/acpi/arm64/iort.c | 2 --
 include/asm-generic/vmlinux.lds.h | 1 -
 include/linux/acpi_iort.h | 3 ---
 3 files changed, 6 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index e323ece..e7b1940 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1000,6 +1000,4 @@ void __init acpi_iort_init(void)
}
 
iort_init_platform_devices();
-
-   acpi_probe_device_table(iort);
 }
diff --git a/include/asm-generic/vmlinux.lds.h 
b/include/asm-generic/vmlinux.lds.h
index 0968d13..9faa26c 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -566,7 +566,6 @@
IRQCHIP_OF_MATCH_TABLE()\
ACPI_PROBE_TABLE(irqchip)   \
ACPI_PROBE_TABLE(clksrc)\
-   ACPI_PROBE_TABLE(iort)  \
EARLYCON_TABLE()
 
 #define INIT_TEXT  \
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 77e0809..f167e1d04 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -52,7 +52,4 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev)
 { return NULL; }
 #endif
 
-#define IORT_ACPI_DECLARE(name, table_id, fn)  \
-   ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
-
 #endif /* __ACPI_IORT_H__ */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH V10 09/12] drivers: acpi: Handle IOMMU lookup failure with deferred probing or error

2017-04-04 Thread Sricharan R
This is an equivalent to the DT's handling of the iommu master's probe
with deferred probing when the corrsponding iommu is not probed yet.
The lack of a registered IOMMU can be caused by the lack of a driver for
the IOMMU, the IOMMU device probe not having been performed yet, having
been deferred, or having failed.

The first case occurs when the firmware describes the bus master and
IOMMU topology correctly but no device driver exists for the IOMMU yet
or the device driver has not been compiled in. Return NULL, the caller
will configure the device without an IOMMU.

The second and third cases are handled by deferring the probe of the bus
master device which will eventually get reprobed after the IOMMU.

The last case is currently handled by deferring the probe of the bus
master device as well. A mechanism to either configure the bus master
device without an IOMMU or to fail the bus master device probe depending
on whether the IOMMU is optional or mandatory would be a good
enhancement.

Tested-by: Hanjun Guo 
[Lorenzo: Added fixes for dma_coherent_mask overflow, acpi_dma_configure
  called multiple times for same device]
Signed-off-by: Lorenzo Pieralisi 
Signed-off-by: Sricharan R 
---

 [V10] Added Lorenzo's ACPI fix for coherent_dma_mask overflow
   and the fix for dma_configure getting called more than
   once for the same device.

 drivers/acpi/arm64/iort.c  | 33 -
 drivers/acpi/scan.c| 11 ---
 drivers/base/dma-mapping.c |  2 +-
 include/acpi/acpi_bus.h|  2 +-
 include/linux/acpi.h   |  7 +--
 5 files changed, 47 insertions(+), 8 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 3dd9ec3..e323ece 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -543,6 +543,14 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
device *dev,
const struct iommu_ops *ops = NULL;
int ret = -ENODEV;
struct fwnode_handle *iort_fwnode;
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+   /*
+* If we already translated the fwspec there
+* is nothing left to do, return the iommu_ops.
+*/
+   if (fwspec && fwspec->ops)
+   return fwspec->ops;
 
if (node) {
iort_fwnode = iort_get_fwnode(node);
@@ -550,8 +558,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct 
device *dev,
return NULL;
 
ops = iommu_ops_from_fwnode(iort_fwnode);
+   /*
+* If the ops look-up fails, this means that either
+* the SMMU drivers have not been probed yet or that
+* the SMMU drivers are not built in the kernel;
+* Depending on whether the SMMU drivers are built-in
+* in the kernel or not, defer the IOMMU configuration
+* or just abort it.
+*/
if (!ops)
-   return NULL;
+   return iort_iommu_driver_enabled(node->type) ?
+  ERR_PTR(-EPROBE_DEFER) : NULL;
 
ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
}
@@ -625,12 +642,26 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
 
while (parent) {
ops = iort_iommu_xlate(dev, parent, streamid);
+   if (IS_ERR_OR_NULL(ops))
+   return ops;
 
parent = iort_node_get_id(node, ,
  IORT_IOMMU_TYPE, i++);
}
}
 
+   /*
+* If we have reason to believe the IOMMU driver missed the initial
+* add_device callback for dev, replay it to get things in order.
+*/
+   if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
+   dev->bus && !dev->iommu_group) {
+   int err = ops->add_device(dev);
+
+   if (err)
+   ops = ERR_PTR(err);
+   }
+
return ops;
 }
 
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1926918..2a513cc 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1373,20 +1373,25 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device 
*adev)
  * @dev: The pointer to the device
  * @attr: device dma attributes
  */
-void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
 {
const struct iommu_ops *iommu;
+   u64 size;
 
iort_set_dma_mask(dev);
 
iommu = iort_iommu_configure(dev);
+   if (IS_ERR(iommu))
+   return PTR_ERR(iommu);
 
+   size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
/*
 * Assume dma valid range starts at 0 and covers the whole
 

[PATCH V10 08/12] iommu: of: Handle IOMMU lookup failure with deferred probing or error

2017-04-04 Thread Sricharan R
From: Laurent Pinchart 

Failures to look up an IOMMU when parsing the DT iommus property need to
be handled separately from the .of_xlate() failures to support deferred
probing.

The lack of a registered IOMMU can be caused by the lack of a driver for
the IOMMU, the IOMMU device probe not having been performed yet, having
been deferred, or having failed.

The first case occurs when the device tree describes the bus master and
IOMMU topology correctly but no device driver exists for the IOMMU yet
or the device driver has not been compiled in. Return NULL, the caller
will configure the device without an IOMMU.

The second and third cases are handled by deferring the probe of the bus
master device which will eventually get reprobed after the IOMMU.

The last case is currently handled by deferring the probe of the bus
master device as well. A mechanism to either configure the bus master
device without an IOMMU or to fail the bus master device probe depending
on whether the IOMMU is optional or mandatory would be a good
enhancement.

Tested-by: Marek Szyprowski 
Signed-off-by: Laurent Pichart 
Signed-off-by: Sricharan R 
---
 drivers/base/dma-mapping.c | 5 +++--
 drivers/iommu/of_iommu.c   | 4 ++--
 drivers/of/device.c| 7 ++-
 include/linux/of_device.h  | 9 ++---
 4 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 449b948..82bd45c 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -353,6 +353,7 @@ int dma_configure(struct device *dev)
 {
struct device *bridge = NULL, *dma_dev = dev;
enum dev_dma_attr attr;
+   int ret = 0;
 
if (dev_is_pci(dev)) {
bridge = pci_get_host_bridge_device(to_pci_dev(dev));
@@ -363,7 +364,7 @@ int dma_configure(struct device *dev)
}
 
if (dma_dev->of_node) {
-   of_dma_configure(dev, dma_dev->of_node);
+   ret = of_dma_configure(dev, dma_dev->of_node);
} else if (has_acpi_companion(dma_dev)) {
attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
if (attr != DEV_DMA_NOT_SUPPORTED)
@@ -373,7 +374,7 @@ int dma_configure(struct device *dev)
if (bridge)
pci_put_host_bridge_device(bridge);
 
-   return 0;
+   return ret;
 }
 
 void dma_deconfigure(struct device *dev)
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index c8be889..9f44ee8 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -236,7 +236,7 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
ops = ERR_PTR(err);
}
 
-   return IS_ERR(ops) ? NULL : ops;
+   return ops;
 }
 
 static int __init of_iommu_init(void)
@@ -247,7 +247,7 @@ static int __init of_iommu_init(void)
for_each_matching_node_and_match(np, matches, ) {
const of_iommu_init_fn init_fn = match->data;
 
-   if (init_fn(np))
+   if (init_fn && init_fn(np))
pr_err("Failed to initialise IOMMU %s\n",
of_node_full_name(np));
}
diff --git a/drivers/of/device.c b/drivers/of/device.c
index c2ae6bb..bea8aec 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -82,7 +82,7 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-void of_dma_configure(struct device *dev, struct device_node *np)
+int of_dma_configure(struct device *dev, struct device_node *np)
 {
u64 dma_addr, paddr, size;
int ret;
@@ -129,10 +129,15 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
coherent ? " " : " not ");
 
iommu = of_iommu_configure(dev, np);
+   if (IS_ERR(iommu))
+   return PTR_ERR(iommu);
+
dev_dbg(dev, "device is%sbehind an iommu\n",
iommu ? " " : " not ");
 
arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
+
+   return 0;
 }
 EXPORT_SYMBOL_GPL(of_dma_configure);
 
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index af98455..2cacdd8 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -55,7 +55,7 @@ static inline struct device_node *of_cpu_device_node_get(int 
cpu)
return of_node_get(cpu_dev->of_node);
 }
 
-void of_dma_configure(struct device *dev, struct device_node *np);
+int of_dma_configure(struct device *dev, struct device_node *np);
 void of_dma_deconfigure(struct device *dev);
 #else /* CONFIG_OF */
 
@@ -104,8 +104,11 @@ static inline struct device_node 
*of_cpu_device_node_get(int cpu)
 {
return NULL;
 }
-static inline void of_dma_configure(struct device *dev, struct 

[PATCH V10 02/12] iommu/of: Prepare for deferred IOMMU configuration

2017-04-04 Thread Sricharan R
From: Robin Murphy 

IOMMU configuration represents unchanging properties of the hardware,
and as such should only need happen once in a device's lifetime, but
the necessary interaction with the IOMMU device and driver complicates
exactly when that point should be.

Since the only reasonable tool available for handling the inter-device
dependency is probe deferral, we need to prepare of_iommu_configure()
to run later than it is currently called (i.e. at driver probe rather
than device creation), to handle being retried, and to tell whether a
not-yet present IOMMU should be waited for or skipped (by virtue of
having declared a built-in driver or not).

Tested-by: Marek Szyprowski 
Signed-off-by: Robin Murphy 
---
 drivers/iommu/of_iommu.c | 43 ++-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 8f4e599..c8be889 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,6 +96,19 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
+static bool of_iommu_driver_present(struct device_node *np)
+{
+   /*
+* If the IOMMU still isn't ready by the time we reach init, assume
+* it never will be. We don't want to defer indefinitely, nor attempt
+* to dereference __iommu_of_table after it's been freed.
+*/
+   if (system_state > SYSTEM_BOOTING)
+   return false;
+
+   return of_match_node(&__iommu_of_table, np);
+}
+
 static const struct iommu_ops
 *of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
 {
@@ -104,12 +117,20 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
int err;
 
ops = iommu_ops_from_fwnode(fwnode);
-   if (!ops || !ops->of_xlate)
+   if ((ops && !ops->of_xlate) ||
+   (!ops && !of_iommu_driver_present(iommu_spec->np)))
return NULL;
 
err = iommu_fwspec_init(dev, _spec->np->fwnode, ops);
if (err)
return ERR_PTR(err);
+   /*
+* The otherwise-empty fwspec handily serves to indicate the specific
+* IOMMU device we're waiting for, which will be useful if we ever get
+* a proper probe-ordering dependency mechanism in future.
+*/
+   if (!ops)
+   return ERR_PTR(-EPROBE_DEFER);
 
err = ops->of_xlate(dev, iommu_spec);
if (err)
@@ -186,14 +207,34 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
   struct device_node *master_np)
 {
const struct iommu_ops *ops;
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
 
if (!master_np)
return NULL;
 
+   if (fwspec) {
+   if (fwspec->ops)
+   return fwspec->ops;
+
+   /* In the deferred case, start again from scratch */
+   iommu_fwspec_free(dev);
+   }
+
if (dev_is_pci(dev))
ops = of_pci_iommu_init(to_pci_dev(dev), master_np);
else
ops = of_platform_iommu_init(dev, master_np);
+   /*
+* If we have reason to believe the IOMMU driver missed the initial
+* add_device callback for dev, replay it to get things in order.
+*/
+   if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
+   dev->bus && !dev->iommu_group) {
+   int err = ops->add_device(dev);
+
+   if (err)
+   ops = ERR_PTR(err);
+   }
 
return IS_ERR(ops) ? NULL : ops;
 }
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH V10 06/12] of: device: Fix overflow of coherent_dma_mask

2017-04-04 Thread Sricharan R
Size of the dma-range is calculated as coherent_dma_mask + 1
and passed to arch_setup_dma_ops further. It overflows when
the coherent_dma_mask is set for full 64 bits 0x,
resulting in size getting passed as 0 wrongly. Fix this by
passsing in max(mask, mask + 1). Note that in this case
when the mask is set to full 64bits, we will be passing the mask
itself to arch_setup_dma_ops instead of the size. The real fix
for this should be to make arch_setup_dma_ops receive the
mask and handle it, to be done in the future.

Signed-off-by: Sricharan R 
---
 drivers/of/device.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/of/device.c b/drivers/of/device.c
index c17c19d..c2ae6bb 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -107,7 +107,7 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
ret = of_dma_get_range(np, _addr, , );
if (ret < 0) {
dma_addr = offset = 0;
-   size = dev->coherent_dma_mask + 1;
+   size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
} else {
offset = PFN_DOWN(paddr - dma_addr);
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH V10 03/12] of: dma: Move range size workaround to of_dma_get_range()

2017-04-04 Thread Sricharan R
From: Laurent Pinchart 

Invalid dma-ranges values should be worked around when retrieving the
DMA range in of_dma_get_range(), not by all callers of the function.
This isn't much of a problem now that we have a single caller, but that
situation will change when moving DMA configuration to device probe
time.

Tested-by: Marek Szyprowski 
Signed-off-by: Laurent Pinchart 
---
 drivers/of/address.c | 20 ++--
 drivers/of/device.c  | 15 ---
 2 files changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 02b2903..6aeb816 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -819,8 +819,8 @@ void __iomem *of_io_request_and_map(struct device_node *np, 
int index,
  * CPU addr (phys_addr_t)  : pna cells
  * size: nsize cells
  *
- * It returns -ENODEV if "dma-ranges" property was not found
- * for this device in DT.
+ * Return 0 on success, -ENODEV if the "dma-ranges" property was not found for
+ * this device in DT, or -EINVAL if the CPU address or size is invalid.
  */
 int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 
*size)
 {
@@ -880,6 +880,22 @@ int of_dma_get_range(struct device_node *np, u64 
*dma_addr, u64 *paddr, u64 *siz
*dma_addr = dmaaddr;
 
*size = of_read_number(ranges + naddr + pna, nsize);
+   /*
+* DT nodes sometimes incorrectly set the size as a mask. Work around
+* those incorrect DT by computing the size as mask + 1.
+*/
+   if (*size & 1) {
+   pr_warn("%s: size 0x%llx for dma-range in node(%s) set as 
mask\n",
+   __func__, *size, np->full_name);
+   *size = *size + 1;
+   }
+
+   if (!*size) {
+   pr_err("%s: invalid size zero for dma-range in node(%s)\n",
+  __func__, np->full_name);
+   ret = -EINVAL;
+   goto out;
+   }
 
pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n",
 *dma_addr, *paddr, *size);
diff --git a/drivers/of/device.c b/drivers/of/device.c
index b1e6beb..09dedd0 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -110,21 +110,6 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
size = dev->coherent_dma_mask + 1;
} else {
offset = PFN_DOWN(paddr - dma_addr);
-
-   /*
-* Add a work around to treat the size as mask + 1 in case
-* it is defined in DT as a mask.
-*/
-   if (size & 1) {
-   dev_warn(dev, "Invalid size 0x%llx for dma-range\n",
-size);
-   size = size + 1;
-   }
-
-   if (!size) {
-   dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
-   return;
-   }
dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
}
 
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH V10 07/12] of/acpi: Configure dma operations at probe time for platform/amba/pci bus devices

2017-04-04 Thread Sricharan R
Configuring DMA ops at probe time will allow deferring device probe when
the IOMMU isn't available yet. The dma_configure for the device is
now called from the generic device_attach callback just before the
bus/driver probe is called. This way, configuring the DMA ops for the
device would be called at the same place for all bus_types, hence the
deferred probing mechanism should work for all buses as well.

pci_bus_add_devices(platform/amba)(_device_create/driver_register)
   | |
pci_bus_add_device (device_add/driver_register)
   | |
device_attach   device_initial_probe
   | |
__device_attach_driver__device_attach_driver
   |
driver_probe_device
   |
really_probe
   |
dma_configure

Similarly on the device/driver_unregister path __device_release_driver is
called which inturn calls dma_deconfigure.

This patch changes the dma ops configuration to probe time for
both OF and ACPI based platform/amba/pci bus devices.

Tested-by: Marek Szyprowski 
Tested-by: Hanjun Guo 
Acked-by: Bjorn Helgaas  (drivers/pci part)
Acked-by: Rafael J. Wysocki 
Signed-off-by: Sricharan R 
---

 [V10] Added dummy dma_(de)configure functions in case
   of !CONFIG_HAS_DMA to avoid build breaks.

 drivers/acpi/glue.c |  5 -
 drivers/base/dd.c   |  9 +
 drivers/base/dma-mapping.c  | 40 
 drivers/of/platform.c   |  5 +
 drivers/pci/probe.c | 28 
 include/linux/dma-mapping.h | 12 
 6 files changed, 62 insertions(+), 37 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index fb19e1c..c05f241 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -176,7 +176,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
struct list_head *physnode_list;
unsigned int node_id;
int retval = -EINVAL;
-   enum dev_dma_attr attr;
 
if (has_acpi_companion(dev)) {
if (acpi_dev) {
@@ -233,10 +232,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device 
*acpi_dev)
if (!has_acpi_companion(dev))
ACPI_COMPANION_SET(dev, acpi_dev);
 
-   attr = acpi_get_dma_attr(acpi_dev);
-   if (attr != DEV_DMA_NOT_SUPPORTED)
-   acpi_dma_configure(dev, attr);
-
acpi_physnode_link_name(physical_node_name, node_id);
retval = sysfs_create_link(_dev->dev.kobj, >kobj,
   physical_node_name);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a1fbf55..4882f06 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -356,6 +357,10 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
if (ret)
goto pinctrl_bind_failed;
 
+   ret = dma_configure(dev);
+   if (ret)
+   goto dma_failed;
+
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
@@ -417,6 +422,8 @@ static int really_probe(struct device *dev, struct 
device_driver *drv)
goto done;
 
 probe_failed:
+   dma_deconfigure(dev);
+dma_failed:
if (dev->bus)
blocking_notifier_call_chain(>bus->p->bus_notifier,
 BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
@@ -826,6 +833,8 @@ static void __device_release_driver(struct device *dev, 
struct device *parent)
drv->remove(dev);
 
device_links_driver_cleanup(dev);
+   dma_deconfigure(dev);
+
devres_release_all(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index efd71cf..449b948 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -7,9 +7,11 @@
  * This file is released under the GPLv2.
  */
 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -341,3 +343,41 @@ void dma_common_free_remap(void *cpu_addr, size_t size, 
unsigned long vm_flags)
vunmap(cpu_addr);
 }
 #endif
+
+/*
+ * Common configuration to enable DMA API use for a device
+ */
+#include 
+
+int dma_configure(struct device *dev)
+{
+   struct device *bridge = NULL, *dma_dev = dev;
+   enum dev_dma_attr attr;
+
+   if (dev_is_pci(dev)) {
+   bridge = pci_get_host_bridge_device(to_pci_dev(dev));
+   dma_dev = bridge;
+   if (IS_ENABLED(CONFIG_OF) && dma_dev->parent &&
+   dma_dev->parent->of_node)
+   dma_dev = dma_dev->parent;
+   }
+
+  

[PATCH V10 04/12] of: dma: Make of_dma_deconfigure() public

2017-04-04 Thread Sricharan R
From: Laurent Pinchart 

As part of moving DMA initializing to probe time the
of_dma_deconfigure() function will need to be called from different
source files. Make it public and move it to drivers/of/device.c where
the of_dma_configure() function is.

Tested-by: Marek Szyprowski 
Signed-off-by: Laurent Pinchart 
---
 drivers/of/device.c   | 12 
 drivers/of/platform.c |  5 -
 include/linux/of_device.h |  3 +++
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/of/device.c b/drivers/of/device.c
index 09dedd0..c17c19d 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -136,6 +136,18 @@ void of_dma_configure(struct device *dev, struct 
device_node *np)
 }
 EXPORT_SYMBOL_GPL(of_dma_configure);
 
+/**
+ * of_dma_deconfigure - Clean up DMA configuration
+ * @dev:   Device for which to clean up DMA configuration
+ *
+ * Clean up all configuration performed by of_dma_configure_ops() and free all
+ * resources that have been allocated.
+ */
+void of_dma_deconfigure(struct device *dev)
+{
+   arch_teardown_dma_ops(dev);
+}
+
 int of_device_register(struct platform_device *pdev)
 {
device_initialize(>dev);
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 5dfcc96..5344db5 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -158,11 +158,6 @@ struct platform_device *of_device_alloc(struct device_node 
*np,
 }
 EXPORT_SYMBOL(of_device_alloc);
 
-static void of_dma_deconfigure(struct device *dev)
-{
-   arch_teardown_dma_ops(dev);
-}
-
 /**
  * of_platform_device_create_pdata - Alloc, initialize and register an 
of_device
  * @np: pointer to node to create device for
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index c12dace..af98455 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -56,6 +56,7 @@ static inline struct device_node *of_cpu_device_node_get(int 
cpu)
 }
 
 void of_dma_configure(struct device *dev, struct device_node *np);
+void of_dma_deconfigure(struct device *dev);
 #else /* CONFIG_OF */
 
 static inline int of_driver_match_device(struct device *dev,
@@ -105,6 +106,8 @@ static inline struct device_node 
*of_cpu_device_node_get(int cpu)
 }
 static inline void of_dma_configure(struct device *dev, struct device_node *np)
 {}
+static inline void of_dma_deconfigure(struct device *dev)
+{}
 #endif /* CONFIG_OF */
 
 #endif /* _LINUX_OF_DEVICE_H */
-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
Code Aurora Forum, hosted by The Linux Foundation

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH V10 01/12] iommu/of: Refactor of_iommu_configure() for error handling

2017-04-04 Thread Sricharan R
From: Robin Murphy 

In preparation for some upcoming cleverness, rework the control flow in
of_iommu_configure() to minimise duplication and improve the propogation
of errors. It's also as good a time as any to switch over from the
now-just-a-compatibility-wrapper of_iommu_get_ops() to using the generic
IOMMU instance interface directly.

Tested-by: Marek Szyprowski 
Signed-off-by: Robin Murphy 
---
 drivers/iommu/of_iommu.c | 83 +++-
 1 file changed, 53 insertions(+), 30 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 2683e9f..8f4e599 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -96,6 +96,28 @@ int of_get_dma_window(struct device_node *dn, const char 
*prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
+static const struct iommu_ops
+*of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
+{
+   const struct iommu_ops *ops;
+   struct fwnode_handle *fwnode = _spec->np->fwnode;
+   int err;
+
+   ops = iommu_ops_from_fwnode(fwnode);
+   if (!ops || !ops->of_xlate)
+   return NULL;
+
+   err = iommu_fwspec_init(dev, _spec->np->fwnode, ops);
+   if (err)
+   return ERR_PTR(err);
+
+   err = ops->of_xlate(dev, iommu_spec);
+   if (err)
+   return ERR_PTR(err);
+
+   return ops;
+}
+
 static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
 {
struct of_phandle_args *iommu_spec = data;
@@ -105,10 +127,11 @@ static int __get_pci_rid(struct pci_dev *pdev, u16 alias, 
void *data)
 }
 
 static const struct iommu_ops
-*of_pci_iommu_configure(struct pci_dev *pdev, struct device_node *bridge_np)
+*of_pci_iommu_init(struct pci_dev *pdev, struct device_node *bridge_np)
 {
const struct iommu_ops *ops;
struct of_phandle_args iommu_spec;
+   int err;
 
/*
 * Start by tracing the RID alias down the PCI topology as
@@ -123,56 +146,56 @@ static int __get_pci_rid(struct pci_dev *pdev, u16 alias, 
void *data)
 * bus into the system beyond, and which IOMMU it ends up at.
 */
iommu_spec.np = NULL;
-   if (of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
-  "iommu-map-mask", _spec.np, iommu_spec.args))
-   return NULL;
+   err = of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
+"iommu-map-mask", _spec.np,
+iommu_spec.args);
+   if (err)
+   return err == -ENODEV ? NULL : ERR_PTR(err);
 
-   ops = iommu_ops_from_fwnode(_spec.np->fwnode);
-   if (!ops || !ops->of_xlate ||
-   iommu_fwspec_init(>dev, _spec.np->fwnode, ops) ||
-   ops->of_xlate(>dev, _spec))
-   ops = NULL;
+   ops = of_iommu_xlate(>dev, _spec);
 
of_node_put(iommu_spec.np);
return ops;
 }
 
-const struct iommu_ops *of_iommu_configure(struct device *dev,
-  struct device_node *master_np)
+static const struct iommu_ops
+*of_platform_iommu_init(struct device *dev, struct device_node *np)
 {
struct of_phandle_args iommu_spec;
-   struct device_node *np;
const struct iommu_ops *ops = NULL;
int idx = 0;
 
-   if (dev_is_pci(dev))
-   return of_pci_iommu_configure(to_pci_dev(dev), master_np);
-
/*
 * We don't currently walk up the tree looking for a parent IOMMU.
 * See the `Notes:' section of
 * Documentation/devicetree/bindings/iommu/iommu.txt
 */
-   while (!of_parse_phandle_with_args(master_np, "iommus",
-  "#iommu-cells", idx,
-  _spec)) {
-   np = iommu_spec.np;
-   ops = iommu_ops_from_fwnode(>fwnode);
-
-   if (!ops || !ops->of_xlate ||
-   iommu_fwspec_init(dev, >fwnode, ops) ||
-   ops->of_xlate(dev, _spec))
-   goto err_put_node;
-
-   of_node_put(np);
+   while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells",
+  idx, _spec)) {
+   ops = of_iommu_xlate(dev, _spec);
+   of_node_put(iommu_spec.np);
idx++;
+   if (IS_ERR_OR_NULL(ops))
+   break;
}
 
return ops;
+}
+
+const struct iommu_ops *of_iommu_configure(struct device *dev,
+  struct device_node *master_np)
+{
+   const struct iommu_ops *ops;
+
+   if (!master_np)
+   return NULL;
+
+   if (dev_is_pci(dev))
+   ops = of_pci_iommu_init(to_pci_dev(dev), master_np);
+   else
+   ops = of_platform_iommu_init(dev, master_np);
 

[PATCH V10 00/12] IOMMU probe deferral support

2017-04-04 Thread Sricharan R
This series calls the dma ops configuration for the devices
at a generic place so that it works for all busses.
The dma_configure_ops for a device is now called during
the device_attach callback just before the probe of the
bus/driver is called. Similarly dma_deconfigure is called during
device/driver_detach path.

pci_bus_add_devices(platform/amba)(_device_create/driver_register)
   | |
pci_bus_add_device (device_add/driver_register)
   | |
device_attach   device_initial_probe
   | |
__device_attach_driver__device_attach_driver
   |
driver_probe_device
   |
really_probe
   |
dma_configure

Similarly on the device/driver_unregister path __device_release_driver is
called which inturn calls dma_deconfigure.

Rebased the series against mainline 4.11-rc5. Applies and builds cleanly
against mainline and linux-next, iommu-next.
  
* Tested with platform and pci devices for probe deferral
  and reprobe on arm64 based platform.

Previous post of this series [8]. 

Please note that, i have kept the tested/acked tags intact from V8
because V9/10 were for more fixes that was added, so the original
tags that was given for the functional testing remains the same.

 [V10]
 * Rebased on top of 4.11-rc5.
 
 * Fixed coherent_dma_mask 64bit overflow issue [8]
   for OF. The fix for OF was added as a separate
   patch#6, since the issue is true even without probe deferral,
   but gets reproduced with the probe deferral series.
   Added Lorenzo's ACPI fix for coherent_dma_mask overflow
   and the fix for dma_configure getting called more than
   once for the same device.

 * Also fixed an build issue caught by kbuild robot for
   m68k arch. The issue was dma_(de)configure was not
   getting defined for !CONFIG_HAS_DMA, so fixed that as well.

 [V9]
 * Rebased on top of 4.11-rc1.

 * Merged Robin's fixes for legacy binding issue,
   pci devices with no iommu-map property and deferencing
   of_iommu_table after init.
 
 [V8]
 * Picked up all the acks and tested tags from Marek and
   Hanjun for DT and ACPI patches respectively, since
   no functional changes was done.

 * Addressed Minor comments Sinan and Bjorn.

 * Added Robin's fix for fixing the deferencing NULL for
   of_iommu_table after init in patch #2.

 * Rebased it on top of linux-next

 [V7]
 * Updated the subject and commit log for patch #6 as per
   comments from Lorenzo. No functional changes.

 [V6]
 * Fixed a bug in dma_configure function pointed out by
   Robin.
 * Reordered the patches as per comments from Robin and
   Lorenzo.
 * Added Tags.

 [V5]
 * Reworked the pci configuration code hanging outside and
   pushed it to dma_configure as in PATCH#5,6,7.
   Also added a couple of patches that Lorenzo provided for
   correcting the Probe deferring mechanism in case of
   ACPI devices from here [5].

 [V4]
 * Took the reworked patches [2] from Robin's branch and
   rebased on top of Lorenzo's ACPI IORT ARM support series [3].

 * Added the patches for moving the dma ops configuration of
   acpi based devices to probe time as well.
 [V3]
 * Removed the patch to split dma_masks/dma_ops configuration
   separately based on review comments that both masks and ops are
   required only during the device probe time.

 * Reworked the series based on Generic DT bindings series.

 * Added call to iommu's remove_device in the cleanup path for arm and
   arm64.

 * Removed the notifier trick in arm64 to handle early device
   registration.

 * Added reset of dma_ops in cleanup path for arm based on comments.

 * Fixed the pci_iommu_configure path and tested with PCI device as
   well.
 
 * Fixed a bug to return the correct iommu_ops from patch 7 [4] in
   last post.

 * Fixed few other cosmetic comments.
  
 [V2]
 * Updated the Initial post to call dma_configure/deconfigure from
   generic code
 
 * Added iommu add_device callback from of_iommu_configure path

 [V1]
 * Initial post from Laurent Pinchart [1]

[1] http://lists.linuxfoundation.org/pipermail/iommu/2015-May/013016.html
[2] 
http://www.linux-arm.org/git?p=linux-rm.git;a=shortlog;h=refs/heads/iommu/defer
[3] https://lkml.org/lkml/2016/11/21/141
[4] https://www.mail-archive.com/iommu@xx/msg13940.html
[5] git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/linux.git 
iommu/probe-deferral
[6] http://www.spinics.net/lists/linux-pci/msg57992.html
[7] https://www.spinics.net/lists/arm-kernel/msg556209.html
[8] http://patchwork.ozlabs.org/patch/743898/

Laurent Pinchart (3):
  of: dma: Move range size workaround to of_dma_get_range()
  of: dma: Make of_dma_deconfigure() public
  iommu: of: Handle IOMMU lookup failure with deferred probing or error