Re: [PATCH v3 0/5] enhance DMA CMA on x86

2014-09-30 Thread Peter Hurley
On 09/30/2014 07:45 PM, Thomas Gleixner wrote:
> Whether the proposed patchset is the correct solution to support it is
> a completely different question.

This patchset has been in mainline since 3.16 and has already caused
regressions, so the question of whether this is the correct solution has
already been answered.

> So either you stop this right now and help Akinobu to find the proper
> solution 

If this is only a test platform for ARM parts then I don't think it
unreasonable to suggest forking x86 swiotlb support into a iommu=cma
selector that gets DMA mapping working for this test platform and doesn't
cause a bunch of breakage.

Which is different than if the plan is to ship production units for x86;
then a general purpose solution will be required.

As to the good design of a general purpose solution for allocating and
mapping huge order pages, you are certainly more qualified to help Akinobu
than I am.

Regards,
Peter Hurley

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


[PATCH v4 1/2] iopoll: Introduce memory-mapped IO polling macros

2014-09-30 Thread Mitchel Humpherys
From: Matt Wagantall 

It is sometimes necessary to poll a memory-mapped register until its value
satisfies some condition. Introduce a family of convenience macros that do
this. Tight-looping, sleeping, and timing out can all be accomplished using
these macros.

Cc: Thierry Reding 
Cc: Will Deacon 
Signed-off-by: Matt Wagantall 
Signed-off-by: Mitchel Humpherys 
---
Changes since v3:

  - Updated commit message to better reflect the patch content
---
 include/linux/iopoll.h | 77 ++
 1 file changed, 77 insertions(+)
 create mode 100644 include/linux/iopoll.h

diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
new file mode 100644
index 00..594b0d4f03
--- /dev/null
+++ b/include/linux/iopoll.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _LINUX_IOPOLL_H
+#define _LINUX_IOPOLL_H
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * readl_poll_timeout - Periodically poll an address until a condition is met 
or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops)
+ * @timeout_us: Timeout in us, 0 means never timeout
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ */
+#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \
+({ \
+   ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); \
+   might_sleep_if(timeout_us); \
+   for (;;) { \
+   (val) = readl(addr); \
+   if (cond) \
+   break; \
+   if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { \
+   (val) = readl(addr); \
+   break; \
+   } \
+   if (sleep_us) \
+   usleep_range(DIV_ROUND_UP(sleep_us, 4), sleep_us); \
+   } \
+   (cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
+ * readl_poll_timeout_atomic - Periodically poll an address until a condition 
is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @max_reads: Maximum number of reads before giving up
+ * @time_between_us: Time to udelay() between successive reads
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout.
+ */
+#define readl_poll_timeout_atomic(addr, val, cond, max_reads, time_between_us) 
\
+({ \
+   int count; \
+   for (count = (max_reads); count > 0; count--) { \
+   (val) = readl(addr); \
+   if (cond) \
+   break; \
+   udelay(time_between_us); \
+   } \
+   (cond) ? 0 : -ETIMEDOUT; \
+})
+
+#endif /* _LINUX_IOPOLL_H */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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


Re: [PATCH v3 2/2] iommu/arm-smmu: add support for iova_to_phys through ATS1PR

2014-09-30 Thread Mitchel Humpherys
On Tue, Sep 30 2014 at 03:23:34 AM, Will Deacon  wrote:
> Hi Mitch,
>
> On Sun, Sep 28, 2014 at 04:27:29AM +0100, Mitchel Humpherys wrote:
>> Currently, we provide the iommu_ops.iova_to_phys service by doing a
>> table walk in software to translate IO virtual addresses to physical
>> addresses. On SMMUs that support it, it can be useful to ask the SMMU
>> itself to do the translation. This can be used to warm the TLBs for an
>> SMMU. It can also be useful for testing and hardware validation.
>> 
>> Since the address translation registers are optional on SMMUv2, only
>> enable hardware translations when using SMMUv1 or when SMMU_IDR0.S1TS=1
>> and SMMU_IDR0.ATOSNS=0, as described in the ARM SMMU v1-v2 spec.
>
> [...]
>
>> +static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
>> +dma_addr_t iova)
>> +{
>> +struct arm_smmu_domain *smmu_domain = domain->priv;
>> +struct arm_smmu_device *smmu = smmu_domain->smmu;
>> +struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
>> +struct device *dev = smmu->dev;
>> +void __iomem *cb_base;
>> +u32 tmp;
>> +u64 phys;
>> +
>> +cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
>> +
>> +if (smmu->version == 1) {
>> +u32 reg = iova & ~0xFFF;
>
> Cosmetic comment, but hex constants are lowercase everywhere else in the
> file.

Ah, woops.  Let me fix that.

>
>> +writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
>> +} else {
>> +u32 reg = iova & ~0xFFF;
>> +writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
>> +reg = (iova & ~0xFFF) >> 32;
>> +writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_HI);
>> +}
>> +
>> +if (readl_poll_timeout(cb_base + ARM_SMMU_CB_ATSR, tmp,
>> +!(tmp & ATSR_ACTIVE), 10, ATSR_LOOP_TIMEOUT)) {
>> +dev_err(dev,
>> +"iova to phys timed out on 0x%pa. Falling back to 
>> software table walk.\n",
>> +&iova);
>> +return arm_smmu_iova_to_phys_soft(domain, iova);
>> +}
>> +
>> +phys = readl_relaxed(cb_base + ARM_SMMU_CB_PAR_LO);
>> +phys |= ((u64) readl_relaxed(cb_base + ARM_SMMU_CB_PAR_HI)) << 32;
>
> The absence of locking in this function concerns me a bit. For the software
> implementation, we're just reading page tables, but here we're writing ATS
> registers and I think we need to ensure serialisation against another
> iova_to_phys on the same domain.

Good catch, let me take the domain lock here.  I'll also have to move to
readl_poll_timeout_atomic since the domain lock is a spinlock.

>
>> +if (phys & CB_PAR_F) {
>> +dev_err(dev, "translation fault!\n");
>> +dev_err(dev, "PAR = 0x%llx\n", phys);
>> +}
>> +phys = (phys & 0xFFF000ULL) | (iova & 0x0FFF);
>> +
>> +return phys;
>
> You can return phys == 0 on failure (at least, the callers in kvm and vfio
> treat this as an error).

Ah yes, I agree that a 0 return value from iommu_iova_to_phys appears to
be treated as an error.  Let me fix that.


-Mitch

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


[PATCH v4 2/2] iommu/arm-smmu: add support for iova_to_phys through ATS1PR

2014-09-30 Thread Mitchel Humpherys
Currently, we provide the iommu_ops.iova_to_phys service by doing a
table walk in software to translate IO virtual addresses to physical
addresses. On SMMUs that support it, it can be useful to ask the SMMU
itself to do the translation. This can be used to warm the TLBs for an
SMMU. It can also be useful for testing and hardware validation.

Since the address translation registers are optional on SMMUv2, only
enable hardware translations when using SMMUv1 or when SMMU_IDR0.S1TS=1
and SMMU_IDR0.ATOSNS=0, as described in the ARM SMMU v1-v2 spec.

Signed-off-by: Mitchel Humpherys 
---
Changes since v3:

  - Added locking around address translation op
  - Return 0 on iova_to_phys failure
---
 drivers/iommu/arm-smmu.c | 79 +++-
 1 file changed, 78 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 37dc3dd0df..c80c12a104 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -36,6 +36,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -140,6 +141,7 @@
 #define ID0_S2TS   (1 << 29)
 #define ID0_NTS(1 << 28)
 #define ID0_SMS(1 << 27)
+#define ID0_ATOSNS (1 << 26)
 #define ID0_PTFS_SHIFT 24
 #define ID0_PTFS_MASK  0x2
 #define ID0_PTFS_V8_ONLY   0x2
@@ -233,11 +235,16 @@
 #define ARM_SMMU_CB_TTBR0_HI   0x24
 #define ARM_SMMU_CB_TTBCR  0x30
 #define ARM_SMMU_CB_S1_MAIR0   0x38
+#define ARM_SMMU_CB_PAR_LO 0x50
+#define ARM_SMMU_CB_PAR_HI 0x54
 #define ARM_SMMU_CB_FSR0x58
 #define ARM_SMMU_CB_FAR_LO 0x60
 #define ARM_SMMU_CB_FAR_HI 0x64
 #define ARM_SMMU_CB_FSYNR0 0x68
 #define ARM_SMMU_CB_S1_TLBIASID0x610
+#define ARM_SMMU_CB_ATS1PR_LO  0x800
+#define ARM_SMMU_CB_ATS1PR_HI  0x804
+#define ARM_SMMU_CB_ATSR   0x8f0
 
 #define SCTLR_S1_ASIDPNE   (1 << 12)
 #define SCTLR_CFCFG(1 << 7)
@@ -249,6 +256,10 @@
 #define SCTLR_M(1 << 0)
 #define SCTLR_EAE_SBOP (SCTLR_AFE | SCTLR_TRE)
 
+#define CB_PAR_F   (1 << 0)
+
+#define ATSR_ACTIVE(1 << 0)
+
 #define RESUME_RETRY   (0 << 0)
 #define RESUME_TERMINATE   (1 << 0)
 
@@ -366,6 +377,7 @@ struct arm_smmu_device {
 #define ARM_SMMU_FEAT_TRANS_S1 (1 << 2)
 #define ARM_SMMU_FEAT_TRANS_S2 (1 << 3)
 #define ARM_SMMU_FEAT_TRANS_NESTED (1 << 4)
+#define ARM_SMMU_FEAT_TRANS_OPS(1 << 5)
u32 features;
 
 #define ARM_SMMU_OPT_SECURE_CFG_ACCESS (1 << 0)
@@ -1524,7 +1536,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, 
unsigned long iova,
return ret ? 0 : size;
 }
 
-static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
+static phys_addr_t arm_smmu_iova_to_phys_soft(struct iommu_domain *domain,
 dma_addr_t iova)
 {
pgd_t *pgdp, pgd;
@@ -1557,6 +1569,66 @@ static phys_addr_t arm_smmu_iova_to_phys(struct 
iommu_domain *domain,
return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK);
 }
 
+static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
+   dma_addr_t iova)
+{
+   struct arm_smmu_domain *smmu_domain = domain->priv;
+   struct arm_smmu_device *smmu = smmu_domain->smmu;
+   struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+   struct device *dev = smmu->dev;
+   void __iomem *cb_base;
+   u32 tmp;
+   u64 phys;
+   unsigned long flags;
+
+   cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+
+   spin_lock_irqsave(&smmu_domain->lock, flags);
+
+   if (smmu->version == 1) {
+   u32 reg = iova & ~0xfff;
+   writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
+   } else {
+   u32 reg = iova & ~0xfff;
+   writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
+   reg = (iova & ~0xfff) >> 32;
+   writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_HI);
+   }
+
+   if (readl_poll_timeout_atomic(cb_base + ARM_SMMU_CB_ATSR, tmp,
+   !(tmp & ATSR_ACTIVE), 50, 100)) {
+   dev_err(dev,
+   "iova to phys timed out on 0x%pa. Falling back to 
software table walk.\n",
+   &iova);
+   return arm_smmu_iova_to_phys_soft(domain, iova);
+   }
+
+   phys = readl_relaxed(cb_base + ARM_SMMU_CB_PAR_LO);
+   phys |= ((u64) readl_relaxed(cb_base + ARM_SMMU_CB_PAR_HI)) << 32;
+
+   spin_unlock_irqrestore(&smmu_domain->lock, flags);
+
+   if (phys & CB_PAR_F) {
+ 

[PATCH v4 0/2] iommu/arm-smmu: hard iova_to_phys

2014-09-30 Thread Mitchel Humpherys
This series introduces support for performing iova-to-phys translations via
the ARM SMMU hardware on supported implementations. We also make use of
some new generic macros for polling hardware registers.

v1..v2:

  - Renamed one of the iopoll macros to use the more standard `_atomic'
suffix
  - Removed some convenience iopoll wrappers to encourage explicitness

v2..v3:

  - Removed unnecessary `dev_name's

v3..v4:

  - Updated the iopoll commit message to reflect the patch better
  - Added locking around address translation op
  - Return 0 on iova_to_phys failure


Matt Wagantall (1):
  iopoll: Introduce memory-mapped IO polling macros

Mitchel Humpherys (1):
  iommu/arm-smmu: add support for iova_to_phys through ATS1PR

 drivers/iommu/arm-smmu.c | 79 +++-
 include/linux/iopoll.h   | 77 ++
 2 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/iopoll.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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


Re: [PATCH v3 0/5] enhance DMA CMA on x86

2014-09-30 Thread Peter Hurley
On 09/30/2014 07:45 PM, Thomas Gleixner wrote:
> On Tue, 30 Sep 2014, Peter Hurley wrote:
>> I read the UFS Unified Memory Extension v1.0 (JESD220-1) specification and
>> it is not clear to me that using DMA mapping is the right approach to
>> supporting UM, at least on x86.
>>
>> And without a mainline user, the merits of this approach are not evident.
>> I cannot even find a production x86 UFS controller, much less one that
>> supports UME.
>>
>> The only PCI UFS controller I could find (and that mainline supports) is
>> Samsung's x86 FPGA-based test unit for developing UFS devices in a x86 test
>> environment, and not a production x86 design.
> 
> And how is that relevant? That device exists and you have no reason to
> deny it to be supported just because you are not interested in it.
>  
>> Unless there's something else I've missed, I don't think these patches
>> belong in mainline.
> 
> You missed that there is no reason WHY such a device should not be
> supported in mainline.

Mainline already supports this card right now without these patches.

>> Samsung's own roadmap
>> (http://www.slideshare.net/linaroorg/next-gen-mobilestorageufs)
>> mentions nothing about bringing UFS to x86 designs.
> 
> And that's telling you what? 
> 
>- That we should deny Samsung proper support for their obviously
>  x86 based test card
> 
>- That we should ignore a JEDEC Standard which is obviously never
>  going to hit x86 land just because you decide it?
> 
> Your argumentation is just ass backwards. Linux wants to support the
> full zoo of hardware including this particular PCI card. Period.
> 
> Whether the proposed patchset is the correct solution to support it is
> a completely different question.

And there is currently no way to determine that because there is no
user in mainline that requires this support.

Which you would understand if you had read more carefully.

Regards,
Peter Hurley

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


Re: [PATCH v3 0/5] enhance DMA CMA on x86

2014-09-30 Thread Thomas Gleixner
On Tue, 30 Sep 2014, Peter Hurley wrote:
> I read the UFS Unified Memory Extension v1.0 (JESD220-1) specification and
> it is not clear to me that using DMA mapping is the right approach to
> supporting UM, at least on x86.
> 
> And without a mainline user, the merits of this approach are not evident.
> I cannot even find a production x86 UFS controller, much less one that
> supports UME.
> 
> The only PCI UFS controller I could find (and that mainline supports) is
> Samsung's x86 FPGA-based test unit for developing UFS devices in a x86 test
> environment, and not a production x86 design.

And how is that relevant? That device exists and you have no reason to
deny it to be supported just because you are not interested in it.
 
> Unless there's something else I've missed, I don't think these patches
> belong in mainline.

You missed that there is no reason WHY such a device should not be
supported in mainline.

> Samsung's own roadmap
> (http://www.slideshare.net/linaroorg/next-gen-mobilestorageufs)
> mentions nothing about bringing UFS to x86 designs.

And that's telling you what? 

   - That we should deny Samsung proper support for their obviously
 x86 based test card

   - That we should ignore a JEDEC Standard which is obviously never
 going to hit x86 land just because you decide it?

Your argumentation is just ass backwards. Linux wants to support the
full zoo of hardware including this particular PCI card. Period.

Whether the proposed patchset is the correct solution to support it is
a completely different question.

So either you stop this right now and help Akinobu to find the proper
solution or you just go back in your uncontaminated x86 cave and STFU.

Thanks,

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


Re: [PATCH v3 0/5] enhance DMA CMA on x86

2014-09-30 Thread Akinobu Mita
2014-09-30 23:34 GMT+09:00 Peter Hurley :
> On 09/29/2014 10:32 AM, Akinobu Mita wrote:
>> 2014-09-29 21:09 GMT+09:00 Peter Hurley :
>>> On 09/27/2014 08:31 PM, Akinobu Mita wrote:
 2014-09-27 23:30 GMT+09:00 Peter Hurley :
> On 04/15/2014 09:08 AM, Akinobu Mita wrote:
>> This patch set enhances the DMA Contiguous Memory Allocator on x86.
>>>
>>> [...]
>>>
> What this patchset does is restrict all iommu configurations which can
> map all of system memory to one _very_ small physical region, thus 
> disabling
> the whole point of an iommu.
>
> Now I know why my GPU is causing paging to disk! And why my RAID 
> controller
> stalls for ages when I do a git log at the same time as a kernel build!

 The solution I have for this is that instead of trying to
 dma_alloc_from_contiguous() firstly, call alloc_pages() in 
 dma_alloc_coherent().
 dma_alloc_from_contiguous() should be called only when alloc_pages() is 
 failed
 or DMA_ATTR_FORCE_CONTIGUOUS is specified in dma_attr.
>>>
>>> Why is all this extra complexity being added when there are no X86 users
>>> of DMA_ATTR_FORCE_CONTIGUOUS?
>>
>> I misunderstood DMA_ATTR_FORCE_CONTIGUOUS.  It is specified to request
>> that underlaying DMA mapping span physically contiguous with IOMMU.
>> But current alloc_dma_coherent() for intel-iommu always returns
>> physically contiguous memory, so it is ignored on x86.
>>
> And the apparent goal of this patchset is to enable DMA allocation below
> 4GB, which is already supported in the existing page allocator with the
> GFP_DMA32 flag?!

 The goal of this patchset is to enable huge DMA allocation which
 alloc_pages() can't (> MAX_ORDER) for the devices that require it.
>>>
>>> What x86 devices need > MAX_ORDER DMA allocation and why can't they allocate
>>> directly from dma_alloc_from_contiguous()?
>>
>> I need this for UFS unified memory extension which is apparently not in
>> mainline for now.
>> http://www.jedec.org/standards-documents/docs/jesd220-1
>> http://www.jedec.org/sites/default/files/T_Fujisawa_MF_2013.pdf
>>
>> But there must be some other use cases on x86, too.  Because I have
>> received several emails privately from developers who care its status.
>>
>> And allocating directly from dma_alloc_from_contiguous() in the driver
>> doesn't work with IOMMU, as it just returns memory regoin and doesn't
>> create DMA mapping.
>
>
> I read the UFS Unified Memory Extension v1.0 (JESD220-1) specification and
> it is not clear to me that using DMA mapping is the right approach to
> supporting UM, at least on x86.

Without DMA mapping, there is no way for the devices to access host
memory.  Unified memory extension requires a single contiguous memory
region instead of multiple scattered mapping.

> And without a mainline user, the merits of this approach are not evident.
> I cannot even find a production x86 UFS controller, much less one that
> supports UME.
>
> The only PCI UFS controller I could find (and that mainline supports) is
> Samsung's x86 FPGA-based test unit for developing UFS devices in a x86 test
> environment, and not a production x86 design.
>
> Samsung's own roadmap 
> (http://www.slideshare.net/linaroorg/next-gen-mobilestorageufs)
> mentions nothing about bringing UFS to x86 designs.
>
> Unless there's something else I've missed, I don't think these patches
> belong in mainline.

Removing CONFIG_CMA_DMA support from x86_64 will disappoint me, but it's
personal opinion.  FWIW, MIPS also starts supporting it in linux-next.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 16/17] iommu/omap: Fix bus error on debugfs access of unattached IOMMU

2014-09-30 Thread Suman Anna
Any debugfs access on an OMAP IOMMU that is not enabled (done during
attach) results in a bus error due to access of registers without
the clock or the reset enabled for the respective IOMMU. So, add a
check to make sure the IOMMU is enabled/attached by a client device.
This gracefully prints a "Operation not permitted" trace when the
corresponding IOMMU is not enabled.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu-debug.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 54a0dc6..e7b8aca 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -24,6 +24,11 @@ static DEFINE_MUTEX(iommu_debug_lock);
 
 static struct dentry *iommu_debug_root;
 
+static inline bool is_omap_iommu_detached(struct omap_iommu *obj)
+{
+   return !obj->domain;
+}
+
 static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
   size_t count, loff_t *ppos)
 {
@@ -31,6 +36,9 @@ static ssize_t debug_read_regs(struct file *file, char __user 
*userbuf,
char *p, *buf;
ssize_t bytes;
 
+   if (is_omap_iommu_detached(obj))
+   return -EPERM;
+
buf = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -54,6 +62,9 @@ static ssize_t debug_read_tlb(struct file *file, char __user 
*userbuf,
char *p, *buf;
ssize_t bytes, rest;
 
+   if (is_omap_iommu_detached(obj))
+   return -EPERM;
+
buf = kmalloc(count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -139,6 +150,9 @@ static ssize_t debug_read_pagetable(struct file *file, char 
__user *userbuf,
char *p, *buf;
size_t bytes;
 
+   if (is_omap_iommu_detached(obj))
+   return -EPERM;
+
buf = (char *)__get_free_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
-- 
2.1.0

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


[PATCH 09/17] iommu/omap: Consolidate OMAP IOMMU modules

2014-09-30 Thread Suman Anna
The OMAP IOMMU driver was originally designed as modules, and split
into a core module and a thin arch-specific module through the OMAP
arch-specific struct iommu_functions, to scale for both OMAP1 and
OMAP2+ IOMMU variants. The driver can only be built for OMAP2+
platforms currently, and also can only be built-in after the
adaptation to generic IOMMU API. The OMAP1 variant was never added
and will most probably be never added (the code for the only potential
user, its parent, DSP processor has already been cleaned up). So,
consolidate the OMAP2 specific omap-iommu2 module into the core OMAP
IOMMU driver - this eliminates the arch-specific ops structure and
simplifies the driver into a single module that only implements the
generic IOMMU API's iommu_ops.

The following are the main changes:
- omap-iommu2 module is completely eliminated, with the common
  definitions moved to the internal omap-iommu.h, and the ops
  implementations moved into omap-iommu.c
- OMAP arch-specific struct iommu_functions is also eliminated,
  with the ops implementations directly absorbed into the calling
  functions
- iotlb_alloc_cr() is no longer inlined and defined only when
  PREFETCH_IOTLB is defined
- iotlb_dump_cr() is similarly defined only when CONFIG_OMAP_IOMMU_DEBUG
  is defined
- Elimination of the OMAP IOMMU exported functions to register the
  arch ops, omap_install_iommu_arch() & omap_uninstall_iommu_arch()
- Any stale comments about OMAP1 are also cleaned up

Signed-off-by: Suman Anna 
---
 drivers/iommu/Makefile  |   1 -
 drivers/iommu/omap-iommu.c  | 263 ++---
 drivers/iommu/omap-iommu.h  |  61 +
 drivers/iommu/omap-iommu2.c | 311 
 4 files changed, 217 insertions(+), 419 deletions(-)
 delete mode 100644 drivers/iommu/omap-iommu2.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 16edef7..18fa446 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -11,7 +11,6 @@ obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
-obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 332bfb9..9ace5557 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -76,53 +76,23 @@ struct iotlb_lock {
short vict;
 };
 
-/* accommodate the difference between omap1 and omap2/3 */
-static const struct iommu_functions *arch_iommu;
-
 static struct platform_driver omap_iommu_driver;
 static struct kmem_cache *iopte_cachep;
 
 /**
- * omap_install_iommu_arch - Install archtecure specific iommu functions
- * @ops:   a pointer to architecture specific iommu functions
- *
- * There are several kind of iommu algorithm(tlb, pagetable) among
- * omap series. This interface installs such an iommu algorighm.
- **/
-int omap_install_iommu_arch(const struct iommu_functions *ops)
-{
-   if (arch_iommu)
-   return -EBUSY;
-
-   arch_iommu = ops;
-   return 0;
-}
-EXPORT_SYMBOL_GPL(omap_install_iommu_arch);
-
-/**
- * omap_uninstall_iommu_arch - Uninstall archtecure specific iommu functions
- * @ops:   a pointer to architecture specific iommu functions
- *
- * This interface uninstalls the iommu algorighm installed previously.
- **/
-void omap_uninstall_iommu_arch(const struct iommu_functions *ops)
-{
-   if (arch_iommu != ops)
-   pr_err("%s: not your arch\n", __func__);
-
-   arch_iommu = NULL;
-}
-EXPORT_SYMBOL_GPL(omap_uninstall_iommu_arch);
-
-/**
  * omap_iommu_save_ctx - Save registers for pm off-mode support
  * @dev:   client device
  **/
 void omap_iommu_save_ctx(struct device *dev)
 {
struct omap_iommu *obj = dev_to_omap_iommu(dev);
+   u32 *p = obj->ctx;
+   int i;
 
-   arch_iommu->save_ctx(obj);
+   for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
+   p[i] = iommu_read_reg(obj, i * sizeof(u32));
+   dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
+   }
 }
 EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
 
@@ -133,20 +103,75 @@ EXPORT_SYMBOL_GPL(omap_iommu_save_ctx);
 void omap_iommu_restore_ctx(struct device *dev)
 {
struct omap_iommu *obj = dev_to_omap_iommu(dev);
+   u32 *p = obj->ctx;
+   int i;
 
-   arch_iommu->restore_ctx(obj);
+   for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) {
+   iommu_write_reg(obj, p[i], i * sizeof(u32));
+   dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
+   }
 }
 EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
 
+static void __iommu_set_twl(struct omap_iommu *obj, bool on)
+{
+   u32 l = iommu_read_reg(obj, MMU_CNTL);
+
+   if 

[PATCH 02/17] iommu/omap: Remove unused isr_priv field from omap_iommu

2014-09-30 Thread Suman Anna
The isr_priv field is a left-over from before the IOMMU API
adaptation, this was used to store the callback data. This is
no longer relevant, so remove it.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 5c14000..18a0f3a 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -30,7 +30,6 @@ struct omap_iommu {
const char  *name;
void __iomem*regbase;
struct device   *dev;
-   void*isr_priv;
struct iommu_domain *domain;
 
spinlock_t  iommu_lock; /* global for this whole object */
-- 
2.1.0

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


[PATCH 13/17] iommu/omap: Remove couple of unused exported functions

2014-09-30 Thread Suman Anna
The exported functions omap_foreach_iommu_device() and
omap_iotlb_cr_to_e() have been deleted, as they are no
longer needed.

The function omap_foreach_iommu_device() is not required
after the consolidation of the OMAP IOMMU debug module,
and the function omap_iotlb_cr_to_e() is not required
after making the debugfs entry 'pagetable' read-only.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.c | 21 -
 drivers/iommu/omap-iommu.h |  5 -
 2 files changed, 26 deletions(-)

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 717d654..b3bc087 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -203,20 +203,6 @@ static void iommu_disable(struct omap_iommu *obj)
 /*
  * TLB operations
  */
-void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
-{
-   BUG_ON(!cr || !e);
-
-   e->da   = cr->cam & MMU_CAM_VATAG_MASK;
-   e->pa   = cr->ram & MMU_RAM_PADDR_MASK;
-   e->valid= cr->cam & MMU_CAM_V;
-   e->pgsz = cr->cam & MMU_CAM_PGSZ_MASK;
-   e->endian   = cr->ram & MMU_RAM_ENDIAN_MASK;
-   e->elsz = cr->ram & MMU_RAM_ELSZ_MASK;
-   e->mixed= cr->ram & MMU_RAM_MIXED;
-}
-EXPORT_SYMBOL_GPL(omap_iotlb_cr_to_e);
-
 static inline int iotlb_cr_valid(struct cr_regs *cr)
 {
if (!cr)
@@ -593,13 +579,6 @@ size_t omap_dump_tlb_entries(struct omap_iommu *obj, char 
*buf, ssize_t bytes)
 }
 EXPORT_SYMBOL_GPL(omap_dump_tlb_entries);
 
-int omap_foreach_iommu_device(void *data, int (*fn)(struct device *, void *))
-{
-   return driver_for_each_device(&omap_iommu_driver.driver,
- NULL, data, fn);
-}
-EXPORT_SYMBOL_GPL(omap_foreach_iommu_device);
-
 /*
  * H/W pagetable operations
  */
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 6e9a8d2..2659139 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -190,14 +190,9 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct 
device *dev)
 /*
  * global functions
  */
-extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
-
 extern int
 omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
 
-extern int omap_foreach_iommu_device(void *data,
-   int (*fn)(struct device *, void *));
-
 extern ssize_t
 omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
 extern size_t
-- 
2.1.0

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


[PATCH 08/17] iommu/omap: Simplify omap2_iommu_fault_isr()

2014-09-30 Thread Suman Anna
The function omap2_iommu_fault_isr() does an unnecessary
recomputation of the return value. The logic relies on
setting the same bit fields as the MMU fault error status
bits, so simplify this function and remove the unneeded
macros. These macros were originally exported to notify
MMU faults to users prior to the IOMMU framework adaptation,
but are now redundant.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu2.c | 20 +---
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c
index 372141b..ce2fff3 100644
--- a/drivers/iommu/omap-iommu2.c
+++ b/drivers/iommu/omap-iommu2.c
@@ -53,13 +53,6 @@
 ((pgsz) == MMU_CAM_PGSZ_64K) ? 0x :\
 ((pgsz) == MMU_CAM_PGSZ_4K)  ? 0xf000 : 0)
 
-/* IOMMU errors */
-#define OMAP_IOMMU_ERR_TLB_MISS(1 << 0)
-#define OMAP_IOMMU_ERR_TRANS_FAULT (1 << 1)
-#define OMAP_IOMMU_ERR_EMU_MISS(1 << 2)
-#define OMAP_IOMMU_ERR_TBLWALK_FAULT   (1 << 3)
-#define OMAP_IOMMU_ERR_MULTIHIT_FAULT  (1 << 4)
-
 static void __iommu_set_twl(struct omap_iommu *obj, bool on)
 {
u32 l = iommu_read_reg(obj, MMU_CNTL);
@@ -122,7 +115,6 @@ static void omap2_iommu_set_twl(struct omap_iommu *obj, 
bool on)
 static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, u32 *ra)
 {
u32 stat, da;
-   u32 errs = 0;
 
stat = iommu_read_reg(obj, MMU_IRQSTATUS);
stat &= MMU_IRQ_MASK;
@@ -134,19 +126,9 @@ static u32 omap2_iommu_fault_isr(struct omap_iommu *obj, 
u32 *ra)
da = iommu_read_reg(obj, MMU_FAULT_AD);
*ra = da;
 
-   if (stat & MMU_IRQ_TLBMISS)
-   errs |= OMAP_IOMMU_ERR_TLB_MISS;
-   if (stat & MMU_IRQ_TRANSLATIONFAULT)
-   errs |= OMAP_IOMMU_ERR_TRANS_FAULT;
-   if (stat & MMU_IRQ_EMUMISS)
-   errs |= OMAP_IOMMU_ERR_EMU_MISS;
-   if (stat & MMU_IRQ_TABLEWALKFAULT)
-   errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
-   if (stat & MMU_IRQ_MULTIHITFAULT)
-   errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
iommu_write_reg(obj, stat, MMU_IRQSTATUS);
 
-   return errs;
+   return stat;
 }
 
 static void omap2_tlb_read_cr(struct omap_iommu *obj, struct cr_regs *cr)
-- 
2.1.0

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


[PATCH 12/17] iommu/omap: Integrate omap-iommu-debug into omap-iommu

2014-09-30 Thread Suman Anna
The debugfs support for OMAP IOMMU is currently implemented
as a module, warranting certain OMAP-specific IOMMU API to
be exported. The OMAP IOMMU, when enabled, can only be built-in
into the kernel, so integrate the OMAP IOMMU debug module
into the OMAP IOMMU driver. This helps in eliminating the
need to export most of the current OMAP IOMMU API.

The following are the main changes:
- The OMAP_IOMMU_DEBUG Kconfig option is eliminated, and
  the OMAP IOMMU debugfs support is built alongside the OMAP
  IOMMU driver, and enabled automatically only when debugfs
  is enabled.
- The debugfs directory and entry creation logic is reversed,
  the calls are invoked by the OMAP IOMMU driver now.
- The current iffy circular logic of adding IOMMU archdata
  to the IOMMU devices itself to get a pointer to the omap_iommu
  object in the debugfs support code is replaced by directly
  using the omap_iommu structure while creating the debugfs
  entries.
- The debugfs root directory is renamed from the generic name
  "iommu" to a specific name "omap_iommu".
- Unneeded headers have also been cleaned up while at this.
- There will no longer be a omap-iommu-debug.ko module after
  this patch.

Signed-off-by: Suman Anna 
---
 drivers/iommu/Kconfig|   9 
 drivers/iommu/Makefile   |   3 +-
 drivers/iommu/omap-iommu-debug.c | 102 ---
 drivers/iommu/omap-iommu.c   |  11 +++--
 drivers/iommu/omap-iommu.h   |   7 +++
 5 files changed, 45 insertions(+), 87 deletions(-)

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd51122..9724d4a 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -143,15 +143,6 @@ config OMAP_IOMMU
depends on ARCH_OMAP2PLUS
select IOMMU_API
 
-config OMAP_IOMMU_DEBUG
-   tristate "Export OMAP IOMMU internals in DebugFS"
-   depends on OMAP_IOMMU && DEBUG_FS
-   help
- Select this to see extensive information about
- the internal state of OMAP IOMMU in debugfs.
-
- Say N unless you know you need this.
-
 config TEGRA_IOMMU_GART
bool "Tegra GART IOMMU Support"
depends on ARCH_TEGRA_2x_SOC
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 18fa446..e0a4fed 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -10,8 +10,7 @@ obj-$(CONFIG_DMAR_TABLE) += dmar.o
 obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
-obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
-obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
+obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o omap-iommu-debug.o
 obj-$(CONFIG_TEGRA_IOMMU_GART) += tegra-gart.o
 obj-$(CONFIG_TEGRA_IOMMU_SMMU) += tegra-smmu.o
 obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 28de657..54a0dc6 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -10,15 +10,11 @@
  * published by the Free Software Foundation.
  */
 
-#include 
 #include 
-#include 
 #include 
 #include 
 #include 
-#include 
 #include 
-#include 
 #include 
 
 #include "omap-iopgtable.h"
@@ -31,8 +27,7 @@ static struct dentry *iommu_debug_root;
 static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
   size_t count, loff_t *ppos)
 {
-   struct device *dev = file->private_data;
-   struct omap_iommu *obj = dev_to_omap_iommu(dev);
+   struct omap_iommu *obj = file->private_data;
char *p, *buf;
ssize_t bytes;
 
@@ -55,8 +50,7 @@ static ssize_t debug_read_regs(struct file *file, char __user 
*userbuf,
 static ssize_t debug_read_tlb(struct file *file, char __user *userbuf,
  size_t count, loff_t *ppos)
 {
-   struct device *dev = file->private_data;
-   struct omap_iommu *obj = dev_to_omap_iommu(dev);
+   struct omap_iommu *obj = file->private_data;
char *p, *buf;
ssize_t bytes, rest;
 
@@ -141,8 +135,7 @@ out:
 static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
 {
-   struct device *dev = file->private_data;
-   struct omap_iommu *obj = dev_to_omap_iommu(dev);
+   struct omap_iommu *obj = file->private_data;
char *p, *buf;
size_t bytes;
 
@@ -181,93 +174,58 @@ DEBUG_FOPS_RO(pagetable);
 #define __DEBUG_ADD_FILE(attr, mode)   \
{   \
struct dentry *dent;\
-   dent = debugfs_create_file(#attr, mode, parent, \
-  dev, &debug_##attr##_fops);  \
+   dent = debugfs_create_file(#attr, mode, obj->debug_dir, \
+  obj, 

[PATCH 00/17] OMAP IOMMU Cleanup & Consolidation

2014-09-30 Thread Suman Anna
Hi,

The OMAP IOMMU driver is currently designed as three different
pieces - a core OMAP IOMMU driver that implements the generic
IOMMU API ops, a OMAP arch-specific layer that implements the
OMAP specific arch iommu_functions, and an independent debugfs
module. The former two are always built-in, while the last one
is tristate.

The driver supports OMAP2+ SoCs only, and this series performs
a whole lot of cleanup and consolidates all the above pieces
into a single built-in driver. The OMAP arch-specific layer is
eliminated completely (absorbed into the core OMAP driver), and
the debugfs portion is still maintained as a separate file, but
not a separate module anymore. This cleanup and consolidation
eliminates most of the currently exported functions from the
OMAP IOMMU driver.

The series also includes couple of fixes to the OMAP IOMMU
debugfs entries - permissions on one debugfs entry, eliminate
bus errors on debugfs access on disabled IOMMUs; and one
enhancement to list all valid page table entries instead of
listing only a page worth of data.

The patches are baselined on 3.17-rc3 and on top of the OMAP
IOMMU patches staged for 3.18 [1]; a reference branch with all
these patches is available is hosted at [2].

I am posting this series for review with the intention to have
them make it to 3.19, so I can repost once rc1 is out if needed.

[1] http://git.kernel.org/cgit/linux/kernel/git/joro/iommu.git/log/?h=arm/omap
[2] 
https://github.com/sumananna/omap-kernel/commits/iommu/submit/3.17-rc3-cleanup-consolidation

regards
Suman


Suman Anna (17):
  iommu/omap: Remove refcount field from omap_iommu object
  iommu/omap: Remove unused isr_priv field from omap_iommu
  iommu/omap: Remove duplicate declarations
  iommu/omap: Remove conditional definition of dev_to_omap_iommu()
  iommu/omap: Remove ver debugfs entry
  iommu/omap: Remove omap_iommu_arch_version() and version field
  iommu/omap: Remove bogus version check in context save/restore
  iommu/omap: Simplify omap2_iommu_fault_isr()
  iommu/omap: Consolidate OMAP IOMMU modules
  iommu/omap: Fix the permissions on nr_tlb_entries
  iommu/omap: Make pagetable debugfs entry read-only
  iommu/omap: Integrate omap-iommu-debug into omap-iommu
  iommu/omap: Remove couple of unused exported functions
  iommu/omap: Do not export unneeded functions
  iommu/omap: Reset the domain field upon detaching
  iommu/omap: Fix bus error on debugfs access of unattached IOMMU
  iommu/omap: Switch pagetable debugfs entry to use seq_file

 drivers/iommu/Kconfig|   9 --
 drivers/iommu/Makefile   |   4 +-
 drivers/iommu/omap-iommu-debug.c | 244 
 drivers/iommu/omap-iommu.c   | 304 ++-
 drivers/iommu/omap-iommu.h   |  90 +--
 drivers/iommu/omap-iommu2.c  | 337 ---
 6 files changed, 298 insertions(+), 690 deletions(-)
 delete mode 100644 drivers/iommu/omap-iommu2.c

-- 
2.1.0

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


[PATCH 05/17] iommu/omap: Remove ver debugfs entry

2014-09-30 Thread Suman Anna
The debugfs entry 'ver' to read the OMAP IOMMU version is
not much useful for developers, so it has been removed. The
same can be deduced from the register dump, provided by the
debugfs entry 'regs', REVISION register. This also allows us
to remove the omap_iommu_arch_revision() which is currently
returning a fixed value.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu-debug.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 531658d..0fb92aa 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -30,17 +30,6 @@ static DEFINE_MUTEX(iommu_debug_lock);
 
 static struct dentry *iommu_debug_root;
 
-static ssize_t debug_read_ver(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
-   u32 ver = omap_iommu_arch_version();
-   char buf[MAXCOLUMN], *p = buf;
-
-   p += sprintf(p, "H/W version: %d.%d\n", (ver >> 4) & 0xf , ver & 0xf);
-
-   return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
-}
-
 static ssize_t debug_read_regs(struct file *file, char __user *userbuf,
   size_t count, loff_t *ppos)
 {
@@ -228,7 +217,6 @@ static ssize_t debug_read_pagetable(struct file *file, char 
__user *userbuf,
.llseek = generic_file_llseek,  \
};
 
-DEBUG_FOPS_RO(ver);
 DEBUG_FOPS_RO(regs);
 DEBUG_FOPS_RO(tlb);
 DEBUG_FOPS(pagetable);
@@ -273,7 +261,6 @@ static int iommu_debug_register(struct device *dev, void 
*data)
if (!d)
goto nomem;
 
-   DEBUG_ADD_FILE_RO(ver);
DEBUG_ADD_FILE_RO(regs);
DEBUG_ADD_FILE_RO(tlb);
DEBUG_ADD_FILE(pagetable);
-- 
2.1.0

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


[PATCH 15/17] iommu/omap: Reset the domain field upon detaching

2014-09-30 Thread Suman Anna
The .domain field in omap_iommu struct is set properly when the
OMAP IOMMU device is attached to, but is never reset properly
on detach. Reset this properly so that the OMAP IOMMU debugfs
logic can depend on this field before allowing the debugfs
operations.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index a140873..3769dc0 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1202,6 +1202,7 @@ static void _omap_iommu_detach_dev(struct 
omap_iommu_domain *omap_domain,
 
omap_domain->iommu_dev = arch_data->iommu_dev = NULL;
omap_domain->dev = NULL;
+   oiommu->domain = NULL;
 }
 
 static void omap_iommu_detach_dev(struct iommu_domain *domain,
-- 
2.1.0

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


[PATCH 17/17] iommu/omap: Switch pagetable debugfs entry to use seq_file

2014-09-30 Thread Suman Anna
The debugfs entry 'pagetable' that shows the page table entry
(PTE) data currently outputs only data that can be fit into a
page. Switch the entry to use the seq_file interface so that
it can show all the valid page table entries.

The patch also corrected the output for L2 entries, and prints
the proper L2 PTE instead of the previous L1 page descriptor
pointer.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu-debug.c | 81 ++--
 1 file changed, 28 insertions(+), 53 deletions(-)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index e7b8aca..096947c5 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -85,95 +85,70 @@ static ssize_t debug_read_tlb(struct file *file, char 
__user *userbuf,
return bytes;
 }
 
-#define dump_ioptable_entry_one(lv, da, val)   \
-   ({  \
-   int __err = 0;  \
-   ssize_t bytes;  \
-   const int maxcol = 22;  \
-   const char *str = "%d: %08x %08x\n";\
-   bytes = snprintf(p, maxcol, str, lv, da, val);  \
-   p += bytes; \
-   len -= bytes;   \
-   if (len < maxcol)   \
-   __err = -ENOMEM;\
-   __err;  \
-   })
-
-static ssize_t dump_ioptable(struct omap_iommu *obj, char *buf, ssize_t len)
+static void dump_ioptable(struct seq_file *s)
 {
-   int i;
-   u32 *iopgd;
-   char *p = buf;
+   int i, j;
+   u32 da;
+   u32 *iopgd, *iopte;
+   struct omap_iommu *obj = s->private;
 
spin_lock(&obj->page_table_lock);
 
iopgd = iopgd_offset(obj, 0);
for (i = 0; i < PTRS_PER_IOPGD; i++, iopgd++) {
-   int j, err;
-   u32 *iopte;
-   u32 da;
-
if (!*iopgd)
continue;
 
if (!(*iopgd & IOPGD_TABLE)) {
da = i << IOPGD_SHIFT;
-
-   err = dump_ioptable_entry_one(1, da, *iopgd);
-   if (err)
-   goto out;
+   seq_printf(s, "1: 0x%08x 0x%08x\n", da, *iopgd);
continue;
}
 
iopte = iopte_offset(iopgd, 0);
-
for (j = 0; j < PTRS_PER_IOPTE; j++, iopte++) {
if (!*iopte)
continue;
 
da = (i << IOPGD_SHIFT) + (j << IOPTE_SHIFT);
-   err = dump_ioptable_entry_one(2, da, *iopgd);
-   if (err)
-   goto out;
+   seq_printf(s, "2: 0x%08x 0x%08x\n", da, *iopte);
}
}
-out:
-   spin_unlock(&obj->page_table_lock);
 
-   return p - buf;
+   spin_unlock(&obj->page_table_lock);
 }
 
-static ssize_t debug_read_pagetable(struct file *file, char __user *userbuf,
-   size_t count, loff_t *ppos)
+static int debug_read_pagetable(struct seq_file *s, void *data)
 {
-   struct omap_iommu *obj = file->private_data;
-   char *p, *buf;
-   size_t bytes;
+   struct omap_iommu *obj = s->private;
 
if (is_omap_iommu_detached(obj))
return -EPERM;
 
-   buf = (char *)__get_free_page(GFP_KERNEL);
-   if (!buf)
-   return -ENOMEM;
-   p = buf;
-
-   p += sprintf(p, "L: %8s %8s\n", "da:", "pa:");
-   p += sprintf(p, "-\n");
-
mutex_lock(&iommu_debug_lock);
 
-   bytes = PAGE_SIZE - (p - buf);
-   p += dump_ioptable(obj, p, bytes);
-
-   bytes = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+   seq_printf(s, "L: %8s %8s\n", "da:", "pte:");
+   seq_puts(s, "--\n");
+   dump_ioptable(s);
 
mutex_unlock(&iommu_debug_lock);
-   free_page((unsigned long)buf);
 
-   return bytes;
+   return 0;
 }
 
+#define DEBUG_SEQ_FOPS_RO(name)
   \
+   static int debug_open_##name(struct inode *inode, struct file *file)   \
+   {  \
+   return single_open(file, debug_read_##name, inode->i_private); \
+   }  \
+  \
+   static const struct file_operations debug_##name##_fops = {\
+   .open   = debug_open_##name,  

[PATCH 06/17] iommu/omap: Remove omap_iommu_arch_version() and version field

2014-09-30 Thread Suman Anna
The function omap_iommu_arch_version() is not used anymore,
and is not required either, so remove it. The .version field
in struct iommu_functions that this function uses is also
removed, as it is not really an ops to retrieve a version and
there won't be any usage for this field either.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.c  | 9 -
 drivers/iommu/omap-iommu.h  | 4 
 drivers/iommu/omap-iommu2.c | 2 --
 3 files changed, 15 deletions(-)

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index ed26701..332bfb9 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -138,15 +138,6 @@ void omap_iommu_restore_ctx(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(omap_iommu_restore_ctx);
 
-/**
- * omap_iommu_arch_version - Return running iommu arch version
- **/
-u32 omap_iommu_arch_version(void)
-{
-   return arch_iommu->version;
-}
-EXPORT_SYMBOL_GPL(omap_iommu_arch_version);
-
 static int iommu_enable(struct omap_iommu *obj)
 {
int err;
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index d7c5132..45fe67d 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -70,8 +70,6 @@ struct cr_regs {
 
 /* architecture specific functions */
 struct iommu_functions {
-   unsigned long   version;
-
int (*enable)(struct omap_iommu *obj);
void (*disable)(struct omap_iommu *obj);
void (*set_twl)(struct omap_iommu *obj, bool on);
@@ -191,8 +189,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct 
device *dev)
 /*
  * global functions
  */
-extern u32 omap_iommu_arch_version(void);
-
 extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e);
 
 extern int
diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c
index 5e1ea3b..2f6a9f7 100644
--- a/drivers/iommu/omap-iommu2.c
+++ b/drivers/iommu/omap-iommu2.c
@@ -297,8 +297,6 @@ static void omap2_cr_to_e(struct cr_regs *cr, struct 
iotlb_entry *e)
 }
 
 static const struct iommu_functions omap2_iommu_ops = {
-   .version= IOMMU_ARCH_VERSION,
-
.enable = omap2_iommu_enable,
.disable= omap2_iommu_disable,
.set_twl= omap2_iommu_set_twl,
-- 
2.1.0

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


[PATCH 14/17] iommu/omap: Do not export unneeded functions

2014-09-30 Thread Suman Anna
The following functions were exported previously for usage by
the OMAP IOMMU debug module:
omap_iommu_dump_ctx()
omap_dump_tlb_entries()
omap_iopgtable_store_entry()

These functions need not be exported anymore as the OMAP IOMMU
debugfs code is integrated with the OMAP IOMMU driver, and
there won't be external users for these functions. So, remove
the EXPORT_SYMBOL_GPL on these. The omap_iopgtable_store_entry()
is also made internal only, after making the 'pagetable' debugfs
entry read-only.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.c | 6 ++
 drivers/iommu/omap-iommu.h | 3 ---
 2 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index b3bc087..a140873 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -509,7 +509,6 @@ ssize_t omap_iommu_dump_ctx(struct omap_iommu *obj, char 
*buf, ssize_t bytes)
 
return bytes;
 }
-EXPORT_SYMBOL_GPL(omap_iommu_dump_ctx);
 
 static int
 __dump_tlb_entries(struct omap_iommu *obj, struct cr_regs *crs, int num)
@@ -577,7 +576,6 @@ size_t omap_dump_tlb_entries(struct omap_iommu *obj, char 
*buf, ssize_t bytes)
 
return p - buf;
 }
-EXPORT_SYMBOL_GPL(omap_dump_tlb_entries);
 
 /*
  * H/W pagetable operations
@@ -760,7 +758,8 @@ iopgtable_store_entry_core(struct omap_iommu *obj, struct 
iotlb_entry *e)
  * @obj:   target iommu
  * @e: an iommu tlb entry info
  **/
-int omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e)
+static int
+omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e)
 {
int err;
 
@@ -770,7 +769,6 @@ int omap_iopgtable_store_entry(struct omap_iommu *obj, 
struct iotlb_entry *e)
prefetch_iotlb_entry(obj, e);
return err;
 }
-EXPORT_SYMBOL_GPL(omap_iopgtable_store_entry);
 
 /**
  * iopgtable_lookup_entry - Lookup an iommu pte entry
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 2659139..f32ddc3 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -190,9 +190,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct 
device *dev)
 /*
  * global functions
  */
-extern int
-omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
-
 extern ssize_t
 omap_iommu_dump_ctx(struct omap_iommu *obj, char *buf, ssize_t len);
 extern size_t
-- 
2.1.0

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


[PATCH 07/17] iommu/omap: Remove bogus version check in context save/restore

2014-09-30 Thread Suman Anna
The omap2_iommu_save_ctx() and omap2_iommu_restore_ctx()
performs a sanity version check against a fixed value
that is correct only for OMAP2/OMAP3 IOMMUs. This fixed check
does not scale for all OMAP2+ IOMMUs and is not absolutely
required, so it has been removed.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu2.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/iommu/omap-iommu2.c b/drivers/iommu/omap-iommu2.c
index 2f6a9f7..372141b 100644
--- a/drivers/iommu/omap-iommu2.c
+++ b/drivers/iommu/omap-iommu2.c
@@ -26,8 +26,6 @@
 /*
  * omap2 architecture specific register bit definitions
  */
-#define IOMMU_ARCH_VERSION 0x0011
-
 /* IRQSTATUS & IRQENABLE */
 #define MMU_IRQ_MULTIHITFAULT  (1 << 4)
 #define MMU_IRQ_TABLEWALKFAULT (1 << 3)
@@ -268,8 +266,6 @@ static void omap2_iommu_save_ctx(struct omap_iommu *obj)
p[i] = iommu_read_reg(obj, i * sizeof(u32));
dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
}
-
-   BUG_ON(p[0] != IOMMU_ARCH_VERSION);
 }
 
 static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
@@ -281,8 +277,6 @@ static void omap2_iommu_restore_ctx(struct omap_iommu *obj)
iommu_write_reg(obj, p[i], i * sizeof(u32));
dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]);
}
-
-   BUG_ON(p[0] != IOMMU_ARCH_VERSION);
 }
 
 static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e)
-- 
2.1.0

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


[PATCH 10/17] iommu/omap: Fix the permissions on nr_tlb_entries

2014-09-30 Thread Suman Anna
The permissions on the debugfs entry "nr_tlb_entries" should
have been octal, not decimal, so fix it.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu-debug.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index 0fb92aa..a520438 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -256,7 +256,7 @@ static int iommu_debug_register(struct device *dev, void 
*data)
goto nomem;
parent = d;
 
-   d = debugfs_create_u8("nr_tlb_entries", 400, parent,
+   d = debugfs_create_u8("nr_tlb_entries", 0400, parent,
  (u8 *)&obj->nr_tlb_entries);
if (!d)
goto nomem;
-- 
2.1.0

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


[PATCH 11/17] iommu/omap: Make pagetable debugfs entry read-only

2014-09-30 Thread Suman Anna
Remove the writeability on the 'pagetable' debugfs entry,
so that the mapping/unmapping into an OMAP IOMMU is only
limited to actual client devices/drivers at kernel-level.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu-debug.c | 48 ++--
 1 file changed, 2 insertions(+), 46 deletions(-)

diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c
index a520438..28de657 100644
--- a/drivers/iommu/omap-iommu-debug.c
+++ b/drivers/iommu/omap-iommu-debug.c
@@ -24,8 +24,6 @@
 #include "omap-iopgtable.h"
 #include "omap-iommu.h"
 
-#define MAXCOLUMN 100 /* for short messages */
-
 static DEFINE_MUTEX(iommu_debug_lock);
 
 static struct dentry *iommu_debug_root;
@@ -82,39 +80,6 @@ static ssize_t debug_read_tlb(struct file *file, char __user 
*userbuf,
return bytes;
 }
 
-static ssize_t debug_write_pagetable(struct file *file,
-const char __user *userbuf, size_t count, loff_t *ppos)
-{
-   struct iotlb_entry e;
-   struct cr_regs cr;
-   int err;
-   struct device *dev = file->private_data;
-   struct omap_iommu *obj = dev_to_omap_iommu(dev);
-   char buf[MAXCOLUMN], *p = buf;
-
-   count = min(count, sizeof(buf));
-
-   mutex_lock(&iommu_debug_lock);
-   if (copy_from_user(p, userbuf, count)) {
-   mutex_unlock(&iommu_debug_lock);
-   return -EFAULT;
-   }
-
-   sscanf(p, "%x %x", &cr.cam, &cr.ram);
-   if (!cr.cam || !cr.ram) {
-   mutex_unlock(&iommu_debug_lock);
-   return -EINVAL;
-   }
-
-   omap_iotlb_cr_to_e(&cr, &e);
-   err = omap_iopgtable_store_entry(obj, &e);
-   if (err)
-   dev_err(obj->dev, "%s: fail to store cr\n", __func__);
-
-   mutex_unlock(&iommu_debug_lock);
-   return count;
-}
-
 #define dump_ioptable_entry_one(lv, da, val)   \
({  \
int __err = 0;  \
@@ -202,14 +167,6 @@ static ssize_t debug_read_pagetable(struct file *file, 
char __user *userbuf,
return bytes;
 }
 
-#define DEBUG_FOPS(name)   \
-   static const struct file_operations debug_##name##_fops = { \
-   .open = simple_open,\
-   .read = debug_read_##name,  \
-   .write = debug_write_##name,\
-   .llseek = generic_file_llseek,  \
-   };
-
 #define DEBUG_FOPS_RO(name)\
static const struct file_operations debug_##name##_fops = { \
.open = simple_open,\
@@ -219,7 +176,7 @@ static ssize_t debug_read_pagetable(struct file *file, char 
__user *userbuf,
 
 DEBUG_FOPS_RO(regs);
 DEBUG_FOPS_RO(tlb);
-DEBUG_FOPS(pagetable);
+DEBUG_FOPS_RO(pagetable);
 
 #define __DEBUG_ADD_FILE(attr, mode)   \
{   \
@@ -230,7 +187,6 @@ DEBUG_FOPS(pagetable);
return -ENOMEM; \
}
 
-#define DEBUG_ADD_FILE(name) __DEBUG_ADD_FILE(name, 0600)
 #define DEBUG_ADD_FILE_RO(name) __DEBUG_ADD_FILE(name, 0400)
 
 static int iommu_debug_register(struct device *dev, void *data)
@@ -263,7 +219,7 @@ static int iommu_debug_register(struct device *dev, void 
*data)
 
DEBUG_ADD_FILE_RO(regs);
DEBUG_ADD_FILE_RO(tlb);
-   DEBUG_ADD_FILE(pagetable);
+   DEBUG_ADD_FILE_RO(pagetable);
 
return 0;
 
-- 
2.1.0

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


[PATCH 01/17] iommu/omap: Remove refcount field from omap_iommu object

2014-09-30 Thread Suman Anna
The refcount field in omap_iommu object is primarily used to check
if an IOMMU device has already been enabled, but this is already
implicit in the omap_iommu_attach_dev() which ensures that only
a single device can attach to an IOMMU. This field is redundant,
and so has been cleaned up.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.c | 15 +++
 drivers/iommu/omap-iommu.h |  1 -
 2 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 4b432c4..ed26701 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -819,8 +819,9 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
u32 *iopgd, *iopte;
struct omap_iommu *obj = data;
struct iommu_domain *domain = obj->domain;
+   struct omap_iommu_domain *omap_domain = domain->priv;
 
-   if (!obj->refcount)
+   if (!omap_domain->iommu_dev)
return IRQ_NONE;
 
errs = iommu_report_fault(obj, &da);
@@ -880,13 +881,6 @@ static struct omap_iommu *omap_iommu_attach(const char 
*name, u32 *iopgd)
 
spin_lock(&obj->iommu_lock);
 
-   /* an iommu device can only be attached once */
-   if (++obj->refcount > 1) {
-   dev_err(dev, "%s: already attached!\n", obj->name);
-   err = -EBUSY;
-   goto err_enable;
-   }
-
obj->iopgd = iopgd;
err = iommu_enable(obj);
if (err)
@@ -899,7 +893,6 @@ static struct omap_iommu *omap_iommu_attach(const char 
*name, u32 *iopgd)
return obj;
 
 err_enable:
-   obj->refcount--;
spin_unlock(&obj->iommu_lock);
return ERR_PTR(err);
 }
@@ -915,9 +908,7 @@ static void omap_iommu_detach(struct omap_iommu *obj)
 
spin_lock(&obj->iommu_lock);
 
-   if (--obj->refcount == 0)
-   iommu_disable(obj);
-
+   iommu_disable(obj);
obj->iopgd = NULL;
 
spin_unlock(&obj->iommu_lock);
diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 4f1b68c..5c14000 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -33,7 +33,6 @@ struct omap_iommu {
void*isr_priv;
struct iommu_domain *domain;
 
-   unsigned intrefcount;
spinlock_t  iommu_lock; /* global for this whole object */
 
/*
-- 
2.1.0

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


[PATCH 04/17] iommu/omap: Remove conditional definition of dev_to_omap_iommu()

2014-09-30 Thread Suman Anna
The dev_to_omap_iommu() is local to the OMAP IOMMU modules, and
need not be defined conditionally. The CONFIG_IOMMU_API dependency
check was added in the past to fix a compilation issue back when
the header resided in the arch/arm layers, and is no longer
needed.

While at this, fix the header against double inclusion as well.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.h | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 4fc51c8..d7c5132 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -10,6 +10,9 @@
  * published by the Free Software Foundation.
  */
 
+#ifndef _OMAP_IOMMU_H
+#define _OMAP_IOMMU_H
+
 #if defined(CONFIG_ARCH_OMAP1)
 #error "iommu for this processor not implemented yet"
 #endif
@@ -92,7 +95,6 @@ struct iommu_functions {
ssize_t (*dump_ctx)(struct omap_iommu *obj, char *buf, ssize_t len);
 };
 
-#ifdef CONFIG_IOMMU_API
 /**
  * dev_to_omap_iommu() - retrieves an omap iommu object from a user device
  * @dev: iommu client device
@@ -103,7 +105,6 @@ static inline struct omap_iommu *dev_to_omap_iommu(struct 
device *dev)
 
return arch_data->iommu_dev;
 }
-#endif
 
 /*
  * MMU Register offsets
@@ -220,3 +221,5 @@ static inline void iommu_write_reg(struct omap_iommu *obj, 
u32 val, size_t offs)
 {
__raw_writel(val, obj->regbase + offs);
 }
+
+#endif /* _OMAP_IOMMU_H */
-- 
2.1.0

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


[PATCH 03/17] iommu/omap: Remove duplicate declarations

2014-09-30 Thread Suman Anna
The omap_iommu_save_ctx() and omap_iommu_restore_ctx() declarations
are defined in include/linux/omap-iommu.h and do not belong in the
internal drivers/iommu/omap-iommu.h header, so remove them.

Signed-off-by: Suman Anna 
---
 drivers/iommu/omap-iommu.h | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/iommu/omap-iommu.h b/drivers/iommu/omap-iommu.h
index 18a0f3a..4fc51c8 100644
--- a/drivers/iommu/omap-iommu.h
+++ b/drivers/iommu/omap-iommu.h
@@ -197,9 +197,6 @@ extern void omap_iotlb_cr_to_e(struct cr_regs *cr, struct 
iotlb_entry *e);
 extern int
 omap_iopgtable_store_entry(struct omap_iommu *obj, struct iotlb_entry *e);
 
-extern void omap_iommu_save_ctx(struct device *dev);
-extern void omap_iommu_restore_ctx(struct device *dev);
-
 extern int omap_foreach_iommu_device(void *data,
int (*fn)(struct device *, void *));
 
-- 
2.1.0

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


Re: [RFC PATCH v3 7/7] arm: dma-mapping: plumb our iommu mapping ops into arch_setup_dma_ops

2014-09-30 Thread Will Deacon
Hi Thierry,

On Thu, Sep 25, 2014 at 07:40:23AM +0100, Thierry Reding wrote:
> On Wed, Sep 24, 2014 at 05:33:38PM +0100, Will Deacon wrote:
> > On Tue, Sep 23, 2014 at 08:14:01AM +0100, Thierry Reding wrote:
> > > On Mon, Sep 22, 2014 at 06:43:37PM +0100, Will Deacon wrote:
> > > > Yup. In this case, the iommu_dma_mapping passed to arch_setup_dma_ops
> > > > contains a domain and an allocator for each IOMMU instance in the 
> > > > system.
> > > > It would then be up to the architecture how it makes use of those, but
> > > > the most obvious thing to do would be to attach devices mastering 
> > > > through
> > > > an IOMMU instance to that per-instance domain.
> > > > 
> > > > The other use-case is isolation (one domain per device), which I guess
> > > > matches what the ARM code is doing at the moment.
> > > 
> > > I think there are two cases here. You can have a composite device that
> > > wants to manage a single domain (using its own allocator) for a set of
> > > hardware devices. At the same time a set of devices (think 2D and 3D
> > > engines) could want to use a multiple domains for process separation.
> > > In that case I'd expect a logical DRM device to allocate one domain per
> > > process and then associate the 2D and 3D engines with that same domain
> > > on process switch.
> > 
> > Sure, but that's well outside of what the dma-mapping API is going to setup
> > as a default domain. These specialist setups are certainly possible, but I
> > think they should be driven by, for example, the DRM code as opposed to
> > being in the core dma-mapping code.
> 
> I completely agree that these special cases should be driven by the
> drivers that need them. However the problem here is that the current
> patch will already attach the device to an IOMMU domain by default.

Sure, but that's not an unfixable problem if somebody cares enough to do it.
Right now, I see a small handful of callers for the IOMMU API and nearly all
of them would work perfectly well with a default domain. The big exception
to that is VFIO, but that requires the device to be unbound from the host
driver, so we could detach the mapping at that point.

> So I think what we're going to need is a way to prevent the default
> attachment to DMA/IOMMU. Or alternatively not associate devices with
> IOMMU domains by default but let drivers explicitly make the decision.

Which drivers and how would they know what to do? I think you might be
jumping the gun a bit here, given where mainline is with using the IOMMU
for anything at all.

> > > What I proposed a while back was to leave it up to the IOMMU driver to
> > > choose an allocator for the device. Or rather, choose whether to use a
> > > custom allocator or the DMA/IOMMU integration allocator. The way this
> > > worked was to keep a list of devices in the IOMMU driver. Devices in
> > > this list would be added to domain reserved for DMA/IOMMU integration.
> > > Those would typically be devices such as SD/MMC, audio, ... devices that
> > > are in-kernel and need no per-process separation. By default devices
> > > wouldn't be added to a domain, so devices forming a composite DRM device
> > > would be able to manage their own domain.
> > 
> > I'd live to have as little of this as possible in the IOMMU drivers, as we
> > should leave those to deal with the IOMMU hardware and not domain
> > management. Having subsystems manage their own dma ops is an extension to
> > the dma-mapping API.
> 
> It's not an extension, really. It's more that both need to be able to
> coexist. For some devices you may want to create an IOMMU domain and
> hook it up with the DMA mapping functions, for others you don't and
> handle mapping to IOVA space explicitly.

I think it's an extension in the sense that mainline doesn't currently do
what you want, regardless of this patch series. My motivation is to enable
IOMMU-backed DMA-mapping so that I can continue implementing the virtual
SMMU work I started a while back. Patches welcome to enable any other
use-cases -- I don't think they're mutually exclusive.

> There is another issue with the approach you propose. I'm not sure if
> Tegra is special in this case (I'd expect not), but what we do is make
> an IOMMU domain correspond to an address space. Address spaces are a
> pretty limited resource (earlier generations have 4, newer have 128)
> and each address space can be up to 4 GiB. So I've always envisioned
> that we should be using a single IOMMU domain for devices that don't
> expose direct buffer access to userspace (SATA, PCIe, audio, SD/MMC,
> USB, ...). All of those would typically need only a small number of
> small buffers, so using a separate address space for each seems like a
> big waste.

I agree here, the ARM DMA-mapping code should really be doing one domain
per SMMU instance; all I've done is hook up the existing code which wasn't
previously being called.

> Doing so would leave a large number of address spaces available for
> things like a GPU driver to

Re: [PATCH v3 0/5] enhance DMA CMA on x86

2014-09-30 Thread Peter Hurley
On 09/29/2014 10:32 AM, Akinobu Mita wrote:
> 2014-09-29 21:09 GMT+09:00 Peter Hurley :
>> On 09/27/2014 08:31 PM, Akinobu Mita wrote:
>>> 2014-09-27 23:30 GMT+09:00 Peter Hurley :
 On 04/15/2014 09:08 AM, Akinobu Mita wrote:
> This patch set enhances the DMA Contiguous Memory Allocator on x86.
>>
>> [...]
>>
 What this patchset does is restrict all iommu configurations which can
 map all of system memory to one _very_ small physical region, thus 
 disabling
 the whole point of an iommu.

 Now I know why my GPU is causing paging to disk! And why my RAID controller
 stalls for ages when I do a git log at the same time as a kernel build!
>>>
>>> The solution I have for this is that instead of trying to
>>> dma_alloc_from_contiguous() firstly, call alloc_pages() in 
>>> dma_alloc_coherent().
>>> dma_alloc_from_contiguous() should be called only when alloc_pages() is 
>>> failed
>>> or DMA_ATTR_FORCE_CONTIGUOUS is specified in dma_attr.
>>
>> Why is all this extra complexity being added when there are no X86 users
>> of DMA_ATTR_FORCE_CONTIGUOUS?
> 
> I misunderstood DMA_ATTR_FORCE_CONTIGUOUS.  It is specified to request
> that underlaying DMA mapping span physically contiguous with IOMMU.
> But current alloc_dma_coherent() for intel-iommu always returns
> physically contiguous memory, so it is ignored on x86.
> 
 And the apparent goal of this patchset is to enable DMA allocation below
 4GB, which is already supported in the existing page allocator with the
 GFP_DMA32 flag?!
>>>
>>> The goal of this patchset is to enable huge DMA allocation which
>>> alloc_pages() can't (> MAX_ORDER) for the devices that require it.
>>
>> What x86 devices need > MAX_ORDER DMA allocation and why can't they allocate
>> directly from dma_alloc_from_contiguous()?
> 
> I need this for UFS unified memory extension which is apparently not in
> mainline for now.
> http://www.jedec.org/standards-documents/docs/jesd220-1
> http://www.jedec.org/sites/default/files/T_Fujisawa_MF_2013.pdf
> 
> But there must be some other use cases on x86, too.  Because I have
> received several emails privately from developers who care its status.
> 
> And allocating directly from dma_alloc_from_contiguous() in the driver
> doesn't work with IOMMU, as it just returns memory regoin and doesn't
> create DMA mapping.


I read the UFS Unified Memory Extension v1.0 (JESD220-1) specification and
it is not clear to me that using DMA mapping is the right approach to
supporting UM, at least on x86.

And without a mainline user, the merits of this approach are not evident.
I cannot even find a production x86 UFS controller, much less one that
supports UME.

The only PCI UFS controller I could find (and that mainline supports) is
Samsung's x86 FPGA-based test unit for developing UFS devices in a x86 test
environment, and not a production x86 design.

Samsung's own roadmap 
(http://www.slideshare.net/linaroorg/next-gen-mobilestorageufs)
mentions nothing about bringing UFS to x86 designs.

Unless there's something else I've missed, I don't think these patches
belong in mainline.

Regards,
Peter Hurley



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


[PATCH 1/2] driver core: Add BUS_NOTIFY_REMOVED_DEVICE event

2014-09-30 Thread Joerg Roedel
From: Joerg Roedel 

This event closes an important gap in the bus notifiers.
There is already the BUS_NOTIFY_DEL_DEVICE event, but that
is sent when the device is still bound to its device driver.

This is too early for the IOMMU code to destroy any mappings
for the device, as they might still be in use by the driver.

The new BUS_NOTIFY_REMOVED_DEVICE event introduced with this
patch closes this gap as it is sent when the device is
already unbound from its device driver and almost completly
removed from the driver core.

With this event the IOMMU code can safely destroy any
mappings and other data structures when a device is removed.

Signed-off-by: Joerg Roedel 
---
 drivers/base/core.c|  3 +++
 include/linux/device.h | 11 ++-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 20da3ad..7b270a2 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1211,6 +1211,9 @@ void device_del(struct device *dev)
 */
if (platform_notify_remove)
platform_notify_remove(dev);
+   if (dev->bus)
+   blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+BUS_NOTIFY_REMOVED_DEVICE, dev);
kobject_uevent(&dev->kobj, KOBJ_REMOVE);
cleanup_device_parent(dev);
kobject_del(&dev->kobj);
diff --git a/include/linux/device.h b/include/linux/device.h
index 43d183a..d0d5c5d 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -181,13 +181,14 @@ extern int bus_unregister_notifier(struct bus_type *bus,
  * with the device lock held in the core, so be careful.
  */
 #define BUS_NOTIFY_ADD_DEVICE  0x0001 /* device added */
-#define BUS_NOTIFY_DEL_DEVICE  0x0002 /* device removed */
-#define BUS_NOTIFY_BIND_DRIVER 0x0003 /* driver about to be
+#define BUS_NOTIFY_DEL_DEVICE  0x0002 /* device to be removed */
+#define BUS_NOTIFY_REMOVED_DEVICE  0x0003 /* device removed */
+#define BUS_NOTIFY_BIND_DRIVER 0x0004 /* driver about to be
  bound */
-#define BUS_NOTIFY_BOUND_DRIVER0x0004 /* driver bound to 
device */
-#define BUS_NOTIFY_UNBIND_DRIVER   0x0005 /* driver about to be
+#define BUS_NOTIFY_BOUND_DRIVER0x0005 /* driver bound to 
device */
+#define BUS_NOTIFY_UNBIND_DRIVER   0x0006 /* driver about to be
  unbound */
-#define BUS_NOTIFY_UNBOUND_DRIVER  0x0006 /* driver is unbound
+#define BUS_NOTIFY_UNBOUND_DRIVER  0x0007 /* driver is unbound
  from the device */
 
 extern struct kset *bus_get_kset(struct bus_type *bus);
-- 
1.9.1

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


[PATCH 2/2] iommu/vt-d: Only remove domain when device is removed

2014-09-30 Thread Joerg Roedel
From: Joerg Roedel 

This makes sure any RMRR mappings stay in place when the
driver is unbound from the device.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/intel-iommu.c | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 5619f26..eaf825a 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3865,16 +3865,7 @@ static int device_notifier(struct notifier_block *nb,
if (iommu_dummy(dev))
return 0;
 
-   if (action != BUS_NOTIFY_UNBOUND_DRIVER &&
-   action != BUS_NOTIFY_DEL_DEVICE)
-   return 0;
-
-   /*
-* If the device is still attached to a device driver we can't
-* tear down the domain yet as DMA mappings may still be in use.
-* Wait for the BUS_NOTIFY_UNBOUND_DRIVER event to do that.
-*/
-   if (action == BUS_NOTIFY_DEL_DEVICE && dev->driver != NULL)
+   if (action != BUS_NOTIFY_REMOVED_DEVICE)
return 0;
 
domain = find_domain(dev);
-- 
1.9.1

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


[PATCH 0/2] iommu/vt-d: Keep RMRR mappings around on driver unbind

2014-09-30 Thread Joerg Roedel
Hi,

here is a patch-set to fix an issue recently discovered when
the Intel IOMMU is in use with devices that need RMRR
mappings.

The problem is that the RMRR mappings are destroyed when the
device driver is unbound from the device, causing DMAR
faults.

To solve this problem a device driver core change is
necessary to catch the right point in time for the IOMMU
code to destroy any mappings for a device.

With this patch-set the RMRR mappings are only destroyed
when the device is actually removed from the system.

Please review.

Thanks,

Joerg

Joerg Roedel (2):
  driver core: Add BUS_NOTIFY_REMOVED_DEVICE event
  iommu/vt-d: Only remove domain when device is removed

 drivers/base/core.c |  3 +++
 drivers/iommu/intel-iommu.c | 11 +--
 include/linux/device.h  | 11 ++-
 3 files changed, 10 insertions(+), 15 deletions(-)

-- 
1.9.1

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


Re: [PATCH v3 2/2] iommu/arm-smmu: add support for iova_to_phys through ATS1PR

2014-09-30 Thread Will Deacon
Hi Mitch,

On Sun, Sep 28, 2014 at 04:27:29AM +0100, Mitchel Humpherys wrote:
> Currently, we provide the iommu_ops.iova_to_phys service by doing a
> table walk in software to translate IO virtual addresses to physical
> addresses. On SMMUs that support it, it can be useful to ask the SMMU
> itself to do the translation. This can be used to warm the TLBs for an
> SMMU. It can also be useful for testing and hardware validation.
> 
> Since the address translation registers are optional on SMMUv2, only
> enable hardware translations when using SMMUv1 or when SMMU_IDR0.S1TS=1
> and SMMU_IDR0.ATOSNS=0, as described in the ARM SMMU v1-v2 spec.

[...]

> +static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
> + dma_addr_t iova)
> +{
> + struct arm_smmu_domain *smmu_domain = domain->priv;
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> + struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + struct device *dev = smmu->dev;
> + void __iomem *cb_base;
> + u32 tmp;
> + u64 phys;
> +
> + cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
> +
> + if (smmu->version == 1) {
> + u32 reg = iova & ~0xFFF;

Cosmetic comment, but hex constants are lowercase everywhere else in the
file.

> + writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
> + } else {
> + u32 reg = iova & ~0xFFF;
> + writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_LO);
> + reg = (iova & ~0xFFF) >> 32;
> + writel_relaxed(reg, cb_base + ARM_SMMU_CB_ATS1PR_HI);
> + }
> +
> + if (readl_poll_timeout(cb_base + ARM_SMMU_CB_ATSR, tmp,
> + !(tmp & ATSR_ACTIVE), 10, ATSR_LOOP_TIMEOUT)) {
> + dev_err(dev,
> + "iova to phys timed out on 0x%pa. Falling back to 
> software table walk.\n",
> + &iova);
> + return arm_smmu_iova_to_phys_soft(domain, iova);
> + }
> +
> + phys = readl_relaxed(cb_base + ARM_SMMU_CB_PAR_LO);
> + phys |= ((u64) readl_relaxed(cb_base + ARM_SMMU_CB_PAR_HI)) << 32;

The absence of locking in this function concerns me a bit. For the software
implementation, we're just reading page tables, but here we're writing ATS
registers and I think we need to ensure serialisation against another
iova_to_phys on the same domain.

> + if (phys & CB_PAR_F) {
> + dev_err(dev, "translation fault!\n");
> + dev_err(dev, "PAR = 0x%llx\n", phys);
> + }
> + phys = (phys & 0xFFF000ULL) | (iova & 0x0FFF);
> +
> + return phys;

You can return phys == 0 on failure (at least, the callers in kvm and vfio
treat this as an error).

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