Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-04-29 Thread Yong Wu
Dear Tomasz,
 About a hardcode your comment, please help check below.

Dear Mark,
  I would like to add a item in the dtsi of mtk-iommu. Please also
help have a look.


   +static const struct mtk_iommu_port mtk_iommu_mt8173_port[] = {
   +   /* port namem4uid slaveid larbid portid
tfid */
   +   /* larb0 */
   +   {M4U_PORT_DISP_OVL0,  0,  0,0,  0,
MTK_TFID(0, 0)},
   +   {M4U_PORT_DISP_RDMA0, 0,  0,0,  1,
MTK_TFID(0, 1)},
   +   {M4U_PORT_DISP_WDMA0, 0,  0,0,  2,
MTK_TFID(0, 2)},
   +   {M4U_PORT_DISP_OD_R,  0,  0,0,  3,
MTK_TFID(0, 3)},
   +   {M4U_PORT_DISP_OD_W,  0,  0,0,  4,
MTK_TFID(0, 4)},
   +   {M4U_PORT_MDP_RDMA0,  0,  0,0,  5,
MTK_TFID(0, 5)},
   +   {M4U_PORT_MDP_WDMA,   0,  0,0,  6,
MTK_TFID(0, 6)},
   +   {M4U_PORT_MDP_WROT0,  0,  0,0,  7,
MTK_TFID(0, 7)},
[...]
 
   +};
   +
  
  Anyway, is it really necessary to hardcode the SoC specific topology
  data in this driver? Is there really any use besides of printing
port
  name? If not, you could just print the values in a way letting you
  quickly look up in the datasheet, without hardcoding this. Or even
  better, you could print which devices are attached to the port.
  
 a) Printing the port name is for debug. We could not request every
iommu
 user to understand smilocal arbiter. When there is irq, they have to
 look up the iommu's datasheet to find out which port error. if we
print
 it directly, It may be more easily to debug.
 
 b) In mtk_iommu_config_port, according to this hardcode we can be
easily
 to get out which local arbiter and which port we prepare to config.
 
 c) If we support different SOCs, we could change this arrays easily.
 
  
 There is no similar code in the others iommu, so I prepare to
delete it, But we really need know which local arbiter and which port we
are going to config(which port will enable iommu)
so we prepare add a item in the dtsi like this:

iommu: mmsys_iommu@10205000 {
compatible = mediatek,mt8173-iommu;
...
+   larb-portes-nr = M4U_LARB0_PORT_NR
+M4U_LARB1_PORT_NR
+M4U_LARB2_PORT_NR
+M4U_LARB3_PORT_NR
+M4U_LARB4_PORT_NR
+M4U_LARB5_PORT_NR;
larb = larb0 larb1 larb2 larb3 larb4 larb5;
#iommu-cells = 1;
};
larb-portes-nr : the number of the portes in each local arbiter.

If we have this item, we can get which larb and which port from the
portid in the dtsi of the iommu user.

And while there is isr, I will print the larb-id and the port-id
instead of the string of the port name.

The M4U_LARB0_PORT_NR/... will be added in
dt-bindings/iommu/mt8173-iommu-port.h[0]

Dear Mark, 
  As above, if I add this item in the dtsi of iommu, is it ok?


[0]:http://lists.linuxfoundation.org/pipermail/iommu/2015-March/012450.html
 

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


Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-04-15 Thread Yong Wu
On Wed, 2015-04-15 at 11:20 +0900, Tomasz Figa wrote:
 On Tue, Apr 14, 2015 at 3:31 PM, Yong Wu yong...@mediatek.com wrote:
  
+
+   piommu-protect_va = devm_kmalloc(piommu-dev, 
MTK_PROTECT_PA_ALIGN*2,
  
   style: Operators like * should have space on both sides.
  
+ GFP_KERNEL);
  
   Shouldn't dma_alloc_coherent() be used for this?
We don't care the data in it. I think they are the same. Could you
   help tell me why dma_alloc_coherent may be better.
 
  Can you guarantee that at the time you allocate the memory using
  devm_kmalloc() the memory is not dirty (i.e. some write back data are
  stored in CPU cache) and is not going to be written back in some time,
  overwriting data put there by IOMMU hardware?
 
  As I noted in the function mtk_iommu_hw_init:
 
 /* protect memory,HW will write here while translation fault */
 protectpa = __virt_to_phys(piommu-protect_va);
 
   We don’t care the content of this buffer, It is ok even though its
  data is dirty.
  It seem to be a the protect memory. While a translation fault
  happened, The iommu HW will overwrite here instead of writing to the
  fault physical address which may be 0 or some random address.
 
 
 Do you mean that it's just a dummy page for hardware behind the IOMMU
 to access when the mapping is not available? How would that work with
 potential on demand paging when the hardware needs to be blocked until
 the mapping is created?
 
 Best regards,
 Tomasz
 1. YES
 2. Sorry. Our iommu HW can not support this right now. The HW can not
be blocked until the mapping is created.
If the page is not ready, we can not get the physical address, then
How to fill the pagetable for that memory. I think the dmaiommu may
guaranty it?


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

Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-04-15 Thread Tomasz Figa
On Wed, Apr 15, 2015 at 4:06 PM, Yong Wu yong...@mediatek.com wrote:
 On Wed, 2015-04-15 at 11:20 +0900, Tomasz Figa wrote:
 On Tue, Apr 14, 2015 at 3:31 PM, Yong Wu yong...@mediatek.com wrote:
  
+
+   piommu-protect_va = devm_kmalloc(piommu-dev, 
MTK_PROTECT_PA_ALIGN*2,
  
   style: Operators like * should have space on both sides.
  
+ GFP_KERNEL);
  
   Shouldn't dma_alloc_coherent() be used for this?
We don't care the data in it. I think they are the same. Could you
   help tell me why dma_alloc_coherent may be better.
 
  Can you guarantee that at the time you allocate the memory using
  devm_kmalloc() the memory is not dirty (i.e. some write back data are
  stored in CPU cache) and is not going to be written back in some time,
  overwriting data put there by IOMMU hardware?
 
  As I noted in the function mtk_iommu_hw_init:
 
 /* protect memory,HW will write here while translation fault */
 protectpa = __virt_to_phys(piommu-protect_va);
 
   We don’t care the content of this buffer, It is ok even though its
  data is dirty.
  It seem to be a the protect memory. While a translation fault
  happened, The iommu HW will overwrite here instead of writing to the
  fault physical address which may be 0 or some random address.
 

 Do you mean that it's just a dummy page for hardware behind the IOMMU
 to access when the mapping is not available? How would that work with
 potential on demand paging when the hardware needs to be blocked until
 the mapping is created?

 Best regards,
 Tomasz
  1. YES
  2. Sorry. Our iommu HW can not support this right now. The HW can not
 be blocked until the mapping is created.

OK, that explains it. Well, then I guess this is necessary and
contents of that memory don't matter that much. (Although, this might
be a minor security issue, because the faulting hardware would get
access to some data previously stored by kernel code. Not sure how
much of a threat would that be, though.)

 If the page is not ready, we can not get the physical address, then
 How to fill the pagetable for that memory. I think the dmaiommu may
 guaranty it?

If your hardware can't block until the mapping is created then what
you do currently seems to be the only option. (+/- the missing cache
maintenance at initialization)

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

Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-04-14 Thread Yong Wu
Hi Tomasz,

 Thanks very much for you suggestion and explain so detail.
 please help check below.

On Fri, 2015-03-27 at 18:41 +0900, Tomasz Figa wrote:
 Hi Yong Wu,
 
 Sorry for long delay, I had to figure out some time to look at this again.
 
 On Wed, Mar 18, 2015 at 8:22 PM, Yong Wu yong...@mediatek.com wrote:
 
   +   imudev = piommu-dev;
   +
   +   spin_lock_irqsave(priv-portlock, flags);
 
  What is protected by this spinlock?
  We will write a register of the local arbiter while config port. If
  some modules are in the same local arbiter, it may be overwrite. so I
  add it here.
 
 
 OK. Maybe it could be called larb_lock then? It would be good to have
 structures or code that should be running under this spinlock
 annotated with proper comments. And purpose of the lock documented in
 a comment as well (probably in a kerneldoc-style documentation of
 priv).
   Thanks. I have move the spinlock into the smi driver, it will lock
for writing the local arbiter regsiter only.
 
   +static void mtk_iommu_detach_device(struct iommu_domain *domain,
   +   struct device *dev)
   +{
 
  No hardware (de)configuration or clean-up necessary?
  I will add it. Actually we design like this:If a device have attached to
  iommu domain, it won't detach from it.
 
 Isn't proper clean-up required for module removal? Some drivers might
 be required to be loadable modules, which should be unloadable.
 
 
   +
   +   piommu-protect_va = devm_kmalloc(piommu-dev, 
   MTK_PROTECT_PA_ALIGN*2,
 
  style: Operators like * should have space on both sides.
 
   + GFP_KERNEL);
 
  Shouldn't dma_alloc_coherent() be used for this?
   We don't care the data in it. I think they are the same. Could you
  help tell me why dma_alloc_coherent may be better.
 
 Can you guarantee that at the time you allocate the memory using
 devm_kmalloc() the memory is not dirty (i.e. some write back data are
 stored in CPU cache) and is not going to be written back in some time,
 overwriting data put there by IOMMU hardware?
 
As I noted in the function mtk_iommu_hw_init:

   /* protect memory,HW will write here while translation fault */
   protectpa = __virt_to_phys(piommu-protect_va);

 We don’t care the content of this buffer, It is ok even though its
data is dirty.
It seem to be a the protect memory. While a translation fault
happened, The iommu HW will overwrite here instead of writing to the
fault physical address which may be 0 or some random address.

   +
   +   iommu_set_fault_handler(domain, mtk_iommu_fault_handler, piommu);
 
  I don't see any other drivers doing this. Isn't this for upper layers,
  so that they can set their own generic fault handlers?
   I think that this function is related with the iommu domain, we
  have only one multimedia iommu domain. so I add it after the iommu
  domain are created.
 
 No, this function is for drivers of IOMMU clients (i.e. master IP
 blocks) which want to subscribe to page fault to do things like paging
 on demand and so on. It shouldn't be called by IOMMU driver. Please
 see other IOMMU drivers, for example rockchip-iommmu.c.
 Thanks. I have read it. I will delete it and print the error info
in the ISR. Also call the report_iommu_fault in the ISR.

 Best regards,
 Tomasz


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

Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-04-14 Thread Tomasz Figa
On Tue, Apr 14, 2015 at 3:31 PM, Yong Wu yong...@mediatek.com wrote:
 
   +
   +   piommu-protect_va = devm_kmalloc(piommu-dev, 
   MTK_PROTECT_PA_ALIGN*2,
 
  style: Operators like * should have space on both sides.
 
   + GFP_KERNEL);
 
  Shouldn't dma_alloc_coherent() be used for this?
   We don't care the data in it. I think they are the same. Could you
  help tell me why dma_alloc_coherent may be better.

 Can you guarantee that at the time you allocate the memory using
 devm_kmalloc() the memory is not dirty (i.e. some write back data are
 stored in CPU cache) and is not going to be written back in some time,
 overwriting data put there by IOMMU hardware?

 As I noted in the function mtk_iommu_hw_init:

/* protect memory,HW will write here while translation fault */
protectpa = __virt_to_phys(piommu-protect_va);

  We don’t care the content of this buffer, It is ok even though its
 data is dirty.
 It seem to be a the protect memory. While a translation fault
 happened, The iommu HW will overwrite here instead of writing to the
 fault physical address which may be 0 or some random address.


Do you mean that it's just a dummy page for hardware behind the IOMMU
to access when the mapping is not available? How would that work with
potential on demand paging when the hardware needs to be blocked until
the mapping is created?

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

Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-17 Thread Will Deacon
On Mon, Mar 09, 2015 at 12:11:43PM +, Yong Wu wrote:
 On Fri, 2015-03-06 at 10:58 +, Will Deacon wrote:
  On Fri, Mar 06, 2015 at 10:48:17AM +, yong...@mediatek.com wrote:
   From: Yong Wu yong...@mediatek.com
   
   This patch adds support for mediatek m4u (MultiMedia Memory Management 
   Unit).
   Currently this only supports m4u gen 2 with 2 levels of page table on 
   mt8173.
  
  [...]
  
   +/* 2 level pagetable: pgd - pte */
   +#define F_PTE_TYPE_GET(regval)  (regval  0x3)
   +#define F_PTE_TYPE_LARGE BIT(0)
   +#define F_PTE_TYPE_SMALL BIT(1)
   +#define F_PTE_B_BIT  BIT(2)
   +#define F_PTE_C_BIT  BIT(3)
   +#define F_PTE_BIT32_BIT  BIT(9)
   +#define F_PTE_S_BIT  BIT(10)
   +#define F_PTE_NG_BIT BIT(11)
   +#define F_PTE_PA_LARGE_MSK(~0UL  16)
   +#define F_PTE_PA_LARGE_GET(regval)((regval  16)  0x)
   +#define F_PTE_PA_SMALL_MSK(~0UL  12)
   +#define F_PTE_PA_SMALL_GET(regval)((regval  12)  (~0))
   +#define F_PTE_TYPE_IS_LARGE_PAGE(pte) ((imu_pte_val(pte)  0x3) == \
   +   F_PTE_TYPE_LARGE)
   +#define F_PTE_TYPE_IS_SMALL_PAGE(pte) ((imu_pte_val(pte)  0x3) == \
   +   F_PTE_TYPE_SMALL)
  
  This looks like the ARM short-descriptor format to me. Could you please
  add a new page table format to the io-pgtable code, so that other IOMMU
  drivers can make use of this? I know there was some interest in using
  short descriptor for the ARM SMMU, for example.
 Currently I not familiar with the io-pgtable,I may need some time
 for it and the ARM short-descriptor. 

Well, you can read the LPAE version I wrote in io-pgtable-arm.c for some
inspiration (it's used by arm-smmu.c and ipmmu-vmsa.c).

 And there are some difference between mediatek's pagetable with the
 standard short-descriptor, like bit 9. we use it for the dram over 4GB.
 Then how should we do if there are some difference. 

That can easily be handled using a quirk (see, for example,
IO_PGTABLE_QUIRK_ARM_NS).

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


Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-12 Thread Yong Wu
Dear Tomasz,

  Thanks very much for review so detail!

  Please check my reply below. Others I will fix it in the next
version.
   
  And I have got your comment of [2/5]. Do you have plan for the
other patch?

On Sun, 2015-03-08 at 13:12 +0900, Tomasz Figa wrote:
 Hi Yong Wu,
 
 Thanks for this series. Please see my comments inline.
 
 On Fri, Mar 6, 2015 at 7:48 PM,  yong...@mediatek.com wrote:
  From: Yong Wu yong...@mediatek.com
 
  This patch adds support for mediatek m4u (MultiMedia Memory Management 
  Unit).
  Currently this only supports m4u gen 2 with 2 levels of page table on 
  mt8173.
 
[snip]
  +static const struct mtk_iommu_port mtk_iommu_mt8173_port[] = {
  +   /* port namem4uid slaveid larbid portid tfid */
  +   /* larb0 */
  +   {M4U_PORT_DISP_OVL0,  0,  0,0,  0, MTK_TFID(0, 0)},
  +   {M4U_PORT_DISP_RDMA0, 0,  0,0,  1, MTK_TFID(0, 1)},
  +   {M4U_PORT_DISP_WDMA0, 0,  0,0,  2, MTK_TFID(0, 2)},
  +   {M4U_PORT_DISP_OD_R,  0,  0,0,  3, MTK_TFID(0, 3)},
  +   {M4U_PORT_DISP_OD_W,  0,  0,0,  4, MTK_TFID(0, 4)},
  +   {M4U_PORT_MDP_RDMA0,  0,  0,0,  5, MTK_TFID(0, 5)},
  +   {M4U_PORT_MDP_WDMA,   0,  0,0,  6, MTK_TFID(0, 6)},
  +   {M4U_PORT_MDP_WROT0,  0,  0,0,  7, MTK_TFID(0, 7)},
 
 [snip]
 
  +   {M4U_PORT_HSIC_MAS,  1,  0,6,  12, 0x11},
  +   {M4U_PORT_HSIC_DEV,  1,  0,6,  13, 0x19},
  +   {M4U_PORT_AP_DMA,1,  0,6,  14, 0x18},
  +   {M4U_PORT_HSIC_DMA,  1,  0,6,  15, 0xc8},
  +   {M4U_PORT_MSDC0, 1,  0,6,  16, 0x0},
  +   {M4U_PORT_MSDC3, 1,  0,6,  17, 0x20},
  +   {M4U_PORT_UNKNOWN,   1,  0,6,  18, 0xf},
 
 Why the MTK_TFID() macro is not used for perisys iommu?
 
   The perisys iommu don't connected with SMI and Local arbiter.
it's translation fault id is not MTK_TFID(x, y).it is special.
   For this perisys iommu , it is different with multimedia iommu,
we don't support it in this version, We have plan to delete perisys
iommu port next time.

  +};
  +
 
 Anyway, is it really necessary to hardcode the SoC specific topology
 data in this driver? Is there really any use besides of printing port
 name? If not, you could just print the values in a way letting you
 quickly look up in the datasheet, without hardcoding this. Or even
 better, you could print which devices are attached to the port.
 
a) Printing the port name is for debug. We could not request every iommu
user to understand smilocal arbiter. When there is irq, they have to
look up the iommu's datasheet to find out which port error. if we print
it directly, It may be more easily to debug.

b) In mtk_iommu_config_port, according to this hardcode we can be easily
to get out which local arbiter and which port we prepare to config.

c) If we support different SOCs, we could change this arrays easily.

  +static const struct mtk_iommu_cfg mtk_iommu_mt8173_cfg = {
  +   .larb_nr = 6,
  +   .m4u_port_nr = ARRAY_SIZE(mtk_iommu_mt8173_port),
  +   .pport = mtk_iommu_mt8173_port,
  +};
  +
  +static const char *mtk_iommu_get_port_name(const struct mtk_iommu_info 
  *piommu,
  +  unsigned int portid)
  +{
  +   const struct mtk_iommu_port *pcurport = NULL;
  +
  +   pcurport = piommu-imucfg-pport + portid;
  +   if (portid  piommu-imucfg-m4u_port_nr  pcurport)
  +   return pcurport-port_name;
  +   else
  +   return UNKNOWN_PORT;
  +}
 
 This function seems to be used just for printing the hardcoded port names.
 
  +
  +static int mtk_iommu_get_port_by_tfid(const struct mtk_iommu_info *pimu,
  + int tf_id)
  +{
  +   const struct mtk_iommu_cfg *pimucfg = pimu-imucfg;
  +   int i;
  +   unsigned int portid = pimucfg-m4u_port_nr;
  +
  +   for (i = 0; i  pimucfg-m4u_port_nr; i++) {
  +   if (pimucfg-pport[i].tf_id == tf_id) {
  +   portid = i;
  +   break;
  +   }
  +   }
  +   if (i == pimucfg-m4u_port_nr)
  +   dev_err(pimu-dev, tf_id find fail, tfid %d\n, tf_id);
  +   return portid;
  +}
 
 This function seems to be used just for finding an index into the
 array of hardcoded port names for printing purposes.
   Yes. mtk_iommu_get_port_name and mtk_iommu_get_port_by_tfid is
only for find out the right port to print for improve debug.
 
[snip]
  +
  +static int mtk_iommu_invalidate_tlb(const struct mtk_iommu_info *piommu,
  +   int isinvall, unsigned int iova_start,
  +   unsigned int iova_end)
  +{
  +   void __iomem *m4u_base = piommu-m4u_base;
  +   u32 val;
  +   u64 start, end;
  +
  +   start = 

Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-09 Thread Yong Wu
Dear Mitchel,
 Thanks very much for your review.

On Fri, 2015-03-06 at 09:15 -0800, Mitchel Humpherys wrote:
 On Fri, Mar 06 2015 at 02:48:17 AM, yong...@mediatek.com wrote:
  From: Yong Wu yong...@mediatek.com
 
  This patch adds support for mediatek m4u (MultiMedia Memory Management 
  Unit).
  Currently this only supports m4u gen 2 with 2 levels of page table on 
  mt8173.
 
 [...]
 
  +static int mtk_iommu_invalidate_tlb(const struct mtk_iommu_info *piommu,
  +   int isinvall, unsigned int iova_start,
  +   unsigned int iova_end)
  +{
  +   void __iomem *m4u_base = piommu-m4u_base;
  +   u32 val;
  +   u64 start, end;
  +
  +   start = sched_clock();
  +
  +   if (!isinvall) {
  +   iova_start = round_down(iova_start, SZ_4K);
  +   iova_end = round_up(iova_end, SZ_4K);
  +   }
  +
  +   val = F_MMU_INV_EN_L2 | F_MMU_INV_EN_L1;
  +
  +   writel(val, m4u_base + REG_INVLID_SEL);
  +
  +   if (isinvall) {
  +   writel(F_MMU_INV_ALL, m4u_base + REG_MMU_INVLD);
  +   } else {
  +   writel(iova_start, m4u_base + REG_MMU_INVLD_SA);
  +   writel(iova_end, m4u_base + REG_MMU_INVLD_EA);
  +   writel(F_MMU_INV_RANGE, m4u_base + REG_MMU_INVLD);
  +
  +   while (!readl(m4u_base + REG_MMU_CPE_DONE)) {
  +   end = sched_clock();
  +   if (end - start = 1ULL) {
  +   dev_warn(piommu-dev, invalid don't done\n);
  +   writel(F_MMU_INV_ALL, m4u_base + REG_MMU_INVLD);
  +   }
  +   };
 
 Superfluous `;'.  Also, maybe you should be using readl_poll_timeout?
   Thanks.
   For the readl_poll_timeout, My base is 3.19-rc7 and robin's patch.
it don't have this interface.  I will try to add it in the next version.
 
  +   writel(0, m4u_base + REG_MMU_CPE_DONE);
  +   }
  +
  +   return 0;
  +}
 
 
 
 -Mitch
 


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


Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-09 Thread Tomasz Figa
Hi,

You can find part 2 of my comments inline.

On Fri, Mar 6, 2015 at 7:48 PM,  yong...@mediatek.com wrote:

[snip]

 +static irqreturn_t mtk_iommu_isr(int irq, void *dev_id)
 +{
 +   struct iommu_domain *domain = dev_id;
 +   struct mtk_iommu_domain *mtkdomain = domain-priv;
 +   struct mtk_iommu_info *piommu = mtkdomain-piommuinfo;
 +
 +   if (irq == piommu-irq)
 +   report_iommu_fault(domain, piommu-dev, 0, 0);

In addition to my previous comment about how this gets called from
this handler, you need to keep in mind that the function called by
report_iommu_fault() might actually be a different function than
mtk_iommu_fault_handler(), because upper layers can provide their own
handlers. This means that you need to perform any operations on
hardware from this handler and only use the iommu fault handler as a
way to tell an upper layer about the fault (including notifying the
user through kernel log if there is no special handler installed and
the generic fallback is used).

 +   else
 +   dev_err(piommu-dev, irq number:%d\n, irq);
 +
 +   return IRQ_HANDLED;
 +}

[snip]

 +static int mtk_iommu_fault_handler(struct iommu_domain *imudomain,
 +  struct device *dev, unsigned long iova,
 +  int m4uindex, void *pimu)
 +{
 +   void __iomem *m4u_base;
 +   u32 int_state, regval;
 +   int m4u_slave_id = 0;
 +   unsigned int layer, write, m4u_port;
 +   unsigned int fault_mva, fault_pa;
 +   struct mtk_iommu_info *piommu = pimu;
 +   struct mtk_iommu_domain *mtkdomain = imudomain-priv;
 +
 +   m4u_base = piommu-m4u_base;
 +   int_state = readl(m4u_base + REG_MMU_MAIN_FAULT_ST);
 +
 +   /* read error info from registers */
 +   fault_mva = readl(m4u_base + REG_MMU_FAULT_VA(m4u_slave_id));
 +   layer = !!(fault_mva  F_MMU_FAULT_VA_LAYER_BIT);
 +   write = !!(fault_mva  F_MMU_FAULT_VA_WRITE_BIT);
 +   fault_mva = F_MMU_FAULT_VA_MSK;
 +   fault_pa = readl(m4u_base + REG_MMU_INVLD_PA(m4u_slave_id));
 +   regval = readl(m4u_base + REG_MMU_INT_ID(m4u_slave_id));
 +   regval = F_MMU0_INT_ID_TF_MSK;
 +   m4u_port = mtk_iommu_get_port_by_tfid(piommu, regval);
 +
 +   if (int_state  F_INT_TRANSLATION_FAULT(m4u_slave_id)) {
 +   struct m4u_pte_info_t pte;
 +   unsigned long flags;
 +
 +   spin_lock_irqsave(mtkdomain-pgtlock, flags);
 +   m4u_get_pte_info(mtkdomain, fault_mva, pte);
 +   spin_unlock_irqrestore(mtkdomain-pgtlock, flags);
 +
 +   if (pte.size == MMU_SMALL_PAGE_SIZE ||
 +   pte.size == MMU_LARGE_PAGE_SIZE) {
 +   dev_err_ratelimited(
 +   dev,
 +   fault:port=%s iova=0x%x pa=0x%x layer=%d %s;
 +   
 pgd(0x%x)-pte(0x%x)-pa(%pad)sz(0x%x)Valid(%d)\n,
 +   mtk_iommu_get_port_name(piommu, m4u_port),
 +   fault_mva, fault_pa, layer,
 +   write ? write : read,
 +   imu_pgd_val(*pte.pgd), imu_pte_val(*pte.pte),
 +   pte.pa, pte.size, pte.valid);
 +   } else {
 +   dev_err_ratelimited(
 +   dev,
 +   fault:port=%s iova=0x%x pa=0x%x layer=%d %s;
 +   pgd(0x%x)-pa(%pad)sz(0x%x)Valid(%d)\n,
 +   mtk_iommu_get_port_name(piommu, m4u_port),
 +   fault_mva, fault_pa, layer,
 +   write ? write : read,
 +   imu_pgd_val(*pte.pgd),
 +   pte.pa, pte.size, pte.valid);
 +   }
 +   }
 +
 +   if (int_state  F_INT_MAIN_MULTI_HIT_FAULT(m4u_slave_id))
 +   dev_err_ratelimited(dev, multi-hit!port=%s iova=0x%x\n,
 +   mtk_iommu_get_port_name(piommu, m4u_port),
 +   fault_mva);
 +
 +   if (int_state  F_INT_INVALID_PA_FAULT(m4u_slave_id)) {
 +   if (!(int_state  F_INT_TRANSLATION_FAULT(m4u_slave_id)))
 +   dev_err_ratelimited(dev, invalid pa!port=%s 
 iova=0x%x\n,
 +   mtk_iommu_get_port_name(piommu,
 +   m4u_port),
 +   fault_mva);
 +   }
 +   if (int_state  F_INT_ENTRY_REPLACEMENT_FAULT(m4u_slave_id))
 +   dev_err_ratelimited(dev, replace-fault!port=%s iova=0x%x\n,
 +   mtk_iommu_get_port_name(piommu, m4u_port),
 +   fault_mva);
 +
 +   if (int_state  F_INT_TLB_MISS_FAULT(m4u_slave_id))
 +   

Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-09 Thread Tomasz Figa
On Mon, Mar 9, 2015 at 11:46 PM, Yingjoe Chen yingjoe.c...@mediatek.com wrote:
 On Mon, 2015-03-09 at 20:11 +0900, Tomasz Figa wrote:
 ...
  +/*
  + * pimudev is a global var for dma_alloc_coherent.
  + * It is not accepatable, we will delete it if domain_alloc is enabled
  + */
  +static struct device *pimudev;

 This is indeed not acceptable. Could you replace dma_alloc_coherent()
 with something that doesn't require device pointer, e.g.
 alloc_pages()? (Although that would require you to handle cache
 maintenance in the driver, due to cached memory allocated.) I need to
 think about a better solution for this.

 Hi,

 For 2nd level page table, we use cached memory now. Currently we are
 using __dma_flush_range to flush the cache, which is also unacceptable.

 For proper cache management, we'll need to use dma_map_single or
 dma_sync_*, which still need a deivce*.

Looking at how already mainlined drivers do this, they either use
dmac_flush_range()
(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/iommu/msm_iommu.c?id=refs/tags/v4.0-rc3#n80)
or directly __cpuc_flush_dcache_area() and outer_flush_range()
(https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/iommu/rockchip-iommu.c?id=refs/tags/v4.0-rc3#n93).

Joerg, what's your opinion on this?

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


Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-09 Thread Yingjoe Chen
On Tue, 2015-03-10 at 02:00 +0900, Tomasz Figa wrote:
 On Mon, Mar 9, 2015 at 11:46 PM, Yingjoe Chen yingjoe.c...@mediatek.com 
 wrote:
  On Mon, 2015-03-09 at 20:11 +0900, Tomasz Figa wrote:
  ...
   +/*
   + * pimudev is a global var for dma_alloc_coherent.
   + * It is not accepatable, we will delete it if domain_alloc is enabled
   + */
   +static struct device *pimudev;
 
  This is indeed not acceptable. Could you replace dma_alloc_coherent()
  with something that doesn't require device pointer, e.g.
  alloc_pages()? (Although that would require you to handle cache
  maintenance in the driver, due to cached memory allocated.) I need to
  think about a better solution for this.
 
  Hi,
 
  For 2nd level page table, we use cached memory now. Currently we are
  using __dma_flush_range to flush the cache, which is also unacceptable.
 
  For proper cache management, we'll need to use dma_map_single or
  dma_sync_*, which still need a deivce*.
 
 Looking at how already mainlined drivers do this, they either use
 dmac_flush_range()
 (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/iommu/msm_iommu.c?id=refs/tags/v4.0-rc3#n80)
 or directly __cpuc_flush_dcache_area() and outer_flush_range()
 (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/iommu/rockchip-iommu.c?id=refs/tags/v4.0-rc3#n93).

Hi,

These only exist in arch/arm, not arm64. I think we should avoid using
API start with __ in drivers. This driver might be used in both
arm/arm64, I think the only option for us is DMA APIs.

Actually, I'm thinking that we should change to use coherent memory for
2nd level page table as well and totally skip the cache flush. It seems
dma_pool_create is suitable to replace kmem_cache we are using right
now. However it still need a device*, which we have to fix anyway.

Joe.C


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


Re: [PATCH 2/5] iommu/mediatek: Add mt8173 IOMMU driver

2015-03-06 Thread Mitchel Humpherys
On Fri, Mar 06 2015 at 02:48:17 AM, yong...@mediatek.com wrote:
 From: Yong Wu yong...@mediatek.com

 This patch adds support for mediatek m4u (MultiMedia Memory Management Unit).
 Currently this only supports m4u gen 2 with 2 levels of page table on mt8173.

[...]

 +static int mtk_iommu_invalidate_tlb(const struct mtk_iommu_info *piommu,
 + int isinvall, unsigned int iova_start,
 + unsigned int iova_end)
 +{
 + void __iomem *m4u_base = piommu-m4u_base;
 + u32 val;
 + u64 start, end;
 +
 + start = sched_clock();
 +
 + if (!isinvall) {
 + iova_start = round_down(iova_start, SZ_4K);
 + iova_end = round_up(iova_end, SZ_4K);
 + }
 +
 + val = F_MMU_INV_EN_L2 | F_MMU_INV_EN_L1;
 +
 + writel(val, m4u_base + REG_INVLID_SEL);
 +
 + if (isinvall) {
 + writel(F_MMU_INV_ALL, m4u_base + REG_MMU_INVLD);
 + } else {
 + writel(iova_start, m4u_base + REG_MMU_INVLD_SA);
 + writel(iova_end, m4u_base + REG_MMU_INVLD_EA);
 + writel(F_MMU_INV_RANGE, m4u_base + REG_MMU_INVLD);
 +
 + while (!readl(m4u_base + REG_MMU_CPE_DONE)) {
 + end = sched_clock();
 + if (end - start = 1ULL) {
 + dev_warn(piommu-dev, invalid don't done\n);
 + writel(F_MMU_INV_ALL, m4u_base + REG_MMU_INVLD);
 + }
 + };

Superfluous `;'.  Also, maybe you should be using readl_poll_timeout?

 + writel(0, m4u_base + REG_MMU_CPE_DONE);
 + }
 +
 + return 0;
 +}



-Mitch

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