Re: [PATCH 2/4] iommu/arm-smmu: Allow disabling unmatched stream bypass

2016-02-09 Thread Will Deacon
Hi Robin,

On Tue, Jan 26, 2016 at 06:06:35PM +, Robin Murphy wrote:
> Borrow the disable_bypass parameter from the SMMUv3 driver as a handy
> debugging/security feature so that unmatched stream IDs (i.e. devices
> not attached to an IOMMU domain) may be configured to fault.
> 
> Signed-off-by: Robin Murphy 
> ---
>  drivers/iommu/arm-smmu.c | 32 +++-
>  1 file changed, 23 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 1f9093d..d1b7dc1 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -141,6 +141,8 @@
>  #define ID2_PTFS_16K (1 << 13)
>  #define ID2_PTFS_64K (1 << 14)
>  
> +#define sGFSR_USF(1 << 1)
> +
>  /* Global TLB invalidation */
>  #define ARM_SMMU_GR0_TLBIVMID0x64
>  #define ARM_SMMU_GR0_TLBIALLNSNH 0x68
> @@ -263,6 +265,10 @@ static int force_stage;
>  module_param_named(force_stage, force_stage, int, S_IRUGO);
>  MODULE_PARM_DESC(force_stage,
>   "Force SMMU mappings to be installed at a particular stage of 
> translation. A value of '1' or '2' forces the corresponding stage. All other 
> values are ignored (i.e. no stage is forced). Note that selecting a specific 
> stage will disable support for nested translation.");
> +static bool disable_bypass;
> +module_param_named(disable_bypass, disable_bypass, bool, S_IRUGO);
> +MODULE_PARM_DESC(disable_bypass,
> + "Disable bypass streams such that incoming transactions from devices 
> that are not attached to an iommu domain will report an abort back to the 
> device and will not be allowed to pass through the SMMU.");
>  
>  enum arm_smmu_arch_version {
>   ARM_SMMU_V1 = 1,
> @@ -704,8 +710,12 @@ static irqreturn_t arm_smmu_global_fault(int irq, void 
> *dev)
>   if (!gfsr)
>   return IRQ_NONE;
>  
> - dev_err_ratelimited(smmu->dev,
> - "Unexpected global fault, this could be serious\n");
> + if (gfsr & sGFSR_USF)
> + dev_err_ratelimited(smmu->dev, "Unmatched stream fault: ID 
> 0x%x\n",
> + gfsynr1 & SMR_ID_MASK);
> + else

I think I'd rather drop this message -- a global error is still indicative
that something has gone horriby wrong, and we already print the gsynr
registers below. Furthermore, if we take multiple faults, it might look
like they're all exclusively due to unmatched streams.

On top of that, I'm not convinced that USF will be set for an SMMU that
doesn't implement stream-matching (because it will match an S2CR of type
FAULT).

Other than that, looks good.

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


Re: [PATCH 4/4] iommu/arm-smmu: Use per-context TLB sync as appropriate

2016-02-09 Thread Will Deacon
On Tue, Jan 26, 2016 at 06:06:37PM +, Robin Murphy wrote:
> TLB synchronisation is a mighty big hammmer to bring down on the
> transaction stream, typically stalling all in-flight transactions until
> the sync completes. Since in most cases (except at stage 2 on SMMUv1)
> a per-context sync operation is available, prefer that over the global
> operation when performing TLB maintenance for a single domain, to avoid
> unecessarily disrupting ongoing traffic in other contexts.
> 
> Signed-off-by: Robin Murphy 
> ---
>  drivers/iommu/arm-smmu.c | 32 
>  1 file changed, 24 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 18e0e10..bf1895c 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -219,6 +219,8 @@
>  #define ARM_SMMU_CB_S1_TLBIVAL   0x620
>  #define ARM_SMMU_CB_S2_TLBIIPAS2 0x630
>  #define ARM_SMMU_CB_S2_TLBIIPAS2L0x638
> +#define ARM_SMMU_CB_TLBSYNC  0x7f0
> +#define ARM_SMMU_CB_TLBSTATUS0x7f4
>  #define ARM_SMMU_CB_ATS1PR   0x800
>  #define ARM_SMMU_CB_ATSR 0x8f0
>  
> @@ -546,14 +548,22 @@ static void __arm_smmu_free_bitmap(unsigned long *map, 
> int idx)
>  }
>  
>  /* Wait for any pending TLB invalidations to complete */
> -static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
> +static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, int cbndx)
>  {
>   int count = 0;
> - void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
> + void __iomem *base, __iomem *status;
>  
> - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_sTLBGSYNC);
> - while (readl_relaxed(gr0_base + ARM_SMMU_GR0_sTLBGSTATUS)
> -& sTLBGSTATUS_GSACTIVE) {
> + if (cbndx < 0) {
> + base = ARM_SMMU_GR0(smmu);
> + status = base + ARM_SMMU_GR0_sTLBGSTATUS;
> + writel_relaxed(0, base + ARM_SMMU_GR0_sTLBGSYNC);
> + } else {
> + base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cbndx);
> + status = base + ARM_SMMU_CB_TLBSTATUS;
> + writel_relaxed(0, base + ARM_SMMU_CB_TLBSYNC);
> + }
> +
> + while (readl_relaxed(status) & sTLBGSTATUS_GSACTIVE) {
>   cpu_relax();
>   if (++count == TLB_LOOP_TIMEOUT) {
>   dev_err_ratelimited(smmu->dev,
> @@ -567,7 +577,13 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device 
> *smmu)
>  static void arm_smmu_tlb_sync(void *cookie)
>  {
>   struct arm_smmu_domain *smmu_domain = cookie;
> - __arm_smmu_tlb_sync(smmu_domain->smmu);
> + int cbndx = smmu_domain->cfg.cbndx;
> +
> + if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2 &&
> + smmu_domain->smmu->version < ARM_SMMU_V2)
> + cbndx = -1;

I think it would be cleaner just to override the sync function pointer
when we initialise a stage-2 page table for an SMMUv1 implementation.

Any reason not to go that way?

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


Re: [PATCH 1/4] iommu/arm-smmu: Treat all device transactions as unprivileged

2016-02-09 Thread Will Deacon
On Tue, Jan 26, 2016 at 06:06:34PM +, Robin Murphy wrote:
> The IOMMU API has no concept of privilege so assumes all devices and
> mappings are equal, and indeed most non-CPU master devices on an AMBA
> interconnect make little use of the attribute bits on the bus thus by
> default perform unprivileged data accesses.
> 
> Some devices, however, believe themselves more equal than others, such
> as programmable DMA controllers whose 'master' thread issues bus
> transactions marked as privileged instruction fetches, while the data
> accesses of its channel threads (under the control of Linux, at least)
> are marked as unprivileged. This poses a problem for implementing the
> DMA API on an IOMMU conforming to ARM VMSAv8, under which a page that is
> unprivileged-writeable is also implicitly privileged-execute-never.
> Given that, there is no one set of attributes with which iommu_map() can
> implement, say, dma_alloc_coherent() that will allow every possible type
> of access without something running into unexecepted permission faults.
> 
> Fortunately the SMMU architecture provides a means to mitigate such
> issues by overriding the incoming attributes of a transaction; make use
> of that to strip the privileged/unprivileged status off incoming
> transactions, leaving just the instruction/data dichotomy which the
> IOMMU API does at least understand; Four states good, two states better.
> 
> Signed-off-by: Robin Murphy 
> ---
>  drivers/iommu/arm-smmu.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 59ee4b8..1f9093d 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -167,6 +167,9 @@
>  #define S2CR_TYPE_BYPASS (1 << S2CR_TYPE_SHIFT)
>  #define S2CR_TYPE_FAULT  (2 << S2CR_TYPE_SHIFT)
>  
> +#define S2CR_PRIVCFG_SHIFT   24
> +#define S2CR_PRIVCFG_UNPRIV  (2 << S2CR_PRIVCFG_SHIFT)
> +
>  /* Context bank attribute registers */
>  #define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
>  #define CBAR_VMID_SHIFT  0
> @@ -1083,7 +1086,7 @@ static int arm_smmu_domain_add_master(struct 
> arm_smmu_domain *smmu_domain,
>   u32 idx, s2cr;
>  
>   idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
> - s2cr = S2CR_TYPE_TRANS |
> + s2cr = S2CR_TYPE_TRANS | S2CR_PRIVCFG_UNPRIV |
>  (smmu_domain->cfg.cbndx << S2CR_CBNDX_SHIFT);
>   writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx));

Hmm, do we also need to worry about the bypass case? I guess not for the
moment, but I anticipate horrible things.

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


Re: [PATCH 0/4] Miscellaneous ARM SMMU patches

2016-02-09 Thread Will Deacon
On Tue, Jan 26, 2016 at 06:06:33PM +, Robin Murphy wrote:
> Here's my current "miscellaneous SMMU enhancements" branch for your
> consideration. Patch #1 solves a subtle corner case that cropped up
> while exercising stage 1 context formats on the DMA330-MMU500 model;
> #3 will be wanted fairly soon for DMA ops integration so may as well
> get some exposure now; #2 and #4 are more nice-to-haves.

Cheers, Robin. I've queued #1 and #3 for 4.6. If you address the comments
on the other two, I can queue those as well.

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


Re: [PATCH] iommu/arm-smmu-v2: Workaround for ThunderX errata#27704

2016-02-09 Thread Robin Murphy

On 05/02/16 18:47, tchalama...@caviumnetworks.com wrote:

From: Tirumalesh Chalamarla 

An issue exists whereby the Linux kernel requires that ASIDs are a
unique namespace per SMMU.


I too tend to consider the SMMUv2 architecture an "issue", but we should 
probably still call it by its name ;)



 That ASID-local choice conflicts with the
CN88xx SMMU, where only shared ASID namespaces are supported;
specifically within a given node SMMU0 and SMMU1 share, as does SMMU2
and SMMU3. CN88xx SMMU also requires global VMIDs.


"Global" meaning unique across all 4 SMMUs? Or just unique across each 
pair as per ASIDs?...



This patch tries to address these issuee by supplying asid and vmid
transformations from devicetree.

Signed-off-by: Akula Geethasowjanya 
Signed-off-by: Tirumalesh Chalamarla 
---
  .../devicetree/bindings/iommu/arm,smmu.txt | 16 ++
  drivers/iommu/arm-smmu.c   | 59 ++
  2 files changed, 65 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt 
b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
index 7180745..eef06d0 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
@@ -55,6 +55,22 @@ conditions.
aliases of secure registers have to be used during
SMMU configuration.

+- thunderx,smmu-asid-transform : Enable proper handling for buggy
+ implementations that require special transformations
+ for smmu asid. if this property exists asid-transform
+ property must be present.
+
+- thunderx,smmu-vmid-transform : Enable proper handling for buggy
+ implementations that require special transformations
+ for smmu vmid. if this property exists vmid-transform
+ property must be present.
+
+- asid-transform   : Transform mask that needs to be applied to asid.
+   This property has to be specified as '/bits/ 8' value.
+
+- vmid-transform   : Transform mask that needs to be applied to vmid.
+   This property has to be specified as '/bits/ 8' value.
+


...because I've seen a ThunderX boot log indicating 4x128 context banks, 
and I don't see how applying an 8-bit mask to an 8-bit value is going to 
produce anything _globally_ unique in that case.


Regardless, I'm not sure this is an accurate description of the hardware 
as DT should be - this is more implying that each SMMU _requires_ a 
particular set of ASIDs/VMIDs to be used, which is not the same thing 
that the commit message and other comments say.


Robin.


  Example:

  smmu {
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 59ee4b8..8047834 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -300,8 +300,12 @@ struct arm_smmu_device {
u32 features;

  #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
+#define ARM_SMMU_OPT_TRANSFORM_ASID(1 << 1)
+#define ARM_SMMU_OPT_TRANSFORM_VMID(1 << 2)
u32 options;
enum arm_smmu_arch_version  version;
+   u8  asid_transform;
+   u8  vmid_transform;

u32 num_context_banks;
u32 num_s2_context_banks;
@@ -330,8 +334,25 @@ struct arm_smmu_cfg {
  };
  #define INVALID_IRPTNDX   0xff

-#define ARM_SMMU_CB_ASID(cfg)  ((cfg)->cbndx)
-#define ARM_SMMU_CB_VMID(cfg)  ((cfg)->cbndx + 1)
+/*
+ * ThunderX has a unique requirement because of ERRATA#27704
+ * An issue exists whereby the Linux kernel requires that ASIDs are a
+ * unique namespace per SMMU.  That ASID-local choice conflicts with the
+ * CN88xx SMMU, where only shared ASID namespaces are supported;
+ * specifically within a given node SMMU0 and SMMU1 share, as does SMMU2
+ * and SMMU3.
+ * CN88xx SMMU also requires global VMIDs.
+ */
+
+#define ARM_SMMU_CB_ASID(smmu, cfg)\
+   (((smmu)->options & ARM_SMMU_OPT_TRANSFORM_ASID) \
+   ? ((cfg)->cbndx | (smmu)->asid_transform) \
+   : ((cfg)->cbndx))
+
+#define ARM_SMMU_CB_VMID(smmu, cfg)\
+   (((smmu)->options & ARM_SMMU_OPT_TRANSFORM_VMID) \
+   ? (((cfg)->cbndx + 1) | (smmu)->vmid_transform)   \
+   : ((cfg)->cbndx + 1))

  enum arm_smmu_domain_stage {
ARM_SMMU_DOMAIN_S1 = 0,
@@ -361,6 +382,8 @@ struct arm_smmu_option_prop {

  static struct arm_smmu_option_prop arm_smmu_options[] = {
{ ARM_SMMU_OPT_SECURE_CFG_ACCESS, "calxeda,smmu-secure-config-access" },
+   { 

Re: [PATCH] iommu/arm-smmu-v2: Workaround for ThunderX errata#27704

2016-02-09 Thread Chalamarla, Tirumalesh





On 2/9/16, 3:52 AM, "Robin Murphy"  wrote:

>On 05/02/16 18:47, tchalama...@caviumnetworks.com wrote:
>> From: Tirumalesh Chalamarla 
>>
>> An issue exists whereby the Linux kernel requires that ASIDs are a
>> unique namespace per SMMU.
>
>I too tend to consider the SMMUv2 architecture an "issue", but we should 
>probably still call it by its name ;)
>
>>  That ASID-local choice conflicts with the
>> CN88xx SMMU, where only shared ASID namespaces are supported;
>> specifically within a given node SMMU0 and SMMU1 share, as does SMMU2
>> and SMMU3. CN88xx SMMU also requires global VMIDs.
>
>"Global" meaning unique across all 4 SMMUs? Or just unique across each 
>pair as per ASIDs?...
>
>> This patch tries to address these issuee by supplying asid and vmid
>> transformations from devicetree.
>>
>> Signed-off-by: Akula Geethasowjanya 
>> Signed-off-by: Tirumalesh Chalamarla 
>> ---
>>   .../devicetree/bindings/iommu/arm,smmu.txt | 16 ++
>>   drivers/iommu/arm-smmu.c   | 59 
>> ++
>>   2 files changed, 65 insertions(+), 10 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.txt 
>> b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
>> index 7180745..eef06d0 100644
>> --- a/Documentation/devicetree/bindings/iommu/arm,smmu.txt
>> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.txt
>> @@ -55,6 +55,22 @@ conditions.
>> aliases of secure registers have to be used during
>> SMMU configuration.
>>
>> +- thunderx,smmu-asid-transform  : Enable proper handling for buggy
>> +  implementations that require special transformations
>> +  for smmu asid. if this property exists asid-transform
>> +  property must be present.
>> +
>> +- thunderx,smmu-vmid-transform  : Enable proper handling for buggy
>> +  implementations that require special transformations
>> +  for smmu vmid. if this property exists vmid-transform
>> +  property must be present.
>> +
>> +- asid-transform: Transform mask that needs to be applied to asid.
>> +This property has to be specified as '/bits/ 8' value.
>> +
>> +- vmid-transform: Transform mask that needs to be applied to vmid.
>> +This property has to be specified as '/bits/ 8' value.
>> +
>
>...because I've seen a ThunderX boot log indicating 4x128 context banks, 
>and I don't see how applying an 8-bit mask to an 8-bit value is going to 
>produce anything _globally_ unique in that case.
>
>Regardless, I'm not sure this is an accurate description of the hardware 
>as DT should be - this is more implying that each SMMU _requires_ a 
>particular set of ASIDs/VMIDs to be used, which is not the same thing 
>that the commit message and other comments say.

I am rewriting this patch to include additional patches to support 16bit VMID 
and ASID. Will rebase this patch on top of it.
Though for 128 bit 7 bits are sufficient I thought it is still good idea to 
have this on top of 16bit VMID and ASID. 
>
>Robin.
>
>>   Example:
>>
>>   smmu {
>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
>> index 59ee4b8..8047834 100644
>> --- a/drivers/iommu/arm-smmu.c
>> +++ b/drivers/iommu/arm-smmu.c
>> @@ -300,8 +300,12 @@ struct arm_smmu_device {
>>  u32 features;
>>
>>   #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
>> +#define ARM_SMMU_OPT_TRANSFORM_ASID (1 << 1)
>> +#define ARM_SMMU_OPT_TRANSFORM_VMID (1 << 2)
>>  u32 options;
>>  enum arm_smmu_arch_version  version;
>> +u8  asid_transform;
>> +u8  vmid_transform;
>>
>>  u32 num_context_banks;
>>  u32 num_s2_context_banks;
>> @@ -330,8 +334,25 @@ struct arm_smmu_cfg {
>>   };
>>   #define INVALID_IRPTNDX0xff
>>
>> -#define ARM_SMMU_CB_ASID(cfg)   ((cfg)->cbndx)
>> -#define ARM_SMMU_CB_VMID(cfg)   ((cfg)->cbndx + 1)
>> +/*
>> + * ThunderX has a unique requirement because of ERRATA#27704
>> + * An issue exists whereby the Linux kernel requires that ASIDs are a
>> + * unique namespace per SMMU.  That ASID-local choice conflicts with the
>> + * CN88xx SMMU, where only shared ASID namespaces are supported;
>> + * specifically within a given node SMMU0 and SMMU1 share, as does SMMU2
>> + * and SMMU3.
>> + * CN88xx SMMU also requires global VMIDs.
>> + */
>> +
>> +#define ARM_SMMU_CB_ASID(smmu, cfg) \
>> +(((smmu)->options & ARM_SMMU_OPT_TRANSFORM_ASID)\
>> +? ((cfg)->cbndx | (smmu)->asid_transform)   \
>> +: ((cfg)->cbndx))
>> +

DMAR error messages after 'shutdown -r'.

2016-02-09 Thread Valdis Kletnieks
Am seeing some DMAR error messages on reboot after a 'shutdown -r now'.
(Finally got annoyed enough to track it down while doing a git bisect)

Hardware: Dell Latitude E6530 laptop.

Working (booting from power-off state):

[0.027673] Freeing SMP alternatives memory: 28K (b5111000 - 
b5118000)
[0.048239] ftrace: allocating 31090 entries in 122 pages
[0.061910] DMAR: Host address width 36
[0.061913] DMAR: DRHD base: 0x00fed9 flags: 0x1
[0.061966] DMAR: dmar0: reg_base_addr fed9 ver 1:0 cap c9008020660262 
ecap f0105a
[0.061968] DMAR: RMRR base: 0x00cdb11000 end: 0x00cdb30fff
[0.061972] DMAR-IR: IOAPIC id 2 under DRHD base  0xfed9 IOMMU 0
[0.061974] DMAR-IR: HPET id 0 under DRHD base 0xfed9
[0.061975] DMAR-IR: Queued invalidation will be enabled to support x2apic 
and Intr-remapping.
[0.062187] DMAR-IR: Enabled IRQ remapping in x2apic mode
[0.062189] x2apic enabled

Failure mode (rebooting after a shutdown -r)

[0.027629] Freeing SMP alternatives memory: 28K (8e111000 - 
8e118000)
[0.048199] ftrace: allocating 31090 entries in 122 pages
[0.061837] DMAR: Host address width 36
[0.061841] DMAR: DRHD base: 0x00fed9 flags: 0x1
[0.061894] DMAR: dmar0: reg_base_addr fed9 ver 1:0 cap c9008020660262 
ecap f0105a
[0.061896] DMAR: RMRR base: 0x00cdb11000 end: 0x00cdb30fff
[0.061899] DMAR-IR: IOAPIC id 2 under DRHD base  0xfed9 IOMMU 0
[0.061901] DMAR-IR: HPET id 0 under DRHD base 0xfed9
[0.061903] DMAR-IR: Queued invalidation will be enabled to support x2apic 
and Intr-remapping.
 Error here
[0.062027] DMAR: DRHD: handling fault status reg 2
[0.062034] DMAR: DMAR:[DMA Read] Request device [00:1f.2] fault addr 
cdacd000
   DMAR:[fault reason 06] PTE Read access is not set

[0.062132] DMAR-IR: Enabled IRQ remapping in x2apic mode
[0.062134] x2apic enabled

CPU: Intel(R) Core(TM) i5-3340M CPU @ 2.70GH

lspci:
00:00.0 Host bridge: Intel Corporation 3rd Gen Core processor DRAM Controller 
(rev 09)
00:01.0 PCI bridge: Intel Corporation Xeon E3-1200 v2/3rd Gen Core processor 
PCI Express Root Port (rev 09)
00:14.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family 
USB xHCI Host Controller (rev 04)
00:16.0 Communication controller: Intel Corporation 7 Series/C210 Series 
Chipset Family MEI Controller #1 (rev 04)
00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network 
Connection (rev 04)
00:1a.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family 
USB Enhanced Host Controller #2 (rev 04)
00:1b.0 Audio device: Intel Corporation 7 Series/C210 Series Chipset Family 
High Definition Audio Controller (rev 04)
00:1c.0 PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI 
Express Root Port 1 (rev c4)
00:1c.1 PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI 
Express Root Port 2 (rev c4)
00:1c.2 PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI 
Express Root Port 3 (rev c4)
00:1c.3 PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI 
Express Root Port 4 (rev c4)
00:1c.5 PCI bridge: Intel Corporation 7 Series/C210 Series Chipset Family PCI 
Express Root Port 6 (rev c4)
00:1d.0 USB controller: Intel Corporation 7 Series/C210 Series Chipset Family 
USB Enhanced Host Controller #1 (rev 04)
00:1f.0 ISA bridge: Intel Corporation QM77 Express Chipset LPC Controller (rev 
04)
00:1f.2 SATA controller: Intel Corporation 7 Series Chipset Family 6-port SATA 
Controller [AHCI mode] (rev 04)
00:1f.3 SMBus: Intel Corporation 7 Series/C210 Series Chipset Family SMBus 
Controller (rev 04)
01:00.0 VGA compatible controller: NVIDIA Corporation GF108GLM [NVS 5200M] (rev 
a1)
01:00.1 Audio device: NVIDIA Corporation GF108 High Definition Audio Controller 
(rev a1)
03:00.0 Network controller: Broadcom Corporation BCM4313 802.11bgn Wireless 
Network Adapter (rev 01)
0c:00.0 SD Host controller: O2 Micro, Inc. OZ600FJ0/OZ900FJ0/OZ600FJS SD/MMC 
Card Reader Controller (rev 05)



pgp96tigNlNjf.pgp
Description: PGP signature
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v2 3/6] iommu/amd: Introduce amd_iommu_get_num_iommus()

2016-02-09 Thread Suravee Suthikulpanit

Hi Joerg,

On 01/07/2016 06:15 AM, Joerg Roedel wrote:

On Fri, Jan 01, 2016 at 12:13:37PM -0600, Suravee Suthikulpanit wrote:

+int amd_iommu_get_num_iommus(void)
+{
+   return amd_iommus_present;
+}
+EXPORT_SYMBOL(amd_iommu_get_num_iommus);


Is this export needed? The perf code can't be build as a module.

Otherwise it looks good.



Right. I am fixing this in V3 and sending out shortly.

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


[PATCH V3 3/5] iommu/amd: Introduce amd_iommu_get_num_iommus()

2016-02-09 Thread Suravee Suthikulpanit
This patch introduces amd_iommu_get_num_iommus(). Initially, this is
intended to be used by Perf AMD IOMMU driver.

Signed-off-by: Suravee Suthikulpanit 
---
 drivers/iommu/amd_iommu_init.c| 7 ++-
 include/linux/perf/perf_event_amd_iommu.h | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 275c0f5..531b2e1 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1030,7 +1030,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, 
struct ivhd_header *h)
 
/* Add IOMMU to internal data structures */
list_add_tail(>list, _iommu_list);
-   iommu->index = amd_iommus_present++;
+   iommu->index = amd_iommus_present++;
 
if (unlikely(iommu->index >= MAX_IOMMUS)) {
WARN(1, "AMD-Vi: System has more IOMMUs than supported by this 
driver\n");
@@ -2244,6 +2244,11 @@ bool amd_iommu_v2_supported(void)
 }
 EXPORT_SYMBOL(amd_iommu_v2_supported);
 
+int amd_iommu_get_num_iommus(void)
+{
+   return amd_iommus_present;
+}
+
 /
  *
  * IOMMU EFR Performance Counter support functionality. This code allows
diff --git a/include/linux/perf/perf_event_amd_iommu.h 
b/include/linux/perf/perf_event_amd_iommu.h
index 815eabb..cb820c2 100644
--- a/include/linux/perf/perf_event_amd_iommu.h
+++ b/include/linux/perf/perf_event_amd_iommu.h
@@ -25,6 +25,8 @@
 #define PC_MAX_SPEC_CNTRS  16
 
 /* amd_iommu_init.c external support functions */
+extern int amd_iommu_get_num_iommus(void);
+
 extern bool amd_iommu_pc_supported(void);
 
 extern u8 amd_iommu_pc_get_max_banks(void);
-- 
2.5.0

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


[PATCH V3 0/5] perf/amd/iommu: Enable multi-IOMMU support

2016-02-09 Thread Suravee Suthikulpanit
From: Suravee Suthikulpanit 

This patch series modifies the existing perf_event_amd_iommu driver
to support systems with multiple IOMMUs. It introduces new AMD IOMMU APIs,
which will are used by the AMD IOMMU Perf driver to access performance
counters in multiple IOMMUs.

In addition, this series should also fix current AMD IOMMU PMU driver
initialization issue in some existing KV and CZ platform.

Note that this patch also fixes the issue where IOMMU driver fails
to write to IOMMU perf counter as reported by Andreas Hartmann here
(http://comments.gmane.org/gmane.linux.kernel.pci/49147).

Git branch containing this patch series is available here:

https://github.com/ssuthiku/linux.git  perf-iommu-v3

Changes from V2 ( https://lkml.org/lkml/2016/1/1/141)
  * Ported to 4.5.0-rc2
  * Add reviewed by Joerg for patch 1 and 2
  * Remove EXPORT_SYMBOL from patch 3 (per Joerg suggestion)
  * Merge patch 4/6 and 6/6 from V2 into 5/5 in V3 and add
more description in the commit message and in code comment.
  * Patch 5: modify the logic to update counts to get rid off
un-necessary local64_cmpxchg().

Changes from V1 (https://lkml.org/lkml/2015/12/22/535):
  * Update patch3 and 6 to use amd_iommus_present instead of introducing
amd_iommu_cnt static variable since they are the same thing

Suravee Suthikulpanit (5):
  perf/amd/iommu: Consolidate and move perf_event_amd_iommu header
  perf/amd/iommu: Modify functions to query max banks and counters
  iommu/amd: Introduce amd_iommu_get_num_iommus()
  perf/amd/iommu: Introduce get_iommu_bnk_cnt_evt_idx
  perf/amd/iommu: Enable support for multiple IOMMUs

 arch/x86/kernel/cpu/perf_event_amd_iommu.c | 164 -
 arch/x86/kernel/cpu/perf_event_amd_iommu.h |  40 ---
 drivers/iommu/amd_iommu_init.c | 116 
 drivers/iommu/amd_iommu_proto.h|   7 --
 include/linux/perf/perf_event_amd_iommu.h  |  43 
 5 files changed, 254 insertions(+), 116 deletions(-)
 delete mode 100644 arch/x86/kernel/cpu/perf_event_amd_iommu.h
 create mode 100644 include/linux/perf/perf_event_amd_iommu.h

-- 
2.5.0

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


[PATCH V3 1/5] perf/amd/iommu: Consolidate and move perf_event_amd_iommu header

2016-02-09 Thread Suravee Suthikulpanit
This patch consolidates "arch/x86/kernel/cpu/perf_event_amd_iommu.h" and
"drivers/iommu/amd_iommu_proto.h", which contain duplicate function
declarations, into "include/linux/perf/perf_event_amd_iommu.h"

Reviewed-by: Joerg Roedel 
Signed-off-by: Suravee Suthikulpanit 
---
 arch/x86/kernel/cpu/perf_event_amd_iommu.c |  2 +-
 arch/x86/kernel/cpu/perf_event_amd_iommu.h | 40 --
 drivers/iommu/amd_iommu_init.c |  2 ++
 drivers/iommu/amd_iommu_proto.h|  7 --
 include/linux/perf/perf_event_amd_iommu.h  | 40 ++
 5 files changed, 43 insertions(+), 48 deletions(-)
 delete mode 100644 arch/x86/kernel/cpu/perf_event_amd_iommu.h
 create mode 100644 include/linux/perf/perf_event_amd_iommu.h

diff --git a/arch/x86/kernel/cpu/perf_event_amd_iommu.c 
b/arch/x86/kernel/cpu/perf_event_amd_iommu.c
index 97242a9..d44525e 100644
--- a/arch/x86/kernel/cpu/perf_event_amd_iommu.c
+++ b/arch/x86/kernel/cpu/perf_event_amd_iommu.c
@@ -12,12 +12,12 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 
 #include "perf_event.h"
-#include "perf_event_amd_iommu.h"
 
 #define COUNTER_SHIFT  16
 
diff --git a/arch/x86/kernel/cpu/perf_event_amd_iommu.h 
b/arch/x86/kernel/cpu/perf_event_amd_iommu.h
deleted file mode 100644
index 845d173..000
--- a/arch/x86/kernel/cpu/perf_event_amd_iommu.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2013 Advanced Micro Devices, Inc.
- *
- * Author: Steven Kinney 
- * Author: Suravee Suthikulpanit 
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _PERF_EVENT_AMD_IOMMU_H_
-#define _PERF_EVENT_AMD_IOMMU_H_
-
-/* iommu pc mmio region register indexes */
-#define IOMMU_PC_COUNTER_REG   0x00
-#define IOMMU_PC_COUNTER_SRC_REG   0x08
-#define IOMMU_PC_PASID_MATCH_REG   0x10
-#define IOMMU_PC_DOMID_MATCH_REG   0x18
-#define IOMMU_PC_DEVID_MATCH_REG   0x20
-#define IOMMU_PC_COUNTER_REPORT_REG0x28
-
-/* maximun specified bank/counters */
-#define PC_MAX_SPEC_BNKS   64
-#define PC_MAX_SPEC_CNTRS  16
-
-/* iommu pc reg masks*/
-#define IOMMU_BASE_DEVID   0x
-
-/* amd_iommu_init.c external support functions */
-extern bool amd_iommu_pc_supported(void);
-
-extern u8 amd_iommu_pc_get_max_banks(u16 devid);
-
-extern u8 amd_iommu_pc_get_max_counters(u16 devid);
-
-extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr,
-   u8 fxn, u64 *value, bool is_write);
-
-#endif /*_PERF_EVENT_AMD_IOMMU_H_*/
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 013bdff..b6d684c 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -27,6 +27,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include 
 #include 
 #include 
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 0bd9eb3..ac2da91 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -55,13 +55,6 @@ extern int amd_iommu_domain_set_gcr3(struct iommu_domain 
*dom, int pasid,
 extern int amd_iommu_domain_clear_gcr3(struct iommu_domain *dom, int pasid);
 extern struct iommu_domain *amd_iommu_get_v2_domain(struct pci_dev *pdev);
 
-/* IOMMU Performance Counter functions */
-extern bool amd_iommu_pc_supported(void);
-extern u8 amd_iommu_pc_get_max_banks(u16 devid);
-extern u8 amd_iommu_pc_get_max_counters(u16 devid);
-extern int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn,
-   u64 *value, bool is_write);
-
 #ifdef CONFIG_IRQ_REMAP
 extern int amd_iommu_create_irq_domain(struct amd_iommu *iommu);
 #else
diff --git a/include/linux/perf/perf_event_amd_iommu.h 
b/include/linux/perf/perf_event_amd_iommu.h
new file mode 100644
index 000..845d173
--- /dev/null
+++ b/include/linux/perf/perf_event_amd_iommu.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 Advanced Micro Devices, Inc.
+ *
+ * Author: Steven Kinney 
+ * Author: Suravee Suthikulpanit 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _PERF_EVENT_AMD_IOMMU_H_
+#define _PERF_EVENT_AMD_IOMMU_H_
+
+/* iommu pc mmio region register indexes */
+#define IOMMU_PC_COUNTER_REG   0x00
+#define IOMMU_PC_COUNTER_SRC_REG   0x08
+#define IOMMU_PC_PASID_MATCH_REG   0x10
+#define IOMMU_PC_DOMID_MATCH_REG   0x18
+#define IOMMU_PC_DEVID_MATCH_REG   0x20

[PATCH] iommu: fix second argument of trace_map() to report correct paddr

2016-02-09 Thread Yoshihiro Shimoda
Since iommu_map() code added pgsize value to the paddr, trace_map()
used wrong paddr. So, this patch adds "orig_paddr" value in the
iommu_map() to use for the trace_map().

Signed-off-by: Yoshihiro Shimoda 
---
 drivers/iommu/iommu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0e3b009..bfd4f7c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1314,6 +1314,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long 
iova,
unsigned long orig_iova = iova;
unsigned int min_pagesz;
size_t orig_size = size;
+   phys_addr_t orig_paddr = paddr;
int ret = 0;
 
if (unlikely(domain->ops->map == NULL ||
@@ -1358,7 +1359,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long 
iova,
if (ret)
iommu_unmap(domain, orig_iova, orig_size - size);
else
-   trace_map(orig_iova, paddr, orig_size);
+   trace_map(orig_iova, orig_paddr, orig_size);
 
return ret;
 }
-- 
1.9.1

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


[PATCH v3 4/8] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-02-09 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund 
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.7.1

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

[PATCH v3 2/8] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-02-09 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to map be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund 
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 75857cd..e3aba4e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.7.1

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

[PATCH v3 8/8] ARM: dts: r8a7791: add iommus to dmac0 and dmac1

2016-02-09 Thread Niklas Söderlund
Signed-off-by: Niklas Söderlund 
---
 arch/arm/boot/dts/r8a7791.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 2a369dd..6dff061 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -283,6 +283,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -314,6 +329,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.1

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

[PATCH v3 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-02-09 Thread Niklas Söderlund
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund 
---
 include/linux/dma-mapping.h | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..21bf986 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,33 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->map_resource)
+   return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.7.1

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

[PATCH v3 1/8] iommu: Add MMIO mapping type

2016-02-09 Thread Niklas Söderlund
From: Robin Murphy 

On some platforms, MMIO regions might need slightly different treatment
compared to mapping regular memory; add the notion of MMIO mappings to
the IOMMU API's memory type flags, so that callers can let the IOMMU
drivers know to do the right thing.

Signed-off-by: Robin Murphy 
Acked-by: Laurent Pinchart 
---
 drivers/iommu/io-pgtable-arm.c | 4 +++-
 include/linux/iommu.h  | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 381ca5a..3ff4f87 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -364,7 +364,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
arm_lpae_io_pgtable *data,
pte |= ARM_LPAE_PTE_HAP_READ;
if (prot & IOMMU_WRITE)
pte |= ARM_LPAE_PTE_HAP_WRITE;
-   if (prot & IOMMU_CACHE)
+   if (prot & IOMMU_MMIO)
+   pte |= ARM_LPAE_PTE_MEMATTR_DEV;
+   else if (prot & IOMMU_CACHE)
pte |= ARM_LPAE_PTE_MEMATTR_OIWB;
else
pte |= ARM_LPAE_PTE_MEMATTR_NC;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a5c539f..34b6432 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -30,6 +30,7 @@
 #define IOMMU_WRITE(1 << 1)
 #define IOMMU_CACHE(1 << 2) /* DMA cache coherency */
 #define IOMMU_NOEXEC   (1 << 3)
+#define IOMMU_MMIO (1 << 4) /* e.g. things like MSI doorbells */
 
 struct iommu_ops;
 struct iommu_group;
-- 
2.7.1

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


[PATCH v3 5/8] dmaengine: rcar-dmac: group slave configuration

2016-02-09 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund 
---
 drivers/dma/sh/rcar-dmac.c | 37 +
 1 file changed, 21 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..743873c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,21 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   dma_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +149,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +798,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1043,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1098,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1115,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.7.1

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

[PATCH v3 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-02-09 Thread Niklas Söderlund
Signed-off-by: Niklas Söderlund 
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 7dfd393..048bbf8 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -325,6 +340,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.7.1

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

[PATCH v3 6/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-09 Thread Niklas Söderlund
Enable slave transfers to devices behind IPMMU:s by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund 
---
 drivers/dma/sh/rcar-dmac.c | 57 ++
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 743873c..268407c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1106,21 +1106,68 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return desc;
 }
 
+static int rcar_dmac_set_slave_addr(struct dma_chan *chan,
+struct rcar_dmac_chan_slave *slave,
+phys_addr_t addr, size_t size)
+{
+   struct dma_attrs attrs;
+   enum dma_data_direction dir;
+
+   init_dma_attrs();
+   dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, );
+   dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, );
+
+   /*
+* We can't know the direction at this time, see documentation for
+* 'direction' in struct dma_slave_config.
+*/
+   dir = DMA_BIDIRECTIONAL;
+
+   if (slave->xfer_size) {
+   dma_unmap_resource(chan->device->dev, slave->slave_addr,
+   slave->xfer_size, dir, );
+   slave->slave_addr = 0;
+   slave->xfer_size = 0;
+   }
+
+   if (size) {
+   slave->slave_addr = dma_map_resource(chan->device->dev, addr,
+   size, dir, );
+
+   if (dma_mapping_error(chan->device->dev, slave->slave_addr)) {
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap",
+   rchan->index, size, );
+   return -EIO;
+   }
+
+   slave->xfer_size = size;
+   }
+
+   return 0;
+}
+
 static int rcar_dmac_device_config(struct dma_chan *chan,
   struct dma_slave_config *cfg)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   int ret;
 
/*
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src.slave_addr = cfg->src_addr;
-   rchan->dst.slave_addr = cfg->dst_addr;
-   rchan->src.xfer_size = cfg->src_addr_width;
-   rchan->dst.xfer_size = cfg->dst_addr_width;
 
-   return 0;
+   ret = rcar_dmac_set_slave_addr(chan, >src, cfg->src_addr,
+   cfg->src_addr_width);
+   if (ret)
+   return ret;
+
+   ret = rcar_dmac_set_slave_addr(chan, >dst, cfg->dst_addr,
+   cfg->dst_addr_width);
+   return ret;
 }
 
 static int rcar_dmac_chan_terminate_all(struct dma_chan *chan)
-- 
2.7.1

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

[PATCH v3 0/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-02-09 Thread Niklas Söderlund
Hi,

This series add iommu support to rcar-dmac. It's tested on koelsch with
CONFIG_IPMMU_VMSA and by enabling the ipmmu_ds node in r8a7791.dtsi. I
verified operation by interacting with /dev/mmcblk1  which is a device
behind the iommu.

The series depends on out of tree patch '[PATCH] dmaengine: use
phys_addr_t for slave configuration' which currently is under review.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error check where
  inverted.
- Use DMA_BIDIRECTIONAL in rcar_dmac_device_config since we at that
  point can't be sure what direction the mapping is going to be used.

* Changes since v1
- Add and use a dma_{map,unmap}_page_attrs to be able to map the page
  using attributes DMA_ATTR_NO_KERNEL_MAPPING and
  DMA_ATTR_SKIP_CPU_SYNC. Thanks Laurent.
- Drop check if dmac is part of a iommu group or not, let the DMA
  mapping api handle it.
- Move slave configuration data around in rcar-dmac to avoid code
  duplication.
- Fix build issue reported by 'kbuild test robot' regarding phys_to_page
  not availability on some configurations.
- Add DT information for r8a7791.

* Changes since RFC
- Switch to use the dma-mapping api instead of using the iommu_map()
  directly. Turns out the dma-mapper is much smarter then me...
- Dropped the patch to expose domain->ops->pgsize_bitmap from within the
  iommu api.
- Dropped the patch showing how I tested the RFC.

Niklas Söderlund (7):
  dma-mapping: add {map,unmap}_resource to dma_map_ops
  dma-mapping: add dma_{map,unmap}_resource
  arm: dma-mapping: add {map,unmap}_resource for iommu ops
  dmaengine: rcar-dmac: group slave configuration
  dmaengine: rcar-dmac: add iommu support for slave transfers
  ARM: dts: r8a7790: add iommus to dmac0 and dmac1
  ARM: dts: r8a7791: add iommus to dmac0 and dmac1

Robin Murphy (1):
  iommu: Add MMIO mapping type

 arch/arm/boot/dts/r8a7790.dtsi | 30 +++
 arch/arm/boot/dts/r8a7791.dtsi | 30 +++
 arch/arm/mm/dma-mapping.c  | 63 +++
 drivers/dma/sh/rcar-dmac.c | 86 +-
 drivers/iommu/io-pgtable-arm.c |  4 +-
 include/linux/dma-mapping.h| 33 
 include/linux/iommu.h  |  1 +
 7 files changed, 229 insertions(+), 18 deletions(-)

--
2.7.1

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