Re: [PATCH v7 2/9] ACPI/IORT: Add support for RMR node parsing

2021-10-05 Thread Laurentiu Tudor



On 9/17/2021 2:26 PM, Shameerali Kolothum Thodi wrote:
> 
> 
>> -Original Message-
>> From: Jon Nettleton [mailto:j...@solid-run.com]
>> Sent: 16 September 2021 12:17
>> To: Shameerali Kolothum Thodi 
>> Cc: Robin Murphy ; Lorenzo Pieralisi
>> ; Laurentiu Tudor ;
>> linux-arm-kernel ; ACPI Devel Maling
>> List ; Linux IOMMU
>> ; Joerg Roedel ; Will
>> Deacon ; wanghuiqiang ;
>> Guohanjun (Hanjun Guo) ; Steven Price
>> ; Sami Mujawar ; Eric
>> Auger ; yangyicong 
>> Subject: Re: [PATCH v7 2/9] ACPI/IORT: Add support for RMR node parsing
>>
>> On Thu, Sep 16, 2021 at 10:26 AM Shameerali Kolothum Thodi
>>  wrote:
>>>
>>>
>>>
>>>> -Original Message-
>>>> From: Jon Nettleton [mailto:j...@solid-run.com]
>>>> Sent: 16 September 2021 08:52
>>>> To: Shameerali Kolothum Thodi
>> 
>>>> Cc: Robin Murphy ; Lorenzo Pieralisi
>>>> ; Laurentiu Tudor
>>>> ; linux-arm-kernel
>>>> ; ACPI Devel Maling List
>>>> ; Linux IOMMU
>>>> ; Joerg Roedel ;
>>>> Will Deacon ; wanghuiqiang
>>>> ; Guohanjun (Hanjun Guo)
>>>> ; Steven Price ; Sami
>>>> Mujawar ; Eric Auger
>> ;
>>>> yangyicong 
>>>> Subject: Re: [PATCH v7 2/9] ACPI/IORT: Add support for RMR node
>>>> parsing
>>>>
>>>> On Thu, Sep 16, 2021 at 9:26 AM Shameerali Kolothum Thodi
>>>>  wrote:
>>>>>
>>>>>
>>>>>
>>>>>> -Original Message-
>>>>>> From: Jon Nettleton [mailto:j...@solid-run.com]
>>>>>> Sent: 06 September 2021 20:51
>>>>>> To: Robin Murphy 
>>>>>> Cc: Lorenzo Pieralisi ; Shameerali
>>>>>> Kolothum Thodi ; Laurentiu
>>>>>> Tudor ; linux-arm-kernel
>>>>>> ; ACPI Devel Maling List
>>>>>> ; Linux IOMMU
>>>>>> ; Linuxarm
>>>>>> ; Joerg Roedel ; Will
>>>>>> Deacon ; wanghuiqiang
>>>>>> ; Guohanjun (Hanjun Guo)
>>>>>> ; Steven Price ;
>>>>>> Sami Mujawar ; Eric Auger
>>>> ;
>>>>>> yangyicong 
>>>>>> Subject: Re: [PATCH v7 2/9] ACPI/IORT: Add support for RMR node
>>>>>> parsing
>>>>>>
>>>>> [...]
>>>>>
>>>>>>>>
>>>>>>>> On the prot value assignment based on the remapping flag,
>>>>>>>> I'd like to hear Robin/Joerg's opinion, I'd avoid being in a
>>>>>>>> situation where "normally" this would work but then we have
>>>>>>>> to quirk
>>>> it.
>>>>>>>>
>>>>>>>> Is this a valid assumption _always_ ?
>>>>>>>
>>>>>>> No. Certainly applying IOMMU_CACHE without reference to the
>>>>>>> device's _CCA attribute or how CPUs may be accessing a shared
>>>>>>> buffer could lead to a loss of coherency. At worst, applying
>>>>>>> IOMMU_MMIO to a device-private buffer *could* cause the device
>>>>>>> to lose coherency with itself if the memory underlying the RMR
>>>>>>> may have allocated into system caches. Note that the expected
>>>>>>> use for non-remappable RMRs is the device holding some sort of
>>>>>>> long-lived private data in system RAM - the MSI doorbell trick
>>>>>>> is far more of a niche
>>>> hack really.
>>>>>>>
>>>>>>> At the very least I think we need to refer to the device's
>>>>>>> memory access properties here.
>>>>>>>
>>>>>>> Jon, Laurentiu - how do RMRs correspond to the EFI memory map
>>>>>>> on your firmware? I'm starting to think that as long as the
>>>>>>> underlying memory is described appropriately there then we
>>>>>>> should be able to infer correct attributes from the EFI memory type
>> and flags.
>>>>>>
>>>>>> The devices are all cache coherent and marked as _CCA, 1.  The
>>>>>> Memory regions are in the virt table as
>>>> ARM_MEMORY_REGION_ATTRIBUTE_DEVICE.
>>>>>>
>>>>>> The current chicken and egg problem we have is that during the
>>>>>&g

Re: [PATCH v7 2/9] ACPI/IORT: Add support for RMR node parsing

2021-08-05 Thread Laurentiu Tudor



On 8/5/2021 7:03 PM, Lorenzo Pieralisi wrote:
> On Thu, Aug 05, 2021 at 09:07:17AM +0100, Shameer Kolothum wrote:
> 
> [...]
> 
>> +static void __init iort_node_get_rmr_info(struct acpi_iort_node *iort_node)
>> +{
>> +struct acpi_iort_node *smmu;
>> +struct acpi_iort_rmr *rmr;
>> +struct acpi_iort_rmr_desc *rmr_desc;
>> +u32 map_count = iort_node->mapping_count;
>> +u32 sid;
>> +int i;
>> +
>> +if (!iort_node->mapping_offset || map_count != 1) {
>> +pr_err(FW_BUG "Invalid ID mapping, skipping RMR node %p\n",
>> +   iort_node);
>> +return;
>> +}
>> +
>> +/* Retrieve associated smmu and stream id */
>> +smmu = iort_node_get_id(iort_node, , 0);
>> +if (!smmu) {
>> +pr_err(FW_BUG "Invalid SMMU reference, skipping RMR node %p\n",
>> +   iort_node);
>> +return;
>> +}
>> +
>> +/* Retrieve RMR data */
>> +rmr = (struct acpi_iort_rmr *)iort_node->node_data;
>> +if (!rmr->rmr_offset || !rmr->rmr_count) {
>> +pr_err(FW_BUG "Invalid RMR descriptor array, skipping RMR node 
>> %p\n",
>> +   iort_node);
>> +return;
>> +}
>> +
>> +rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, iort_node,
>> +rmr->rmr_offset);
>> +
>> +iort_rmr_desc_check_overlap(rmr_desc, rmr->rmr_count);
>> +
>> +for (i = 0; i < rmr->rmr_count; i++, rmr_desc++) {
>> +struct iommu_resv_region *region;
>> +enum iommu_resv_type type;
>> +int prot = IOMMU_READ | IOMMU_WRITE;
>> +u64 addr = rmr_desc->base_address, size = rmr_desc->length;
>> +
>> +if (!IS_ALIGNED(addr, SZ_64K) || !IS_ALIGNED(size, SZ_64K)) {
>> +/* PAGE align base addr and size */
>> +addr &= PAGE_MASK;
>> +size = PAGE_ALIGN(size + 
>> offset_in_page(rmr_desc->base_address));
>> +
>> +pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] not 
>> aligned to 64K, continue with [0x%llx - 0x%llx]\n",
>> +   rmr_desc->base_address,
>> +   rmr_desc->base_address + rmr_desc->length - 1,
>> +   addr, addr + size - 1);
>> +}
>> +if (rmr->flags & IOMMU_RMR_REMAP_PERMITTED) {
>> +type = IOMMU_RESV_DIRECT_RELAXABLE;
>> +/*
>> + * Set IOMMU_CACHE as IOMMU_RESV_DIRECT_RELAXABLE is
>> + * normally used for allocated system memory that is
>> + * then used for device specific reserved regions.
>> + */
>> +prot |= IOMMU_CACHE;
>> +} else {
>> +type = IOMMU_RESV_DIRECT;
>> +/*
>> + * Set IOMMU_MMIO as IOMMU_RESV_DIRECT is normally used
>> + * for device memory like MSI doorbell.
>> + */
>> +prot |= IOMMU_MMIO;
>> +}
> 
> On the prot value assignment based on the remapping flag, I'd like to
> hear Robin/Joerg's opinion, I'd avoid being in a situation where
> "normally" this would work but then we have to quirk it.
> 
> Is this a valid assumption _always_ ?

I think we enable quite a bit of platforms with this assumption, so IMHO
it's a fair compromise for now. As per Jon's comment and oob
discussions, in the long run the spec should probably be updated to
include a way of explicitly specifying memory attributes.

---
Thanks & Best Regards, Laurentiu

> 
>> +
>> +region = iommu_alloc_resv_region(addr, size, prot, type);
>> +if (region) {
>> +region->fw_data.rmr.flags = rmr->flags;
>> +region->fw_data.rmr.sid = sid;
>> +region->fw_data.rmr.smmu = smmu;
>> +list_add_tail(>list, _rmr_list);
>> +}
>> +}
>> +}
>> +
>> +static void __init iort_parse_rmr(void)
>> +{
>> +struct acpi_iort_node *iort_node, *iort_end;
>> +struct acpi_table_iort *iort;
>> +int i;
>> +
>> +if (iort_table->revision < 3)
>> +return;
>> +
>> +iort = (struct acpi_table_iort *)iort_table;
>> +
>> +iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort,
>> + iort->node_offset);
>> +iort_end = ACPI_ADD_PTR(struct acpi_iort_node, iort,
>> +iort_table->length);
>> +
>> +for (i = 0; i < iort->node_count; i++) {
>> +if (WARN_TAINT(iort_node >= iort_end, TAINT_FIRMWARE_WORKAROUND,
>> +   "IORT node pointer overflows, bad table!\n"))
>> +return;
>> +
>> +if (iort_node->type == ACPI_IORT_NODE_RMR)
>> +iort_node_get_rmr_info(iort_node);
>> +
>> +iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
>> +   

Re: [PATCH v6 0/9] ACPI/IORT: Support for IORT RMR node

2021-07-19 Thread Laurentiu Tudor
On 7/16/2021 11:34 AM, Shameer Kolothum wrote:
> Hi,
> 
> Major Changes from v5:
> - Addressed comments from Robin & Lorenzo.
>   : Moved iort_parse_rmr() to acpi_iort_init() from
> iort_init_platform_devices().
>   : Removed use of struct iort_rmr_entry during the initial
> parse. Using struct iommu_resv_region instead.
>   : Report RMR address alignment and overlap errors, but continue.
>   : Reworked arm_smmu_init_bypass_stes() (patch # 6).
> - Updated SMMUv2 bypass SMR code. Thanks to Jon N (patch #8).
> - Set IOMMU protection flags(IOMMU_CACHE, IOMMU_MMIO) based
>   on Type of RMR region. Suggested by Jon N.
> 
> Sanity tested on a HiSilicon D06(SMMUv3). Further testing and
> feedback is greatly appreciated.
> 
> Thanks,
> Shameer
> 
> --
> v4 --> v5
>  -Added a fw_data union to struct iommu_resv_region and removed
>   struct iommu_rmr (Based on comments from Joerg/Robin).
>  -Added iommu_put_rmrs() to release mem.
>  -Thanks to Steve for verifying on SMMUv2, but not added the Tested-by
>   yet because of the above changes.
> 
> v3 -->v4
> -Included the SMMUv2 SMR bypass install changes suggested by
>  Steve(patch #7)
> -As per Robin's comments, RMR reserve implementation is now
>  more generic  (patch #8) and dropped v3 patches 8 and 10.
> -Rebase to 5.13-rc1
> 
> RFC v2 --> v3
>  -Dropped RFC tag as the ACPICA header changes are now ready to be
>   part of 5.13[0]. But this series still has a dependency on that patch.
>  -Added IORT E.b related changes(node flags, _DSM function 5 checks for
>   PCIe).
>  -Changed RMR to stream id mapping from M:N to M:1 as per the spec and
>   discussion here[1].
>  -Last two patches add support for SMMUv2(Thanks to Jon Nettleton!)
> --
> 
> Jon Nettleton (1):
>   iommu/arm-smmu: Get associated RMR info and install bypass SMR
> 
> Shameer Kolothum (8):
>   iommu: Introduce a union to struct iommu_resv_region
>   ACPI/IORT: Add support for RMR node parsing
>   iommu/dma: Introduce generic helper to retrieve RMR info
>   ACPI/IORT: Add a helper to retrieve RMR memory regions
>   iommu/arm-smmu-v3: Introduce strtab init helper
>   iommu/arm-smmu-v3: Refactor arm_smmu_init_bypass_stes() to force
> bypass
>   iommu/arm-smmu-v3: Get associated RMR info and install bypass STE
>   iommu/dma: Reserve any RMR regions associated with a dev
> 
>  drivers/acpi/arm64/iort.c   | 172 +++-
>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c |  76 +++--
>  drivers/iommu/arm/arm-smmu/arm-smmu.c   |  48 ++
>  drivers/iommu/dma-iommu.c   |  89 +-
>  include/linux/acpi_iort.h   |   7 +
>  include/linux/dma-iommu.h   |  13 ++
>  include/linux/iommu.h   |  11 ++
>  7 files changed, 393 insertions(+), 23 deletions(-)
>
Validated on a NXP LX2160A with SMMUv2, so:

Tested-by: Laurentiu Tudor 

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v5 3/8] ACPI/IORT: Add a helper to retrieve RMR memory regions

2021-06-03 Thread Laurentiu Tudor
Hi Jon,

On 6/3/2021 3:27 PM, Jon Nettleton wrote:
> On Wed, May 26, 2021 at 7:11 PM Laurentiu Tudor  
> wrote:
>>
>>
>>
>> On 5/26/2021 7:36 PM, Shameerali Kolothum Thodi wrote:
>>>
>>>
>>>> -Original Message-
>>>> From: Laurentiu Tudor [mailto:laurentiu.tu...@nxp.com]
>>>> Sent: 26 May 2021 08:53
>>>> To: Shameerali Kolothum Thodi ;
>>>> linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
>>>> iommu@lists.linux-foundation.org
>>>> Cc: j...@solid-run.com; Linuxarm ;
>>>> steven.pr...@arm.com; Guohanjun (Hanjun Guo) ;
>>>> yangyicong ; sami.muja...@arm.com;
>>>> robin.mur...@arm.com; wanghuiqiang 
>>>> Subject: Re: [PATCH v5 3/8] ACPI/IORT: Add a helper to retrieve RMR memory
>>>> regions
>>>>
>>>> Hi Shameer,
>>>>
>>>> On 5/24/2021 2:02 PM, Shameer Kolothum wrote:
>>>>> Add a helper function that retrieves RMR memory descriptors
>>>>> associated with a given IOMMU. This will be used by IOMMU
>>>>> drivers to setup necessary mappings.
>>>>>
>>>>> Now that we have this, invoke it from the generic helper
>>>>> interface.
>>>>>
>>>>> Signed-off-by: Shameer Kolothum
>>>> 
>>>>> ---
>>>>>  drivers/acpi/arm64/iort.c | 50
>>>> +++
>>>>>  drivers/iommu/dma-iommu.c |  4 
>>>>>  include/linux/acpi_iort.h |  7 ++
>>>>>  3 files changed, 61 insertions(+)
>>>>>
>>>>> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>>>>> index fea1ffaedf3b..01917caf58de 100644
>>>>> --- a/drivers/acpi/arm64/iort.c
>>>>> +++ b/drivers/acpi/arm64/iort.c
>>>>> @@ -12,6 +12,7 @@
>>>>>
>>>>>  #include 
>>>>>  #include 
>>>>> +#include 
>>>>>  #include 
>>>>>  #include 
>>>>>  #include 
>>>>> @@ -837,6 +838,53 @@ static inline int iort_add_device_replay(struct
>>>> device *dev)
>>>>> return err;
>>>>>  }
>>>>>
>>>>> +/**
>>>>> + * iort_iommu_get_rmrs - Helper to retrieve RMR info associated with
>>>> IOMMU
>>>>> + * @iommu: fwnode for the IOMMU
>>>>> + * @head: RMR list head to be populated
>>>>> + *
>>>>> + * Returns: 0 on success, <0 failure
>>>>> + */
>>>>> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
>>>>> +   struct list_head *head)
>>>>> +{
>>>>> +   struct iort_rmr_entry *e;
>>>>> +   struct acpi_iort_node *iommu;
>>>>> +   int rmrs = 0;
>>>>> +
>>>>> +   iommu = iort_get_iort_node(iommu_fwnode);
>>>>> +   if (!iommu || list_empty(_rmr_list))
>>>>> +   return -ENODEV;
>>>>> +
>>>>> +   list_for_each_entry(e, _rmr_list, list) {
>>>>> +   int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_NOEXEC |
>>>> IOMMU_MMIO;
>>>>
>>>> We have a case with an IP block that needs EXEC rights on its reserved
>>>> memory, so could you please drop the IOMMU_NOEXEC flag?
>>>
>>> Ok, I think I can drop that one if there are no other concerns. I was not 
>>> quite
>>> sure what to include here in the first place as the IORT spec is not giving 
>>> any
>>> further details about the RMR regions(May be the flags field can be 
>>> extended to
>>> describe these details).
>>>
>>
>> That would be great, given that some preliminary investigations on my
>> side revealed that our IP block seems to be quite sensitive to memory
>> attributes. I need to spend some more time on this but at first sight
>> looks like it needs cacheable, normal memory (not mmio mapping).
>>
>> ---
>> Thanks & Best Regards, Laurentiu
> 
> Laurentiu,
> 
> Is this regarding the mc-bin memory block or another IP?  I am currently
> running this patchset with IOMMU_NOEXEC under ACPI without any problems.

It's the MC firmware needing EXEC rights on its reserved memory. On my
side, with IOMMU_NOEXEC, as soon as the direct mappings are created I
get SMMU faults triggered by the FW.

> If so maybe we can touch base off list and align on the implementation.

Sure, just let me know when you have the time.

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


Re: [PATCH v5 3/8] ACPI/IORT: Add a helper to retrieve RMR memory regions

2021-05-26 Thread Laurentiu Tudor



On 5/26/2021 7:36 PM, Shameerali Kolothum Thodi wrote:
> 
> 
>> -Original Message-----
>> From: Laurentiu Tudor [mailto:laurentiu.tu...@nxp.com]
>> Sent: 26 May 2021 08:53
>> To: Shameerali Kolothum Thodi ;
>> linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
>> iommu@lists.linux-foundation.org
>> Cc: j...@solid-run.com; Linuxarm ;
>> steven.pr...@arm.com; Guohanjun (Hanjun Guo) ;
>> yangyicong ; sami.muja...@arm.com;
>> robin.mur...@arm.com; wanghuiqiang 
>> Subject: Re: [PATCH v5 3/8] ACPI/IORT: Add a helper to retrieve RMR memory
>> regions
>>
>> Hi Shameer,
>>
>> On 5/24/2021 2:02 PM, Shameer Kolothum wrote:
>>> Add a helper function that retrieves RMR memory descriptors
>>> associated with a given IOMMU. This will be used by IOMMU
>>> drivers to setup necessary mappings.
>>>
>>> Now that we have this, invoke it from the generic helper
>>> interface.
>>>
>>> Signed-off-by: Shameer Kolothum
>> 
>>> ---
>>>  drivers/acpi/arm64/iort.c | 50
>> +++
>>>  drivers/iommu/dma-iommu.c |  4 
>>>  include/linux/acpi_iort.h |  7 ++
>>>  3 files changed, 61 insertions(+)
>>>
>>> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
>>> index fea1ffaedf3b..01917caf58de 100644
>>> --- a/drivers/acpi/arm64/iort.c
>>> +++ b/drivers/acpi/arm64/iort.c
>>> @@ -12,6 +12,7 @@
>>>
>>>  #include 
>>>  #include 
>>> +#include 
>>>  #include 
>>>  #include 
>>>  #include 
>>> @@ -837,6 +838,53 @@ static inline int iort_add_device_replay(struct
>> device *dev)
>>> return err;
>>>  }
>>>
>>> +/**
>>> + * iort_iommu_get_rmrs - Helper to retrieve RMR info associated with
>> IOMMU
>>> + * @iommu: fwnode for the IOMMU
>>> + * @head: RMR list head to be populated
>>> + *
>>> + * Returns: 0 on success, <0 failure
>>> + */
>>> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
>>> +   struct list_head *head)
>>> +{
>>> +   struct iort_rmr_entry *e;
>>> +   struct acpi_iort_node *iommu;
>>> +   int rmrs = 0;
>>> +
>>> +   iommu = iort_get_iort_node(iommu_fwnode);
>>> +   if (!iommu || list_empty(_rmr_list))
>>> +   return -ENODEV;
>>> +
>>> +   list_for_each_entry(e, _rmr_list, list) {
>>> +   int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_NOEXEC |
>> IOMMU_MMIO;
>>
>> We have a case with an IP block that needs EXEC rights on its reserved
>> memory, so could you please drop the IOMMU_NOEXEC flag?
> 
> Ok, I think I can drop that one if there are no other concerns. I was not 
> quite
> sure what to include here in the first place as the IORT spec is not giving 
> any
> further details about the RMR regions(May be the flags field can be extended 
> to
> describe these details).
> 

That would be great, given that some preliminary investigations on my
side revealed that our IP block seems to be quite sensitive to memory
attributes. I need to spend some more time on this but at first sight
looks like it needs cacheable, normal memory (not mmio mapping).

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 3/8] ACPI/IORT: Add a helper to retrieve RMR memory regions

2021-05-26 Thread Laurentiu Tudor
Hi Shameer,

On 5/24/2021 2:02 PM, Shameer Kolothum wrote:
> Add a helper function that retrieves RMR memory descriptors
> associated with a given IOMMU. This will be used by IOMMU
> drivers to setup necessary mappings.
> 
> Now that we have this, invoke it from the generic helper
> interface.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 50 +++
>  drivers/iommu/dma-iommu.c |  4 
>  include/linux/acpi_iort.h |  7 ++
>  3 files changed, 61 insertions(+)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index fea1ffaedf3b..01917caf58de 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -12,6 +12,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -837,6 +838,53 @@ static inline int iort_add_device_replay(struct device 
> *dev)
>   return err;
>  }
>  
> +/**
> + * iort_iommu_get_rmrs - Helper to retrieve RMR info associated with IOMMU
> + * @iommu: fwnode for the IOMMU
> + * @head: RMR list head to be populated
> + *
> + * Returns: 0 on success, <0 failure
> + */
> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
> + struct list_head *head)
> +{
> + struct iort_rmr_entry *e;
> + struct acpi_iort_node *iommu;
> + int rmrs = 0;
> +
> + iommu = iort_get_iort_node(iommu_fwnode);
> + if (!iommu || list_empty(_rmr_list))
> + return -ENODEV;
> +
> + list_for_each_entry(e, _rmr_list, list) {
> + int prot = IOMMU_READ | IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;

We have a case with an IP block that needs EXEC rights on its reserved
memory, so could you please drop the IOMMU_NOEXEC flag?

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu: arm-smmu-impl: add NXP hook to preserve bootmappings

2020-12-02 Thread Laurentiu Tudor
Hi Robin,

Sorry for the late reply, we had a few days of over here. Comments inline.

On 11/25/2020 8:10 PM, Robin Murphy wrote:
> On 2020-11-25 15:50, laurentiu.tu...@nxp.com wrote:
>> From: Laurentiu Tudor 
>>
>> Add a NXP specific hook to preserve SMMU mappings present at
>> boot time (created by the boot loader). These are needed for
>> MC firmware present on some NXP chips to continue working
>> across kernel boot and SMMU initialization.
>>
>> Signed-off-by: Laurentiu Tudor 
>> ---
>>   drivers/iommu/arm/arm-smmu/arm-smmu-impl.c | 33 ++
>>   1 file changed, 33 insertions(+)
>>
>> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
>> b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
>> index 7fed89c9d18a..ca07d9d4be69 100644
>> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
>> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
>> @@ -187,6 +187,36 @@ static const struct arm_smmu_impl
>> mrvl_mmu500_impl = {
>>   .reset = arm_mmu500_reset,
>>   };
>>   +static int nxp_cfg_probe(struct arm_smmu_device *smmu)
>> +{
>> +    int i, cnt = 0;
>> +    u32 smr;
>> +
>> +    for (i = 0; i < smmu->num_mapping_groups; i++) {
>> +    smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
>> +
>> +    if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) {
> 
> I bet this is fun over kexec...

Right. I haven't even considered kexec.

> Note that the Qualcomm special case got a bit of a free pass since it
> involves working around a totally broken hypervisor, plus gets to play
> the "nobody sane will run an enterprise distro on their phone" card to
> an extent; I don't think the likes of Layerscape kit get it quite so
> easy ;)

I agree that this is not ideal, but the plan here was to have something
to boot vanilla kernel OOB on our chips, which is something on my mind
for quite a while now. I do realize that we won't get away with it
in the long run.

>> +    smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr);
>> +    smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr);
>> +    smmu->smrs[i].valid = true;
>> +
>> +    smmu->s2crs[i].type = S2CR_TYPE_BYPASS;
>> +    smmu->s2crs[i].privcfg = S2CR_PRIVCFG_DEFAULT;
>> +    smmu->s2crs[i].cbndx = 0xff;
>> +
>> +    cnt++;
>> +    }
>> +    }
>> +
>> +    dev_notice(smmu->dev, "\tpreserved %d boot mapping%s\n", cnt,
>> +   cnt == 1 ? "" : "s");
> 
> That gets you around the initial SMMU reset, but what happens for the
> arbitrarily long period of time between the MC device getting attached
> to a default domain and the MC driver actually probing and (presumably)
> being able to map and reinitialise its firmware?

Perhaps I'm missing something, but won't the MC firmware live based on
this bypass mapping created by the bootloader and that gets preserved?

>> +
>> +    return 0;
>> +}
>> +
>> +static const struct arm_smmu_impl nxp_impl = {
>> +    .cfg_probe = nxp_cfg_probe,
>> +};
> 
> I believe you're mostly using MMU-500, so you probably don't want to
> simply throw out the relevant errata workarounds.
> 
>>   struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device
>> *smmu)
>>   {
>> @@ -226,5 +256,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct
>> arm_smmu_device *smmu)
>>   if (of_device_is_compatible(np, "marvell,ap806-smmu-500"))
>>   smmu->impl = _mmu500_impl;
>>   +    if (of_property_read_bool(np, "nxp,keep-boot-mappings"))
>> +    smmu->impl = _impl;
> 
> Normally you'd get a "what about ACPI?" here, but given the number of
> calls and email threads we've had specifically about trying to make ACPI
> support for these platforms work, that gets upgraded to at least a "WHAT
> ABOUT ACPI!?" :P
I do have ACPI in mind, but for now I just wanted to have a
first impression on the approach. One idea I was pondering on was to
have this property in the MC node (quick reminder: MC is exposed as a NC
in ACPI, should be able to replicate the property in there too). In the
mean time, we are in collaboration with our partners on using RMRR by
adding support for it in the arm-smmu-v2 driver.

> But seriously, the case of device firmware in memory being active before
> handover to Linux is *literally* the original reason behind IORT RMRs.
> We already know we need a way to specify the equivalent thing for DT
> systems, such that both can be handled commonly. I really don't want to
> have to support a vendor-specific mechanism for not-even-fully-solving a
> completely generic issue, sorry.
> 

I remember that some months ago there was a proposal from nvidia [1] to
map per-device reserved memory into SMMU. Would it make sense to revive
it as it seemed a viable solution for our case too?

[1]
https://patchwork.kernel.org/project/linux-arm-kernel/list/?series=213701=%2A=both

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

[PATCH] iommu: arm-smmu-impl: add NXP hook to preserve bootmappings

2020-11-25 Thread laurentiu . tudor
From: Laurentiu Tudor 

Add a NXP specific hook to preserve SMMU mappings present at
boot time (created by the boot loader). These are needed for
MC firmware present on some NXP chips to continue working
across kernel boot and SMMU initialization.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/arm/arm-smmu/arm-smmu-impl.c | 33 ++
 1 file changed, 33 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
index 7fed89c9d18a..ca07d9d4be69 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
@@ -187,6 +187,36 @@ static const struct arm_smmu_impl mrvl_mmu500_impl = {
.reset = arm_mmu500_reset,
 };
 
+static int nxp_cfg_probe(struct arm_smmu_device *smmu)
+{
+   int i, cnt = 0;
+   u32 smr;
+
+   for (i = 0; i < smmu->num_mapping_groups; i++) {
+   smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
+
+   if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) {
+   smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr);
+   smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr);
+   smmu->smrs[i].valid = true;
+
+   smmu->s2crs[i].type = S2CR_TYPE_BYPASS;
+   smmu->s2crs[i].privcfg = S2CR_PRIVCFG_DEFAULT;
+   smmu->s2crs[i].cbndx = 0xff;
+
+   cnt++;
+   }
+   }
+
+   dev_notice(smmu->dev, "\tpreserved %d boot mapping%s\n", cnt,
+  cnt == 1 ? "" : "s");
+
+   return 0;
+}
+
+static const struct arm_smmu_impl nxp_impl = {
+   .cfg_probe = nxp_cfg_probe,
+};
 
 struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
 {
@@ -226,5 +256,8 @@ struct arm_smmu_device *arm_smmu_impl_init(struct 
arm_smmu_device *smmu)
if (of_device_is_compatible(np, "marvell,ap806-smmu-500"))
smmu->impl = _mmu500_impl;
 
+   if (of_property_read_bool(np, "nxp,keep-boot-mappings"))
+   smmu->impl = _impl;
+
return smmu;
 }
-- 
2.17.1

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


Re: [PATCH v3 0/8] iommu/arm-smmu: Support maintaining bootloader mappings

2020-09-16 Thread Laurentiu Tudor


On 9/4/2020 6:55 PM, Bjorn Andersson wrote:
> Based on previous attempts and discussions this is the latest attempt at
> inheriting stream mappings set up by the bootloader, for e.g. boot splash or
> efifb.
> 
> Per Will's request this builds on the work by Jordan and Rob for the Adreno
> SMMU support. It applies cleanly ontop of v16 of their series, which can be
> found at
> https://lore.kernel.org/linux-arm-msm/20200901164707.2645413-1-robdcl...@gmail.com/
> 
> Bjorn Andersson (8):
>   iommu/arm-smmu: Refactor context bank allocation
>   iommu/arm-smmu: Delay modifying domain during init
>   iommu/arm-smmu: Consult context bank allocator for identify domains
>   iommu/arm-smmu-qcom: Emulate bypass by using context banks
>   iommu/arm-smmu-qcom: Consistently initialize stream mappings
>   iommu/arm-smmu: Add impl hook for inherit boot mappings
>   iommu/arm-smmu: Provide helper for allocating identity domain
>   iommu/arm-smmu-qcom: Setup identity domain for boot mappings
> 
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 111 ++-
>  drivers/iommu/arm/arm-smmu/arm-smmu.c  | 122 ++---
>  drivers/iommu/arm/arm-smmu/arm-smmu.h  |  14 ++-
>  3 files changed, 205 insertions(+), 42 deletions(-)
> 

Tested on a NXP LX2160A with John's tree [1] and below diff [2], so for
the whole series:

Tested-by: Laurentiu Tudor 

[1]
https://git.linaro.org/people/john.stultz/android-dev.git/log/?h=dev/db845c-mainline-WIP
[2]
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
@@ -190,11 +190,43 @@ static const struct arm_smmu_impl mrvl_mmu500_impl = {
.reset = arm_mmu500_reset,
 };

+static int nxp_smmu_inherit_mappings(struct arm_smmu_device *smmu)
+{
+   u32 smr;
+   int i, cnt = 0;
+
+   for (i = 0; i < smmu->num_mapping_groups; i++) {
+   smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
+
+   if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) {
+   smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr);
+   smmu->smrs[i].mask =
FIELD_GET(ARM_SMMU_SMR_MASK, smr);
+   smmu->smrs[i].valid = true;
+
+   smmu->s2crs[i].type = S2CR_TYPE_BYPASS;
+   smmu->s2crs[i].privcfg = S2CR_PRIVCFG_DEFAULT;
+   smmu->s2crs[i].count++;
+
+   cnt++;
+   }
+   }
+
+   dev_notice(smmu->dev, "\tpreserved %d boot mapping%s\n", cnt,
+  cnt == 1 ? "" : "s");
+
+   return 0;
+}
+
+static const struct arm_smmu_impl nxp_impl = {
+   .inherit_mappings = nxp_smmu_inherit_mappings,
+};

 struct arm_smmu_device *arm_smmu_impl_init(struct arm_smmu_device *smmu)
 {
const struct device_node *np = smmu->dev->of_node;

/*
 * Set the impl for model-specific implementation quirks first,
 * such that platform integration quirks can pick it up and
@@ -229,5 +261,12 @@ struct arm_smmu_device *arm_smmu_impl_init(struct
arm_smmu_device *smmu)
if (of_device_is_compatible(np, "marvell,ap806-smmu-500"))
smmu->impl = _mmu500_impl;

+   if (of_property_read_bool(np, "nxp,keep-bypass-mappings"))
+   smmu->impl = _impl;

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


Re: [PATCH v3 0/8] iommu/arm-smmu: Support maintaining bootloader mappings

2020-09-09 Thread Laurentiu Tudor
Hi Bjorn,

On 9/4/2020 6:55 PM, Bjorn Andersson wrote:
> Based on previous attempts and discussions this is the latest attempt at
> inheriting stream mappings set up by the bootloader, for e.g. boot splash or
> efifb.
> 
> Per Will's request this builds on the work by Jordan and Rob for the Adreno
> SMMU support. It applies cleanly ontop of v16 of their series, which can be
> found at
> https://lore.kernel.org/linux-arm-msm/20200901164707.2645413-1-robdcl...@gmail.com/

Is there a git repo available with all the patches put together?

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 5/5] iommu/arm-smmu: Setup identity domain for boot mappings

2020-07-28 Thread Laurentiu Tudor



On 7/9/2020 10:57 PM, Bjorn Andersson wrote:
> On Thu 09 Jul 08:50 PDT 2020, Laurentiu Tudor wrote:
> 
>>
>>
>> On 7/9/2020 8:01 AM, Bjorn Andersson wrote:
>>> With many Qualcomm platforms not having functional S2CR BYPASS a
>>> temporary IOMMU domain, without translation, needs to be allocated in
>>> order to allow these memory transactions.
>>>
>>> Unfortunately the boot loader uses the first few context banks, so
>>> rather than overwriting a active bank the last context bank is used and
>>> streams are diverted here during initialization.
>>>
>>> This also performs the readback of SMR registers for the Qualcomm
>>> platform, to trigger the mechanism.
>>>
>>> This is based on prior work by Thierry Reding and Laurentiu Tudor.
>>>
>>> Signed-off-by: Bjorn Andersson 
>>> ---
>>>  drivers/iommu/arm-smmu-qcom.c | 11 +
>>>  drivers/iommu/arm-smmu.c  | 80 +--
>>>  drivers/iommu/arm-smmu.h  |  3 ++
>>>  3 files changed, 90 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c
>>> index 86b1917459a4..397df27c1d69 100644
>>> --- a/drivers/iommu/arm-smmu-qcom.c
>>> +++ b/drivers/iommu/arm-smmu-qcom.c
>>> @@ -26,6 +26,7 @@ static const struct of_device_id 
>>> qcom_smmu_client_of_match[] = {
>>>  static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
>>>  {
>>> unsigned int last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 
>>> 1);
>>> +   u32 smr;
>>> u32 reg;
>>> int i;
>>>  
>>> @@ -56,6 +57,16 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device 
>>> *smmu)
>>> }
>>> }
>>>  
>>> +   for (i = 0; i < smmu->num_mapping_groups; i++) {
>>> +   smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
>>> +
>>> +   if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) {
>>> +   smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr);
>>> +   smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr);
>>> +   smmu->smrs[i].valid = true;
>>> +   }
>>> +   }
>>> +
>>> return 0;
>>>  }
>>>  
>>> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
>>> index e2d6c0aaf1ea..a7cb27c1a49e 100644
>>> --- a/drivers/iommu/arm-smmu.c
>>> +++ b/drivers/iommu/arm-smmu.c
>>> @@ -652,7 +652,8 @@ static void arm_smmu_write_context_bank(struct 
>>> arm_smmu_device *smmu, int idx)
>>>  }
>>>  
>>>  static int arm_smmu_init_domain_context(struct iommu_domain *domain,
>>> -   struct arm_smmu_device *smmu)
>>> +   struct arm_smmu_device *smmu,
>>> +   bool boot_domain)
>>>  {
>>> int irq, start, ret = 0;
>>> unsigned long ias, oas;
>>> @@ -770,6 +771,15 @@ static int arm_smmu_init_domain_context(struct 
>>> iommu_domain *domain,
>>> ret = -EINVAL;
>>> goto out_unlock;
>>> }
>>> +
>>> +   /*
>>> +* Use the last context bank for identity mappings during boot, to
>>> +* avoid overwriting in-use bank configuration while we're setting up
>>> +* the new mappings.
>>> +*/
>>> +   if (boot_domain)
>>> +   start = smmu->num_context_banks - 1;
>>> +
>>> ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
>>>   smmu->num_context_banks);
>>> if (ret < 0)
>>> @@ -1149,7 +1159,10 @@ static int arm_smmu_attach_dev(struct iommu_domain 
>>> *domain, struct device *dev)
>>> struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>>> struct arm_smmu_master_cfg *cfg;
>>> struct arm_smmu_device *smmu;
>>> +   bool free_identity_domain = false;
>>> +   int idx;
>>> int ret;
>>> +   int i;
>>>  
>>> if (!fwspec || fwspec->ops != _smmu_ops) {
>>> dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
>>> @@ -1174,7 +1187,7 @@ static int arm_smmu_attach_dev(struct iommu_domain 
>>> *domain, struct device *dev)
>>> return ret;
>>>  
>>> /* En

Re: [PATCH 5/5] iommu/arm-smmu: Setup identity domain for boot mappings

2020-07-09 Thread Laurentiu Tudor



On 7/9/2020 8:01 AM, Bjorn Andersson wrote:
> With many Qualcomm platforms not having functional S2CR BYPASS a
> temporary IOMMU domain, without translation, needs to be allocated in
> order to allow these memory transactions.
> 
> Unfortunately the boot loader uses the first few context banks, so
> rather than overwriting a active bank the last context bank is used and
> streams are diverted here during initialization.
> 
> This also performs the readback of SMR registers for the Qualcomm
> platform, to trigger the mechanism.
> 
> This is based on prior work by Thierry Reding and Laurentiu Tudor.
> 
> Signed-off-by: Bjorn Andersson 
> ---
>  drivers/iommu/arm-smmu-qcom.c | 11 +
>  drivers/iommu/arm-smmu.c  | 80 +--
>  drivers/iommu/arm-smmu.h  |  3 ++
>  3 files changed, 90 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iommu/arm-smmu-qcom.c b/drivers/iommu/arm-smmu-qcom.c
> index 86b1917459a4..397df27c1d69 100644
> --- a/drivers/iommu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm-smmu-qcom.c
> @@ -26,6 +26,7 @@ static const struct of_device_id 
> qcom_smmu_client_of_match[] = {
>  static int qcom_smmu_cfg_probe(struct arm_smmu_device *smmu)
>  {
>   unsigned int last_s2cr = ARM_SMMU_GR0_S2CR(smmu->num_mapping_groups - 
> 1);
> + u32 smr;
>   u32 reg;
>   int i;
>  
> @@ -56,6 +57,16 @@ static int qcom_smmu_cfg_probe(struct arm_smmu_device 
> *smmu)
>   }
>   }
>  
> + for (i = 0; i < smmu->num_mapping_groups; i++) {
> + smr = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_SMR(i));
> +
> + if (FIELD_GET(ARM_SMMU_SMR_VALID, smr)) {
> + smmu->smrs[i].id = FIELD_GET(ARM_SMMU_SMR_ID, smr);
> + smmu->smrs[i].mask = FIELD_GET(ARM_SMMU_SMR_MASK, smr);
> + smmu->smrs[i].valid = true;
> + }
> + }
> +
>   return 0;
>  }
>  
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index e2d6c0aaf1ea..a7cb27c1a49e 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -652,7 +652,8 @@ static void arm_smmu_write_context_bank(struct 
> arm_smmu_device *smmu, int idx)
>  }
>  
>  static int arm_smmu_init_domain_context(struct iommu_domain *domain,
> - struct arm_smmu_device *smmu)
> + struct arm_smmu_device *smmu,
> + bool boot_domain)
>  {
>   int irq, start, ret = 0;
>   unsigned long ias, oas;
> @@ -770,6 +771,15 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>   ret = -EINVAL;
>   goto out_unlock;
>   }
> +
> + /*
> +  * Use the last context bank for identity mappings during boot, to
> +  * avoid overwriting in-use bank configuration while we're setting up
> +  * the new mappings.
> +  */
> + if (boot_domain)
> + start = smmu->num_context_banks - 1;
> +
>   ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
> smmu->num_context_banks);
>   if (ret < 0)
> @@ -1149,7 +1159,10 @@ static int arm_smmu_attach_dev(struct iommu_domain 
> *domain, struct device *dev)
>   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>   struct arm_smmu_master_cfg *cfg;
>   struct arm_smmu_device *smmu;
> + bool free_identity_domain = false;
> + int idx;
>   int ret;
> + int i;
>  
>   if (!fwspec || fwspec->ops != _smmu_ops) {
>   dev_err(dev, "cannot attach to SMMU, is it on the same bus?\n");
> @@ -1174,7 +1187,7 @@ static int arm_smmu_attach_dev(struct iommu_domain 
> *domain, struct device *dev)
>   return ret;
>  
>   /* Ensure that the domain is finalised */
> - ret = arm_smmu_init_domain_context(domain, smmu);
> + ret = arm_smmu_init_domain_context(domain, smmu, false);
>   if (ret < 0)
>   goto rpm_put;
>  
> @@ -1190,9 +1203,34 @@ static int arm_smmu_attach_dev(struct iommu_domain 
> *domain, struct device *dev)
>   goto rpm_put;
>   }
>  
> + /* Decrement use counter for any references to the identity domain */
> + mutex_lock(>stream_map_mutex);
> + if (smmu->identity) {
> + struct arm_smmu_domain *identity = 
> to_smmu_domain(smmu->identity);
> +
> + for_each_cfg_sme(cfg, fwspec, i, idx) {
> + dev_err(smmu->dev, "%s() %#x\n", __func__, 
> smmu->smrs[idx].id);

Debug leftovers?

Apart from that I plan to give this a go on some NXP chips. Will keep
you updated.

Thanks a lot Bjorn.

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


Re: [EXT] Re: [PATCH v2 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-07-09 Thread Laurentiu Tudor



On 7/9/2020 12:26 PM, Makarand Pawagi wrote:
> 
> 
>> -Original Message-
>> From: Lorenzo Pieralisi 
>> Sent: Thursday, July 9, 2020 2:50 PM
>> To: Laurentiu Tudor 
>> Cc: linux-arm-ker...@lists.infradead.org; Makarand Pawagi
>> ; Diana Madalina Craciun (OSS)
>> ; iommu@lists.linux-foundation.org; linux-
>> a...@vger.kernel.org; devicet...@vger.kernel.org; linux-...@vger.kernel.org;
>> Rob Herring ; Rafael J. Wysocki ;
>> Joerg Roedel ; Hanjun Guo ; Bjorn
>> Helgaas ; Sudeep Holla ;
>> Robin Murphy ; Catalin Marinas
>> ; Will Deacon ; Marc Zyngier
>> 
>> Subject: [EXT] Re: [PATCH v2 12/12] bus: fsl-mc: Add ACPI support for fsl-mc
>>
>> Caution: EXT Email
>>
>> On Wed, Jul 01, 2020 at 07:55:28PM +0300, Laurentiu Tudor wrote:
>>>
>>>
>>> On 6/19/2020 11:20 AM, Lorenzo Pieralisi wrote:
>>>> From: Makarand Pawagi 
>>>>
>>>> Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table
>>>> to extract memory and other resources.
>>>>
>>>> Interrupt (GIC ITS) information is extracted from the MADT table by
>>>> drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.
>>>>
>>>> IORT table is parsed to configure DMA.
>>>>
>>>> Signed-off-by: Makarand Pawagi 
>>>> Signed-off-by: Diana Craciun 
>>>> Signed-off-by: Laurentiu Tudor 
>>>> ---
>>>>  drivers/bus/fsl-mc/fsl-mc-bus.c | 73 
>>>>  drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +
>>>>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 92
>>>> -
>>>>  3 files changed, 150 insertions(+), 52 deletions(-)
>>>>
>>>> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>> b/drivers/bus/fsl-mc/fsl-mc-bus.c index 824ff77bbe86..324d49d6df89
>>>> 100644
>>>> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>> @@ -18,6 +18,8 @@
>>>>  #include 
>>>>  #include 
>>>>  #include 
>>>> +#include 
>>>> +#include 
>>>>
>>>>  #include "fsl-mc-private.h"
>>>>
>>>> @@ -38,6 +40,7 @@ struct fsl_mc {
>>>> struct fsl_mc_device *root_mc_bus_dev;
>>>> u8 num_translation_ranges;
>>>> struct fsl_mc_addr_translation_range *translation_ranges;
>>>> +   void *fsl_mc_regs;
>>>>  };
>>>>
>>>>  /**
>>>> @@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
>>>> phys_addr_t start_phys_addr;
>>>>  };
>>>>
>>>> +#define FSL_MC_FAPR0x28
>>>> +#define MC_FAPR_PL BIT(18)
>>>> +#define MC_FAPR_BMTBIT(17)
>>>> +
>>>>  /**
>>>>   * fsl_mc_bus_match - device to driver matching callback
>>>>   * @dev: the fsl-mc device to match against @@ -124,7 +131,10 @@
>>>> static int fsl_mc_dma_configure(struct device *dev)
>>>> while (dev_is_fsl_mc(dma_dev))
>>>> dma_dev = dma_dev->parent;
>>>>
>>>> -   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
>>>> +   if (dev_of_node(dma_dev))
>>>> +   return of_dma_configure_id(dev, dma_dev->of_node, 0,
>>>> + _id);
>>>> +
>>>> +   return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, _id);
>>>>  }
>>>>
>>>>  static ssize_t modalias_show(struct device *dev, struct
>>>> device_attribute *attr, @@ -865,8 +875,11 @@ static int
>> fsl_mc_bus_probe(struct platform_device *pdev)
>>>> struct fsl_mc_io *mc_io = NULL;
>>>> int container_id;
>>>> phys_addr_t mc_portal_phys_addr;
>>>> -   u32 mc_portal_size;
>>>> -   struct resource res;
>>>> +   u32 mc_portal_size, mc_stream_id;
>>>> +   struct resource *plat_res;
>>>> +
>>>> +   if (!iommu_present(_mc_bus_type))
>>>> +   return -EPROBE_DEFER;
>>>>
>>>> mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
>>>> if (!mc)
>>>> @@ -874,19 +887,33 @@ static int fsl_mc_bus_probe(struct
>>>> platform_device *pdev)
>>>>
>>>> platform_set_drvdata(pdev, mc);
>>>>
>>>> +   plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>>>> +   mc->fsl_mc_regs = devm_i

Re: [EXT] Re: [PATCH v2 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-07-09 Thread Laurentiu Tudor



On 7/9/2020 1:37 PM, Makarand Pawagi wrote:
> 
> 
>> -Original Message-----
>> From: Laurentiu Tudor 
>> Sent: Thursday, July 9, 2020 3:45 PM
>> To: Makarand Pawagi ; Lorenzo Pieralisi
>> 
>> Cc: linux-arm-ker...@lists.infradead.org; Diana Madalina Craciun (OSS)
>> ; iommu@lists.linux-foundation.org; linux-
>> a...@vger.kernel.org; devicet...@vger.kernel.org; linux-...@vger.kernel.org;
>> Rob Herring ; Rafael J. Wysocki ;
>> Joerg Roedel ; Hanjun Guo ; Bjorn
>> Helgaas ; Sudeep Holla ;
>> Robin Murphy ; Catalin Marinas
>> ; Will Deacon ; Marc Zyngier
>> 
>> Subject: Re: [EXT] Re: [PATCH v2 12/12] bus: fsl-mc: Add ACPI support for 
>> fsl-mc
>>
>>
>>
>> On 7/9/2020 12:26 PM, Makarand Pawagi wrote:
>>>
>>>
>>>> -Original Message-
>>>> From: Lorenzo Pieralisi 
>>>> Sent: Thursday, July 9, 2020 2:50 PM
>>>> To: Laurentiu Tudor 
>>>> Cc: linux-arm-ker...@lists.infradead.org; Makarand Pawagi
>>>> ; Diana Madalina Craciun (OSS)
>>>> ; iommu@lists.linux-foundation.org; linux-
>>>> a...@vger.kernel.org; devicet...@vger.kernel.org;
>>>> linux-...@vger.kernel.org; Rob Herring ; Rafael
>>>> J. Wysocki ; Joerg Roedel ;
>>>> Hanjun Guo ; Bjorn Helgaas
>>>> ; Sudeep Holla ; Robin
>>>> Murphy ; Catalin Marinas
>>>> ; Will Deacon ; Marc
>>>> Zyngier 
>>>> Subject: [EXT] Re: [PATCH v2 12/12] bus: fsl-mc: Add ACPI support for
>>>> fsl-mc
>>>>
>>>> Caution: EXT Email
>>>>
>>>> On Wed, Jul 01, 2020 at 07:55:28PM +0300, Laurentiu Tudor wrote:
>>>>>
>>>>>
>>>>> On 6/19/2020 11:20 AM, Lorenzo Pieralisi wrote:
>>>>>> From: Makarand Pawagi 
>>>>>>
>>>>>> Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table
>>>>>> to extract memory and other resources.
>>>>>>
>>>>>> Interrupt (GIC ITS) information is extracted from the MADT table by
>>>>>> drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.
>>>>>>
>>>>>> IORT table is parsed to configure DMA.
>>>>>>
>>>>>> Signed-off-by: Makarand Pawagi 
>>>>>> Signed-off-by: Diana Craciun 
>>>>>> Signed-off-by: Laurentiu Tudor 
>>>>>> ---
>>>>>>  drivers/bus/fsl-mc/fsl-mc-bus.c | 73 
>>>>>>  drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +
>>>>>>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 92
>>>>>> -
>>>>>>  3 files changed, 150 insertions(+), 52 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>>>> b/drivers/bus/fsl-mc/fsl-mc-bus.c index 824ff77bbe86..324d49d6df89
>>>>>> 100644
>>>>>> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>>>> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>>>> @@ -18,6 +18,8 @@
>>>>>>  #include 
>>>>>>  #include 
>>>>>>  #include 
>>>>>> +#include 
>>>>>> +#include 
>>>>>>
>>>>>>  #include "fsl-mc-private.h"
>>>>>>
>>>>>> @@ -38,6 +40,7 @@ struct fsl_mc {
>>>>>> struct fsl_mc_device *root_mc_bus_dev;
>>>>>> u8 num_translation_ranges;
>>>>>> struct fsl_mc_addr_translation_range *translation_ranges;
>>>>>> +   void *fsl_mc_regs;
>>>>>>  };
>>>>>>
>>>>>>  /**
>>>>>> @@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
>>>>>> phys_addr_t start_phys_addr;
>>>>>>  };
>>>>>>
>>>>>> +#define FSL_MC_FAPR0x28
>>>>>> +#define MC_FAPR_PL BIT(18)
>>>>>> +#define MC_FAPR_BMTBIT(17)
>>>>>> +
>>>>>>  /**
>>>>>>   * fsl_mc_bus_match - device to driver matching callback
>>>>>>   * @dev: the fsl-mc device to match against @@ -124,7 +131,10 @@
>>>>>> static int fsl_mc_dma_configure(struct device *dev)
>>>>>> while (dev_is_fsl_mc(dma_dev))
>>>>>> dma_dev = dma_dev->parent;
>>>>>>
>>&

Re: [PATCH v2 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-07-01 Thread Laurentiu Tudor



On 6/19/2020 11:20 AM, Lorenzo Pieralisi wrote:
> From: Makarand Pawagi 
> 
> Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table to
> extract memory and other resources.
> 
> Interrupt (GIC ITS) information is extracted from the MADT table
> by drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.
> 
> IORT table is parsed to configure DMA.
> 
> Signed-off-by: Makarand Pawagi 
> Signed-off-by: Diana Craciun 
> Signed-off-by: Laurentiu Tudor 
> ---
>  drivers/bus/fsl-mc/fsl-mc-bus.c | 73 
>  drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +
>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 92 -
>  3 files changed, 150 insertions(+), 52 deletions(-)
> 
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index 824ff77bbe86..324d49d6df89 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -18,6 +18,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  
>  #include "fsl-mc-private.h"
>  
> @@ -38,6 +40,7 @@ struct fsl_mc {
>   struct fsl_mc_device *root_mc_bus_dev;
>   u8 num_translation_ranges;
>   struct fsl_mc_addr_translation_range *translation_ranges;
> + void *fsl_mc_regs;
>  };
>  
>  /**
> @@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
>   phys_addr_t start_phys_addr;
>  };
>  
> +#define FSL_MC_FAPR  0x28
> +#define MC_FAPR_PL   BIT(18)
> +#define MC_FAPR_BMT  BIT(17)
> +
>  /**
>   * fsl_mc_bus_match - device to driver matching callback
>   * @dev: the fsl-mc device to match against
> @@ -124,7 +131,10 @@ static int fsl_mc_dma_configure(struct device *dev)
>   while (dev_is_fsl_mc(dma_dev))
>   dma_dev = dma_dev->parent;
>  
> - return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> + if (dev_of_node(dma_dev))
> + return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> +
> + return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, _id);
>  }
>  
>  static ssize_t modalias_show(struct device *dev, struct device_attribute 
> *attr,
> @@ -865,8 +875,11 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
>   struct fsl_mc_io *mc_io = NULL;
>   int container_id;
>   phys_addr_t mc_portal_phys_addr;
> - u32 mc_portal_size;
> - struct resource res;
> + u32 mc_portal_size, mc_stream_id;
> + struct resource *plat_res;
> +
> + if (!iommu_present(_mc_bus_type))
> + return -EPROBE_DEFER;
>  
>   mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
>   if (!mc)
> @@ -874,19 +887,33 @@ static int fsl_mc_bus_probe(struct platform_device 
> *pdev)
>  
>   platform_set_drvdata(pdev, mc);
>  
> + plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + mc->fsl_mc_regs = devm_ioremap_resource(>dev, plat_res);
> + if (IS_ERR(mc->fsl_mc_regs))
> + return PTR_ERR(mc->fsl_mc_regs);
> +
> + if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(>dev)) {
> + mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
> + /*
> +  * HW ORs the PL and BMT bit, places the result in bit 15 of
> +  * the StreamID and ORs in the ICID. Calculate it accordingly.
> +  */
> + mc_stream_id = (mc_stream_id & 0x) |
> + ((mc_stream_id & (MC_FAPR_PL | MC_FAPR_BMT)) ?
> + 0x4000 : 0);
> + error = acpi_dma_configure_id(>dev, DEV_DMA_COHERENT,
> +   _stream_id);
> + if (error)
> + dev_warn(>dev, "failed to configure dma: %d.\n",
> +  error);
> + }
> +
>   /*
>* Get physical address of MC portal for the root DPRC:
>*/
> - error = of_address_to_resource(pdev->dev.of_node, 0, );
> - if (error < 0) {
> - dev_err(>dev,
> - "of_address_to_resource() failed for %pOF\n",
> - pdev->dev.of_node);
> - return error;
> - }
> -
> - mc_portal_phys_addr = res.start;
> - mc_portal_size = resource_size();
> + plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mc_portal_phys_addr = plat_res->start;
> + mc_portal_size = resource_size(plat_res);
>   error = fsl_create_mc_io(>dev, mc_portal_phys_addr,
>mc_portal_size, NULL,
>FSL_MC_IO_ATOMIC_CONTEXT_PORT

Re: [RFC 0/2] iommu: arm-smmu: Add support for early direct mappings

2020-05-27 Thread Laurentiu Tudor


On 5/26/2020 11:34 PM, John Stultz wrote:
> On Thu, May 14, 2020 at 12:34 PM  wrote:
>>
>> On Thu 27 Feb 18:57 PST 2020, Bjorn Andersson wrote:
>>
>> Rob, Will, we're reaching the point where upstream has enough
>> functionality that this is becoming a critical issue for us.
>>
>> E.g. Lenovo Yoga C630 is lacking this and a single dts patch to boot
>> mainline with display, GPU, WiFi and audio working and the story is
>> similar on several devboards.
>>
>> As previously described, the only thing I want is the stream mapping
>> related to the display controller in place, either with the CB with
>> translation disabled or possibly with a way to specify the framebuffer
>> region (although this turns out to mess things up in the display
>> driver...)
>>
>> I did pick this up again recently and concluded that by omitting the
>> streams for the USB controllers causes an instability issue seen on one
>> of the controller to disappear. So I would prefer if we somehow could
>> have a mechanism to only pick the display streams and the context
>> allocation for this.
>>
>>
>> Can you please share some pointers/insights/wishes for how we can
>> conclude on this subject?
> 
> Ping? I just wanted to follow up on this discussion as this small
> series is crucial for booting mainline on the Dragonboard 845c
> devboard. It would be really valuable to be able to get some solution
> upstream so we can test mainline w/o adding additional patches.

+1

There are also some NXP chips that depend on this. Also, I've submitted
a v2 [1] a while back that tries to address the feedback on the initial
implementation.

[1] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=164853

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


Re: [PATCH 09/12] dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus

2020-05-22 Thread Laurentiu Tudor
On 5/22/2020 5:02 PM, Rob Herring wrote:
> On Fri, May 22, 2020 at 3:42 AM Robin Murphy  wrote:
>>
>> On 2020-05-22 00:10, Rob Herring wrote:
>>> On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
>>>  wrote:
>>>>
>>>> From: Laurentiu Tudor 
>>>>
>>>> The existing bindings cannot be used to specify the relationship
>>>> between fsl-mc devices and GIC ITSes.
>>>>
>>>> Add a generic binding for mapping fsl-mc devices to GIC ITSes, using
>>>> msi-map property.
>>>>
>>>> Signed-off-by: Laurentiu Tudor 
>>>> Cc: Rob Herring 
>>>> ---
>>>>   .../devicetree/bindings/misc/fsl,qoriq-mc.txt | 30 +--
>>>>   1 file changed, 27 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt 
>>>> b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
>>>> index 9134e9bcca56..b0813b2d0493 100644
>>>> --- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
>>>> +++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
>>>> @@ -18,9 +18,9 @@ same hardware "isolation context" and a 10-bit value 
>>>> called an ICID
>>>>   the requester.
>>>>
>>>>   The generic 'iommus' property is insufficient to describe the 
>>>> relationship
>>>> -between ICIDs and IOMMUs, so an iommu-map property is used to define
>>>> -the set of possible ICIDs under a root DPRC and how they map to
>>>> -an IOMMU.
>>>> +between ICIDs and IOMMUs, so the iommu-map and msi-map properties are used
>>>> +to define the set of possible ICIDs under a root DPRC and how they map to
>>>> +an IOMMU and a GIC ITS respectively.
>>>>
>>>>   For generic IOMMU bindings, see
>>>>   Documentation/devicetree/bindings/iommu/iommu.txt.
>>>> @@ -28,6 +28,9 @@ Documentation/devicetree/bindings/iommu/iommu.txt.
>>>>   For arm-smmu binding, see:
>>>>   Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
>>>>
>>>> +For GICv3 and GIC ITS bindings, see:
>>>> +Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml.
>>>> +
>>>>   Required properties:
>>>>
>>>>   - compatible
>>>> @@ -119,6 +122,15 @@ Optional properties:
>>>> associated with the listed IOMMU, with the iommu-specifier
>>>> (i - icid-base + iommu-base).
>>>>
>>>> +- msi-map: Maps an ICID to a GIC ITS and associated iommu-specifier
>>>> +  data.
>>>> +
>>>> +  The property is an arbitrary number of tuples of
>>>> +  (icid-base,iommu,iommu-base,length).
>>>
>>> I'm confused because the example has GIC ITS phandle, not an IOMMU.
>>>
>>> What is an iommu-base?
>>
>> Right, I was already halfway through writing a reply to say that all the
>> copy-pasted "iommu" references here should be using the terminology from
>> the pci-msi.txt binding instead.
>>
>>>> +
>>>> +  Any ICID in the interval [icid-base, icid-base + length) is
>>>> +  associated with the listed GIC ITS, with the iommu-specifier
>>>> +  (i - icid-base + iommu-base).
>>>>   Example:
>>>>
>>>>   smmu: iommu@500 {
>>>> @@ -128,6 +140,16 @@ Example:
>>>>  ...
>>>>   };
>>>>
>>>> +   gic: interrupt-controller@600 {
>>>> +   compatible = "arm,gic-v3";
>>>> +   ...
>>>> +   its: gic-its@602 {
>>>> +   compatible = "arm,gic-v3-its";
>>>> +   msi-controller;
>>>> +   ...
>>>> +   };
>>>> +   };
>>>> +
>>>>   fsl_mc: fsl-mc@80c00 {
>>>>   compatible = "fsl,qoriq-mc";
>>>>   reg = <0x0008 0x0c00 0 0x40>,/* MC portal 
>>>> base */
>>>> @@ -135,6 +157,8 @@ Example:
>>>>   msi-parent = <>;
>>
>> Side note: is it right to keep msi-parent here? It rather implies that
>> the MC itself has a 'native' Device ID rather than an ICID, which I
>> believe is not strictly true. Plus it's extra-confusing that 

Re: [PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc

2020-05-21 Thread Laurentiu Tudor
Hi Lorenzo,

On 5/21/2020 4:00 PM, Lorenzo Pieralisi wrote:
> From: Diana Craciun 
> 
> Add ACPI support in the fsl-mc driver. Driver parses MC DSDT table to
> extract memory and other resources.
> 
> Interrupt (GIC ITS) information is extracted from the MADT table
> by drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.
> 
> IORT table is parsed to configure DMA.
> 
> Signed-off-by: Makarand Pawagi 
> Signed-off-by: Diana Craciun 
> Signed-off-by: Laurentiu Tudor 
> ---

The author of this patch should be Makarand. I think I accidentaly broke
it when we exchanged the patches. Very sorry about it.

---
Best Regards, Laurentiu


>  drivers/bus/fsl-mc/fsl-mc-bus.c | 73 +++-
>  drivers/bus/fsl-mc/fsl-mc-msi.c | 37 +-
>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 75 -
>  3 files changed, 150 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
> index 824ff77bbe86..324d49d6df89 100644
> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> @@ -18,6 +18,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  
>  #include "fsl-mc-private.h"
>  
> @@ -38,6 +40,7 @@ struct fsl_mc {
>   struct fsl_mc_device *root_mc_bus_dev;
>   u8 num_translation_ranges;
>   struct fsl_mc_addr_translation_range *translation_ranges;
> + void *fsl_mc_regs;
>  };
>  
>  /**
> @@ -56,6 +59,10 @@ struct fsl_mc_addr_translation_range {
>   phys_addr_t start_phys_addr;
>  };
>  
> +#define FSL_MC_FAPR  0x28
> +#define MC_FAPR_PL   BIT(18)
> +#define MC_FAPR_BMT  BIT(17)
> +
>  /**
>   * fsl_mc_bus_match - device to driver matching callback
>   * @dev: the fsl-mc device to match against
> @@ -124,7 +131,10 @@ static int fsl_mc_dma_configure(struct device *dev)
>   while (dev_is_fsl_mc(dma_dev))
>   dma_dev = dma_dev->parent;
>  
> - return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> + if (dev_of_node(dma_dev))
> + return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> +
> + return acpi_dma_configure_id(dev, DEV_DMA_COHERENT, _id);
>  }
>  
>  static ssize_t modalias_show(struct device *dev, struct device_attribute 
> *attr,
> @@ -865,8 +875,11 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
>   struct fsl_mc_io *mc_io = NULL;
>   int container_id;
>   phys_addr_t mc_portal_phys_addr;
> - u32 mc_portal_size;
> - struct resource res;
> + u32 mc_portal_size, mc_stream_id;
> + struct resource *plat_res;
> +
> + if (!iommu_present(_mc_bus_type))
> + return -EPROBE_DEFER;
>  
>   mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
>   if (!mc)
> @@ -874,19 +887,33 @@ static int fsl_mc_bus_probe(struct platform_device 
> *pdev)
>  
>   platform_set_drvdata(pdev, mc);
>  
> + plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> + mc->fsl_mc_regs = devm_ioremap_resource(>dev, plat_res);
> + if (IS_ERR(mc->fsl_mc_regs))
> + return PTR_ERR(mc->fsl_mc_regs);
> +
> + if (IS_ENABLED(CONFIG_ACPI) && !dev_of_node(>dev)) {
> + mc_stream_id = readl(mc->fsl_mc_regs + FSL_MC_FAPR);
> + /*
> +  * HW ORs the PL and BMT bit, places the result in bit 15 of
> +  * the StreamID and ORs in the ICID. Calculate it accordingly.
> +  */
> + mc_stream_id = (mc_stream_id & 0x) |
> + ((mc_stream_id & (MC_FAPR_PL | MC_FAPR_BMT)) ?
> + 0x4000 : 0);
> + error = acpi_dma_configure_id(>dev, DEV_DMA_COHERENT,
> +   _stream_id);
> + if (error)
> + dev_warn(>dev, "failed to configure dma: %d.\n",
> +  error);
> + }
> +
>   /*
>* Get physical address of MC portal for the root DPRC:
>*/
> - error = of_address_to_resource(pdev->dev.of_node, 0, );
> - if (error < 0) {
> - dev_err(>dev,
> - "of_address_to_resource() failed for %pOF\n",
> - pdev->dev.of_node);
> - return error;
> - }
> -
> - mc_portal_phys_addr = res.start;
> - mc_portal_size = resource_size();
> + plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + mc_portal_phys_addr = plat_res->start;
> + mc_portal_size = resource_size(plat_res);
>

Re: [RFC PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation

2020-04-16 Thread Laurentiu Tudor



On 4/15/2020 7:04 PM, Lorenzo Pieralisi wrote:
> On Wed, Apr 15, 2020 at 06:44:37PM +0300, Laurentiu Tudor wrote:
>>
>>
>> On 4/14/2020 5:32 PM, Lorenzo Pieralisi wrote:
>>> On Wed, Mar 25, 2020 at 06:48:55PM +0200, Laurentiu Tudor wrote:
>>>> Hi Lorenzo,
>>>>
>>>> On 3/25/2020 2:51 PM, Lorenzo Pieralisi wrote:
>>>>> On Thu, Feb 27, 2020 at 12:05:39PM +0200, laurentiu.tu...@nxp.com wrote:
>>>>>> From: Laurentiu Tudor 
>>>>>>
>>>>>> The devices on this bus are not discovered by way of device tree
>>>>>> but by queries to the firmware. It makes little sense to trick the
>>>>>> generic of layer into thinking that these devices are of related so
>>>>>> that we can get our dma configuration. Instead of doing that, add
>>>>>> our custom dma configuration implementation.
>>>>>>
>>>>>> Signed-off-by: Laurentiu Tudor 
>>>>>> ---
>>>>>>  drivers/bus/fsl-mc/fsl-mc-bus.c | 31 ++-
>>>>>>  1 file changed, 30 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c 
>>>>>> b/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>>>> index 36eb25f82c8e..eafaa0e0b906 100644
>>>>>> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>>>> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>>>> @@ -132,11 +132,40 @@ static int fsl_mc_bus_uevent(struct device *dev, 
>>>>>> struct kobj_uevent_env *env)
>>>>>>  static int fsl_mc_dma_configure(struct device *dev)
>>>>>>  {
>>>>>>  struct device *dma_dev = dev;
>>>>>> +struct iommu_fwspec *fwspec;
>>>>>> +const struct iommu_ops *iommu_ops;
>>>>>> +struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
>>>>>> +int ret;
>>>>>> +u32 icid;
>>>>>>  
>>>>>>  while (dev_is_fsl_mc(dma_dev))
>>>>>>  dma_dev = dma_dev->parent;
>>>>>>  
>>>>>> -return of_dma_configure(dev, dma_dev->of_node, 0);
>>>>>> +fwspec = dev_iommu_fwspec_get(dma_dev);
>>>>>> +if (!fwspec)
>>>>>> +return -ENODEV;
>>>>>> +iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode);
>>>>>> +if (!iommu_ops)
>>>>>> +return -ENODEV;
>>>>>> +
>>>>>> +ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops);
>>>>>> +if (ret)
>>>>>> +return ret;
>>>>>> +
>>>>>> +icid = mc_dev->icid;
>>>>>> +ret = iommu_fwspec_add_ids(dev, , 1);
>>>>>
>>>>> I see. So with this patch we would use the MC named component only to
>>>>> retrieve the iommu_ops
>>>>
>>>> Right. I'd also add that the implementation tries to follow the existing
>>>> standard .dma_configure implementations, e.g. of_dma_configure +
>>>> of_iommu_configure. I'd also note that similarly to the ACPI case, this
>>>> MC FW device is probed as a platform device in the DT scenario, binding
>>>> here [1].
>>>> A similar approach is used for the retrieval of the msi irq domain, see
>>>> following patch.
>>>>
>>>>> - the streamid are injected directly here bypassing OF/IORT bindings 
>>>>> translations altogether. 
>>>>
>>>> Actually I've submitted a v2 [2] that calls into .of_xlate() to allow
>>>> the smmu driver to do some processing on the raw streamid coming from
>>>> the firmware. I have not yet tested this with ACPI but expect it to
>>>> work, however, it's debatable how valid is this approach in the context
>>>> of ACPI.
>>>
>>> Actually, what I think you need is of_map_rid() (and an IORT
>>> equivalent, that I am going to write - generalizing iort_msi_map_rid()).
>>>
>>> Would that be enough to enable IORT "normal" mappings in the MC bus
>>> named components ?
>>>
>>
>> At a first glance, looks like this could very well fix the ACPI
>> scenario, but I have some unclarities on the approach:
>>  * are we goin

Re: [RFC PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation

2020-04-15 Thread Laurentiu Tudor



On 4/14/2020 5:32 PM, Lorenzo Pieralisi wrote:
> On Wed, Mar 25, 2020 at 06:48:55PM +0200, Laurentiu Tudor wrote:
>> Hi Lorenzo,
>>
>> On 3/25/2020 2:51 PM, Lorenzo Pieralisi wrote:
>>> On Thu, Feb 27, 2020 at 12:05:39PM +0200, laurentiu.tu...@nxp.com wrote:
>>>> From: Laurentiu Tudor 
>>>>
>>>> The devices on this bus are not discovered by way of device tree
>>>> but by queries to the firmware. It makes little sense to trick the
>>>> generic of layer into thinking that these devices are of related so
>>>> that we can get our dma configuration. Instead of doing that, add
>>>> our custom dma configuration implementation.
>>>>
>>>> Signed-off-by: Laurentiu Tudor 
>>>> ---
>>>>  drivers/bus/fsl-mc/fsl-mc-bus.c | 31 ++-
>>>>  1 file changed, 30 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c 
>>>> b/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>> index 36eb25f82c8e..eafaa0e0b906 100644
>>>> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
>>>> @@ -132,11 +132,40 @@ static int fsl_mc_bus_uevent(struct device *dev, 
>>>> struct kobj_uevent_env *env)
>>>>  static int fsl_mc_dma_configure(struct device *dev)
>>>>  {
>>>>struct device *dma_dev = dev;
>>>> +  struct iommu_fwspec *fwspec;
>>>> +  const struct iommu_ops *iommu_ops;
>>>> +  struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
>>>> +  int ret;
>>>> +  u32 icid;
>>>>  
>>>>while (dev_is_fsl_mc(dma_dev))
>>>>dma_dev = dma_dev->parent;
>>>>  
>>>> -  return of_dma_configure(dev, dma_dev->of_node, 0);
>>>> +  fwspec = dev_iommu_fwspec_get(dma_dev);
>>>> +  if (!fwspec)
>>>> +  return -ENODEV;
>>>> +  iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode);
>>>> +  if (!iommu_ops)
>>>> +  return -ENODEV;
>>>> +
>>>> +  ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops);
>>>> +  if (ret)
>>>> +  return ret;
>>>> +
>>>> +  icid = mc_dev->icid;
>>>> +  ret = iommu_fwspec_add_ids(dev, , 1);
>>>
>>> I see. So with this patch we would use the MC named component only to
>>> retrieve the iommu_ops
>>
>> Right. I'd also add that the implementation tries to follow the existing
>> standard .dma_configure implementations, e.g. of_dma_configure +
>> of_iommu_configure. I'd also note that similarly to the ACPI case, this
>> MC FW device is probed as a platform device in the DT scenario, binding
>> here [1].
>> A similar approach is used for the retrieval of the msi irq domain, see
>> following patch.
>>
>>> - the streamid are injected directly here bypassing OF/IORT bindings 
>>> translations altogether. 
>>
>> Actually I've submitted a v2 [2] that calls into .of_xlate() to allow
>> the smmu driver to do some processing on the raw streamid coming from
>> the firmware. I have not yet tested this with ACPI but expect it to
>> work, however, it's debatable how valid is this approach in the context
>> of ACPI.
> 
> Actually, what I think you need is of_map_rid() (and an IORT
> equivalent, that I am going to write - generalizing iort_msi_map_rid()).
> 
> Would that be enough to enable IORT "normal" mappings in the MC bus
> named components ?
> 

At a first glance, looks like this could very well fix the ACPI
scenario, but I have some unclarities on the approach:
 * are we going to rely in DT and ACPI generic layers even if these
devices are not published / enumerated through DT or ACPI tables?
 * the firmware manages and provides discrete streamids for the devices
it exposes so there's no translation involved. There's no
   requestor_id / input_id involved but it seems that we would still do
some kind of translation relying for this on the DT/ACPI functions.
 * MC firmware has its own stream_id (e.g. on some chips 0x4000, others
0xf00, so outside the range of stream_ids used for the mc devices)
   while for the devices on this bus, MC allocates stream_ids from a
range (e.g. 0x17 - 0x3f). Is it possible to describe this in the IORT table?
 * Regarding the of_map_rid() use you mentioned, I was planning to
decouple the mc bus from the DT layer by dropping the use of
of_map_rid(), see patch 4.
I briefly glanced over the iort code and spotted this static function:
iort_iommu_xlate(). Wouldn't it also help, of course after making it public?

---
Thanks & Best Regards, Laurentiu

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


Re: [RFC PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation

2020-03-25 Thread Laurentiu Tudor
Hi Lorenzo,

On 3/25/2020 2:51 PM, Lorenzo Pieralisi wrote:
> On Thu, Feb 27, 2020 at 12:05:39PM +0200, laurentiu.tu...@nxp.com wrote:
>> From: Laurentiu Tudor 
>>
>> The devices on this bus are not discovered by way of device tree
>> but by queries to the firmware. It makes little sense to trick the
>> generic of layer into thinking that these devices are of related so
>> that we can get our dma configuration. Instead of doing that, add
>> our custom dma configuration implementation.
>>
>> Signed-off-by: Laurentiu Tudor 
>> ---
>>  drivers/bus/fsl-mc/fsl-mc-bus.c | 31 ++-
>>  1 file changed, 30 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c 
>> b/drivers/bus/fsl-mc/fsl-mc-bus.c
>> index 36eb25f82c8e..eafaa0e0b906 100644
>> --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
>> +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
>> @@ -132,11 +132,40 @@ static int fsl_mc_bus_uevent(struct device *dev, 
>> struct kobj_uevent_env *env)
>>  static int fsl_mc_dma_configure(struct device *dev)
>>  {
>>  struct device *dma_dev = dev;
>> +struct iommu_fwspec *fwspec;
>> +const struct iommu_ops *iommu_ops;
>> +struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
>> +int ret;
>> +u32 icid;
>>  
>>  while (dev_is_fsl_mc(dma_dev))
>>  dma_dev = dma_dev->parent;
>>  
>> -return of_dma_configure(dev, dma_dev->of_node, 0);
>> +fwspec = dev_iommu_fwspec_get(dma_dev);
>> +if (!fwspec)
>> +return -ENODEV;
>> +iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode);
>> +if (!iommu_ops)
>> +return -ENODEV;
>> +
>> +ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops);
>> +if (ret)
>> +return ret;
>> +
>> +icid = mc_dev->icid;
>> +ret = iommu_fwspec_add_ids(dev, , 1);
> 
> I see. So with this patch we would use the MC named component only to
> retrieve the iommu_ops

Right. I'd also add that the implementation tries to follow the existing
standard .dma_configure implementations, e.g. of_dma_configure +
of_iommu_configure. I'd also note that similarly to the ACPI case, this
MC FW device is probed as a platform device in the DT scenario, binding
here [1].
A similar approach is used for the retrieval of the msi irq domain, see
following patch.

> - the streamid are injected directly here bypassing OF/IORT bindings 
> translations altogether. 

Actually I've submitted a v2 [2] that calls into .of_xlate() to allow
the smmu driver to do some processing on the raw streamid coming from
the firmware. I have not yet tested this with ACPI but expect it to
work, however, it's debatable how valid is this approach in the context
of ACPI.

> Am I reading this code correctly ?

Yes. Thanks for taking the time.

[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
[2] https://www.spinics.net/lists/arm-kernel/msg794757.html

---
Best Regards, Laurentiu

> 
>> +if (ret)
>> +return ret;
>> +
>> +if (!device_iommu_mapped(dev)) {
>> +ret = iommu_probe_device(dev);
>> +if (ret)
>> +return ret;
>> +}
>> +
>> +arch_setup_dma_ops(dev, 0, *dma_dev->dma_mask + 1, iommu_ops, true);
>> +
>> +return 0;
>>  }
>>  
>>  static ssize_t modalias_show(struct device *dev, struct device_attribute 
>> *attr,
>> -- 
>> 2.17.1
>>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[RFC PATCH v2 4/4] iommu/of: get rid of fsl-mc specific code

2020-03-24 Thread laurentiu . tudor
From: Laurentiu Tudor 

Changing the way we configure dma for fsl-mc devices allows
us to get rid of our fsl-mc specific code in the generic
of iommu code.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/of_iommu.c | 20 
 1 file changed, 20 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 20738aacac89..332072ada474 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -15,7 +15,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #define NO_IOMMU   1
 
@@ -139,23 +138,6 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 
alias, void *data)
return err;
 }
 
-static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev,
-   struct device_node *master_np)
-{
-   struct of_phandle_args iommu_spec = { .args_count = 1 };
-   int err;
-
-   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
-"iommu-map-mask", _spec.np,
-iommu_spec.args);
-   if (err)
-   return err == -ENODEV ? NO_IOMMU : err;
-
-   err = of_iommu_xlate(_dev->dev, _spec);
-   of_node_put(iommu_spec.np);
-   return err;
-}
-
 const struct iommu_ops *of_iommu_configure(struct device *dev,
   struct device_node *master_np)
 {
@@ -188,8 +170,6 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
pci_request_acs();
err = pci_for_each_dma_alias(to_pci_dev(dev),
 of_pci_iommu_init, );
-   } else if (dev_is_fsl_mc(dev)) {
-   err = of_fsl_mc_iommu_init(to_fsl_mc_device(dev), master_np);
} else {
struct of_phandle_args iommu_spec;
int idx = 0;
-- 
2.17.1

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


[RFC PATCH v2 3/4] bus: fsl-mc: Add ACPI support for fsl-mc

2020-03-24 Thread laurentiu . tudor
From: Makarand Pawagi 

ACPI support is added in the fsl-mc driver. Driver will parse
MC DSDT table to extract memory and other resorces.

Interrupt (GIC ITS) information will be extracted from MADT table
by drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.

IORT table will be parsed to configure DMA.

Signed-off-by: Makarand Pawagi 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c | 35 ++-
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 69 -
 2 files changed, 87 insertions(+), 17 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index a3d25c1d4ff8..fbd248597e88 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -952,7 +952,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
phys_addr_t mc_portal_phys_addr;
u32 mc_portal_size;
struct mc_version mc_version;
-   struct resource res;
+   struct resource *plat_res;
 
mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
if (!mc)
@@ -963,16 +963,9 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
/*
 * Get physical address of MC portal for the root DPRC:
 */
-   error = of_address_to_resource(pdev->dev.of_node, 0, );
-   if (error < 0) {
-   dev_err(>dev,
-   "of_address_to_resource() failed for %pOF\n",
-   pdev->dev.of_node);
-   return error;
-   }
-
-   mc_portal_phys_addr = res.start;
-   mc_portal_size = resource_size();
+   plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   mc_portal_phys_addr = plat_res->start;
+   mc_portal_size = resource_size(plat_res);
error = fsl_create_mc_io(>dev, mc_portal_phys_addr,
 mc_portal_size, NULL,
 FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, _io);
@@ -989,11 +982,13 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
dev_info(>dev, "MC firmware version: %u.%u.%u\n",
 mc_version.major, mc_version.minor, mc_version.revision);
 
-   error = get_mc_addr_translation_ranges(>dev,
-  >translation_ranges,
-  >num_translation_ranges);
-   if (error < 0)
-   goto error_cleanup_mc_io;
+   if (dev_of_node(>dev)) {
+   error = get_mc_addr_translation_ranges(>dev,
+   >translation_ranges,
+   >num_translation_ranges);
+   if (error < 0)
+   goto error_cleanup_mc_io;
+   }
 
error = dprc_get_container_id(mc_io, 0, _id);
if (error < 0) {
@@ -1020,6 +1015,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
goto error_cleanup_mc_io;
 
mc->root_mc_bus_dev = mc_bus_dev;
+   mc_bus_dev->dev.fwnode = pdev->dev.fwnode;
return 0;
 
 error_cleanup_mc_io:
@@ -1053,11 +1049,18 @@ static const struct of_device_id 
fsl_mc_bus_match_table[] = {
 
 MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
 
+static const struct acpi_device_id fsl_mc_bus_acpi_match_table[] = {
+   {"NXP0008", 0 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, fsl_mc_bus_acpi_match_table);
+
 static struct platform_driver fsl_mc_bus_driver = {
.driver = {
   .name = "fsl_mc_bus",
   .pm = NULL,
   .of_match_table = fsl_mc_bus_match_table,
+  .acpi_match_table = fsl_mc_bus_acpi_match_table,
   },
.probe = fsl_mc_bus_probe,
.remove = fsl_mc_bus_remove,
diff --git a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c 
b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
index 606efa64adff..6d67834722c9 100644
--- a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
@@ -4,9 +4,11 @@
  *
  * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera 
+ * Copyright 2020 NXP
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -66,7 +68,65 @@ static const struct of_device_id its_device_id[] = {
{},
 };
 
-static int __init its_fsl_mc_msi_init(void)
+static int __init its_fsl_mc_msi_init_one(struct fwnode_handle *handle,
+ const char *name)
+{
+   struct irq_domain *parent;
+   struct irq_domain *mc_msi_domain;
+
+   parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
+   if (!parent || !msi_get_domain_info(parent)) {
+   pr_err("%s: Unable to locate ITS domain\n", name);
+   return -ENXIO;
+   }
+
+   mc_msi_domain = fsl_mc_msi_create_irq_domain(handle,
+
_fsl_mc_msi_domain_info,
+parent);
+   if (!mc_msi_domain)
+   

[RFC PATCH v2 0/4] bus: fsl-mc: Add ACPI support for fsl-mc

2020-03-24 Thread laurentiu . tudor
From: Laurentiu Tudor 

This patch adds ACPI support for the fsl-mc bus driver. First 2 patches
are prerequsite that remove dependencies on device tree. Third patch
adds the actual ACPI support and the final one drops some fsl-mc
specific code in the generic device tree handling code.

Changes in v2:
 - add missing of_xlate call in custom .dma_configure (patch 1)
 - added a cover letter

Diana Craciun (1):
  irqchip/fsl-mc: Change the way the IRQ domain is set for MC devices

Laurentiu Tudor (2):
  bus: fsl-mc: add custom .dma_configure implementation
  iommu/of: get rid of fsl-mc specific code

Makarand Pawagi (1):
  bus: fsl-mc: Add ACPI support for fsl-mc

 drivers/bus/fsl-mc/fsl-mc-bus.c | 85 -
 drivers/bus/fsl-mc/fsl-mc-msi.c | 11 ++-
 drivers/iommu/of_iommu.c| 20 -
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 69 -
 4 files changed, 145 insertions(+), 40 deletions(-)

-- 
2.17.1

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


[RFC PATCH v2 2/4] irqchip/fsl-mc: Change the way the IRQ domain is set for MC devices

2020-03-24 Thread laurentiu . tudor
From: Diana Craciun 

In ACPI the MC bus is represented as a platform device and a named
component in the IORT table. The mc-bus devices are discovered
dynamically at runtime but they share the same fwnode with the parent
platfom device. This patch changes the way the IRQ domain is searched
for the MC devices: it takes the fwnode reference from the parent and
uses the fwnode reference to find the MC IRQ domain.

Signed-off-by: Diana Craciun 
---
 drivers/bus/fsl-mc/fsl-mc-msi.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 8b9c66d7c4ff..1e2e97329781 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -182,16 +182,23 @@ int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
 {
struct irq_domain *msi_domain;
struct device_node *mc_of_node = mc_platform_dev->of_node;
+   struct fwnode_handle *fwnode;
 
-   msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
-  DOMAIN_BUS_FSL_MC_MSI);
+   msi_domain = dev_get_msi_domain(mc_platform_dev);
if (!msi_domain) {
pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
   mc_of_node);
 
return -ENOENT;
}
+   fwnode = msi_domain->fwnode;
+   msi_domain = irq_find_matching_fwnode(fwnode, DOMAIN_BUS_FSL_MC_MSI);
+   if (!msi_domain) {
+   pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
+  mc_of_node);
 
+   return -ENOENT;
+   }
*mc_msi_domain = msi_domain;
return 0;
 }
-- 
2.17.1

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


[RFC PATCH v2 1/4] bus: fsl-mc: add custom .dma_configure implementation

2020-03-24 Thread laurentiu . tudor
From: Laurentiu Tudor 

The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.

Signed-off-by: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c | 50 -
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index a0f8854acb3a..a3d25c1d4ff8 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "fsl-mc-private.h"
 
@@ -130,11 +131,58 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
kobj_uevent_env *env)
 static int fsl_mc_dma_configure(struct device *dev)
 {
struct device *dma_dev = dev;
+   struct iommu_fwspec *fwspec;
+   const struct iommu_ops *iommu_ops;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   int ret;
+   u32 icid;
+
+   /* Skip DMA setup for devices that are not DMA masters */
+   if (dev->type == _mc_bus_dpmcp_type ||
+   dev->type == _mc_bus_dpbp_type ||
+   dev->type == _mc_bus_dpcon_type ||
+   dev->type == _mc_bus_dpio_type)
+   return 0;
 
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
 
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   fwspec = dev_iommu_fwspec_get(dma_dev);
+   if (!fwspec)
+   return -ENODEV;
+   iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode);
+   if (!iommu_ops)
+   return -ENODEV;
+
+   ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops);
+   if (ret)
+   return ret;
+
+   if (iommu_ops->of_xlate) {
+   struct of_phandle_args iommu_spec = {
+   .np = fwspec->iommu_fwnode->dev->of_node,
+   .args[0] = mc_dev->icid,
+   .args_count = 1
+   };
+
+   ret = iommu_ops->of_xlate(dev, _spec);
+   if (ret) {
+   iommu_fwspec_free(dev);
+   return ret;
+   }
+   }
+
+   if (!device_iommu_mapped(dev)) {
+   ret = iommu_probe_device(dev);
+   if (ret) {
+   iommu_fwspec_free(dev);
+   return ret;
+   }
+   }
+
+   arch_setup_dma_ops(dev, 0, *dma_dev->dma_mask + 1, iommu_ops, true);
+
+   return 0;
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-- 
2.17.1

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


Re: [RFC PATCH v2 0/2] iommu: arm-smmu: Add support for early direct mappings

2020-03-17 Thread Laurentiu Tudor

[ +Russell ]

Forgot to Cc: you Russell, sorry about that. This patch series could be 
an important step towards fixing the MC firmware over smmu issue on nxp 
layerscape chips.


---

Best Regards, Laurentiu

On 3/17/2020 4:21 PM, laurentiu.tu...@nxp.com wrote:

From: Thierry Reding 

On some platforms, the firmware will setup hardware to read from a given
region of memory. One such example is a display controller that is
scanning out a splash screen from physical memory.

During Linux' boot process, the ARM SMMU will configure all contexts to
fault by default. This means that memory accesses that happen by an SMMU
master before its driver has had a chance to properly set up the IOMMU
will cause a fault. This is especially annoying for something like the
display controller scanning out a splash screen because the faults will
result in the display controller getting bogus data (all-ones on Tegra)
and since it repeatedly scans that framebuffer, it will keep triggering
such faults and spam the boot log with them.

In order to work around such problems, scan the device tree for IOMMU
masters and set up a special identity domain that will map 1:1 all of
the reserved regions associated with them. This happens before the SMMU
is enabled, so that the mappings are already set up before translations
begin.

One thing that was pointed out earlier, and which I don't have a good
idea on how to solve it, is that the early identity domain is not
discarded. The assumption is that the standard direct mappings code of
the IOMMU framework will replace the early identity domain once devices
are properly attached to domains, but we don't have a good point in time
when it would be safe to remove the early identity domain.

One option that I can think of would be to create an early identity
domain for each master and inherit it when that master is attached to
the domain later on, but that seems rather complicated from an book-
keeping point of view and tricky because we need to be careful not to
map regions twice, etc.

Any good ideas on how to solve this? It'd also be interesting to see if
there's a more generic way of doing this. I know that something like
this isn't necessary on earlier Tegra SoCs with the custom Tegra SMMU
because translations are only enabled when the devices are attached to a
domain. I'm not sure about other IOMMUs, but in the absence of a struct
device, I suspect that we can't really do anything really generic that
would work across drivers.

Previous version: 
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fcover%2F11279577%2Fdata=02%7C01%7Claurentiu.tudor%40nxp.com%7Cb40c3ee306224a2fc8fe08d7ca7e8007%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637200517038451677sdata=rq8Ojkh1fovakZ2jTGHjSUaYROtvjY8ZDItEiqCTuI4%3Dreserved=0

Changes in v2:
  - recreate identity mappings when the device is placed in its rightful domain
  - delete its original identity mappings from the identity domain
  - added a counter to keep track of number of devices with identity mappings
  - free identity domain when the counter reaches 0
  - this should help fix our firmware issue, mentioned here [1]

[1] 
https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.kernel.org%2Fcomment%2F23200041%2Fdata=02%7C01%7Claurentiu.tudor%40nxp.com%7Cb40c3ee306224a2fc8fe08d7ca7e8007%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637200517038451677sdata=Q0T326D1QMz5EtWY%2BzVUxdd01AbKySe8Ota66H2rkiI%3Dreserved=0

Thierry Reding (2):
   iommu: arm-smmu: Extract arm_smmu_of_parse()
   iommu: arm-smmu: Add support for early direct mappings

  drivers/iommu/arm-smmu.c | 280 +--
  drivers/iommu/arm-smmu.h |   3 +
  2 files changed, 275 insertions(+), 8 deletions(-)


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


[RFC PATCH v2 0/2] iommu: arm-smmu: Add support for early direct mappings

2020-03-17 Thread laurentiu . tudor
From: Thierry Reding 

On some platforms, the firmware will setup hardware to read from a given
region of memory. One such example is a display controller that is
scanning out a splash screen from physical memory.

During Linux' boot process, the ARM SMMU will configure all contexts to
fault by default. This means that memory accesses that happen by an SMMU
master before its driver has had a chance to properly set up the IOMMU
will cause a fault. This is especially annoying for something like the
display controller scanning out a splash screen because the faults will
result in the display controller getting bogus data (all-ones on Tegra)
and since it repeatedly scans that framebuffer, it will keep triggering
such faults and spam the boot log with them.

In order to work around such problems, scan the device tree for IOMMU
masters and set up a special identity domain that will map 1:1 all of
the reserved regions associated with them. This happens before the SMMU
is enabled, so that the mappings are already set up before translations
begin.

One thing that was pointed out earlier, and which I don't have a good
idea on how to solve it, is that the early identity domain is not
discarded. The assumption is that the standard direct mappings code of
the IOMMU framework will replace the early identity domain once devices
are properly attached to domains, but we don't have a good point in time
when it would be safe to remove the early identity domain.

One option that I can think of would be to create an early identity
domain for each master and inherit it when that master is attached to
the domain later on, but that seems rather complicated from an book-
keeping point of view and tricky because we need to be careful not to
map regions twice, etc.

Any good ideas on how to solve this? It'd also be interesting to see if
there's a more generic way of doing this. I know that something like
this isn't necessary on earlier Tegra SoCs with the custom Tegra SMMU
because translations are only enabled when the devices are attached to a
domain. I'm not sure about other IOMMUs, but in the absence of a struct
device, I suspect that we can't really do anything really generic that
would work across drivers.

Previous version: https://patchwork.kernel.org/cover/11279577/

Changes in v2:
 - recreate identity mappings when the device is placed in its rightful domain
 - delete its original identity mappings from the identity domain
 - added a counter to keep track of number of devices with identity mappings
 - free identity domain when the counter reaches 0
 - this should help fix our firmware issue, mentioned here [1]

[1] https://patchwork.kernel.org/comment/23200041/

Thierry Reding (2):
  iommu: arm-smmu: Extract arm_smmu_of_parse()
  iommu: arm-smmu: Add support for early direct mappings

 drivers/iommu/arm-smmu.c | 280 +--
 drivers/iommu/arm-smmu.h |   3 +
 2 files changed, 275 insertions(+), 8 deletions(-)

-- 
2.17.1

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


[RFC PATCH v2 2/2] iommu: arm-smmu: Add support for early direct mappings

2020-03-17 Thread laurentiu . tudor
From: Thierry Reding 

On platforms, the firmware will setup hardware to read from a given
region of memory. One such example is a display controller that is
scanning out a splash screen from physical memory.

During Linux's boot process, the ARM SMMU will configure all contexts to
fault by default. This means that memory accesses that happen by an SMMU
master before its driver has had a chance to properly set up the IOMMU
will cause a fault. This is especially annoying for something like the
display controller scanning out a splash screen because the faults will
result in the display controller getting bogus data (all-ones on Tegra)
and since it repeatedly scans that framebuffer, it will keep triggering
such faults and spam the boot log with them.

In order to work around such problems, scan the device tree for IOMMU
masters and set up a special identity domain that will map 1:1 all of
the reserved regions associated with them. This happens before the SMMU
is enabled, so that the mappings are already set up before translations
begin.

Signed-off-by: Thierry Reding 
Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/arm-smmu.c | 257 ++-
 drivers/iommu/arm-smmu.h |   3 +
 2 files changed, 259 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 8a238d5a4b51..083566a27eef 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1158,6 +1158,135 @@ static int arm_smmu_domain_add_master(struct 
arm_smmu_domain *smmu_domain,
return 0;
 }
 
+static int arm_smmu_identity_map_regions(struct iommu_domain *dom,
+struct arm_smmu_device *smmu,
+struct device_node *np)
+{
+   struct device *dev = smmu->dev;
+   struct of_phandle_iterator it;
+   unsigned long page_size;
+   unsigned int count = 0;
+   int ret;
+
+   page_size = 1UL << __ffs(dom->pgsize_bitmap);
+
+   /* parse memory regions and add them to the identity mapping */
+   of_for_each_phandle(, ret, np, "memory-region", NULL, 0) {
+   int prot = IOMMU_READ | IOMMU_WRITE;
+   dma_addr_t start, limit, iova;
+   struct resource res;
+
+   ret = of_address_to_resource(it.node, 0, );
+   if (ret < 0) {
+   dev_err(dev, "failed to parse memory region %pOF: %d\n",
+   it.node, ret);
+   continue;
+   }
+
+   /* check that region is not empty */
+   if (resource_size() == 0) {
+   dev_dbg(dev, "skipping empty memory region %pOF\n",
+   it.node);
+   continue;
+   }
+
+   start = ALIGN(res.start, page_size);
+   limit = ALIGN(res.start + resource_size(), page_size);
+
+   for (iova = start; iova < limit; iova += page_size) {
+   phys_addr_t phys;
+
+   /* check that this IOVA isn't already mapped */
+   phys = iommu_iova_to_phys(dom, iova);
+   if (phys)
+   continue;
+
+   ret = iommu_map(dom, iova, iova, page_size,
+   prot);
+   if (ret < 0) {
+   dev_err(dev, "failed to map %pad for %pOF: 
%d\n",
+   , it.node, ret);
+   continue;
+   }
+   }
+
+   dev_dbg(dev, "identity mapped memory region %pR\n", );
+   count++;
+   }
+
+   return count;
+}
+
+static bool arm_smmu_identity_unmap_regions(struct arm_smmu_device *smmu,
+   struct device_node *np)
+{
+   struct device *dev = smmu->dev;
+   struct of_phandle_iterator it;
+   unsigned long page_size;
+   int ret;
+   bool unmapped = false;
+
+   page_size = 1UL << __ffs(smmu->identity->pgsize_bitmap);
+
+   /* parse memory regions and add them to the identity mapping */
+   of_for_each_phandle(, ret, np, "memory-region", NULL, 0) {
+   dma_addr_t start, limit, iova;
+   struct resource res;
+
+   ret = of_address_to_resource(it.node, 0, );
+   if (ret < 0) {
+   dev_err(dev, "failed to parse memory region %pOF: %d\n",
+   it.node, ret);
+   continue;
+   }
+
+   /* check that region is not empty */
+   if (resource_size() == 0) {
+   dev_dbg(dev, "skipping empty memory region %pOF\n",
+   it.node);
+

[RFC PATCH v2 1/2] iommu: arm-smmu: Extract arm_smmu_of_parse()

2020-03-17 Thread laurentiu . tudor
From: Thierry Reding 

This function will be subsequently used to extract stream ID information
early, before a struct device is available.

Signed-off-by: Thierry Reding 
---
 drivers/iommu/arm-smmu.c | 24 +---
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 16c4b87af42b..8a238d5a4b51 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1584,18 +1584,28 @@ static int arm_smmu_domain_set_attr(struct iommu_domain 
*domain,
return ret;
 }
 
-static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
+static int arm_smmu_of_parse(struct device_node *np, const u32 *args,
+unsigned int count)
 {
-   u32 mask, fwid = 0;
+   u32 fwid = 0, mask;
 
-   if (args->args_count > 0)
-   fwid |= FIELD_PREP(ARM_SMMU_SMR_ID, args->args[0]);
+   if (count > 0)
+   fwid |= FIELD_PREP(ARM_SMMU_SMR_ID, args[0]);
 
-   if (args->args_count > 1)
-   fwid |= FIELD_PREP(ARM_SMMU_SMR_MASK, args->args[1]);
-   else if (!of_property_read_u32(args->np, "stream-match-mask", ))
+   if (count > 1)
+   fwid |= FIELD_PREP(ARM_SMMU_SMR_MASK, args[1]);
+   else if (!of_property_read_u32(np, "stream-match-mask", ))
fwid |= FIELD_PREP(ARM_SMMU_SMR_MASK, mask);
 
+   return fwid;
+}
+
+static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
+{
+   u32 fwid;
+
+   fwid = arm_smmu_of_parse(args->np, args->args, args->args_count);
+
return iommu_fwspec_add_ids(dev, , 1);
 }
 
-- 
2.17.1

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


Re: [RFC 0/2] iommu: arm-smmu: Add support for early direct mappings

2020-03-04 Thread Laurentiu Tudor

Hello,

On 28.02.2020 04:57, Bjorn Andersson wrote:

On Mon 09 Dec 07:07 PST 2019, Thierry Reding wrote:


From: Thierry Reding 



Sorry for the slow response on this, finally got the time to go through
this in detail and try it out on some Qualcomm boards.


On some platforms, the firmware will setup hardware to read from a given
region of memory. One such example is a display controller that is
scanning out a splash screen from physical memory.



This particular use case is the one that we need to figure out for
Qualcomm devices as well; on some devices it's a simple splash screen
(that on many devices can be disabled), but for others we have EFIFB
on the display and no (sane) means to disable this.


During Linux' boot process, the ARM SMMU will configure all contexts to
fault by default. This means that memory accesses that happen by an SMMU
master before its driver has had a chance to properly set up the IOMMU
will cause a fault. This is especially annoying for something like the
display controller scanning out a splash screen because the faults will
result in the display controller getting bogus data (all-ones on Tegra)
and since it repeatedly scans that framebuffer, it will keep triggering
such faults and spam the boot log with them.



As my proposed patches indicated, the Qualcomm platform boots with
stream mapping setup for the hardware used by the bootloader, but
relying on the associated context banks not being enabled.

USFCFG in SCR0 is set and any faults resulting of this will trap into
secure world and the device will be reset.


In order to work around such problems, scan the device tree for IOMMU
masters and set up a special identity domain that will map 1:1 all of
the reserved regions associated with them. This happens before the SMMU
is enabled, so that the mappings are already set up before translations
begin.

One thing that was pointed out earlier, and which I don't have a good
idea on how to solve it, is that the early identity domain is not
discarded. The assumption is that the standard direct mappings code of
the IOMMU framework will replace the early identity domain once devices
are properly attached to domains, but we don't have a good point in time
when it would be safe to remove the early identity domain.

One option that I can think of would be to create an early identity
domain for each master and inherit it when that master is attached to
the domain later on, but that seems rather complicated from an book-
keeping point of view and tricky because we need to be careful not to
map regions twice, etc.



The one concern I ran into with this approach (after resolving below
issues) is that when the display driver probes a new domain will be
created automatically and I get a stream of "Unhandled context fault" in
the log until the driver has mapped the framebuffer in the newly
allocated context.

This is normally not a problem, as we seem to be able to do this
initialization in a few frames, but for the cases where the display
driver probe defer this is a problem.


Also gave this a go on one of NXP's layerscape platforms, and 
encountered the same issue. However, given that in our case it's not 
about a framebuffer device but a firmware, it cause it to crash. :-(


Another apparent problem is that in the current implementation only one 
memory-region per device is supported. Actually it appears that this is 
a limitation of the DT reservation binding - it doesn't seem to allow 
specifying multiple regions per device. In our firmware case we would 
need support for multiple reserved regions (FW memory, FW i/o registers 
a.s.o).


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


Re: [PATCH] iommu: silence iommu group prints

2020-03-04 Thread Laurentiu Tudor




On 04.03.2020 12:52, Russell King - ARM Linux admin wrote:

On Wed, Mar 04, 2020 at 12:33:14PM +0200, Laurentiu Tudor wrote:



On 04.03.2020 12:07, Russell King - ARM Linux admin wrote:

On Wed, Mar 04, 2020 at 11:56:53AM +0200, Laurentiu Tudor wrote:

  From 44ae46501b5379bd0890df87fd3827248626ed03 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Tue, 1 Oct 2019 16:22:48 +0300
Subject: [PATCH 1/6] bus: fsl-mc: make mc work with smmu disable bypass on
Content-Type: text/plain; charset="us-ascii"

Since this commit [1] booting kernel on MC based chips started to
fail because this firmware starts before the kernel and as soon as
SMMU is probed it starts to trigger contiguous faults.


I think you mean "continuous" here.


Yes, thanks.


This is a workaround that allows MC firmware to run with SMMU
in disable bypass mode. It consists of the following steps:
   1. pause the firmware at early boot to get a chance to setup SMMU
   2. request direct mapping for MC device
   3. resume the firmware
The workaround relies on the fact that no state is lost when
pausing / resuming firmware, as per the docs.
With this patch, platforms with MC firmware can now boot without
having to change the default config to set:
CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=n


This alone is a definite improvement, and has been needed for a while.
Please submit this patch with an appropriate Fixes: tag so stable trees
can pick it up.


The thing is that probably this workaround will never make it in the kernel
because it questionable to say the least, e.g. see [1]. My plan is to give
this approach [2] a try sometime soon.


So, if we want to reduce the iommu noise, we need to completely break
the ability to use a mainline kernel on the LX2160A.  This doesn't
seem practical nor sensible.  Someone has to give.



Well, I think it's a bit too early for such conclusions. I'd consider 
this stuff early / experimental work, probably will take quite a while 
for the dust to settle. Anyway, I'll take care not to break the kernel 
when I'll start submitting more official patches.

For now, I'm just hoping that this stuff helps fixing your local tree.

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


Re: [PATCH] iommu: silence iommu group prints

2020-03-04 Thread Laurentiu Tudor




On 04.03.2020 12:07, Russell King - ARM Linux admin wrote:

On Wed, Mar 04, 2020 at 11:56:53AM +0200, Laurentiu Tudor wrote:

 From 44ae46501b5379bd0890df87fd3827248626ed03 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Tue, 1 Oct 2019 16:22:48 +0300
Subject: [PATCH 1/6] bus: fsl-mc: make mc work with smmu disable bypass on
Content-Type: text/plain; charset="us-ascii"

Since this commit [1] booting kernel on MC based chips started to
fail because this firmware starts before the kernel and as soon as
SMMU is probed it starts to trigger contiguous faults.


I think you mean "continuous" here.


Yes, thanks.


This is a workaround that allows MC firmware to run with SMMU
in disable bypass mode. It consists of the following steps:
  1. pause the firmware at early boot to get a chance to setup SMMU
  2. request direct mapping for MC device
  3. resume the firmware
The workaround relies on the fact that no state is lost when
pausing / resuming firmware, as per the docs.
With this patch, platforms with MC firmware can now boot without
having to change the default config to set:
   CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=n


This alone is a definite improvement, and has been needed for a while.
Please submit this patch with an appropriate Fixes: tag so stable trees
can pick it up.


The thing is that probably this workaround will never make it in the 
kernel because it questionable to say the least, e.g. see [1]. My plan 
is to give this approach [2] a try sometime soon.


[1] https://patchwork.kernel.org/comment/23149049/
[2] https://patchwork.kernel.org/cover/11279577/

---
Best Regards, Laurentiu


[1] 954a03be033 ("iommu/arm-smmu: Break insecure users by disabling bypass by 
default")


Please put this where you're referencing it above - it's fine to wrap
the description of the commit when using it in the body of the commit
message.  However, that should _never_ when providing a Fixes: tag
(linux-next has a script which will detect and complain about broken
Fixes: tags.)

Thanks.



Signed-off-by: Laurentiu Tudor 
---
  drivers/bus/fsl-mc/fsl-mc-bus.c | 53 +
  1 file changed, 53 insertions(+)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index a0f8854acb3a..683a6401ffe8 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -18,6 +18,8 @@
  #include 
  #include 
  #include 
+#include 
+#include 
  
  #include "fsl-mc-private.h"
  
@@ -889,6 +891,12 @@ static int get_mc_addr_translation_ranges(struct device *dev,

return 0;
  }
  
+#define FSL_MC_GCR1	0x0

+#define GCR1_P1_STOP   BIT(31)
+
+static u32 boot_gcr1;
+static void __iomem *fsl_mc_regs;
+
  /**
   * fsl_mc_bus_probe - callback invoked when the root MC bus is being
   * added
@@ -906,6 +914,21 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
struct mc_version mc_version;
struct resource res;
  
+	/*

+* The MC firmware requires full access to the whole address space plus
+* it has no way of dealing with any kind of address translation, so
+* request direct mapping for it.
+*/
+   error = iommu_request_dm_for_dev(>dev);
+   if (error)
+   dev_warn(>dev, "iommu_request_dm_for_dev() failed: %d\n",
+error);
+
+   if (fsl_mc_regs) {
+   /* Resume the firmware */
+   writel(boot_gcr1 & ~GCR1_P1_STOP, fsl_mc_regs + FSL_MC_GCR1);
+   }
+
mc = devm_kzalloc(>dev, sizeof(*mc), GFP_KERNEL);
if (!mc)
return -ENOMEM;
@@ -990,6 +1013,13 @@ static int fsl_mc_bus_remove(struct platform_device *pdev)
if (!fsl_mc_is_root_dprc(>root_mc_bus_dev->dev))
return -EINVAL;
  
+	/*

+* Pause back the firmware so that it doesn't trigger faults by the
+* time SMMU gets brought down.
+*/
+   writel(boot_gcr1 | GCR1_P1_STOP, fsl_mc_regs + FSL_MC_GCR1);
+   iounmap(fsl_mc_regs);
+
fsl_mc_device_remove(mc->root_mc_bus_dev);
  
  	fsl_destroy_mc_io(mc->root_mc_bus_dev->mc_io);

@@ -1018,6 +1048,8 @@ static struct platform_driver fsl_mc_bus_driver = {
  static int __init fsl_mc_bus_driver_init(void)
  {
int error;
+   struct device_node *np;
+   struct resource res;
  
  	error = bus_register(_mc_bus_type);

if (error < 0) {
@@ -1039,9 +1071,30 @@ static int __init fsl_mc_bus_driver_init(void)
if (error < 0)
goto error_cleanup_dprc_driver;
  
+	np = of_find_matching_node(NULL, fsl_mc_bus_match_table);

+   if (np && of_device_is_available(np)) {
+   error = of_address_to_resource(np, 1, );
+   if (error)
+   goto error_cleanup_dprc_driver;
+   fsl_mc_regs = ioremap(res.start, resource_size());
+   if (!fsl_mc_regs) {
+ 

Re: [PATCH] iommu: silence iommu group prints

2020-03-04 Thread Laurentiu Tudor



On 04.03.2020 11:51, Russell King - ARM Linux admin wrote:

On Wed, Mar 04, 2020 at 11:42:16AM +0200, Laurentiu Tudor wrote:

On 04.03.2020 11:33, Russell King - ARM Linux admin wrote:

On Wed, Mar 04, 2020 at 10:56:06AM +0200, Laurentiu Tudor wrote:


On 04.03.2020 00:17, Russell King - ARM Linux admin wrote:

On Tue, Mar 03, 2020 at 05:55:05PM +0200, Laurentiu Tudor wrote:

   From c98dc05cdd45ae923654f2427985bd28bcde4bb2 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Thu, 13 Feb 2020 11:59:12 +0200
Subject: [PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation
Content-Type: text/plain; charset="us-ascii"

The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.


Firstly, applying this to v5.5 results in a build failure, due to a
missing linux/iommu.h include.

Secondly, this on its own appears to make the DPAA2 network interfaces
completely disappear.  Looking in /sys/bus/fsl-mc/drivers/*, none of
the DPAA2 drivers are bound to anything, and looking in
/sys/bus/fsl-mc/devices/, there is:

lrwxrwxrwx 1 root root 0 Mar  3 22:06 dprc.1 -> 
../../../devices/platform/soc/80c00.fsl-mc/dprc.1

This is booting with u-boot, so using DT rather than ACPI.


Signed-off-by: Laurentiu Tudor 
---
drivers/bus/fsl-mc/fsl-mc-bus.c | 42 -
1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 36eb25f82c8e..3df015eedae4 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -132,11 +132,51 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
kobj_uevent_env *env)
static int fsl_mc_dma_configure(struct device *dev)
{
struct device *dma_dev = dev;
+   struct iommu_fwspec *fwspec;
+   const struct iommu_ops *iommu_ops;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   int ret;
+   u32 icid;
+
+   /* Skip DMA setup for devices that are not DMA masters */
+   if (dev->type == _mc_bus_dpmcp_type ||
+   dev->type == _mc_bus_dpbp_type ||
+   dev->type == _mc_bus_dpcon_type ||
+   dev->type == _mc_bus_dpio_type)
+   return 0;
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   fwspec = dev_iommu_fwspec_get(dma_dev);
+   if (!fwspec)
+   return -ENODEV;


The problem appears to be here - fwspec is NULL for dprc.1.


Ok, that's because the iommu config is missing from the DT node that's
exposing the MC firmware. I've attached a fresh set of patches that include
on top the missing config and a workaround that makes MC work over SMMU.
Also added the missing #include, thanks for pointing out.
Let me know how it goes.


Shouldn't patch 6 should be first in the series, so that patch 1 does
not cause a regression and bisectability damage?



Correct, width one comment: both 5 and 6 should go first. Once iommu-map is
added in the device tree the workaround for MC with the
arm-smmu.disable_bypass boot arg will no longer work.


So, wouldn't it be reasonable to arrange the patch series like that?



Sure, please see attached.

---
Best Regards, Laurentiu
>From 44ae46501b5379bd0890df87fd3827248626ed03 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Tue, 1 Oct 2019 16:22:48 +0300
Subject: [PATCH 1/6] bus: fsl-mc: make mc work with smmu disable bypass on
Content-Type: text/plain; charset="us-ascii"

Since this commit [1] booting kernel on MC based chips started to
fail because this firmware starts before the kernel and as soon as
SMMU is probed it starts to trigger contiguous faults.
This is a workaround that allows MC firmware to run with SMMU
in disable bypass mode. It consists of the following steps:
 1. pause the firmware at early boot to get a chance to setup SMMU
 2. request direct mapping for MC device
 3. resume the firmware
The workaround relies on the fact that no state is lost when
pausing / resuming firmware, as per the docs.
With this patch, platforms with MC firmware can now boot without
having to change the default config to set:
  CONFIG_ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT=n

[1] 954a03be033 ("iommu/arm-smmu: Break insecure users by disabling bypass by default")

Signed-off-by: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c | 53 +
 1 file changed, 53 insertions(+)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index a0f8854acb3a..683a6401ffe8 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -18,6 +18,8 @@
 #include 
 #include

Re: [PATCH] iommu: silence iommu group prints

2020-03-04 Thread Laurentiu Tudor




On 04.03.2020 11:33, Russell King - ARM Linux admin wrote:

On Wed, Mar 04, 2020 at 10:56:06AM +0200, Laurentiu Tudor wrote:


On 04.03.2020 00:17, Russell King - ARM Linux admin wrote:

On Tue, Mar 03, 2020 at 05:55:05PM +0200, Laurentiu Tudor wrote:

  From c98dc05cdd45ae923654f2427985bd28bcde4bb2 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Thu, 13 Feb 2020 11:59:12 +0200
Subject: [PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation
Content-Type: text/plain; charset="us-ascii"

The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.


Firstly, applying this to v5.5 results in a build failure, due to a
missing linux/iommu.h include.

Secondly, this on its own appears to make the DPAA2 network interfaces
completely disappear.  Looking in /sys/bus/fsl-mc/drivers/*, none of
the DPAA2 drivers are bound to anything, and looking in
/sys/bus/fsl-mc/devices/, there is:

lrwxrwxrwx 1 root root 0 Mar  3 22:06 dprc.1 -> 
../../../devices/platform/soc/80c00.fsl-mc/dprc.1

This is booting with u-boot, so using DT rather than ACPI.


Signed-off-by: Laurentiu Tudor 
---
   drivers/bus/fsl-mc/fsl-mc-bus.c | 42 -
   1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 36eb25f82c8e..3df015eedae4 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -132,11 +132,51 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
kobj_uevent_env *env)
   static int fsl_mc_dma_configure(struct device *dev)
   {
struct device *dma_dev = dev;
+   struct iommu_fwspec *fwspec;
+   const struct iommu_ops *iommu_ops;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   int ret;
+   u32 icid;
+
+   /* Skip DMA setup for devices that are not DMA masters */
+   if (dev->type == _mc_bus_dpmcp_type ||
+   dev->type == _mc_bus_dpbp_type ||
+   dev->type == _mc_bus_dpcon_type ||
+   dev->type == _mc_bus_dpio_type)
+   return 0;
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   fwspec = dev_iommu_fwspec_get(dma_dev);
+   if (!fwspec)
+   return -ENODEV;


The problem appears to be here - fwspec is NULL for dprc.1.


Ok, that's because the iommu config is missing from the DT node that's
exposing the MC firmware. I've attached a fresh set of patches that include
on top the missing config and a workaround that makes MC work over SMMU.
Also added the missing #include, thanks for pointing out.
Let me know how it goes.


Shouldn't patch 6 should be first in the series, so that patch 1 does
not cause a regression and bisectability damage?



Correct, width one comment: both 5 and 6 should go first. Once iommu-map 
is added in the device tree the workaround for MC with the 
arm-smmu.disable_bypass boot arg will no longer work.


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


Re: [PATCH] iommu: silence iommu group prints

2020-03-04 Thread Laurentiu Tudor


On 04.03.2020 00:17, Russell King - ARM Linux admin wrote:

On Tue, Mar 03, 2020 at 05:55:05PM +0200, Laurentiu Tudor wrote:

 From c98dc05cdd45ae923654f2427985bd28bcde4bb2 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Thu, 13 Feb 2020 11:59:12 +0200
Subject: [PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation
Content-Type: text/plain; charset="us-ascii"

The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.


Firstly, applying this to v5.5 results in a build failure, due to a
missing linux/iommu.h include.

Secondly, this on its own appears to make the DPAA2 network interfaces
completely disappear.  Looking in /sys/bus/fsl-mc/drivers/*, none of
the DPAA2 drivers are bound to anything, and looking in
/sys/bus/fsl-mc/devices/, there is:

lrwxrwxrwx 1 root root 0 Mar  3 22:06 dprc.1 -> 
../../../devices/platform/soc/80c00.fsl-mc/dprc.1

This is booting with u-boot, so using DT rather than ACPI.


Signed-off-by: Laurentiu Tudor 
---
  drivers/bus/fsl-mc/fsl-mc-bus.c | 42 -
  1 file changed, 41 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 36eb25f82c8e..3df015eedae4 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -132,11 +132,51 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
kobj_uevent_env *env)
  static int fsl_mc_dma_configure(struct device *dev)
  {
struct device *dma_dev = dev;
+   struct iommu_fwspec *fwspec;
+   const struct iommu_ops *iommu_ops;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   int ret;
+   u32 icid;
+
+   /* Skip DMA setup for devices that are not DMA masters */
+   if (dev->type == _mc_bus_dpmcp_type ||
+   dev->type == _mc_bus_dpbp_type ||
+   dev->type == _mc_bus_dpcon_type ||
+   dev->type == _mc_bus_dpio_type)
+   return 0;
  
  	while (dev_is_fsl_mc(dma_dev))

dma_dev = dma_dev->parent;
  
-	return of_dma_configure(dev, dma_dev->of_node, 0);

+   fwspec = dev_iommu_fwspec_get(dma_dev);
+   if (!fwspec)
+   return -ENODEV;


The problem appears to be here - fwspec is NULL for dprc.1.


Ok, that's because the iommu config is missing from the DT node that's 
exposing the MC firmware. I've attached a fresh set of patches that 
include on top the missing config and a workaround that makes MC work 
over SMMU. Also added the missing #include, thanks for pointing out.

Let me know how it goes.

---
Best Regards, Laurentiu
>From 3d418f04fed9c10b64b3b861d66378a8f7514cc4 Mon Sep 17 00:00:00 2001
From: Laurentiu Tudor 
Date: Thu, 13 Feb 2020 11:59:12 +0200
Subject: [PATCH 1/6] bus: fsl-mc: add custom .dma_configure implementation
Content-Type: text/plain; charset="us-ascii"

The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.

Signed-off-by: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c | 43 -
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index a0f8854acb3a..e2682fbefb42 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "fsl-mc-private.h"
 
@@ -130,11 +131,51 @@ static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
 static int fsl_mc_dma_configure(struct device *dev)
 {
 	struct device *dma_dev = dev;
+	struct iommu_fwspec *fwspec;
+	const struct iommu_ops *iommu_ops;
+	struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+	int ret;
+	u32 icid;
+
+	/* Skip DMA setup for devices that are not DMA masters */
+	if (dev->type == _mc_bus_dpmcp_type ||
+	dev->type == _mc_bus_dpbp_type ||
+	dev->type == _mc_bus_dpcon_type ||
+	dev->type == _mc_bus_dpio_type)
+		return 0;
 
 	while (dev_is_fsl_mc(dma_dev))
 		dma_dev = dma_dev->parent;
 
-	return of_dma_configure(dev, dma_dev->of_node, 0);
+	fwspec = dev_iommu_fwspec_get(dma_dev);
+	if (!fwspec)
+		return -ENODEV;
+	iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode);
+	if (!iommu_ops)
+		return -ENODEV;
+
+	ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops);
+	if (ret)
+		return ret;
+
+	icid = mc_dev->icid;
+	ret = iommu_fwspec_add_ids(dev, , 1);
+	if (ret) {
+		iommu_fwspec_free(dev);
+	

Re: [PATCH] iommu: silence iommu group prints

2020-03-03 Thread Laurentiu Tudor

Hi Russell,

On 03.03.2020 17:49, Russell King - ARM Linux admin wrote:

On Tue, Mar 03, 2020 at 04:18:57PM +0200, Laurentiu Tudor wrote:



On 28.02.2020 20:32, Robin Murphy wrote:

[ +Laurentiu ]

Hi Russell,

Thanks for sharing a log, now I properly understand what's up... further
comments at the end (for context).

On 28/02/2020 10:06 am, Russell King - ARM Linux admin wrote:

On Fri, Feb 28, 2020 at 09:33:40AM +, John Garry wrote:

On 28/02/2020 02:16, Lu Baolu wrote:

Hi,

On 2020/2/27 19:57, Russell King wrote:

On the LX2160A, there are lots (about 160) of IOMMU messages produced
during boot; this is excessive.  Reduce the severity of these messages
to debug level.

Signed-off-by: Russell King 
---
    drivers/iommu/iommu.c | 4 ++--
    1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3ead597e1c57..304281ec623b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -741,7 +741,7 @@ int iommu_group_add_device(struct iommu_group
*group, struct device *dev)
    trace_add_device_to_group(group->id, dev);
-    dev_info(dev, "Adding to iommu group %d\n", group->id);
+    dev_dbg(dev, "Adding to iommu group %d\n", group->id);


I'm not strongly against this. But to me this message seems
to be a good
indicator that a device was probed successfully by the iommu subsystem.
Keeping it in the default kernel message always helps to the kernel
debugging.



I would tend to agree.


Here's the boot messages.  Notice how many of these "Adding to iommu
group" messages there are:

[    0.00] Booting Linux on physical CPU 0x00 [0x410fd083]
[    0.00] Linux version 5.5.0+ (rmk@rmk-PC) (gcc version 4.9.2
(GCC)) #655 SMP PREEMPT Fri Feb 28 09:54:47 GMT 2020
[    0.00] Machine model: SolidRun LX2160A Clearfog CX
[    0.00] earlycon: pl11 at MMIO32 0x021c (options '')
[    0.00] printk: bootconsole [pl11] enabled
[    0.00] efi: Getting EFI parameters from FDT:
[    0.00] efi: UEFI not found.
[    0.00] cma: Reserved 32 MiB at 0xf9c0
[    0.00] On node 0 totalpages: 1555968
[    0.00]   DMA zone: 4096 pages used for memmap
[    0.00]   DMA zone: 0 pages reserved
[    0.00]   DMA zone: 262144 pages, LIFO batch:63
[    0.00]   DMA32 zone: 3832 pages used for memmap
[    0.00]   DMA32 zone: 245248 pages, LIFO batch:63
[    0.00]   Normal zone: 16384 pages used for memmap
[    0.00]   Normal zone: 1048576 pages, LIFO batch:63
[    0.00] psci: probing for conduit method from DT.
[    0.00] psci: PSCIv1.1 detected in firmware.
[    0.00] psci: Using standard PSCI v0.2 function IDs
[    0.00] psci: MIGRATE_INFO_TYPE not supported.
[    0.00] psci: SMC Calling Convention v1.1
[    0.00] percpu: Embedded 31 pages/cpu s88968 r8192 d29816 u126976
[    0.00] pcpu-alloc: s88968 r8192 d29816 u126976 alloc=31*4096
[    0.00] pcpu-alloc: [0] 00 [0] 01 [0] 02 [0] 03 [0] 04 [0] 05
[0] 06 [0] 07
[    0.00] pcpu-alloc: [0] 08 [0] 09 [0] 10 [0] 11 [0] 12 [0] 13
[0] 14 [0] 15
[    0.00] Detected PIPT I-cache on CPU0
[    0.00] CPU features: detected: GIC system register CPU interface
[    0.00] CPU features: detected: EL2 vector hardening
[    0.00] Speculative Store Bypass Disable mitigation not required
[    0.00] CPU features: detected: ARM erratum 1319367
[    0.00] Built 1 zonelists, mobility grouping on.  Total
pages: 1531656
[    0.00] Kernel command line: console=ttyAMA0,115200
root=PARTUUID=c7837e2f-02 rootwait earlycon=pl011,mmio32,0x21c
ramdisk_size=0 pci=pcie_bus_perf arm_smmu.disable_bypass=0
iommu.passthrough=0
[    0.00] Dentry cache hash table entries: 1048576 (order: 11,
8388608 bytes, linear)
[    0.00] Inode-cache hash table entries: 524288 (order: 10,
4194304 bytes, linear)
[    0.00] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.00] software IO TLB: mapped [mem 0xbbfff000-0xb000] (64MB)
[    0.00] Memory: 5991500K/6223872K available (10172K kernel
code, 1376K rwdata, 3888K rodata, 960K init, 4326K bss, 199604K
reserved, 32768K cma-reserved)
[    0.00] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=16,
Nodes=1
[    0.00] rcu: Preemptible hierarchical RCU implementation.
[    0.00] rcu: RCU restricting CPUs from NR_CPUS=64 to
nr_cpu_ids=16.
[    0.00] Tasks RCU enabled.
[    0.00] rcu: RCU calculated value of scheduler-enlistment
delay is 25 jiffies.
[    0.00] rcu: Adjusting geometry for rcu_fanout_leaf=16,
nr_cpu_ids=16
[    0.00] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.00] GICv3: GIC: Using split EOI/Deactivate mode
[    0.00] GICv3: 256 SPIs implemented
[    0.00] GICv3: 0 Extended SPIs implemented
[    0.00] GICv3: Distributor has no Range Selector support
[    0.00] GICv3: 16 PPIs implemented
[    0.00] GICv3:

Re: [PATCH] iommu: silence iommu group prints

2020-03-03 Thread Laurentiu Tudor



On 28.02.2020 20:32, Robin Murphy wrote:

[ +Laurentiu ]

Hi Russell,

Thanks for sharing a log, now I properly understand what's up... further 
comments at the end (for context).


On 28/02/2020 10:06 am, Russell King - ARM Linux admin wrote:

On Fri, Feb 28, 2020 at 09:33:40AM +, John Garry wrote:

On 28/02/2020 02:16, Lu Baolu wrote:

Hi,

On 2020/2/27 19:57, Russell King wrote:

On the LX2160A, there are lots (about 160) of IOMMU messages produced
during boot; this is excessive.  Reduce the severity of these messages
to debug level.

Signed-off-by: Russell King 
---
   drivers/iommu/iommu.c | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3ead597e1c57..304281ec623b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -741,7 +741,7 @@ int iommu_group_add_device(struct iommu_group
*group, struct device *dev)
   trace_add_device_to_group(group->id, dev);
-    dev_info(dev, "Adding to iommu group %d\n", group->id);
+    dev_dbg(dev, "Adding to iommu group %d\n", group->id);


I'm not strongly against this. But to me this message seems to be a 
good

indicator that a device was probed successfully by the iommu subsystem.
Keeping it in the default kernel message always helps to the kernel
debugging.



I would tend to agree.


Here's the boot messages.  Notice how many of these "Adding to iommu
group" messages there are:

[    0.00] Booting Linux on physical CPU 0x00 [0x410fd083]
[    0.00] Linux version 5.5.0+ (rmk@rmk-PC) (gcc version 4.9.2 
(GCC)) #655 SMP PREEMPT Fri Feb 28 09:54:47 GMT 2020

[    0.00] Machine model: SolidRun LX2160A Clearfog CX
[    0.00] earlycon: pl11 at MMIO32 0x021c (options '')
[    0.00] printk: bootconsole [pl11] enabled
[    0.00] efi: Getting EFI parameters from FDT:
[    0.00] efi: UEFI not found.
[    0.00] cma: Reserved 32 MiB at 0xf9c0
[    0.00] On node 0 totalpages: 1555968
[    0.00]   DMA zone: 4096 pages used for memmap
[    0.00]   DMA zone: 0 pages reserved
[    0.00]   DMA zone: 262144 pages, LIFO batch:63
[    0.00]   DMA32 zone: 3832 pages used for memmap
[    0.00]   DMA32 zone: 245248 pages, LIFO batch:63
[    0.00]   Normal zone: 16384 pages used for memmap
[    0.00]   Normal zone: 1048576 pages, LIFO batch:63
[    0.00] psci: probing for conduit method from DT.
[    0.00] psci: PSCIv1.1 detected in firmware.
[    0.00] psci: Using standard PSCI v0.2 function IDs
[    0.00] psci: MIGRATE_INFO_TYPE not supported.
[    0.00] psci: SMC Calling Convention v1.1
[    0.00] percpu: Embedded 31 pages/cpu s88968 r8192 d29816 u126976
[    0.00] pcpu-alloc: s88968 r8192 d29816 u126976 alloc=31*4096
[    0.00] pcpu-alloc: [0] 00 [0] 01 [0] 02 [0] 03 [0] 04 [0] 05 
[0] 06 [0] 07
[    0.00] pcpu-alloc: [0] 08 [0] 09 [0] 10 [0] 11 [0] 12 [0] 13 
[0] 14 [0] 15

[    0.00] Detected PIPT I-cache on CPU0
[    0.00] CPU features: detected: GIC system register CPU interface
[    0.00] CPU features: detected: EL2 vector hardening
[    0.00] Speculative Store Bypass Disable mitigation not required
[    0.00] CPU features: detected: ARM erratum 1319367
[    0.00] Built 1 zonelists, mobility grouping on.  Total pages: 
1531656
[    0.00] Kernel command line: console=ttyAMA0,115200 
root=PARTUUID=c7837e2f-02 rootwait earlycon=pl011,mmio32,0x21c 
ramdisk_size=0 pci=pcie_bus_perf arm_smmu.disable_bypass=0 
iommu.passthrough=0
[    0.00] Dentry cache hash table entries: 1048576 (order: 11, 
8388608 bytes, linear)
[    0.00] Inode-cache hash table entries: 524288 (order: 10, 
4194304 bytes, linear)

[    0.00] mem auto-init: stack:off, heap alloc:off, heap free:off
[    0.00] software IO TLB: mapped [mem 0xbbfff000-0xb000] (64MB)
[    0.00] Memory: 5991500K/6223872K available (10172K kernel 
code, 1376K rwdata, 3888K rodata, 960K init, 4326K bss, 199604K 
reserved, 32768K cma-reserved)
[    0.00] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=16, 
Nodes=1

[    0.00] rcu: Preemptible hierarchical RCU implementation.
[    0.00] rcu: RCU restricting CPUs from NR_CPUS=64 to 
nr_cpu_ids=16.

[    0.00] Tasks RCU enabled.
[    0.00] rcu: RCU calculated value of scheduler-enlistment delay 
is 25 jiffies.
[    0.00] rcu: Adjusting geometry for rcu_fanout_leaf=16, 
nr_cpu_ids=16

[    0.00] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
[    0.00] GICv3: GIC: Using split EOI/Deactivate mode
[    0.00] GICv3: 256 SPIs implemented
[    0.00] GICv3: 0 Extended SPIs implemented
[    0.00] GICv3: Distributor has no Range Selector support
[    0.00] GICv3: 16 PPIs implemented
[    0.00] GICv3: no VLPI support, no direct LPI support
[    0.00] GICv3: CPU0: found redistributor 0 region 
0:0x0620

[    0.00] ITS [mem 0x0602-0x0603]
[ 

RE: [PATCH] iommu: silence iommu group prints

2020-03-02 Thread Laurentiu Tudor
Hi Robin,

> -Original Message-
> From: Robin Murphy 
> Sent: Friday, February 28, 2020 8:32 PM
> 
> [ +Laurentiu ]
> 
> Hi Russell,
> 
> Thanks for sharing a log, now I properly understand what's up... further
> comments at the end (for context).
> 
> On 28/02/2020 10:06 am, Russell King - ARM Linux admin wrote:
> > On Fri, Feb 28, 2020 at 09:33:40AM +, John Garry wrote:
> >> On 28/02/2020 02:16, Lu Baolu wrote:
> >>> Hi,
> >>>
> >>> On 2020/2/27 19:57, Russell King wrote:
>  On the LX2160A, there are lots (about 160) of IOMMU messages produced
>  during boot; this is excessive.  Reduce the severity of these
> messages
>  to debug level.
> 
>  Signed-off-by: Russell King 
>  ---
>     drivers/iommu/iommu.c | 4 ++--
>     1 file changed, 2 insertions(+), 2 deletions(-)
> 
>  diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>  index 3ead597e1c57..304281ec623b 100644
>  --- a/drivers/iommu/iommu.c
>  +++ b/drivers/iommu/iommu.c
>  @@ -741,7 +741,7 @@ int iommu_group_add_device(struct iommu_group
>  *group, struct device *dev)
>     trace_add_device_to_group(group->id, dev);
>  -    dev_info(dev, "Adding to iommu group %d\n", group->id);
>  +    dev_dbg(dev, "Adding to iommu group %d\n", group->id);
> >>>
> >>> I'm not strongly against this. But to me this message seems to be a
> good
> >>> indicator that a device was probed successfully by the iommu subsystem.
> >>> Keeping it in the default kernel message always helps to the kernel
> >>> debugging.
> >>>
> >>
> >> I would tend to agree.
> >

[snip]

> >
> > # dmesg |grep 'Adding to iommu' | wc -l
> > 164
> > # dmesg |grep -v 'Adding to iommu' | wc -l
> > 551
> >
> > So, 23% of the kernel messages on this platform are "Adding to iommu",
> > which is excessive.
> 
> Indeed, however I would note that on most platforms bringing up a
> network interface involves hot-adding 0 devices, so hot-adding 19
> devices as full-blown DMA masters is arguably the root of "excessive"
> already. Per the concern I initially raised, each of those messages
> represents a whole bunch of internal allocation and bookkeeping going
> on, which if it isn't necessary would be far better avoided altogether,
> than simply done more quietly.
> 
> Laurentiu, I guess at the moment the nature of the of_dma_configure()
> integration means we end up treating all DPAA2 objects identically, but
> do you think we have scope to be a bit cleverer in that regard?
> Presumably not every type of object that shows up on the fsl_mc bus is
> really an independent DMA master, so if we could skip doing the full
> DMA/IOMMU/MSI setup for the ones that don't need it, it would work out
> nicer all round. In fact your .dma_configure proposal (which I'll try to
> take a proper look at next week) couldn't have come at a better time for
> that argument :)
 
Thanks! That's a very good point - I'll check on which devices we actually use 
dma apis and filter the rest out. Will keep in mind for the next spin of the 
patches.

---
Best Regards, Laurentiu

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

[RFC PATCH 2/4] irqchip/fsl-mc: Change the way the IRQ domain is set for MC devices

2020-02-27 Thread laurentiu . tudor
From: Diana Craciun 

In ACPI the MC bus is represented as a platform device and a named
component in the IORT table. The mc-bus devices are discovered
dynamically at runtime but they share the same fwnode with the parent
platfom device. This patch changes the way the IRQ domain is searched
for the MC devices: it takes the fwnode reference from the parent and
uses the fwnode reference to find the MC IRQ domain.

Signed-off-by: Diana Craciun 
---
 drivers/bus/fsl-mc/fsl-mc-msi.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 8b9c66d7c4ff..1e2e97329781 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -182,16 +182,23 @@ int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
 {
struct irq_domain *msi_domain;
struct device_node *mc_of_node = mc_platform_dev->of_node;
+   struct fwnode_handle *fwnode;
 
-   msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
-  DOMAIN_BUS_FSL_MC_MSI);
+   msi_domain = dev_get_msi_domain(mc_platform_dev);
if (!msi_domain) {
pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
   mc_of_node);
 
return -ENOENT;
}
+   fwnode = msi_domain->fwnode;
+   msi_domain = irq_find_matching_fwnode(fwnode, DOMAIN_BUS_FSL_MC_MSI);
+   if (!msi_domain) {
+   pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
+  mc_of_node);
 
+   return -ENOENT;
+   }
*mc_msi_domain = msi_domain;
return 0;
 }
-- 
2.17.1

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


[RFC PATCH 3/4] bus: fsl-mc: Add ACPI support for fsl-mc

2020-02-27 Thread laurentiu . tudor
From: Makarand Pawagi 

ACPI support is added in the fsl-mc driver. Driver will parse
MC DSDT table to extract memory and other resorces.

Interrupt (GIC ITS) information will be extracted from MADT table
by drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c.

IORT table will be parsed to configure DMA.

Signed-off-by: Makarand Pawagi 
---
Previous attempt, here: https://patchwork.kernel.org/patch/11353735/

 drivers/bus/fsl-mc/fsl-mc-bus.c | 35 ++-
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 69 -
 2 files changed, 87 insertions(+), 17 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index eafaa0e0b906..c4742a9c0714 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -941,7 +941,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
phys_addr_t mc_portal_phys_addr;
u32 mc_portal_size;
struct mc_version mc_version;
-   struct resource res;
+   struct resource *plat_res;
 
/*
 * The MC firmware requires full access to the whole address space plus
@@ -967,16 +967,9 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
/*
 * Get physical address of MC portal for the root DPRC:
 */
-   error = of_address_to_resource(pdev->dev.of_node, 0, );
-   if (error < 0) {
-   dev_err(>dev,
-   "of_address_to_resource() failed for %pOF\n",
-   pdev->dev.of_node);
-   return error;
-   }
-
-   mc_portal_phys_addr = res.start;
-   mc_portal_size = resource_size();
+   plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   mc_portal_phys_addr = plat_res->start;
+   mc_portal_size = resource_size(plat_res);
error = fsl_create_mc_io(>dev, mc_portal_phys_addr,
 mc_portal_size, NULL,
 FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, _io);
@@ -993,11 +986,13 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
dev_info(>dev, "MC firmware version: %u.%u.%u\n",
 mc_version.major, mc_version.minor, mc_version.revision);
 
-   error = get_mc_addr_translation_ranges(>dev,
-  >translation_ranges,
-  >num_translation_ranges);
-   if (error < 0)
-   goto error_cleanup_mc_io;
+   if (dev_of_node(>dev)) {
+   error = get_mc_addr_translation_ranges(>dev,
+   >translation_ranges,
+   >num_translation_ranges);
+   if (error < 0)
+   goto error_cleanup_mc_io;
+   }
 
error = dprc_get_container_id(mc_io, 0, _id);
if (error < 0) {
@@ -1024,6 +1019,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
goto error_cleanup_mc_io;
 
mc->root_mc_bus_dev = mc_bus_dev;
+   mc_bus_dev->dev.fwnode = pdev->dev.fwnode;
return 0;
 
 error_cleanup_mc_io:
@@ -1064,11 +1060,18 @@ static const struct of_device_id 
fsl_mc_bus_match_table[] = {
 
 MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
 
+static const struct acpi_device_id fsl_mc_bus_acpi_match_table[] = {
+   {"NXP0008", 0 },
+   { }
+};
+MODULE_DEVICE_TABLE(acpi, fsl_mc_bus_acpi_match_table);
+
 static struct platform_driver fsl_mc_bus_driver = {
.driver = {
   .name = "fsl_mc_bus",
   .pm = NULL,
   .of_match_table = fsl_mc_bus_match_table,
+  .acpi_match_table = fsl_mc_bus_acpi_match_table,
   },
.probe = fsl_mc_bus_probe,
.remove = fsl_mc_bus_remove,
diff --git a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c 
b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
index 606efa64adff..6d67834722c9 100644
--- a/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
+++ b/drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c
@@ -4,9 +4,11 @@
  *
  * Copyright (C) 2015-2016 Freescale Semiconductor, Inc.
  * Author: German Rivera 
+ * Copyright 2020 NXP
  *
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -66,7 +68,65 @@ static const struct of_device_id its_device_id[] = {
{},
 };
 
-static int __init its_fsl_mc_msi_init(void)
+static int __init its_fsl_mc_msi_init_one(struct fwnode_handle *handle,
+ const char *name)
+{
+   struct irq_domain *parent;
+   struct irq_domain *mc_msi_domain;
+
+   parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
+   if (!parent || !msi_get_domain_info(parent)) {
+   pr_err("%s: Unable to locate ITS domain\n", name);
+   return -ENXIO;
+   }
+
+   mc_msi_domain = fsl_mc_msi_create_irq_domain(handle,
+
_fsl_mc_msi_domain_info,
+ 

[RFC PATCH 4/4] iommu/of: get rid of fsl-mc specific code

2020-02-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

Changing the way we configure dma for fsl-mc devices allows
us to get rid of our fsl-mc specific code in the generic
of iommu code.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/of_iommu.c | 20 
 1 file changed, 20 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 20738aacac89..332072ada474 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -15,7 +15,6 @@
 #include 
 #include 
 #include 
-#include 
 
 #define NO_IOMMU   1
 
@@ -139,23 +138,6 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 
alias, void *data)
return err;
 }
 
-static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev,
-   struct device_node *master_np)
-{
-   struct of_phandle_args iommu_spec = { .args_count = 1 };
-   int err;
-
-   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
-"iommu-map-mask", _spec.np,
-iommu_spec.args);
-   if (err)
-   return err == -ENODEV ? NO_IOMMU : err;
-
-   err = of_iommu_xlate(_dev->dev, _spec);
-   of_node_put(iommu_spec.np);
-   return err;
-}
-
 const struct iommu_ops *of_iommu_configure(struct device *dev,
   struct device_node *master_np)
 {
@@ -188,8 +170,6 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
pci_request_acs();
err = pci_for_each_dma_alias(to_pci_dev(dev),
 of_pci_iommu_init, );
-   } else if (dev_is_fsl_mc(dev)) {
-   err = of_fsl_mc_iommu_init(to_fsl_mc_device(dev), master_np);
} else {
struct of_phandle_args iommu_spec;
int idx = 0;
-- 
2.17.1

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


[RFC PATCH 1/4] bus: fsl-mc: add custom .dma_configure implementation

2020-02-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

The devices on this bus are not discovered by way of device tree
but by queries to the firmware. It makes little sense to trick the
generic of layer into thinking that these devices are of related so
that we can get our dma configuration. Instead of doing that, add
our custom dma configuration implementation.

Signed-off-by: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c | 31 ++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 36eb25f82c8e..eafaa0e0b906 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -132,11 +132,40 @@ static int fsl_mc_bus_uevent(struct device *dev, struct 
kobj_uevent_env *env)
 static int fsl_mc_dma_configure(struct device *dev)
 {
struct device *dma_dev = dev;
+   struct iommu_fwspec *fwspec;
+   const struct iommu_ops *iommu_ops;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   int ret;
+   u32 icid;
 
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
 
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   fwspec = dev_iommu_fwspec_get(dma_dev);
+   if (!fwspec)
+   return -ENODEV;
+   iommu_ops = iommu_ops_from_fwnode(fwspec->iommu_fwnode);
+   if (!iommu_ops)
+   return -ENODEV;
+
+   ret = iommu_fwspec_init(dev, fwspec->iommu_fwnode, iommu_ops);
+   if (ret)
+   return ret;
+
+   icid = mc_dev->icid;
+   ret = iommu_fwspec_add_ids(dev, , 1);
+   if (ret)
+   return ret;
+
+   if (!device_iommu_mapped(dev)) {
+   ret = iommu_probe_device(dev);
+   if (ret)
+   return ret;
+   }
+
+   arch_setup_dma_ops(dev, 0, *dma_dev->dma_mask + 1, iommu_ops, true);
+
+   return 0;
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
-- 
2.17.1

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


Re: [PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants

2019-11-14 Thread Laurentiu Tudor
On 13.11.2019 22:11, David Miller wrote:
> From: Laurentiu Tudor 
> Date: Wed, 13 Nov 2019 12:24:17 +
> 
>> From: Laurentiu Tudor 
>>
>> This series introduces a few new dma unmap and sync api variants that,
>> on top of what the originals do, return the virtual address
>> corresponding to the input dma address. In order to do that a new dma
>> map op is added, .get_virt_addr that takes the input dma address and
>> returns the virtual address backing it up.
>> The second patch adds an implementation for this new dma map op in the
>> generic iommu dma glue code and wires it in.
>> The third patch updates the dpaa2-eth driver to use the new apis.
> 
> The driver should store the mapping in it's private software state if
> it needs this kind of conversion.

On this hardware there's no way of conveying additional frame 
information, such as original va/pa behind the dma address. We have also 
pondered on the idea of keeping this in some kind of data structure but 
could not find a lock-less solution which obviously would bring 
performance to the ground.
I'll let my colleagues maintaining these ethernet drivers to get into 
more details, if required.

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


[PATCH v3 2/4] iommu/dma: wire-up new dma map op .get_virt_addr

2019-11-13 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Add an implementation of the newly introduced dma map op in the
generic DMA IOMMU generic glue layer and wire it up.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/dma-iommu.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f321279baf9e..98742c1451ce 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1091,6 +1091,18 @@ static unsigned long iommu_dma_get_merge_boundary(struct 
device *dev)
return (1UL << __ffs(domain->pgsize_bitmap)) - 1;
 }
 
+static void *iommu_dma_get_virt_addr(struct device *dev, dma_addr_t dma_handle)
+{
+   struct iommu_domain *domain = iommu_get_dma_domain(dev);
+   phys_addr_t phys;
+
+   phys = iommu_iova_to_phys(domain, dma_handle);
+   if (phys)
+   return phys_to_virt(phys);
+
+   return NULL;
+}
+
 static const struct dma_map_ops iommu_dma_ops = {
.alloc  = iommu_dma_alloc,
.free   = iommu_dma_free,
@@ -1107,6 +1119,7 @@ static const struct dma_map_ops iommu_dma_ops = {
.map_resource   = iommu_dma_map_resource,
.unmap_resource = iommu_dma_unmap_resource,
.get_merge_boundary = iommu_dma_get_merge_boundary,
+   .get_virt_addr  = iommu_dma_get_virt_addr,
 };
 
 /*
-- 
2.17.1

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


[PATCH v3 1/4] dma-mapping: introduce new dma unmap and sync api variants

2019-11-13 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Introduce a few new dma unmap and sync variants that, on top of the
original variants, return the virtual address corresponding to the
input dma address. Additionally, provide an api that can be used to
check at runtime if these variants are actually available.
In order to implement them, a new dma map op is added and used:
void *get_virt_addr(dev, dma_handle);
It does the actual conversion of an input dma address to the output
virtual address.

Signed-off-by: Laurentiu Tudor 
---
 include/linux/dma-mapping.h | 45 +++
 kernel/dma/mapping.c| 53 +
 2 files changed, 98 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4a1c4fca475a..0940bd75df8e 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -132,6 +132,7 @@ struct dma_map_ops {
u64 (*get_required_mask)(struct device *dev);
size_t (*max_mapping_size)(struct device *dev);
unsigned long (*get_merge_boundary)(struct device *dev);
+   void *(*get_virt_addr)(struct device *dev, dma_addr_t dma_handle);
 };
 
 #define DMA_MAPPING_ERROR  (~(dma_addr_t)0)
@@ -442,6 +443,13 @@ static inline int dma_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
return 0;
 }
 
+static inline bool dma_can_unmap_by_dma_addr(struct device *dev)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+
+   return dma_is_direct(ops) || (ops && ops->get_virt_addr);
+}
+
 void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag, unsigned long attrs);
 void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
@@ -458,6 +466,14 @@ int dma_get_sgtable_attrs(struct device *dev, struct 
sg_table *sgt,
 int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs);
+void *dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs);
+struct page *
+dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs);
+void *dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr,
+  size_t size, enum dma_data_direction dir);
 bool dma_can_mmap(struct device *dev);
 int dma_supported(struct device *dev, u64 mask);
 int dma_set_mask(struct device *dev, u64 mask);
@@ -534,6 +550,27 @@ static inline void dmam_free_coherent(struct device *dev, 
size_t size,
void *vaddr, dma_addr_t dma_handle)
 {
 }
+
+static inline void *
+dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+   enum dma_data_direction dir, unsigned long attrs)
+{
+   return NULL;
+}
+
+static inline struct page *
+dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+   return NULL;
+}
+
+static inline void *
+dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr, size_t size,
+enum dma_data_direction dir)
+{
+   return NULL;
+}
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction dir)
 {
@@ -578,6 +615,11 @@ static inline unsigned long dma_get_merge_boundary(struct 
device *dev)
 {
return 0;
 }
+
+static inline bool dma_can_unmap_by_dma_addr(struct device *dev)
+{
+   return false;
+}
 #endif /* CONFIG_HAS_DMA */
 
 static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
@@ -610,10 +652,13 @@ static inline void 
dma_sync_single_range_for_device(struct device *dev,
 
 #define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
 #define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
+#define dma_unmap_single_desc(d, a, s, r) \
+   dma_unmap_single_attrs_desc(d, a, s, r, 0)
 #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
 #define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
 #define dma_map_page(d, p, o, s, r) dma_map_page_attrs(d, p, o, s, r, 0)
 #define dma_unmap_page(d, a, s, r) dma_unmap_page_attrs(d, a, s, r, 0)
+#define dma_unmap_page_desc(d, a, s, r) dma_unmap_page_attrs_desc(d, a, s, r, 
0)
 #define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
 #define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
 
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index d9334f31a5af..2b6f245c9bb1 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -345,6 +345,59 @@ void dma_free_attrs(struct device *dev, size_t size, void

[PATCH v3 3/4] swiotlb: make new {unmap, sync}_desc dma apis work with swiotlb

2019-11-13 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Add a new swiotlb helper to retrieve the original physical
address given a swiotlb physical address and use it in the new
dma_unmap_single_attrs_desc(), dma_sync_single_for_cpu_desc() and
dma_unmap_page_attrs_desc() APIs to make them work with swiotlb.

Signed-off-by: Laurentiu Tudor 
---
 include/linux/swiotlb.h |  7 +++
 kernel/dma/mapping.c| 43 -
 kernel/dma/swiotlb.c|  8 
 3 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index cde3dc18e21a..7a6883a71649 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -73,6 +73,8 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
return paddr >= io_tlb_start && paddr < io_tlb_end;
 }
 
+phys_addr_t swiotlb_get_orig_phys(phys_addr_t tlb_addr);
+
 bool swiotlb_map(struct device *dev, phys_addr_t *phys, dma_addr_t *dma_addr,
size_t size, enum dma_data_direction dir, unsigned long attrs);
 void __init swiotlb_exit(void);
@@ -85,6 +87,11 @@ static inline bool is_swiotlb_buffer(phys_addr_t paddr)
 {
return false;
 }
+
+static inline phys_addr_t swiotlb_get_orig_phys(phys_addr_t tlb_addr)
+{
+   return PHYS_ADDR_MAX;
+}
 static inline bool swiotlb_map(struct device *dev, phys_addr_t *phys,
dma_addr_t *dma_addr, size_t size, enum dma_data_direction dir,
unsigned long attrs)
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index 2b6f245c9bb1..1a2d02727271 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -14,6 +14,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Managed DMA API
@@ -352,10 +353,18 @@ dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t 
addr, size_t size,
const struct dma_map_ops *ops = get_dma_ops(dev);
void *ptr = NULL;
 
-   if (dma_is_direct(ops))
-   ptr = phys_to_virt(dma_to_phys(dev, addr));
-   else if (ops && ops->get_virt_addr)
+   if (dma_is_direct(ops)) {
+   phys_addr_t phys = dma_to_phys(dev, addr);
+
+   if (is_swiotlb_buffer(phys)) {
+   phys = swiotlb_get_orig_phys(phys);
+   ptr = phys == PHYS_ADDR_MAX ? NULL : phys_to_virt(phys);
+   } else {
+   ptr = phys_to_virt(phys);
+   }
+   } else if (ops && ops->get_virt_addr) {
ptr = ops->get_virt_addr(dev, addr);
+   }
 
dma_unmap_page_attrs(dev, addr, size, dir, attrs);
 
@@ -370,10 +379,18 @@ void *dma_unmap_single_attrs_desc(struct device *dev, 
dma_addr_t addr,
const struct dma_map_ops *ops = get_dma_ops(dev);
void *ptr = NULL;
 
-   if (dma_is_direct(ops))
-   ptr = phys_to_virt(dma_to_phys(dev, addr));
-   else if (ops && ops->get_virt_addr)
+   if (dma_is_direct(ops)) {
+   phys_addr_t phys = dma_to_phys(dev, addr);
+
+   if (is_swiotlb_buffer(phys)) {
+   phys = swiotlb_get_orig_phys(phys);
+   ptr = phys == PHYS_ADDR_MAX ? NULL : phys_to_virt(phys);
+   } else {
+   ptr = phys_to_virt(phys);
+   }
+   } else if (ops && ops->get_virt_addr) {
ptr = ops->get_virt_addr(dev, addr);
+   }
 
dma_unmap_single_attrs(dev, addr, size, dir, attrs);
 
@@ -387,10 +404,18 @@ void *dma_sync_single_for_cpu_desc(struct device *dev, 
dma_addr_t addr,
const struct dma_map_ops *ops = get_dma_ops(dev);
void *ptr = NULL;
 
-   if (dma_is_direct(ops))
-   ptr = phys_to_virt(dma_to_phys(dev, addr));
-   else if (ops && ops->get_virt_addr)
+   if (dma_is_direct(ops)) {
+   phys_addr_t phys = dma_to_phys(dev, addr);
+
+   if (is_swiotlb_buffer(phys)) {
+   phys = swiotlb_get_orig_phys(phys);
+   ptr = phys == PHYS_ADDR_MAX ? NULL : phys_to_virt(phys);
+   } else {
+   ptr = phys_to_virt(phys);
+   }
+   } else if (ops && ops->get_virt_addr) {
ptr = ops->get_virt_addr(dev, addr);
+   }
 
dma_sync_single_for_cpu(dev, addr, size, dir);
 
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 673a2cdb2656..9b241cc0535b 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -701,6 +701,14 @@ bool is_swiotlb_active(void)
return io_tlb_end != 0;
 }
 
+phys_addr_t swiotlb_get_orig_phys(phys_addr_t tlb_addr)
+{
+   int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT;
+   phys_addr_t phys = io_tlb_orig_addr[index];
+
+   return phys == INVALID_PHYS_ADDR ? PHYS_ADDR_MAX : phys;
+}
+
 #ifdef CONFIG_DEBUG_FS
 
 static int __init swiotlb_create_debugfs(void)
-- 
2.17.1

__

[PATCH v3 4/4] dpaa2_eth: use new unmap and sync dma api variants

2019-11-13 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Convert this driver to usage of the newly introduced dma unmap and
sync DMA APIs. This will get rid of the unsupported direct usage of
iommu_iova_to_phys() API.

Signed-off-by: Laurentiu Tudor 
---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 43 ---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 2 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 19379bae0144..6b941b753106 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -29,16 +29,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
 
-static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
-   dma_addr_t iova_addr)
-{
-   phys_addr_t phys_addr;
-
-   phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
-
-   return phys_to_virt(phys_addr);
-}
-
 static void validate_rx_csum(struct dpaa2_eth_priv *priv,
 u32 fd_status,
 struct sk_buff *skb)
@@ -85,9 +75,9 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
sgt = vaddr + dpaa2_fd_get_offset(fd);
for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
addr = dpaa2_sg_get_addr([i]);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-   dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   sg_vaddr = dma_unmap_single_desc(dev, addr,
+DPAA2_ETH_RX_BUF_SIZE,
+DMA_BIDIRECTIONAL);
 
free_pages((unsigned long)sg_vaddr, 0);
if (dpaa2_sg_is_final([i]))
@@ -143,9 +133,9 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv 
*priv,
 
/* Get the address and length from the S/G entry */
sg_addr = dpaa2_sg_get_addr(sge);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
-   dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   sg_vaddr = dma_unmap_single_desc(dev, sg_addr,
+DPAA2_ETH_RX_BUF_SIZE,
+DMA_BIDIRECTIONAL);
 
sg_length = dpaa2_sg_get_len(sge);
 
@@ -210,9 +200,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 
*buf_array, int count)
int i;
 
for (i = 0; i < count; i++) {
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
-   dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   vaddr = dma_unmap_single_desc(dev, buf_array[i],
+ DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL);
free_pages((unsigned long)vaddr, 0);
}
 }
@@ -369,9 +359,8 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
/* Tracing point */
trace_dpaa2_rx_fd(priv->net_dev, fd);
 
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-   dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-   DMA_BIDIRECTIONAL);
+   vaddr = dma_sync_single_for_cpu_desc(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+DMA_BIDIRECTIONAL);
 
fas = dpaa2_get_fas(vaddr, false);
prefetch(fas);
@@ -682,7 +671,8 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
u32 fd_len = dpaa2_fd_get_len(fd);
 
fd_addr = dpaa2_fd_get_addr(fd);
-   buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+   buffer_start = dma_sync_single_for_cpu_desc(dev, fd_addr, sizeof(*swa),
+   DMA_BIDIRECTIONAL);
swa = (struct dpaa2_eth_swa *)buffer_start;
 
if (fd_format == dpaa2_fd_single) {
@@ -3435,6 +3425,11 @@ static int dpaa2_eth_probe(struct fsl_mc_device 
*dpni_dev)
 
dev = _dev->dev;
 
+   if (!dma_can_unmap_by_dma_addr(dev)) {
+   dev_err(dev, "required dma unmap/sync APIs not available\n");
+   return -ENOTSUPP;
+   }
+
/* Net device */
net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA2_ETH_MAX_NETDEV_QUEUES);
if (!net_dev) {
@@ -3448,8 +3443,6 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
priv = netdev_priv(net_dev);
priv->net_dev = net_dev;
 
-   priv->iommu_domain = iommu_get_domain_for_dev(dev);
-
 

[PATCH v3 0/4] dma-mapping: introduce new dma unmap and sync variants

2019-11-13 Thread Laurentiu Tudor
From: Laurentiu Tudor 

This series introduces a few new dma unmap and sync api variants that,
on top of what the originals do, return the virtual address
corresponding to the input dma address. In order to do that a new dma
map op is added, .get_virt_addr that takes the input dma address and
returns the virtual address backing it up.
The second patch adds an implementation for this new dma map op in the
generic iommu dma glue code and wires it in.
The third patch updates the dpaa2-eth driver to use the new apis.

Context: https://lkml.org/lkml/2019/5/31/684

Changes in v3
 * drop useless check for null iommu domain (Robin)
 * add dma_can_unmap_by_dma_addr() to check availability of
   these new apis (Christoph)
 * make apis work with direct dma (Christoph)
 * add support for swiotlb (Robin)
 * simplify dpaa2_eth driver code by using dma_unmap_single_desc()
   instead of dma_unmap_page_desc()

Changes in v2
 * use "dma_unmap_*_desc" names (Robin)
 * return va/page instead of phys addr (Robin)

Changes since RFC
 * completely changed the approach: added unmap and sync variants that
   return the phys addr instead of adding a new dma to phys conversion
   function

Laurentiu Tudor (4):
  dma-mapping: introduce new dma unmap and sync api variants
  iommu/dma: wire-up new dma map op .get_virt_addr
  swiotlb: make new {unmap,sync}_desc dma apis work with swiotlb
  dpaa2_eth: use new unmap and sync dma api variants

 drivers/iommu/dma-iommu.c | 13 
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 43 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 include/linux/dma-mapping.h   | 45 +++
 include/linux/swiotlb.h   |  7 ++
 kernel/dma/mapping.c  | 78 +++
 kernel/dma/swiotlb.c  |  8 ++
 7 files changed, 169 insertions(+), 26 deletions(-)

-- 
2.17.1

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


Re: [PATCH v2 1/3] dma-mapping: introduce new dma unmap and sync api variants

2019-11-07 Thread Laurentiu Tudor
Hi Robin,

On 28.10.2019 15:42, Robin Murphy wrote:
> On 24/10/2019 13:41, Laurentiu Tudor wrote:
>> From: Laurentiu Tudor 
>>
>> Introduce a few new dma unmap and sync variants that, on top of the
>> original variants, return the virtual address corresponding to the
>> input dma address.
>> In order to implement this a new dma map op is added and used:
>>  void *get_virt_addr(dev, dma_handle);
>> It does the actual conversion of an input dma address to the output
>> virtual address.
> 
> At this point, I think it might be better to just change the prototype 
> of the .unmap_page/.sync_single_for_cpu callbacks themselves. In cases 
> where .get_virt_addr would be non-trivial, it's most likely duplicating 
> work that the relevant callback has to do anyway (i.e. where the virtual 
> and/or physical address is needed internally for a cache maintenance or 
> bounce buffer operation). 

Looking in the generic dma-iommu, I didn't see any mean of freely 
getting the pa or va bqcking the iova so I can't think of a way of doing 
this without adding a call to iommu_iova_to_phys() somewhere in the 
unmap op implementation. Obviously, this would come with an overhead 
that will probably upset people.
At the moment I can't think at an option other than the initial one, 
that is adding the .get_virt_addr op. Please let me know your opinions 
on this.

---
Thanks & Best Regards, Laurentiu

> It would also help avoid any possible 
> ambiguity about whether .get_virt_addr returns the VA corresponding 
> dma_handle (if one exists) rather than the VA of the buffer *mapped to* 
> dma_handle, which for a bounce-buffering implementation would be 
> different, and the one you actually need - a naive 
> phys_to_virt(dma_to_phys(dma_handle)) would lead you to the wrong place 
> (in fact it looks like DPAA2 would currently go wrong with 
> "swiotlb=force" and the SMMU disabled or in passthrough).
> 
> One question there is whether we'd want careful special-casing to avoid 
> introducing overhead where unmap/sync are currently complete no-ops, or 
> whether an extra phys_to_virt() or so in those paths would be tolerable.
> 
>> Signed-off-by: Laurentiu Tudor 
>> ---
>>   include/linux/dma-mapping.h | 55 +
>>   1 file changed, 55 insertions(+)
>>
>> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
>> index 4a1c4fca475a..ae7bb8a84b9d 100644
>> --- a/include/linux/dma-mapping.h
>> +++ b/include/linux/dma-mapping.h
>> @@ -132,6 +132,7 @@ struct dma_map_ops {
>>   u64 (*get_required_mask)(struct device *dev);
>>   size_t (*max_mapping_size)(struct device *dev);
>>   unsigned long (*get_merge_boundary)(struct device *dev);
>> +    void *(*get_virt_addr)(struct device *dev, dma_addr_t dma_handle);
>>   };
>>   #define DMA_MAPPING_ERROR    (~(dma_addr_t)0)
>> @@ -304,6 +305,21 @@ static inline void dma_unmap_page_attrs(struct 
>> device *dev, dma_addr_t addr,
>>   debug_dma_unmap_page(dev, addr, size, dir);
>>   }
>> +static inline struct page *
>> +dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t 
>> size,
>> +  enum dma_data_direction dir, unsigned long attrs)
>> +{
>> +    const struct dma_map_ops *ops = get_dma_ops(dev);
>> +    void *ptr = NULL;
>> +
>> +    if (ops && ops->get_virt_addr)
>> +    ptr = ops->get_virt_addr(dev, addr);
> 
> Note that this doesn't work for dma-direct, but for the sake of arm64 at 
> least it almost certainly wants to.
> 
> Robin.
> 
>> +    dma_unmap_page_attrs(dev, addr, size, dir, attrs);
>> +
>> +    return ptr ? virt_to_page(ptr) : NULL;
>> +}
>> +
>>   /*
>>    * dma_maps_sg_attrs returns 0 on error and > 0 on success.
>>    * It should never return a value < 0.
>> @@ -390,6 +406,21 @@ static inline void dma_sync_single_for_cpu(struct 
>> device *dev, dma_addr_t addr,
>>   debug_dma_sync_single_for_cpu(dev, addr, size, dir);
>>   }
>> +static inline void *
>> +dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr, 
>> size_t size,
>> + enum dma_data_direction dir)
>> +{
>> +    const struct dma_map_ops *ops = get_dma_ops(dev);
>> +    void *ptr = NULL;
>> +
>> +    if (ops && ops->get_virt_addr)
>> +    ptr = ops->get_virt_addr(dev, addr);
>> +
>> +    dma_sync_single_for_cpu(dev, addr, size, dir);
>> +
>> +    return ptr;
>> +}
>> +
>>   static inline void dma_sync_single_for_device(struct device *dev,
>> 

Re: [PATCH v2 1/3] dma-mapping: introduce new dma unmap and sync api variants

2019-11-06 Thread Laurentiu Tudor

On 28.10.2019 15:42, Robin Murphy wrote:
> On 24/10/2019 13:41, Laurentiu Tudor wrote:
>> From: Laurentiu Tudor 
>>
>> Introduce a few new dma unmap and sync variants that, on top of the
>> original variants, return the virtual address corresponding to the
>> input dma address.
>> In order to implement this a new dma map op is added and used:
>>  void *get_virt_addr(dev, dma_handle);
>> It does the actual conversion of an input dma address to the output
>> virtual address.
> 
> At this point, I think it might be better to just change the prototype 
> of the .unmap_page/.sync_single_for_cpu callbacks themselves. 

I could give this a try. At a first sight, looks like it will be quite 
an intrusive change.

> In cases 
> where .get_virt_addr would be non-trivial, it's most likely duplicating 
> work that the relevant callback has to do anyway (i.e. where the virtual 
> and/or physical address is needed internally for a cache maintenance or 
> bounce buffer operation). It would also help avoid any possible 
> ambiguity about whether .get_virt_addr returns the VA corresponding 
> dma_handle (if one exists) rather than the VA of the buffer *mapped to* 
> dma_handle, which for a bounce-buffering implementation would be 
> different, and the one you actually need - a naive 
> phys_to_virt(dma_to_phys(dma_handle)) would lead you to the wrong place 


> (in fact it looks like DPAA2 would currently go wrong with 
> "swiotlb=force" and the SMMU disabled or in passthrough).

Yes, most likely.

> One question there is whether we'd want careful special-casing to avoid 
> introducing overhead where unmap/sync are currently complete no-ops, or 
> whether an extra phys_to_virt() or so in those paths would be tolerable.
> 
>> Signed-off-by: Laurentiu Tudor 
>> ---
>>   include/linux/dma-mapping.h | 55 +
>>   1 file changed, 55 insertions(+)
>>
>> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
>> index 4a1c4fca475a..ae7bb8a84b9d 100644
>> --- a/include/linux/dma-mapping.h
>> +++ b/include/linux/dma-mapping.h
>> @@ -132,6 +132,7 @@ struct dma_map_ops {
>>   u64 (*get_required_mask)(struct device *dev);
>>   size_t (*max_mapping_size)(struct device *dev);
>>   unsigned long (*get_merge_boundary)(struct device *dev);
>> +    void *(*get_virt_addr)(struct device *dev, dma_addr_t dma_handle);
>>   };
>>   #define DMA_MAPPING_ERROR    (~(dma_addr_t)0)
>> @@ -304,6 +305,21 @@ static inline void dma_unmap_page_attrs(struct 
>> device *dev, dma_addr_t addr,
>>   debug_dma_unmap_page(dev, addr, size, dir);
>>   }
>> +static inline struct page *
>> +dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t 
>> size,
>> +  enum dma_data_direction dir, unsigned long attrs)
>> +{
>> +    const struct dma_map_ops *ops = get_dma_ops(dev);
>> +    void *ptr = NULL;
>> +
>> +    if (ops && ops->get_virt_addr)
>> +    ptr = ops->get_virt_addr(dev, addr);
> 
> Note that this doesn't work for dma-direct, but for the sake of arm64 at 
> least it almost certainly wants to.
> 

Will take care of it.

---
Best Regards, Laurentiu

> 
>> +    dma_unmap_page_attrs(dev, addr, size, dir, attrs);
>> +
>> +    return ptr ? virt_to_page(ptr) : NULL;
>> +}
>> +
>>   /*
>>    * dma_maps_sg_attrs returns 0 on error and > 0 on success.
>>    * It should never return a value < 0.
>> @@ -390,6 +406,21 @@ static inline void dma_sync_single_for_cpu(struct 
>> device *dev, dma_addr_t addr,
>>   debug_dma_sync_single_for_cpu(dev, addr, size, dir);
>>   }
>> +static inline void *
>> +dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr, 
>> size_t size,
>> + enum dma_data_direction dir)
>> +{
>> +    const struct dma_map_ops *ops = get_dma_ops(dev);
>> +    void *ptr = NULL;
>> +
>> +    if (ops && ops->get_virt_addr)
>> +    ptr = ops->get_virt_addr(dev, addr);
>> +
>> +    dma_sync_single_for_cpu(dev, addr, size, dir);
>> +
>> +    return ptr;
>> +}
>> +
>>   static inline void dma_sync_single_for_device(struct device *dev,
>>     dma_addr_t addr, size_t size,
>>     enum dma_data_direction dir)
>> @@ -500,6 +531,12 @@ static inline void dma_sync_single_for_cpu(struct 
>> device *dev, dma_addr_t addr,
>>   size_t size, enum dma_data_direction dir)
>>   {
>>   }
>> +
>> +static inline void *
>

Re: [PATCH v2 3/3] dpaa2_eth: use new unmap and sync dma api variants

2019-11-06 Thread Laurentiu Tudor

On 28.10.2019 13:38, h...@lst.de wrote:
> On Mon, Oct 28, 2019 at 10:55:05AM +0000, Laurentiu Tudor wrote:
>>>> @@ -85,9 +75,10 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
>>>>   sgt = vaddr + dpaa2_fd_get_offset(fd);
>>>>   for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
>>>>   addr = dpaa2_sg_get_addr([i]);
>>>> -    sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
>>>> -    dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
>>>> -   DMA_BIDIRECTIONAL);
>>>> +    sg_vaddr = page_to_virt
>>>> +    (dma_unmap_page_desc(dev, addr,
>>>> +    DPAA2_ETH_RX_BUF_SIZE,
>>>> +    DMA_BIDIRECTIONAL));
>>>
>>> This is doing virt -> page -> virt.  Why not just have the new
>>> function return the VA corresponding to the addr, which would
>>> match the other functions?
>>
>> I'd really like that as it would get rid of the page_to_virt() calls but
>> it will break the symmetry with the dma_map_page() API. I'll let the
>> maintainers decide.
> 
> It would be symmetric with dma_map_single, though.  Maybe we need
> both variants?

Patch 1/3 also adds an dma_unmap_single_desc(). Would it be legal to 
just use dma_unmap_single_desc() in the driver even if the driver does 
it's mappings with dma_map_page()?

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

RE: [PATCH v2 1/3] dma-mapping: introduce new dma unmap and sync api variants

2019-10-29 Thread Laurentiu Tudor



> -Original Message-
> From: h...@lst.de 
> Sent: Monday, October 28, 2019 2:38 PM
> 
> On Thu, Oct 24, 2019 at 12:41:41PM +0000, Laurentiu Tudor wrote:
> > From: Laurentiu Tudor 
> >
> > Introduce a few new dma unmap and sync variants that, on top of the
> > original variants, return the virtual address corresponding to the
> > input dma address.
> > In order to implement this a new dma map op is added and used:
> > void *get_virt_addr(dev, dma_handle);
> > It does the actual conversion of an input dma address to the output
> > virtual address.
> 
> We'll definitively need an implementation for dma-direct at least as
> well.  Also as said previously we need a dma_can_unmap_by_dma_addr()
> or similar helper that tells the driver beforehand if this works, so
> that the driver can either use a sub-optimal workaround or fail the
> probe if this functionality isn't implemented.

Alright. On top of that I need to make this work on booke ppc as we have one 
driver that runs both on arm and ppc and will use these APIs.

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


Re: [PATCH v2 3/3] dpaa2_eth: use new unmap and sync dma api variants

2019-10-28 Thread Laurentiu Tudor
Hi Jonathan,

On 25.10.2019 19:12, Jonathan Lemon wrote:
> 
> 
> On 24 Oct 2019, at 5:41, Laurentiu Tudor wrote:
> 
>> From: Laurentiu Tudor 
>>
>> Convert this driver to usage of the newly introduced dma unmap and
>> sync DMA APIs. This will get rid of the unsupported direct usage of
>> iommu_iova_to_phys() API.
>>
>> Signed-off-by: Laurentiu Tudor 
>> ---
>>  .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 40 +++
>>  .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
>>  2 files changed, 15 insertions(+), 26 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 
>> b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
>> index 19379bae0144..8c3391e6e598 100644
>> --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
>> +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
>> @@ -29,16 +29,6 @@ MODULE_LICENSE("Dual BSD/GPL");
>>  MODULE_AUTHOR("Freescale Semiconductor, Inc");
>>  MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
>>
>> -static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
>> -    dma_addr_t iova_addr)
>> -{
>> -    phys_addr_t phys_addr;
>> -
>> -    phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : 
>> iova_addr;
>> -
>> -    return phys_to_virt(phys_addr);
>> -}
>> -
>>  static void validate_rx_csum(struct dpaa2_eth_priv *priv,
>>   u32 fd_status,
>>   struct sk_buff *skb)
>> @@ -85,9 +75,10 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
>>  sgt = vaddr + dpaa2_fd_get_offset(fd);
>>  for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
>>  addr = dpaa2_sg_get_addr([i]);
>> -    sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
>> -    dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
>> -   DMA_BIDIRECTIONAL);
>> +    sg_vaddr = page_to_virt
>> +    (dma_unmap_page_desc(dev, addr,
>> +    DPAA2_ETH_RX_BUF_SIZE,
>> +    DMA_BIDIRECTIONAL));
> 
> This is doing virt -> page -> virt.  Why not just have the new
> function return the VA corresponding to the addr, which would
> match the other functions?

I'd really like that as it would get rid of the page_to_virt() calls but 
it will break the symmetry with the dma_map_page() API. I'll let the 
maintainers decide.

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

[PATCH v2 3/3] dpaa2_eth: use new unmap and sync dma api variants

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Convert this driver to usage of the newly introduced dma unmap and
sync DMA APIs. This will get rid of the unsupported direct usage of
iommu_iova_to_phys() API.

Signed-off-by: Laurentiu Tudor 
---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 40 +++
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 2 files changed, 15 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 19379bae0144..8c3391e6e598 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -29,16 +29,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
 
-static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
-   dma_addr_t iova_addr)
-{
-   phys_addr_t phys_addr;
-
-   phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
-
-   return phys_to_virt(phys_addr);
-}
-
 static void validate_rx_csum(struct dpaa2_eth_priv *priv,
 u32 fd_status,
 struct sk_buff *skb)
@@ -85,9 +75,10 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
sgt = vaddr + dpaa2_fd_get_offset(fd);
for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
addr = dpaa2_sg_get_addr([i]);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-   dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   sg_vaddr = page_to_virt
+   (dma_unmap_page_desc(dev, addr,
+   DPAA2_ETH_RX_BUF_SIZE,
+   DMA_BIDIRECTIONAL));
 
free_pages((unsigned long)sg_vaddr, 0);
if (dpaa2_sg_is_final([i]))
@@ -143,9 +134,10 @@ static struct sk_buff *build_frag_skb(struct 
dpaa2_eth_priv *priv,
 
/* Get the address and length from the S/G entry */
sg_addr = dpaa2_sg_get_addr(sge);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
-   dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   sg_vaddr = page_to_virt
+   (dma_unmap_page_desc(dev, sg_addr,
+   DPAA2_ETH_RX_BUF_SIZE,
+   DMA_BIDIRECTIONAL));
 
sg_length = dpaa2_sg_get_len(sge);
 
@@ -210,9 +202,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 
*buf_array, int count)
int i;
 
for (i = 0; i < count; i++) {
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
-   dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   vaddr = page_to_virt(dma_unmap_page_desc(dev, buf_array[i],
+DPAA2_ETH_RX_BUF_SIZE,
+DMA_BIDIRECTIONAL));
free_pages((unsigned long)vaddr, 0);
}
 }
@@ -369,9 +361,8 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
/* Tracing point */
trace_dpaa2_rx_fd(priv->net_dev, fd);
 
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-   dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-   DMA_BIDIRECTIONAL);
+   vaddr = dma_sync_single_for_cpu_desc(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+DMA_BIDIRECTIONAL);
 
fas = dpaa2_get_fas(vaddr, false);
prefetch(fas);
@@ -682,7 +673,8 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
u32 fd_len = dpaa2_fd_get_len(fd);
 
fd_addr = dpaa2_fd_get_addr(fd);
-   buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+   buffer_start = dma_sync_single_for_cpu_desc(dev, fd_addr, sizeof(*swa),
+   DMA_BIDIRECTIONAL);
swa = (struct dpaa2_eth_swa *)buffer_start;
 
if (fd_format == dpaa2_fd_single) {
@@ -3448,8 +3440,6 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
priv = netdev_priv(net_dev);
priv->net_dev = net_dev;
 
-   priv->iommu_domain = iommu_get_domain_for_dev(dev);
-
/* Obtain a MC portal */
err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
 >mc_io);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
index 8a0e65b3267f..4e518

[PATCH v2 2/3] iommu/dma: wire-up new dma map op .get_virt_addr

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Add an implementation of the newly introduced dma map op in the
generic DMA IOMMU generic glue layer and wire it up.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/dma-iommu.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f321279baf9e..15e76232d697 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1091,6 +1091,21 @@ static unsigned long iommu_dma_get_merge_boundary(struct 
device *dev)
return (1UL << __ffs(domain->pgsize_bitmap)) - 1;
 }
 
+static void *iommu_dma_get_virt_addr(struct device *dev, dma_addr_t dma_handle)
+{
+   struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+
+   if (domain) {
+   phys_addr_t phys;
+
+   phys = iommu_iova_to_phys(domain, dma_handle);
+   if (phys)
+   return phys_to_virt(phys);
+   }
+
+   return NULL;
+}
+
 static const struct dma_map_ops iommu_dma_ops = {
.alloc  = iommu_dma_alloc,
.free   = iommu_dma_free,
@@ -1107,6 +1122,7 @@ static const struct dma_map_ops iommu_dma_ops = {
.map_resource   = iommu_dma_map_resource,
.unmap_resource = iommu_dma_unmap_resource,
.get_merge_boundary = iommu_dma_get_merge_boundary,
+   .get_virt_addr  = iommu_dma_get_virt_addr,
 };
 
 /*
-- 
2.17.1

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


[PATCH v2 1/3] dma-mapping: introduce new dma unmap and sync api variants

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Introduce a few new dma unmap and sync variants that, on top of the
original variants, return the virtual address corresponding to the
input dma address.
In order to implement this a new dma map op is added and used:
void *get_virt_addr(dev, dma_handle);
It does the actual conversion of an input dma address to the output
virtual address.

Signed-off-by: Laurentiu Tudor 
---
 include/linux/dma-mapping.h | 55 +
 1 file changed, 55 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4a1c4fca475a..ae7bb8a84b9d 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -132,6 +132,7 @@ struct dma_map_ops {
u64 (*get_required_mask)(struct device *dev);
size_t (*max_mapping_size)(struct device *dev);
unsigned long (*get_merge_boundary)(struct device *dev);
+   void *(*get_virt_addr)(struct device *dev, dma_addr_t dma_handle);
 };
 
 #define DMA_MAPPING_ERROR  (~(dma_addr_t)0)
@@ -304,6 +305,21 @@ static inline void dma_unmap_page_attrs(struct device 
*dev, dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir);
 }
 
+static inline struct page *
+dma_unmap_page_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+   void *ptr = NULL;
+
+   if (ops && ops->get_virt_addr)
+   ptr = ops->get_virt_addr(dev, addr);
+
+   dma_unmap_page_attrs(dev, addr, size, dir, attrs);
+
+   return ptr ? virt_to_page(ptr) : NULL;
+}
+
 /*
  * dma_maps_sg_attrs returns 0 on error and > 0 on success.
  * It should never return a value < 0.
@@ -390,6 +406,21 @@ static inline void dma_sync_single_for_cpu(struct device 
*dev, dma_addr_t addr,
debug_dma_sync_single_for_cpu(dev, addr, size, dir);
 }
 
+static inline void *
+dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr, size_t size,
+enum dma_data_direction dir)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+   void *ptr = NULL;
+
+   if (ops && ops->get_virt_addr)
+   ptr = ops->get_virt_addr(dev, addr);
+
+   dma_sync_single_for_cpu(dev, addr, size, dir);
+
+   return ptr;
+}
+
 static inline void dma_sync_single_for_device(struct device *dev,
  dma_addr_t addr, size_t size,
  enum dma_data_direction dir)
@@ -500,6 +531,12 @@ static inline void dma_sync_single_for_cpu(struct device 
*dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir)
 {
 }
+
+static inline void *
+dma_sync_single_for_cpu_desc(struct device *dev, dma_addr_t addr, size_t size,
+enum dma_data_direction dir)
+{
+}
 static inline void dma_sync_single_for_device(struct device *dev,
dma_addr_t addr, size_t size, enum dma_data_direction dir)
 {
@@ -594,6 +631,21 @@ static inline void dma_unmap_single_attrs(struct device 
*dev, dma_addr_t addr,
return dma_unmap_page_attrs(dev, addr, size, dir, attrs);
 }
 
+static inline void *
+dma_unmap_single_attrs_desc(struct device *dev, dma_addr_t addr, size_t size,
+   enum dma_data_direction dir, unsigned long attrs)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+   void *ptr = NULL;
+
+   if (ops && ops->get_virt_addr)
+   ptr = ops->get_virt_addr(dev, addr);
+
+   dma_unmap_single_attrs(dev, addr, size, dir, attrs);
+
+   return ptr;
+}
+
 static inline void dma_sync_single_range_for_cpu(struct device *dev,
dma_addr_t addr, unsigned long offset, size_t size,
enum dma_data_direction dir)
@@ -610,10 +662,13 @@ static inline void 
dma_sync_single_range_for_device(struct device *dev,
 
 #define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
 #define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
+#define dma_unmap_single_desc(d, a, s, r) \
+   dma_unmap_single_attrs_desc(d, a, s, r, 0)
 #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
 #define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
 #define dma_map_page(d, p, o, s, r) dma_map_page_attrs(d, p, o, s, r, 0)
 #define dma_unmap_page(d, a, s, r) dma_unmap_page_attrs(d, a, s, r, 0)
+#define dma_unmap_page_desc(d, a, s, r) dma_unmap_page_attrs_desc(d, a, s, r, 
0)
 #define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
 #define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
 
-- 
2.17.1

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


[PATCH v2 0/3] dma-mapping: introduce new dma unmap and sync variants

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

This series introduces a few new dma unmap and sync api variants that,
on top of what the originals do, return the virtual address
corresponding to the input dma address. In order to do that a new dma
map op is added, .get_virt_addr that takes the input dma address and
returns the virtual address backing it up.
The second patch adds an implementation for this new dma map op in the
generic iommu dma glue code and wires it in.
The third patch updates the dpaa2-eth driver to use the new apis.

Context: https://lkml.org/lkml/2019/5/31/684

Changes in v2
 * use "dma_unmap_*_desc" names (Robin)
 * return va/page instead of phys addr (Robin)

Changes since RFC
 * completely changed the approach: added unmap and sync variants that
   return the phys addr instead of adding a new dma to phys conversion
   function

Laurentiu Tudor (3):
  dma-mapping: introduce new dma unmap and sync api variants
  iommu/dma: wire-up new dma map op .get_virt_addr
  dpaa2_eth: use new unmap and sync dma api variants

 drivers/iommu/dma-iommu.c | 16 ++
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 40 +-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 include/linux/dma-mapping.h   | 55 +++
 4 files changed, 86 insertions(+), 26 deletions(-)

-- 
2.17.1

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


Re: [RFC PATCH 1/3] dma-mapping: introduce a new dma api dma_addr_to_phys_addr()

2019-10-24 Thread Laurentiu Tudor
On 24.10.2019 14:04, Robin Murphy wrote:
> On 2019-10-24 8:49 am, Laurentiu Tudor wrote:
>>
>>
>> On 24.10.2019 05:01, h...@lst.de wrote:
>>> On Wed, Oct 23, 2019 at 11:53:41AM +, Laurentiu Tudor wrote:
>>>> We had an internal discussion over these points you are raising and
>>>> Madalin (cc-ed) came up with another idea: instead of adding this prone
>>>> to misuse api how about experimenting with a new dma unmap and dma sync
>>>> variants that would return the physical address by calling the newly
>>>> introduced dma map op. Something along these lines:
>>>>     * phys_addr_t dma_unmap_page_ret_phys(...)
>>>>     * phys_addr_t dma_unmap_single_ret_phys(...)
>>>>     * phys_addr_t dma_sync_single_for_cpu_ret_phys(...)
>>>> I'm thinking that this proposal should reduce the risks opened by the
>>>> initial variant.
>>>> Please let me know what you think.
>>>
>>> I'm not sure what the ret is supposed to mean, but I generally like
>>> that idea better.
>>
>> It was supposed to be short for "return" but given that I'm not good at
>> naming stuff I'll just drop it.
> 
> Hmm, how about something like "dma_unmap_*_desc" for the context of the 
> mapped DMA address also being used as a descriptor token?

Alright.

>>> We also need to make sure there is an easy way
>>> to figure out if these APIs are available, as they generally aren't
>>> for any non-IOMMU API IOMMU drivers.
>>
>> I was really hoping to manage making them as generic as possible but
>> anyway, I'll start working on a PoC and see how it turns out. This will
>> probably happen sometime next next week as the following week I'll be
>> traveling to a conference.
> 
> AFAICS, even a full implementation of these APIs would have to be 
> capable of returning an indication that there is no valid physical 
> address - e.g. if unmap is called with a bogus DMA address that was 
> never mapped. At that point there'sseemingly no problem just 
> implementing the trivial case on top of any existing unmap/sync 
> callbacks for everyone. I'd imagine that drivers which want this aren't 
> likely to run on the older architectures where the weird IOMMUs live, so 
> they could probably just always treat failure as unexpected and fatal 
> either way.
> 
> In fact, I'm now wondering whether it's likely to be common that users 
> want the physical address specifically, or whether it would make sense 
> to return the original VA/page, both for symmetry with the corresponding 
> map calls and for the ease of being able to return NULL when necessary.

That's sounds wonderful as it should make the code leaner in the drivers.

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

[PATCH 1/3] dma-mapping: introduce new dma unmap and sync api variants

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Introduce a few new dma unmap and sync variants that, on top of the
original variants, return the physical address corresponding to the
input dma address.
In order to implement this a new dma map op is added and used:
phys_addr_t get_phys_addr(dev, dma_handle);
It does the actual conversion of an input dma address to the output
physical address.

Signed-off-by: Laurentiu Tudor 
---
 include/linux/dma-mapping.h | 55 +
 1 file changed, 55 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4a1c4fca475a..d2bccb814eac 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -132,6 +132,7 @@ struct dma_map_ops {
u64 (*get_required_mask)(struct device *dev);
size_t (*max_mapping_size)(struct device *dev);
unsigned long (*get_merge_boundary)(struct device *dev);
+   phys_addr_t (*get_phys_addr)(struct device *dev, dma_addr_t dma_handle);
 };
 
 #define DMA_MAPPING_ERROR  (~(dma_addr_t)0)
@@ -304,6 +305,21 @@ static inline void dma_unmap_page_attrs(struct device 
*dev, dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir);
 }
 
+static inline phys_addr_t
+dma_unmap_page_phys_attrs(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, unsigned long attrs)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+   phys_addr_t phys = 0;
+
+   if (ops && ops->get_phys_addr)
+   phys = ops->get_phys_addr(dev, addr);
+
+   dma_unmap_page_attrs(dev, addr, size, dir, attrs);
+
+   return phys;
+}
+
 /*
  * dma_maps_sg_attrs returns 0 on error and > 0 on success.
  * It should never return a value < 0.
@@ -390,6 +406,21 @@ static inline void dma_sync_single_for_cpu(struct device 
*dev, dma_addr_t addr,
debug_dma_sync_single_for_cpu(dev, addr, size, dir);
 }
 
+static inline phys_addr_t
+dma_sync_single_for_cpu_phys(struct device *dev, dma_addr_t addr, size_t size,
+enum dma_data_direction dir)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+   phys_addr_t phys = 0;
+
+   if (ops && ops->get_phys_addr)
+   phys = ops->get_phys_addr(dev, addr);
+
+   dma_sync_single_for_cpu(dev, addr, size, dir);
+
+   return phys;
+}
+
 static inline void dma_sync_single_for_device(struct device *dev,
  dma_addr_t addr, size_t size,
  enum dma_data_direction dir)
@@ -500,6 +531,12 @@ static inline void dma_sync_single_for_cpu(struct device 
*dev, dma_addr_t addr,
size_t size, enum dma_data_direction dir)
 {
 }
+
+static inline phys_addr_t
+dma_sync_single_for_cpu_phys(struct device *dev, dma_addr_t addr, size_t size,
+enum dma_data_direction dir)
+{
+}
 static inline void dma_sync_single_for_device(struct device *dev,
dma_addr_t addr, size_t size, enum dma_data_direction dir)
 {
@@ -594,6 +631,21 @@ static inline void dma_unmap_single_attrs(struct device 
*dev, dma_addr_t addr,
return dma_unmap_page_attrs(dev, addr, size, dir, attrs);
 }
 
+static inline phys_addr_t
+dma_unmap_single_phys_attrs(struct device *dev, dma_addr_t addr, size_t size,
+   enum dma_data_direction dir, unsigned long attrs)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+   phys_addr_t phys = 0;
+
+   if (ops && ops->get_phys_addr)
+   phys = ops->get_phys_addr(dev, addr);
+
+   dma_unmap_single_attrs(dev, addr, size, dir, attrs);
+
+   return phys;
+}
+
 static inline void dma_sync_single_range_for_cpu(struct device *dev,
dma_addr_t addr, unsigned long offset, size_t size,
enum dma_data_direction dir)
@@ -610,10 +662,13 @@ static inline void 
dma_sync_single_range_for_device(struct device *dev,
 
 #define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, 0)
 #define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, 0)
+#define dma_unmap_single_phys(d, a, s, r) \
+   dma_unmap_single_phys_attrs(d, a, s, r, 0)
 #define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, 0)
 #define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, 0)
 #define dma_map_page(d, p, o, s, r) dma_map_page_attrs(d, p, o, s, r, 0)
 #define dma_unmap_page(d, a, s, r) dma_unmap_page_attrs(d, a, s, r, 0)
+#define dma_unmap_page_phys(d, a, s, r) dma_unmap_page_phys_attrs(d, a, s, r, 
0)
 #define dma_get_sgtable(d, t, v, h, s) dma_get_sgtable_attrs(d, t, v, h, s, 0)
 #define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, 0)
 
-- 
2.17.1

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


[PATCH 2/3] iommu/dma: wire-up new dma map op .get_phys_addr

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Add an implementation of the newly introduced dma map op in the
generic DMA IOMMU generic glue layer and wire it up.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/dma-iommu.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f321279baf9e..e4e2bde586e0 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1091,6 +1091,17 @@ static unsigned long iommu_dma_get_merge_boundary(struct 
device *dev)
return (1UL << __ffs(domain->pgsize_bitmap)) - 1;
 }
 
+static phys_addr_t iommu_dma_get_phys_addr(struct device *dev,
+  dma_addr_t dma_handle)
+{
+   struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+
+   if (domain)
+   return iommu_iova_to_phys(domain, dma_handle);
+
+   return 0;
+}
+
 static const struct dma_map_ops iommu_dma_ops = {
.alloc  = iommu_dma_alloc,
.free   = iommu_dma_free,
@@ -1107,6 +1118,7 @@ static const struct dma_map_ops iommu_dma_ops = {
.map_resource   = iommu_dma_map_resource,
.unmap_resource = iommu_dma_unmap_resource,
.get_merge_boundary = iommu_dma_get_merge_boundary,
+   .get_phys_addr  = iommu_dma_get_phys_addr,
 };
 
 /*
-- 
2.17.1

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


[PATCH 3/3] dpaa2_eth: use new unmap and sync dma api variants

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Convert this driver to usage of the newly introduced dma unmap and
sync DMA APIs. This will get rid of the unsupported direct usage of
iommu_iova_to_phys() API.

Signed-off-by: Laurentiu Tudor 
---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 43 ---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 2 files changed, 18 insertions(+), 26 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 19379bae0144..bd43bfcb3126 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -29,16 +29,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
 
-static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
-   dma_addr_t iova_addr)
-{
-   phys_addr_t phys_addr;
-
-   phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
-
-   return phys_to_virt(phys_addr);
-}
-
 static void validate_rx_csum(struct dpaa2_eth_priv *priv,
 u32 fd_status,
 struct sk_buff *skb)
@@ -85,9 +75,10 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
sgt = vaddr + dpaa2_fd_get_offset(fd);
for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
addr = dpaa2_sg_get_addr([i]);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-   dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   sg_vaddr = phys_to_virt
+   (dma_unmap_page_phys(dev, addr,
+   DPAA2_ETH_RX_BUF_SIZE,
+   DMA_BIDIRECTIONAL));
 
free_pages((unsigned long)sg_vaddr, 0);
if (dpaa2_sg_is_final([i]))
@@ -143,9 +134,10 @@ static struct sk_buff *build_frag_skb(struct 
dpaa2_eth_priv *priv,
 
/* Get the address and length from the S/G entry */
sg_addr = dpaa2_sg_get_addr(sge);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
-   dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   sg_vaddr = phys_to_virt
+   (dma_unmap_page_phys(dev, sg_addr,
+   DPAA2_ETH_RX_BUF_SIZE,
+   DMA_BIDIRECTIONAL));
 
sg_length = dpaa2_sg_get_len(sge);
 
@@ -210,9 +202,9 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 
*buf_array, int count)
int i;
 
for (i = 0; i < count; i++) {
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
-   dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
-  DMA_BIDIRECTIONAL);
+   vaddr = phys_to_virt(dma_unmap_page_phys(dev, buf_array[i],
+DPAA2_ETH_RX_BUF_SIZE,
+DMA_BIDIRECTIONAL));
free_pages((unsigned long)vaddr, 0);
}
 }
@@ -369,9 +361,9 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
/* Tracing point */
trace_dpaa2_rx_fd(priv->net_dev, fd);
 
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-   dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-   DMA_BIDIRECTIONAL);
+   vaddr = phys_to_virt(dma_sync_single_for_cpu_phys(dev, addr,
+ DPAA2_ETH_RX_BUF_SIZE,
+ DMA_BIDIRECTIONAL));
 
fas = dpaa2_get_fas(vaddr, false);
prefetch(fas);
@@ -682,7 +674,10 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
u32 fd_len = dpaa2_fd_get_len(fd);
 
fd_addr = dpaa2_fd_get_addr(fd);
-   buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+   buffer_start = phys_to_virt
+   (dma_sync_single_for_cpu_phys(dev, fd_addr,
+ sizeof(*swa),
+ DMA_BIDIRECTIONAL));
swa = (struct dpaa2_eth_swa *)buffer_start;
 
if (fd_format == dpaa2_fd_single) {
@@ -3448,8 +3443,6 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
priv = netdev_priv(net_dev);
priv->net_dev = net_dev;
 
-   priv->iommu_domain = iommu_get_domain_for_dev(dev);
-
/* Obtain a MC portal */
err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
  

[PATCH 0/3] dma-mapping: introduce new dma unmap and sync variants

2019-10-24 Thread Laurentiu Tudor
From: Laurentiu Tudor 

This series introduces a few new dma unmap and sync api variants that,
on top of what the originals do, return the physical address
corresponding to the input dma address. In order to do that a new dma
map op is added, .get_phys_addr that takes the input dma address and
returns the physical address backing it up.
The second patch adds an implementation for this new dma map op in the
generic iommu dma glue code and wires it in.
The third patch updates the dpaa2-eth driver to use the new apis.

Context: https://lkml.org/lkml/2019/5/31/684

Changes since RFC
 * completely changed the approach: added unmap and sync variants that
   return the phys addr instead of adding a new dma to phys conversion
   function

Laurentiu Tudor (3):
  dma-mapping: introduce new dma unmap and sync api variants
  iommu/dma: wire-up new dma map op .get_phys_addr
  dpaa2_eth: use new unmap and sync dma api variants

 drivers/iommu/dma-iommu.c | 12 
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 43 ++-
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 include/linux/dma-mapping.h   | 55 +++
 4 files changed, 85 insertions(+), 26 deletions(-)

-- 
2.17.1

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


Re: [RFC PATCH 1/3] dma-mapping: introduce a new dma api dma_addr_to_phys_addr()

2019-10-24 Thread Laurentiu Tudor



On 24.10.2019 05:01, h...@lst.de wrote:
> On Wed, Oct 23, 2019 at 11:53:41AM +0000, Laurentiu Tudor wrote:
>> We had an internal discussion over these points you are raising and
>> Madalin (cc-ed) came up with another idea: instead of adding this prone
>> to misuse api how about experimenting with a new dma unmap and dma sync
>> variants that would return the physical address by calling the newly
>> introduced dma map op. Something along these lines:
>>* phys_addr_t dma_unmap_page_ret_phys(...)
>>* phys_addr_t dma_unmap_single_ret_phys(...)
>>* phys_addr_t dma_sync_single_for_cpu_ret_phys(...)
>> I'm thinking that this proposal should reduce the risks opened by the
>> initial variant.
>> Please let me know what you think.
> 
> I'm not sure what the ret is supposed to mean, but I generally like
> that idea better.  

It was supposed to be short for "return" but given that I'm not good at 
naming stuff I'll just drop it.

> We also need to make sure there is an easy way
> to figure out if these APIs are available, as they generally aren't
> for any non-IOMMU API IOMMU drivers.

I was really hoping to manage making them as generic as possible but 
anyway, I'll start working on a PoC and see how it turns out. This will 
probably happen sometime next next week as the following week I'll be 
traveling to a conference.

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


Re: [RFC PATCH 1/3] dma-mapping: introduce a new dma api dma_addr_to_phys_addr()

2019-10-23 Thread Laurentiu Tudor
Hi Robin,

On 22.10.2019 16:25, Robin Murphy wrote:
> On 22/10/2019 13:55, Laurentiu Tudor wrote:
>> From: Laurentiu Tudor 
>>
>> Introduce a new dma map op called dma_addr_to_phys_addr() that converts
>> a dma address to the physical address backing it up and add wrapper for
>> it.
> 
> I'd really love it if there was a name which could encapsulate that this 
> is *only* for extreme special cases of constrained descriptors/pagetable 
> entries/etc. where there's simply no practical way to keep track of a 
> CPU address alongside the DMA address, and the only option is this 
> potentially-arbitrarily-complex operation (I mean, on some systems it 
> may end up taking locks and poking hardware).
> 
> Either way it's tricky - much as I don't like adding an interface which 
> is ripe for drivers to misuse, I also really don't want hacks like 
> bdf95923086f shoved into other APIs to compensate, so on balance I'd 
> probably consider this proposal ever so slightly the lesser evil.

We had an internal discussion over these points you are raising and 
Madalin (cc-ed) came up with another idea: instead of adding this prone 
to misuse api how about experimenting with a new dma unmap and dma sync 
variants that would return the physical address by calling the newly 
introduced dma map op. Something along these lines:
  * phys_addr_t dma_unmap_page_ret_phys(...)
  * phys_addr_t dma_unmap_single_ret_phys(...)
  * phys_addr_t dma_sync_single_for_cpu_ret_phys(...)
I'm thinking that this proposal should reduce the risks opened by the 
initial variant.
Please let me know what you think.

---
Thanks & Best Regards, Laurentiu

Re: [RFC PATCH 1/3] dma-mapping: introduce a new dma api dma_addr_to_phys_addr()

2019-10-22 Thread Laurentiu Tudor

On 22.10.2019 16:25, Robin Murphy wrote:
> On 22/10/2019 13:55, Laurentiu Tudor wrote:
>> From: Laurentiu Tudor 
>>
>> Introduce a new dma map op called dma_addr_to_phys_addr() that converts
>> a dma address to the physical address backing it up and add wrapper for
>> it.
> 
> I'd really love it if there was a name which could encapsulate that this 
> is *only* for extreme special cases of constrained descriptors/pagetable 
> entries/etc. where there's simply no practical way to keep track of a 
> CPU address alongside the DMA address, and the only option is this 
> potentially-arbitrarily-complex operation (I mean, on some systems it 
> may end up taking locks and poking hardware).
> 
> Either way it's tricky - much as I don't like adding an interface which 
> is ripe for drivers to misuse, I also really don't want hacks like 
> bdf95923086f shoved into other APIs to compensate, so on balance I'd 
> probably consider this proposal ever so slightly the lesser evil.
> 
>> Signed-off-by: Laurentiu Tudor 
>> ---
>>   include/linux/dma-mapping.h | 21 +
>>   1 file changed, 21 insertions(+)
>>
>> diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
>> index 4a1c4fca475a..5965d159c9a9 100644
>> --- a/include/linux/dma-mapping.h
>> +++ b/include/linux/dma-mapping.h
>> @@ -132,6 +132,8 @@ struct dma_map_ops {
>>   u64 (*get_required_mask)(struct device *dev);
>>   size_t (*max_mapping_size)(struct device *dev);
>>   unsigned long (*get_merge_boundary)(struct device *dev);
>> +    phys_addr_t (*dma_addr_to_phys_addr)(struct device *dev,
>> + dma_addr_t dma_handle);
> 
> I'd be inclined to name the internal callback something a bit snappier 
> like .get_phys_addr.

Alright. Want me to also rename the wrapper to something like 
dma_get_phys_addr()? Sounds a bit nicer to me.

>>   };
>>   #define DMA_MAPPING_ERROR    (~(dma_addr_t)0)
>> @@ -442,6 +444,19 @@ static inline int dma_mapping_error(struct device 
>> *dev, dma_addr_t dma_addr)
>>   return 0;
>>   }
>> +static inline phys_addr_t dma_addr_to_phys_addr(struct device *dev,
>> +    dma_addr_t dma_handle)
>> +{
>> +    const struct dma_map_ops *ops = get_dma_ops(dev);
>> +
>> +    if (dma_is_direct(ops))
>> +    return (phys_addr_t)dma_handle;
> 
> Well that's not right, is it - remember why you had that namespace 
> collision? ;)
> 

Ugh, correct. Don't know what I was thinking. Will rework the check.

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[RFC PATCH 1/3] dma-mapping: introduce a new dma api dma_addr_to_phys_addr()

2019-10-22 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Introduce a new dma map op called dma_addr_to_phys_addr() that converts
a dma address to the physical address backing it up and add wrapper for
it.

Signed-off-by: Laurentiu Tudor 
---
 include/linux/dma-mapping.h | 21 +
 1 file changed, 21 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 4a1c4fca475a..5965d159c9a9 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -132,6 +132,8 @@ struct dma_map_ops {
u64 (*get_required_mask)(struct device *dev);
size_t (*max_mapping_size)(struct device *dev);
unsigned long (*get_merge_boundary)(struct device *dev);
+   phys_addr_t (*dma_addr_to_phys_addr)(struct device *dev,
+dma_addr_t dma_handle);
 };
 
 #define DMA_MAPPING_ERROR  (~(dma_addr_t)0)
@@ -442,6 +444,19 @@ static inline int dma_mapping_error(struct device *dev, 
dma_addr_t dma_addr)
return 0;
 }
 
+static inline phys_addr_t dma_addr_to_phys_addr(struct device *dev,
+   dma_addr_t dma_handle)
+{
+   const struct dma_map_ops *ops = get_dma_ops(dev);
+
+   if (dma_is_direct(ops))
+   return (phys_addr_t)dma_handle;
+   else if (ops->dma_addr_to_phys_addr)
+   return ops->dma_addr_to_phys_addr(dev, dma_handle);
+
+   return 0;
+}
+
 void *dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
gfp_t flag, unsigned long attrs);
 void dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
@@ -578,6 +593,12 @@ static inline unsigned long dma_get_merge_boundary(struct 
device *dev)
 {
return 0;
 }
+
+static inline phys_addr_t dma_addr_to_phys_addr(struct device *dev,
+   dma_addr_t dma_handle)
+{
+   return 0;
+}
 #endif /* CONFIG_HAS_DMA */
 
 static inline dma_addr_t dma_map_single_attrs(struct device *dev, void *ptr,
-- 
2.17.1

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


[RFC PATCH 2/3] iommu/dma: wire-up new dma op dma_addr_to_phys_addr()

2019-10-22 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Add an implementation of the newly introduced dma map op in the
generic DMA IOMMU generic glue layer and wire it up.

Signed-off-by: Laurentiu Tudor 
---
 drivers/iommu/dma-iommu.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index f321279baf9e..0d2856793ecd 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -1091,6 +1091,17 @@ static unsigned long iommu_dma_get_merge_boundary(struct 
device *dev)
return (1UL << __ffs(domain->pgsize_bitmap)) - 1;
 }
 
+static phys_addr_t iommu_dma_dma_addr_to_phys_addr(struct device *dev,
+  dma_addr_t dma_handle)
+{
+   struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+
+   if (domain)
+   return iommu_iova_to_phys(domain, dma_handle);
+
+   return 0;
+}
+
 static const struct dma_map_ops iommu_dma_ops = {
.alloc  = iommu_dma_alloc,
.free   = iommu_dma_free,
@@ -1107,6 +1118,7 @@ static const struct dma_map_ops iommu_dma_ops = {
.map_resource   = iommu_dma_map_resource,
.unmap_resource = iommu_dma_unmap_resource,
.get_merge_boundary = iommu_dma_get_merge_boundary,
+   .dma_addr_to_phys_addr  = iommu_dma_dma_addr_to_phys_addr,
 };
 
 /*
-- 
2.17.1

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


[RFC PATCH 0/3] dma-mapping: introduce a new dma api

2019-10-22 Thread Laurentiu Tudor
From: Laurentiu Tudor 

This series introduces a new dma api called dma_addr_to_phys_addr()
that converts a dma address to the corresponding physical address.
It consists in a new dma map op and the wrapper api, both added
in the first patch. The second patch adds an implementation in the
iommu dma glue code and wires it up. The third patch updates a driver
to use the new api.

Note: Originally i wanted to use the simpler api name dma_to_phys()
but it's already used in the dma direct apis. It would be great if
there would be a solution (unifying them?) to use this nicer naming.

Context: https://lkml.org/lkml/2019/5/31/684

Laurentiu Tudor (3):
  dma-mapping: introduce a new dma api dma_addr_to_phys_addr()
  iommu/dma: wire-up new dma op dma_addr_to_phys_addr()
  dpaa2_eth: use dma_addr_to_phys_addr() new dma api

 drivers/iommu/dma-iommu.c | 12 +++
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 21 +++
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 include/linux/dma-mapping.h   | 21 +++
 4 files changed, 40 insertions(+), 15 deletions(-)

-- 
2.17.1

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


[RFC PATCH 3/3] dpaa2_eth: use dma_addr_to_phys_addr() new dma api

2019-10-22 Thread Laurentiu Tudor
From: Laurentiu Tudor 

Convert this driver to usage of the newly introduced
dma_addr_to_phys_addr() DMA API. This will get rid of the unsupported
direct usage of iommu_iova_to_phys() API.

Signed-off-by: Laurentiu Tudor 
---
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.c  | 21 +++
 .../net/ethernet/freescale/dpaa2/dpaa2-eth.h  |  1 -
 2 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index 19379bae0144..7332b91ca3a2 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -29,14 +29,9 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Freescale Semiconductor, Inc");
 MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
 
-static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
-   dma_addr_t iova_addr)
+static void *dpaa2_iova_to_virt(struct device *dev, dma_addr_t dma_handle)
 {
-   phys_addr_t phys_addr;
-
-   phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
-
-   return phys_to_virt(phys_addr);
+   return phys_to_virt(dma_addr_to_phys_addr(dev, dma_handle));
 }
 
 static void validate_rx_csum(struct dpaa2_eth_priv *priv,
@@ -85,7 +80,7 @@ static void free_rx_fd(struct dpaa2_eth_priv *priv,
sgt = vaddr + dpaa2_fd_get_offset(fd);
for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
addr = dpaa2_sg_get_addr([i]);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
+   sg_vaddr = dpaa2_iova_to_virt(dev, addr);
dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
   DMA_BIDIRECTIONAL);
 
@@ -143,7 +138,7 @@ static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv 
*priv,
 
/* Get the address and length from the S/G entry */
sg_addr = dpaa2_sg_get_addr(sge);
-   sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
+   sg_vaddr = dpaa2_iova_to_virt(dev, sg_addr);
dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
   DMA_BIDIRECTIONAL);
 
@@ -210,7 +205,7 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 
*buf_array, int count)
int i;
 
for (i = 0; i < count; i++) {
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
+   vaddr = dpaa2_iova_to_virt(dev, buf_array[i]);
dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
   DMA_BIDIRECTIONAL);
free_pages((unsigned long)vaddr, 0);
@@ -369,7 +364,7 @@ static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
/* Tracing point */
trace_dpaa2_rx_fd(priv->net_dev, fd);
 
-   vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
+   vaddr = dpaa2_iova_to_virt(dev, addr);
dma_sync_single_for_cpu(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
DMA_BIDIRECTIONAL);
 
@@ -682,7 +677,7 @@ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
u32 fd_len = dpaa2_fd_get_len(fd);
 
fd_addr = dpaa2_fd_get_addr(fd);
-   buffer_start = dpaa2_iova_to_virt(priv->iommu_domain, fd_addr);
+   buffer_start = dpaa2_iova_to_virt(dev, fd_addr);
swa = (struct dpaa2_eth_swa *)buffer_start;
 
if (fd_format == dpaa2_fd_single) {
@@ -3448,8 +3443,6 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
priv = netdev_priv(net_dev);
priv->net_dev = net_dev;
 
-   priv->iommu_domain = iommu_get_domain_for_dev(dev);
-
/* Obtain a MC portal */
err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
 >mc_io);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h 
b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
index 8a0e65b3267f..4e5183617ebd 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
@@ -374,7 +374,6 @@ struct dpaa2_eth_priv {
 
struct fsl_mc_device *dpbp_dev;
u16 bpid;
-   struct iommu_domain *iommu_domain;
 
bool tx_tstamp; /* Tx timestamping enabled */
bool rx_tstamp; /* Rx timestamping enabled */
-- 
2.17.1

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


RE: [PATCH v3 0/6] Prerequisites for NXP LS104xA SMMU enablement

2019-05-31 Thread Laurentiu Tudor
> -Original Message-
> From: Andreas Färber 
> Sent: Friday, May 31, 2019 8:04 PM
> 
> Hello Laurentiu,
> 
> Am 31.05.19 um 18:46 schrieb Laurentiu Tudor:
> >> -Original Message-
> >> From: Andreas Färber 
> >> Sent: Friday, May 31, 2019 7:15 PM
> >>
> >> Hi Laurentiu,
> >>
> >> Am 30.05.19 um 16:19 schrieb laurentiu.tu...@nxp.com:
> >>> This patch series contains several fixes in preparation for SMMU
> >>> support on NXP LS1043A and LS1046A chips. Once these get picked up,
> >>> I'll submit the actual SMMU enablement patches consisting in the
> >>> required device tree changes.
> >>
> >> Have you thought through what will happen if this patch ordering is not
> >> preserved? In particular, a user installing a future U-Boot update with
> >> the DTB bits but booting a stable kernel without this patch series -
> >> wouldn't that regress dpaa then for our customers?
> >>
> >
> > These are fixes for issues that popped out after enabling SMMU.
> > I do not expect them to break anything.
> 
> That was not my question! You're missing my point: All your patches are
> lacking a Fixes header in their commit message, for backporting them, to
> avoid _your DT patches_ breaking the driver on stable branches!

It does appear that I'm missing your point. For sure, the DT updates solely will
break the kernel without these fixes but I'm not sure I understand how this
could happen. My plan was to share the kernel dts patches sometime after this 
series
makes it through.

---
Best Regards, Laurentiu


RE: [PATCH v3 5/6] dpaa_eth: fix iova handling for contiguous frames

2019-05-31 Thread Laurentiu Tudor
> -Original Message-
> From: Christoph Hellwig 
> Sent: Friday, May 31, 2019 7:56 PM
> 
> On Fri, May 31, 2019 at 04:53:16PM +0000, Laurentiu Tudor wrote:
> > Unfortunately due to our hardware particularities we do not have
> alternatives. This is also the case for our next generation of ethernet
> drivers [1]. I'll let my colleagues that work on the ethernet drivers to
> comment more on this.
> 
> Then you need to enhance the DMA API to support your use case instead
> of using an API only supported for two specific IOMMU implementations.
> 
> Remember in Linux you can should improve core code and not hack around
> it in crappy ways making lots of assumptions in your drivers.

Alright, I'm ok with that. I'll try to come up with something, will keep you in 
the loop.

---
Best Regards, Laurentiu


RE: [PATCH v3 5/6] dpaa_eth: fix iova handling for contiguous frames

2019-05-31 Thread Laurentiu Tudor
Hi Christoph,

> -Original Message-
> From: Christoph Hellwig 
> Sent: Friday, May 31, 2019 7:32 PM
> 
> On Thu, May 30, 2019 at 05:19:50PM +0300, laurentiu.tu...@nxp.com wrote:
> > +static phys_addr_t dpaa_iova_to_phys(const struct dpaa_priv *priv,
> > +dma_addr_t addr)
> > +{
> > +   return priv->domain ? iommu_iova_to_phys(priv->domain, addr) : addr;
> > +}
> 
> Again, a driver using the iommu API must not call iommu_* APIs.
> 
> This chane is not acceptable.

Unfortunately due to our hardware particularities we do not have alternatives. 
This is also the case for our next generation of ethernet drivers [1]. I'll let 
my colleagues that work on the ethernet drivers to comment more on this.

[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c#n37

---
Best Regards, Laurentiu


RE: [PATCH v3 0/6] Prerequisites for NXP LS104xA SMMU enablement

2019-05-31 Thread Laurentiu Tudor
Hello Andreas,

> -Original Message-
> From: Andreas Färber 
> Sent: Friday, May 31, 2019 7:15 PM
> 
> Hi Laurentiu,
> 
> Am 30.05.19 um 16:19 schrieb laurentiu.tu...@nxp.com:
> > This patch series contains several fixes in preparation for SMMU
> > support on NXP LS1043A and LS1046A chips. Once these get picked up,
> > I'll submit the actual SMMU enablement patches consisting in the
> > required device tree changes.
> 
> Have you thought through what will happen if this patch ordering is not
> preserved? In particular, a user installing a future U-Boot update with
> the DTB bits but booting a stable kernel without this patch series -
> wouldn't that regress dpaa then for our customers?
> 

These are fixes for issues that popped out after enabling SMMU. 
I do not expect them to break anything.

---
Best Regards, Laurentiu


RE: [PATCH v3 0/6] Prerequisites for NXP LS104xA SMMU enablement

2019-05-31 Thread Laurentiu Tudor
Hello,

> -Original Message-
> From: David Miller 
> Sent: Friday, May 31, 2019 1:09 AM
> 
> From: laurentiu.tu...@nxp.com
> Date: Thu, 30 May 2019 17:19:45 +0300
> 
> > Depends on this pull request:
> >
> >
> http://lists.infradead.org/pipermail/linux-arm-kernel/2019-May/653554.html
> 
> I'm not sure how you want me to handle this.

Dave, would it make sense / be possible to also pick Leo's PR through your tree?

---
Thanks & Best Regards, Laurentiu


[PATCH v3 4/6] dpaa_eth: base dma mappings on the fman rx port

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

The dma transactions initiator is the rx fman port so that's the device
that the dma mappings should be done. Previously the mappings were done
through the MAC device which makes no sense because it's neither dma-able
nor connected in any way to smmu.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 975f307f0caa..f54b0cd0d175 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2805,8 +2805,15 @@ static int dpaa_eth_probe(struct platform_device *pdev)
return -ENODEV;
}
 
+   mac_dev = dpaa_mac_dev_get(pdev);
+   if (IS_ERR(mac_dev)) {
+   dev_err(>dev, "dpaa_mac_dev_get() failed\n");
+   err = PTR_ERR(mac_dev);
+   goto probe_err;
+   }
+
/* device used for DMA mapping */
-   dev = pdev->dev.parent;
+   dev = fman_port_get_device(mac_dev->port[RX]);
err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
if (err) {
dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
@@ -2831,13 +2838,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
 
priv->msg_enable = netif_msg_init(debug, DPAA_MSG_DEFAULT);
 
-   mac_dev = dpaa_mac_dev_get(pdev);
-   if (IS_ERR(mac_dev)) {
-   dev_err(dev, "dpaa_mac_dev_get() failed\n");
-   err = PTR_ERR(mac_dev);
-   goto free_netdev;
-   }
-
/* If fsl_fm_max_frm is set to a higher value than the all-common 1500,
 * we choose conservatively and let the user explicitly set a higher
 * MTU via ifconfig. Otherwise, the user may end up with different MTUs
@@ -2973,9 +2973,9 @@ static int dpaa_eth_probe(struct platform_device *pdev)
qman_release_cgrid(priv->cgr_data.cgr.cgrid);
 free_dpaa_bps:
dpaa_bps_free(priv);
-free_netdev:
dev_set_drvdata(dev, NULL);
free_netdev(net_dev);
+probe_err:
 
return err;
 }
-- 
2.17.1



[PATCH v3 0/6] Prerequisites for NXP LS104xA SMMU enablement

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

This patch series contains several fixes in preparation for SMMU
support on NXP LS1043A and LS1046A chips. Once these get picked up,
I'll submit the actual SMMU enablement patches consisting in the
required device tree changes.

This patch series contains only part of the previously submitted one,
(including also the device tree changes) available here:

 https://patchwork.kernel.org/cover/10634443/

There are a couple of changes/fixes since then:
 - for consistency, renamed mmu node to smmu
 - new patch page aligning the sizes of the qbman reserved memory
 - rebased on 5.1.0-rc2

Depends on this pull request:

 http://lists.infradead.org/pipermail/linux-arm-kernel/2019-May/653554.html

Changes in v3:
 - cache iommu domain in driver's private data
 - rebased on v5.2.0-rc2
 - rework to get rid of #ifdef spaghetti (David)

Changes in v2:
 - dropped patches dealing with mapping reserved memory in iommu
 - changed logic for qman portal probe status (Leo)
 - moved "#ifdef CONFIG_PAMU" in header file (Leo)
 - rebased on v5.1.0-rc5

Laurentiu Tudor (6):
  fsl/fman: don't touch liodn base regs reserved on non-PAMU SoCs
  fsl/fman: add API to get the device behind a fman port
  dpaa_eth: defer probing after qbman
  dpaa_eth: base dma mappings on the fman rx port
  dpaa_eth: fix iova handling for contiguous frames
  dpaa_eth: fix iova handling for sg frames

 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 131 --
 .../net/ethernet/freescale/dpaa/dpaa_eth.h|   2 +
 drivers/net/ethernet/freescale/fman/fman.c|   6 +-
 .../net/ethernet/freescale/fman/fman_port.c   |  14 ++
 .../net/ethernet/freescale/fman/fman_port.h   |   2 +
 5 files changed, 108 insertions(+), 47 deletions(-)

-- 
2.17.1



[PATCH v3 2/6] fsl/fman: add API to get the device behind a fman port

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

Add an API that retrieves the 'struct device' that the specified fman
port probed against. The new API will be used in a subsequent iommu
enablement related patch.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 drivers/net/ethernet/freescale/fman/fman_port.c | 14 ++
 drivers/net/ethernet/freescale/fman/fman_port.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c 
b/drivers/net/ethernet/freescale/fman/fman_port.c
index ee82ee1384eb..bd76c9730692 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1728,6 +1728,20 @@ u32 fman_port_get_qman_channel_id(struct fman_port *port)
 }
 EXPORT_SYMBOL(fman_port_get_qman_channel_id);
 
+/**
+ * fman_port_get_device
+ * port:   Pointer to the FMan port device
+ *
+ * Get the 'struct device' associated to the specified FMan port device
+ *
+ * Return: pointer to associated 'struct device'
+ */
+struct device *fman_port_get_device(struct fman_port *port)
+{
+   return port->dev;
+}
+EXPORT_SYMBOL(fman_port_get_device);
+
 int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset)
 {
if (port->buffer_offsets.hash_result_offset == ILLEGAL_BASE)
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h 
b/drivers/net/ethernet/freescale/fman/fman_port.h
index 9dbb69f40121..82f12661a46d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.h
+++ b/drivers/net/ethernet/freescale/fman/fman_port.h
@@ -157,4 +157,6 @@ int fman_port_get_tstamp(struct fman_port *port, const void 
*data, u64 *tstamp);
 
 struct fman_port *fman_port_bind(struct device *dev);
 
+struct device *fman_port_get_device(struct fman_port *port);
+
 #endif /* __FMAN_PORT_H */
-- 
2.17.1



[PATCH v3 3/6] dpaa_eth: defer probing after qbman

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

Enabling SMMU altered the order of device probing causing the dpaa1
ethernet driver to get probed before qbman and causing a boot crash.
Add predictability in the probing order by deferring the ethernet
driver probe after qbman and portals by using the recently introduced
qbman APIs.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 31 +++
 1 file changed, 31 insertions(+)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index d3f2408dc9e8..975f307f0caa 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2774,6 +2774,37 @@ static int dpaa_eth_probe(struct platform_device *pdev)
int err = 0, i, channel;
struct device *dev;
 
+   err = bman_is_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev, "failing probe due to bman probe error\n");
+   return -ENODEV;
+   }
+   err = qman_is_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev, "failing probe due to qman probe error\n");
+   return -ENODEV;
+   }
+   err = bman_portals_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev,
+   "failing probe due to bman portals probe error\n");
+   return -ENODEV;
+   }
+   err = qman_portals_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev,
+   "failing probe due to qman portals probe error\n");
+   return -ENODEV;
+   }
+
/* device used for DMA mapping */
dev = pdev->dev.parent;
err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
-- 
2.17.1



[PATCH v3 5/6] dpaa_eth: fix iova handling for contiguous frames

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

The driver relies on the no longer valid assumption that dma addresses
(iovas) are identical to physical addressees and uses phys_to_virt() to
make iova -> vaddr conversions. Fix this by adding a function that does
proper iova -> phys conversions using the iommu api and update the code
to use it.
Also, a dma_unmap_single() call had to be moved further down the code
because iova -> vaddr conversions were required before the unmap.
For now only the contiguous frame case is handled and the SG case is
split in a following patch.
While at it, clean-up a redundant dpaa_bpid2pool() and pass the bp
as parameter.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 42 ++-
 .../net/ethernet/freescale/dpaa/dpaa_eth.h|  2 +
 2 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index f54b0cd0d175..46194a04617a 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -50,6 +50,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1595,6 +1596,12 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
return 0;
 }
 
+static phys_addr_t dpaa_iova_to_phys(const struct dpaa_priv *priv,
+dma_addr_t addr)
+{
+   return priv->domain ? iommu_iova_to_phys(priv->domain, addr) : addr;
+}
+
 /* Cleanup function for outgoing frame descriptors that were built on Tx path,
  * either contiguous frames or scatter/gather ones.
  * Skb freeing is not handled here.
@@ -1617,7 +1624,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
int nr_frags, i;
u64 ns;
 
-   skbh = (struct sk_buff **)phys_to_virt(addr);
+   skbh = (struct sk_buff **)phys_to_virt(dpaa_iova_to_phys(priv, addr));
skb = *skbh;
 
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
@@ -1687,25 +1694,21 @@ static u8 rx_csum_offload(const struct dpaa_priv *priv, 
const struct qm_fd *fd)
  * accommodate the shared info area of the skb.
  */
 static struct sk_buff *contig_fd_to_skb(const struct dpaa_priv *priv,
-   const struct qm_fd *fd)
+   const struct qm_fd *fd,
+   struct dpaa_bp *dpaa_bp,
+   void *vaddr)
 {
ssize_t fd_off = qm_fd_get_offset(fd);
-   dma_addr_t addr = qm_fd_addr(fd);
-   struct dpaa_bp *dpaa_bp;
struct sk_buff *skb;
-   void *vaddr;
 
-   vaddr = phys_to_virt(addr);
WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
 
-   dpaa_bp = dpaa_bpid2pool(fd->bpid);
-   if (!dpaa_bp)
-   goto free_buffer;
-
skb = build_skb(vaddr, dpaa_bp->size +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
-   if (WARN_ONCE(!skb, "Build skb failure on Rx\n"))
-   goto free_buffer;
+   if (WARN_ONCE(!skb, "Build skb failure on Rx\n")) {
+   skb_free_frag(vaddr);
+   return NULL;
+   }
WARN_ON(fd_off != priv->rx_headroom);
skb_reserve(skb, fd_off);
skb_put(skb, qm_fd_get_length(fd));
@@ -1713,10 +1716,6 @@ static struct sk_buff *contig_fd_to_skb(const struct 
dpaa_priv *priv,
skb->ip_summed = rx_csum_offload(priv, fd);
 
return skb;
-
-free_buffer:
-   skb_free_frag(vaddr);
-   return NULL;
 }
 
 /* Build an skb with the data of the first S/G entry in the linear portion and
@@ -2309,12 +2308,12 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct 
qman_portal *portal,
if (!dpaa_bp)
return qman_cb_dqrr_consume;
 
-   dma_unmap_single(dpaa_bp->dev, addr, dpaa_bp->size, DMA_FROM_DEVICE);
-
/* prefetch the first 64 bytes of the frame or the SGT start */
-   vaddr = phys_to_virt(addr);
+   vaddr = phys_to_virt(dpaa_iova_to_phys(priv, addr));
prefetch(vaddr + qm_fd_get_offset(fd));
 
+   dma_unmap_single(dpaa_bp->dev, addr, dpaa_bp->size, DMA_FROM_DEVICE);
+
/* The only FD types that we may receive are contig and S/G */
WARN_ON((fd_format != qm_fd_contig) && (fd_format != qm_fd_sg));
 
@@ -2325,7 +2324,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct 
qman_portal *portal,
(*count_ptr)--;
 
if (likely(fd_format == qm_fd_contig))
-   skb = contig_fd_to_skb(priv, fd);
+   skb = contig_fd_to_skb(priv, fd, dpaa_bp, vaddr);
else
skb = sg_fd_to_skb(priv, fd);
if (!skb)
@@ -2836,6 +2835,9 @@ static int dpaa_eth_probe(struct platform_device *pdev)
priv = netdev_priv(net_d

[PATCH v3 6/6] dpaa_eth: fix iova handling for sg frames

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

The driver relies on the no longer valid assumption that dma addresses
(iovas) are identical to physical addressees and uses phys_to_virt() to
make iova -> vaddr conversions. Fix this also for scatter-gather frames
using the iova -> phys conversion function added in the previous patch.
While at it, clean-up a redundant dpaa_bpid2pool() and pass the bp
as parameter.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 40 +++
 1 file changed, 23 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 46194a04617a..7d978a93dffd 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1641,14 +1641,17 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
 
if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
nr_frags = skb_shinfo(skb)->nr_frags;
-   dma_unmap_single(dev, addr,
-qm_fd_get_offset(fd) + DPAA_SGT_SIZE,
-dma_dir);
 
/* The sgt buffer has been allocated with netdev_alloc_frag(),
 * it's from lowmem.
 */
-   sgt = phys_to_virt(addr + qm_fd_get_offset(fd));
+   sgt = phys_to_virt(dpaa_iova_to_phys(priv,
+addr +
+qm_fd_get_offset(fd)));
+
+   dma_unmap_single(dev, addr,
+qm_fd_get_offset(fd) + DPAA_SGT_SIZE,
+dma_dir);
 
/* sgt[0] is from lowmem, was dma_map_single()-ed */
dma_unmap_single(dev, qm_sg_addr([0]),
@@ -1663,7 +1666,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
}
 
/* Free the page frag that we allocated on Tx */
-   skb_free_frag(phys_to_virt(addr));
+   skb_free_frag(skbh);
} else {
dma_unmap_single(dev, addr,
 skb_tail_pointer(skb) - (u8 *)skbh, dma_dir);
@@ -1724,14 +1727,14 @@ static struct sk_buff *contig_fd_to_skb(const struct 
dpaa_priv *priv,
  * The page fragment holding the S/G Table is recycled here.
  */
 static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
-   const struct qm_fd *fd)
+   const struct qm_fd *fd,
+   struct dpaa_bp *dpaa_bp,
+   void *vaddr)
 {
ssize_t fd_off = qm_fd_get_offset(fd);
-   dma_addr_t addr = qm_fd_addr(fd);
const struct qm_sg_entry *sgt;
struct page *page, *head_page;
-   struct dpaa_bp *dpaa_bp;
-   void *vaddr, *sg_vaddr;
+   void *sg_vaddr;
int frag_off, frag_len;
struct sk_buff *skb;
dma_addr_t sg_addr;
@@ -1740,7 +1743,6 @@ static struct sk_buff *sg_fd_to_skb(const struct 
dpaa_priv *priv,
int *count_ptr;
int i;
 
-   vaddr = phys_to_virt(addr);
WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
 
/* Iterate through the SGT entries and add data buffers to the skb */
@@ -1751,14 +1753,17 @@ static struct sk_buff *sg_fd_to_skb(const struct 
dpaa_priv *priv,
WARN_ON(qm_sg_entry_is_ext([i]));
 
sg_addr = qm_sg_addr([i]);
-   sg_vaddr = phys_to_virt(sg_addr);
-   WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
-   SMP_CACHE_BYTES));
 
/* We may use multiple Rx pools */
dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
-   if (!dpaa_bp)
+   if (!dpaa_bp) {
+   pr_info("%s: fail to get dpaa_bp for sg bpid %d\n",
+   __func__, sgt[i].bpid);
goto free_buffers;
+   }
+   sg_vaddr = phys_to_virt(dpaa_iova_to_phys(priv, sg_addr));
+   WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
+   SMP_CACHE_BYTES));
 
count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
dma_unmap_single(dpaa_bp->dev, sg_addr, dpaa_bp->size,
@@ -1830,10 +1835,11 @@ static struct sk_buff *sg_fd_to_skb(const struct 
dpaa_priv *priv,
/* free all the SG entries */
for (i = 0; i < DPAA_SGT_MAX_ENTRIES ; i++) {
sg_addr = qm_sg_addr([i]);
-   sg_vaddr = phys_to_virt(sg_addr);
-   skb_free_frag(sg_vaddr);
dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
if (dpaa_bp) {
+   sg_addr = dpaa_iova_to_phys(priv, sg_addr);
+   

[PATCH v3 1/6] fsl/fman: don't touch liodn base regs reserved on non-PAMU SoCs

2019-05-30 Thread laurentiu . tudor
From: Laurentiu Tudor 

liodn base registers are specific to PAMU based NXP systems and on SMMU
based ones are reserved. Don't access them if PAMU is compiled in.

Signed-off-by: Laurentiu Tudor 
---
 drivers/net/ethernet/freescale/fman/fman.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman.c 
b/drivers/net/ethernet/freescale/fman/fman.c
index e80fedb27cee..cce6636b1763 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -634,6 +634,9 @@ static void set_port_liodn(struct fman *fman, u8 port_id,
 {
u32 tmp;
 
+   iowrite32be(liodn_ofst, >bmi_regs->fmbm_spliodn[port_id - 1]);
+   if (!IS_ENABLED(CONFIG_FSL_PAMU))
+   return;
/* set LIODN base for this port */
tmp = ioread32be(>dma_regs->fmdmplr[port_id / 2]);
if (port_id % 2) {
@@ -644,7 +647,6 @@ static void set_port_liodn(struct fman *fman, u8 port_id,
tmp |= liodn_base << DMA_LIODN_SHIFT;
}
iowrite32be(tmp, >dma_regs->fmdmplr[port_id / 2]);
-   iowrite32be(liodn_ofst, >bmi_regs->fmbm_spliodn[port_id - 1]);
 }
 
 static void enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg)
@@ -1942,6 +1944,8 @@ static int fman_init(struct fman *fman)
 
fman->liodn_offset[i] =
ioread32be(>bmi_regs->fmbm_spliodn[i - 1]);
+   if (!IS_ENABLED(CONFIG_FSL_PAMU))
+   continue;
liodn_base = ioread32be(>dma_regs->fmdmplr[i / 2]);
if (i % 2) {
/* FMDM_PLR LSB holds LIODN base for odd ports */
-- 
2.17.1



RE: [ARM SMMU] Dynamic StreamID allocation

2019-05-13 Thread Laurentiu Tudor
Hi Pankaj,

> -Original Message-
> From: linux-arm-kernel  On
> Behalf Of Pankaj Bansal
> Sent: Friday, May 10, 2019 3:34 PM
> 
> Hi Will/Robin/Joerg,
> 
> I am s/w engineer from NXP India Pvt. Ltd.
> We are using SMMU-V3 in one of NXP SOC.
> I have a question about the SMMU Stream ID allocation in linux.
> 
> Right now the Stream IDs allocated to a device are mapped via device tree
> to the device.

[snip]

> 
> As the device tree is passed from bootloader to linux, we detect all the
> stream IDs needed by a device in bootloader and add their IDs in
> respective device nodes.
> For each PCIE Endpoint (a unique BDF (Bus Device Function)) on PCIE bus,
> we are assigning a unique Stream ID in bootloader.
> 
> However, this poses an issue with PCIE hot plug.
> If we plug in a pcie device while linux is running, a unique BDF is
> assigned to the device, for which there is no stream ID in device tree.
> 
> How can this problem be solved in linux?
> 
> Is there a way to assign (and revoke) stream IDs at run time?

I think that our main problem is that we enumerate the PCI EPs in the 
bootloader (u-boot) and allocate StreamIDs just for them, completely 
disregarding hotplug scenarios. One simple fix would be to not do this and 
simply allocate a decently sized, fixed range of StreamIDs per PCI controller.

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


RE: [PATCH v2 9/9] dpaa_eth: fix SG frame cleanup

2019-05-02 Thread Laurentiu Tudor



> -Original Message-
> From: Joakim Tjernlund 
> Sent: Thursday, May 2, 2019 1:37 PM
> 
> On Thu, 2019-05-02 at 09:05 +0000, Laurentiu Tudor wrote:
> > Hi Joakim,
> >
> > > -Original Message-
> > > From: Joakim Tjernlund 
> > > Sent: Saturday, April 27, 2019 8:11 PM
> > >
> > > On Sat, 2019-04-27 at 10:10 +0300, laurentiu.tu...@nxp.com wrote:
> > > > From: Laurentiu Tudor 
> > > >
> > > > Fix issue with the entry indexing in the sg frame cleanup code being
> > > > off-by-1. This problem showed up when doing some basic iperf tests
> and
> > > > manifested in traffic coming to a halt.
> > > >
> > > > Signed-off-by: Laurentiu Tudor 
> > > > Acked-by: Madalin Bucur 
> > >
> > > Wasn't this a stable candidate too?
> >
> > Yes, it is. I forgot to add the cc:stable tag, sorry about that.
> 
> Then this is a bug fix that should go directly to linus/stable.
> 
> I note that
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/log/drivers/net/ethernet/freescale/dpaa?h=linux-4.19.y

Not sure I understand ... I don't see the patch in the link.

> is in 4.19 but not in 4.14 , is it not appropriate for 4.14?

I think it makes sense to go in both stable trees.

---
Best Regards, Laurentiu

> >
> > > > ---
> > > >  drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +-
> > > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > > b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > > > index daede7272768..40420edc9ce6 100644
> > > > --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > > > +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > > > @@ -1663,7 +1663,7 @@ static struct sk_buff
> *dpaa_cleanup_tx_fd(const
> > > struct dpaa_priv *priv,
> > > >  qm_sg_entry_get_len([0]),
> dma_dir);
> > > >
> > > > /* remaining pages were mapped with
> skb_frag_dma_map()
> > > */
> > > > -   for (i = 1; i < nr_frags; i++) {
> > > > +   for (i = 1; i <= nr_frags; i++) {
> > > > WARN_ON(qm_sg_entry_is_ext([i]));
> > > >
> > > > dma_unmap_page(dev, qm_sg_addr([i]),
> > > > --
> > > > 2.17.1
> > > >
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH v2 7/9] dpaa_eth: fix iova handling for contiguous frames

2019-05-02 Thread Laurentiu Tudor



> -Original Message-
> From: Christoph Hellwig 
> Sent: Saturday, April 27, 2019 7:46 PM
> 
> On Sat, Apr 27, 2019 at 10:10:29AM +0300, laurentiu.tu...@nxp.com wrote:
> > From: Laurentiu Tudor 
> >
> > The driver relies on the no longer valid assumption that dma addresses
> > (iovas) are identical to physical addressees and uses phys_to_virt() to
> > make iova -> vaddr conversions. Fix this by adding a function that does
> > proper iova -> phys conversions using the iommu api and update the code
> > to use it.
> > Also, a dma_unmap_single() call had to be moved further down the code
> > because iova -> vaddr conversions were required before the unmap.
> > For now only the contiguous frame case is handled and the SG case is
> > split in a following patch.
> > While at it, clean-up a redundant dpaa_bpid2pool() and pass the bp
> > as parameter.
> 
> Err, this is broken.  A driver using the DMA API has no business
> call IOMMU APIs.  Just save the _virtual_ address used for the mapping
> away and use that again.  We should not go through crazy gymnastics
> like this.

I think that due to the particularity of this hardware we don't have a way of 
saving the VA, but I'd let my colleagues maintaining this driver to comment 
more on why we need to do this.

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


RE: [PATCH v2 9/9] dpaa_eth: fix SG frame cleanup

2019-05-02 Thread Laurentiu Tudor
Hi Joakim,

> -Original Message-
> From: Joakim Tjernlund 
> Sent: Saturday, April 27, 2019 8:11 PM
> 
> On Sat, 2019-04-27 at 10:10 +0300, laurentiu.tu...@nxp.com wrote:
> > From: Laurentiu Tudor 
> >
> > Fix issue with the entry indexing in the sg frame cleanup code being
> > off-by-1. This problem showed up when doing some basic iperf tests and
> > manifested in traffic coming to a halt.
> >
> > Signed-off-by: Laurentiu Tudor 
> > Acked-by: Madalin Bucur 
> 
> Wasn't this a stable candidate too?

Yes, it is. I forgot to add the cc:stable tag, sorry about that.

---
Best Regards, Laurentiu
 
> > ---
> >  drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > index daede7272768..40420edc9ce6 100644
> > --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
> > @@ -1663,7 +1663,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const
> struct dpaa_priv *priv,
> >  qm_sg_entry_get_len([0]), dma_dir);
> >
> > /* remaining pages were mapped with skb_frag_dma_map()
> */
> > -   for (i = 1; i < nr_frags; i++) {
> > +   for (i = 1; i <= nr_frags; i++) {
> > WARN_ON(qm_sg_entry_is_ext([i]));
> >
> > dma_unmap_page(dev, qm_sg_addr([i]),
> > --
> > 2.17.1
> >

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


[PATCH v2 8/9] dpaa_eth: fix iova handling for sg frames

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

The driver relies on the no longer valid assumption that dma addresses
(iovas) are identical to physical addressees and uses phys_to_virt() to
make iova -> vaddr conversions. Fix this also for scatter-gather frames
using the iova -> phys conversion function added in the previous patch.
While at it, clean-up a redundant dpaa_bpid2pool() and pass the bp
as parameter.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 41 +++
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index f17edc80dc37..daede7272768 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1646,14 +1646,17 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
 
if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
nr_frags = skb_shinfo(skb)->nr_frags;
-   dma_unmap_single(dev, addr,
-qm_fd_get_offset(fd) + DPAA_SGT_SIZE,
-dma_dir);
 
/* The sgt buffer has been allocated with netdev_alloc_frag(),
 * it's from lowmem.
 */
-   sgt = phys_to_virt(addr + qm_fd_get_offset(fd));
+   sgt = phys_to_virt(dpaa_iova_to_phys(dev,
+addr +
+qm_fd_get_offset(fd)));
+
+   dma_unmap_single(dev, addr,
+qm_fd_get_offset(fd) + DPAA_SGT_SIZE,
+dma_dir);
 
/* sgt[0] is from lowmem, was dma_map_single()-ed */
dma_unmap_single(dev, qm_sg_addr([0]),
@@ -1668,7 +1671,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
}
 
/* Free the page frag that we allocated on Tx */
-   skb_free_frag(phys_to_virt(addr));
+   skb_free_frag(skbh);
} else {
dma_unmap_single(dev, addr,
 skb_tail_pointer(skb) - (u8 *)skbh, dma_dir);
@@ -1729,14 +1732,14 @@ static struct sk_buff *contig_fd_to_skb(const struct 
dpaa_priv *priv,
  * The page fragment holding the S/G Table is recycled here.
  */
 static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
-   const struct qm_fd *fd)
+   const struct qm_fd *fd,
+   struct dpaa_bp *dpaa_bp,
+   void *vaddr)
 {
ssize_t fd_off = qm_fd_get_offset(fd);
-   dma_addr_t addr = qm_fd_addr(fd);
const struct qm_sg_entry *sgt;
struct page *page, *head_page;
-   struct dpaa_bp *dpaa_bp;
-   void *vaddr, *sg_vaddr;
+   void *sg_vaddr;
int frag_off, frag_len;
struct sk_buff *skb;
dma_addr_t sg_addr;
@@ -1745,7 +1748,6 @@ static struct sk_buff *sg_fd_to_skb(const struct 
dpaa_priv *priv,
int *count_ptr;
int i;
 
-   vaddr = phys_to_virt(addr);
WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
 
/* Iterate through the SGT entries and add data buffers to the skb */
@@ -1756,14 +1758,18 @@ static struct sk_buff *sg_fd_to_skb(const struct 
dpaa_priv *priv,
WARN_ON(qm_sg_entry_is_ext([i]));
 
sg_addr = qm_sg_addr([i]);
-   sg_vaddr = phys_to_virt(sg_addr);
-   WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
-   SMP_CACHE_BYTES));
 
/* We may use multiple Rx pools */
dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
-   if (!dpaa_bp)
+   if (!dpaa_bp) {
+   pr_info("%s: fail to get dpaa_bp for sg bpid %d\n",
+   __func__, sgt[i].bpid);
goto free_buffers;
+   }
+   sg_vaddr = phys_to_virt(dpaa_iova_to_phys(dpaa_bp->dev,
+ sg_addr));
+   WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
+   SMP_CACHE_BYTES));
 
count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
dma_unmap_single(dpaa_bp->dev, sg_addr, dpaa_bp->size,
@@ -1835,10 +1841,11 @@ static struct sk_buff *sg_fd_to_skb(const struct 
dpaa_priv *priv,
/* free all the SG entries */
for (i = 0; i < DPAA_SGT_MAX_ENTRIES ; i++) {
sg_addr = qm_sg_addr([i]);
-   sg_vaddr = phys_to_virt(sg_addr);
-   skb_free_frag(sg_vaddr);
dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
if (dpaa_bp) {
+   sg_add

[PATCH v2 6/9] dpaa_eth: base dma mappings on the fman rx port

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

The dma transactions initiator is the rx fman port so that's the device
that the dma mappings should be done. Previously the mappings were done
through the MAC device which makes no sense because it's neither dma-able
nor connected in any way to smmu.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index 647e90e7434f..cdc7e6d83f77 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2805,8 +2805,15 @@ static int dpaa_eth_probe(struct platform_device *pdev)
return -ENODEV;
}
 
+   mac_dev = dpaa_mac_dev_get(pdev);
+   if (IS_ERR(mac_dev)) {
+   dev_err(>dev, "dpaa_mac_dev_get() failed\n");
+   err = PTR_ERR(mac_dev);
+   goto probe_err;
+   }
+
/* device used for DMA mapping */
-   dev = pdev->dev.parent;
+   dev = fman_port_get_device(mac_dev->port[RX]);
err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
if (err) {
dev_err(dev, "dma_coerce_mask_and_coherent() failed\n");
@@ -2831,13 +2838,6 @@ static int dpaa_eth_probe(struct platform_device *pdev)
 
priv->msg_enable = netif_msg_init(debug, DPAA_MSG_DEFAULT);
 
-   mac_dev = dpaa_mac_dev_get(pdev);
-   if (IS_ERR(mac_dev)) {
-   dev_err(dev, "dpaa_mac_dev_get() failed\n");
-   err = PTR_ERR(mac_dev);
-   goto free_netdev;
-   }
-
/* If fsl_fm_max_frm is set to a higher value than the all-common 1500,
 * we choose conservatively and let the user explicitly set a higher
 * MTU via ifconfig. Otherwise, the user may end up with different MTUs
@@ -2973,9 +2973,9 @@ static int dpaa_eth_probe(struct platform_device *pdev)
qman_release_cgrid(priv->cgr_data.cgr.cgrid);
 free_dpaa_bps:
dpaa_bps_free(priv);
-free_netdev:
dev_set_drvdata(dev, NULL);
free_netdev(net_dev);
+probe_err:
 
return err;
 }
-- 
2.17.1

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


[PATCH v2 3/9] fsl/fman: backup and restore ICID registers

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

During probing, FMAN is reset thus losing all its register
settings. Backup port ICID registers before reset and restore
them after, similarly to how it's done on powerpc / PAMU based
platforms.
This also has the side effect of disabling the old code path
(liodn backup/restore handling) that obviously make no sense
in the context of SMMU on ARMs.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 drivers/net/ethernet/freescale/fman/fman.c | 35 +-
 drivers/net/ethernet/freescale/fman/fman.h |  4 +++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/fman/fman.c 
b/drivers/net/ethernet/freescale/fman/fman.c
index e80fedb27cee..ae833e215b74 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -629,6 +629,7 @@ static void set_port_order_restoration(struct fman_fpm_regs 
__iomem *fpm_rg,
iowrite32be(tmp, _rg->fmfp_prc);
 }
 
+#ifdef CONFIG_PPC
 static void set_port_liodn(struct fman *fman, u8 port_id,
   u32 liodn_base, u32 liodn_ofst)
 {
@@ -646,6 +647,27 @@ static void set_port_liodn(struct fman *fman, u8 port_id,
iowrite32be(tmp, >dma_regs->fmdmplr[port_id / 2]);
iowrite32be(liodn_ofst, >bmi_regs->fmbm_spliodn[port_id - 1]);
 }
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+static void save_restore_port_icids(struct fman *fman, bool save)
+{
+   int port_idxes[] = {
+   0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc,
+   0xd, 0xe, 0xf, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+   0x10, 0x11, 0x30, 0x31
+   };
+   int idx, i;
+
+   for (i = 0; i < ARRAY_SIZE(port_idxes); i++) {
+   idx = port_idxes[i];
+   if (save)
+   fman->sp_icids[idx] =
+   ioread32be(>bmi_regs->fmbm_spliodn[idx]);
+   else
+   iowrite32be(fman->sp_icids[idx],
+   >bmi_regs->fmbm_spliodn[idx]);
+   }
+}
+#endif
 
 static void enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg)
 {
@@ -1914,7 +1936,10 @@ static int fman_reset(struct fman *fman)
 static int fman_init(struct fman *fman)
 {
struct fman_cfg *cfg = NULL;
-   int err = 0, i, count;
+   int err = 0, count;
+#ifdef CONFIG_PPC
+   int i;
+#endif
 
if (is_init_done(fman->cfg))
return -EINVAL;
@@ -1934,6 +1959,7 @@ static int fman_init(struct fman *fman)
memset_io((void __iomem *)(fman->base_addr + CGP_OFFSET), 0,
  fman->state->fm_port_num_of_cg);
 
+#ifdef CONFIG_PPC
/* Save LIODN info before FMan reset
 * Skipping non-existent port 0 (i = 1)
 */
@@ -1953,6 +1979,9 @@ static int fman_init(struct fman *fman)
}
fman->liodn_base[i] = liodn_base;
}
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+   save_restore_port_icids(fman, true);
+#endif
 
err = fman_reset(fman);
if (err)
@@ -2181,8 +2210,12 @@ int fman_set_port_params(struct fman *fman,
if (err)
goto return_err;
 
+#ifdef CONFIG_PPC
set_port_liodn(fman, port_id, fman->liodn_base[port_id],
   fman->liodn_offset[port_id]);
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+   save_restore_port_icids(fman, false);
+#endif
 
if (fman->state->rev_info.major < 6)
set_port_order_restoration(fman->fpm_regs, port_id);
diff --git a/drivers/net/ethernet/freescale/fman/fman.h 
b/drivers/net/ethernet/freescale/fman/fman.h
index 935c317fa696..19f20fa58053 100644
--- a/drivers/net/ethernet/freescale/fman/fman.h
+++ b/drivers/net/ethernet/freescale/fman/fman.h
@@ -346,8 +346,12 @@ struct fman {
unsigned long fifo_offset;
size_t fifo_size;
 
+#ifdef CONFIG_PPC
u32 liodn_base[64];
u32 liodn_offset[64];
+#elif defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+   u32 sp_icids[64];
+#endif
 
struct fman_dts_params dts_params;
 };
-- 
2.17.1

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


[PATCH v2 9/9] dpaa_eth: fix SG frame cleanup

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

Fix issue with the entry indexing in the sg frame cleanup code being
off-by-1. This problem showed up when doing some basic iperf tests and
manifested in traffic coming to a halt.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index daede7272768..40420edc9ce6 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -1663,7 +1663,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
 qm_sg_entry_get_len([0]), dma_dir);
 
/* remaining pages were mapped with skb_frag_dma_map() */
-   for (i = 1; i < nr_frags; i++) {
+   for (i = 1; i <= nr_frags; i++) {
WARN_ON(qm_sg_entry_is_ext([i]));
 
dma_unmap_page(dev, qm_sg_addr([i]),
-- 
2.17.1

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


[PATCH v2 5/9] dpaa_eth: defer probing after qbman

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

Enabling SMMU altered the order of device probing causing the dpaa1
ethernet driver to get probed before qbman and causing a boot crash.
Add predictability in the probing order by deferring the ethernet
driver probe after qbman and portals by using the recently introduced
qbman APIs.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 31 +++
 1 file changed, 31 insertions(+)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index dfebc30c4841..647e90e7434f 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2774,6 +2774,37 @@ static int dpaa_eth_probe(struct platform_device *pdev)
int err = 0, i, channel;
struct device *dev;
 
+   err = bman_is_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev, "failing probe due to bman probe error\n");
+   return -ENODEV;
+   }
+   err = qman_is_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev, "failing probe due to qman probe error\n");
+   return -ENODEV;
+   }
+   err = bman_portals_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev,
+   "failing probe due to bman portals probe error\n");
+   return -ENODEV;
+   }
+   err = qman_portals_probed();
+   if (!err)
+   return -EPROBE_DEFER;
+   if (err < 0) {
+   dev_err(>dev,
+   "failing probe due to qman portals probe error\n");
+   return -ENODEV;
+   }
+
/* device used for DMA mapping */
dev = pdev->dev.parent;
err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(40));
-- 
2.17.1

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


[PATCH v2 0/9] Prerequisites for NXP LS104xA SMMU enablement

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

This patch series contains several fixes in preparation for SMMU
support on NXP LS1043A and LS1046A chips. Once these get picked up,
I'll submit the actual SMMU enablement patches consisting in the
required device tree changes.

This patch series contains only part of the previously submitted one,
(including also the device tree changes) available here:

https://patchwork.kernel.org/cover/10634443/

Changes in v2:
 - dropped patches dealing with mapping reserved memory in iommu
 - changed logic for qman portal probe status (Leo)
 - moved "#ifdef CONFIG_PAMU" in header file (Leo)
 - rebased on v5.1.0-rc5

Laurentiu Tudor (9):
  soc/fsl/qman: fixup liodns only on ppc targets
  soc/fsl/qbman_portals: add APIs to retrieve the probing status
  fsl/fman: backup and restore ICID registers
  fsl/fman: add API to get the device behind a fman port
  dpaa_eth: defer probing after qbman
  dpaa_eth: base dma mappings on the fman rx port
  dpaa_eth: fix iova handling for contiguous frames
  dpaa_eth: fix iova handling for sg frames
  dpaa_eth: fix SG frame cleanup

 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 136 --
 drivers/net/ethernet/freescale/fman/fman.c|  35 -
 drivers/net/ethernet/freescale/fman/fman.h|   4 +
 .../net/ethernet/freescale/fman/fman_port.c   |  14 ++
 .../net/ethernet/freescale/fman/fman_port.h   |   2 +
 drivers/soc/fsl/qbman/bman_portal.c   |  20 ++-
 drivers/soc/fsl/qbman/qman_ccsr.c |   2 +-
 drivers/soc/fsl/qbman/qman_portal.c   |  21 ++-
 drivers/soc/fsl/qbman/qman_priv.h |   9 +-
 include/soc/fsl/bman.h|   8 ++
 include/soc/fsl/qman.h|   9 ++
 11 files changed, 202 insertions(+), 58 deletions(-)

-- 
2.17.1

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


[PATCH v2 7/9] dpaa_eth: fix iova handling for contiguous frames

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

The driver relies on the no longer valid assumption that dma addresses
(iovas) are identical to physical addressees and uses phys_to_virt() to
make iova -> vaddr conversions. Fix this by adding a function that does
proper iova -> phys conversions using the iommu api and update the code
to use it.
Also, a dma_unmap_single() call had to be moved further down the code
because iova -> vaddr conversions were required before the unmap.
For now only the contiguous frame case is handled and the SG case is
split in a following patch.
While at it, clean-up a redundant dpaa_bpid2pool() and pass the bp
as parameter.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 .../net/ethernet/freescale/dpaa/dpaa_eth.c| 44 ++-
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c 
b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index cdc7e6d83f77..f17edc80dc37 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -50,6 +50,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1595,6 +1596,17 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
return 0;
 }
 
+static phys_addr_t dpaa_iova_to_phys(struct device *dev, dma_addr_t addr)
+{
+   struct iommu_domain *domain;
+
+   domain = iommu_get_domain_for_dev(dev);
+   if (domain)
+   return iommu_iova_to_phys(domain, addr);
+   else
+   return addr;
+}
+
 /* Cleanup function for outgoing frame descriptors that were built on Tx path,
  * either contiguous frames or scatter/gather ones.
  * Skb freeing is not handled here.
@@ -1617,7 +1629,7 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct 
dpaa_priv *priv,
int nr_frags, i;
u64 ns;
 
-   skbh = (struct sk_buff **)phys_to_virt(addr);
+   skbh = (struct sk_buff **)phys_to_virt(dpaa_iova_to_phys(dev, addr));
skb = *skbh;
 
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
@@ -1687,25 +1699,21 @@ static u8 rx_csum_offload(const struct dpaa_priv *priv, 
const struct qm_fd *fd)
  * accommodate the shared info area of the skb.
  */
 static struct sk_buff *contig_fd_to_skb(const struct dpaa_priv *priv,
-   const struct qm_fd *fd)
+   const struct qm_fd *fd,
+   struct dpaa_bp *dpaa_bp,
+   void *vaddr)
 {
ssize_t fd_off = qm_fd_get_offset(fd);
-   dma_addr_t addr = qm_fd_addr(fd);
-   struct dpaa_bp *dpaa_bp;
struct sk_buff *skb;
-   void *vaddr;
 
-   vaddr = phys_to_virt(addr);
WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
 
-   dpaa_bp = dpaa_bpid2pool(fd->bpid);
-   if (!dpaa_bp)
-   goto free_buffer;
-
skb = build_skb(vaddr, dpaa_bp->size +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
-   if (WARN_ONCE(!skb, "Build skb failure on Rx\n"))
-   goto free_buffer;
+   if (WARN_ONCE(!skb, "Build skb failure on Rx\n")) {
+   skb_free_frag(vaddr);
+   return NULL;
+   }
WARN_ON(fd_off != priv->rx_headroom);
skb_reserve(skb, fd_off);
skb_put(skb, qm_fd_get_length(fd));
@@ -1713,10 +1721,6 @@ static struct sk_buff *contig_fd_to_skb(const struct 
dpaa_priv *priv,
skb->ip_summed = rx_csum_offload(priv, fd);
 
return skb;
-
-free_buffer:
-   skb_free_frag(vaddr);
-   return NULL;
 }
 
 /* Build an skb with the data of the first S/G entry in the linear portion and
@@ -2309,12 +2313,12 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct 
qman_portal *portal,
if (!dpaa_bp)
return qman_cb_dqrr_consume;
 
-   dma_unmap_single(dpaa_bp->dev, addr, dpaa_bp->size, DMA_FROM_DEVICE);
-
/* prefetch the first 64 bytes of the frame or the SGT start */
-   vaddr = phys_to_virt(addr);
+   vaddr = phys_to_virt(dpaa_iova_to_phys(dpaa_bp->dev, addr));
prefetch(vaddr + qm_fd_get_offset(fd));
 
+   dma_unmap_single(dpaa_bp->dev, addr, dpaa_bp->size, DMA_FROM_DEVICE);
+
/* The only FD types that we may receive are contig and S/G */
WARN_ON((fd_format != qm_fd_contig) && (fd_format != qm_fd_sg));
 
@@ -2325,7 +2329,7 @@ static enum qman_cb_dqrr_result rx_default_dqrr(struct 
qman_portal *portal,
(*count_ptr)--;
 
if (likely(fd_format == qm_fd_contig))
-   skb = contig_fd_to_skb(priv, fd);
+   skb = contig_fd_to_skb(priv, fd, dpaa_bp, vaddr);
else
skb = sg_fd_to_skb(priv, fd);
if (!skb)
-- 
2.17.1

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


[PATCH v2 2/9] soc/fsl/qbman_portals: add APIs to retrieve the probing status

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

Add a couple of new APIs to check the probing status of the required
cpu bound qman and bman portals:
 'int bman_portals_probed()' and 'int qman_portals_probed()'.
They return the following values.
 *  1 if qman/bman portals were all probed correctly
 *  0 if qman/bman portals were not yet probed
 * -1 if probing of qman/bman portals failed
Portals are considered successful probed if no error occurred during
the probing of any of the portals and if enough portals were probed
to have one available for each cpu.
The error handling paths were slightly rearranged in order to fit this
new functionality without being too intrusive.
Drivers that use qman/bman portal driver services are required to use
these APIs before calling any functions exported by these drivers or
otherwise they will crash the kernel.
First user will be the dpaa1 ethernet driver, coming in a subsequent
patch.

Signed-off-by: Laurentiu Tudor 
---
 drivers/soc/fsl/qbman/bman_portal.c | 20 
 drivers/soc/fsl/qbman/qman_portal.c | 21 +
 include/soc/fsl/bman.h  |  8 
 include/soc/fsl/qman.h  |  9 +
 4 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/fsl/qbman/bman_portal.c 
b/drivers/soc/fsl/qbman/bman_portal.c
index 2c95cf59f3e7..cf4f10d6f590 100644
--- a/drivers/soc/fsl/qbman/bman_portal.c
+++ b/drivers/soc/fsl/qbman/bman_portal.c
@@ -32,6 +32,7 @@
 
 static struct bman_portal *affine_bportals[NR_CPUS];
 static struct cpumask portal_cpus;
+static int __bman_portals_probed;
 /* protect bman global registers and global data shared among portals */
 static DEFINE_SPINLOCK(bman_lock);
 
@@ -87,6 +88,12 @@ static int bman_online_cpu(unsigned int cpu)
return 0;
 }
 
+int bman_portals_probed(void)
+{
+   return __bman_portals_probed;
+}
+EXPORT_SYMBOL_GPL(bman_portals_probed);
+
 static int bman_portal_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -104,8 +111,10 @@ static int bman_portal_probe(struct platform_device *pdev)
}
 
pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
-   if (!pcfg)
+   if (!pcfg) {
+   __bman_portals_probed = -1;
return -ENOMEM;
+   }
 
pcfg->dev = dev;
 
@@ -113,14 +122,14 @@ static int bman_portal_probe(struct platform_device *pdev)
 DPAA_PORTAL_CE);
if (!addr_phys[0]) {
dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
-   return -ENXIO;
+   goto err_ioremap1;
}
 
addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
 DPAA_PORTAL_CI);
if (!addr_phys[1]) {
dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
-   return -ENXIO;
+   goto err_ioremap1;
}
 
pcfg->cpu = -1;
@@ -128,7 +137,7 @@ static int bman_portal_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(dev, "Can't get %pOF IRQ'\n", node);
-   return -ENXIO;
+   goto err_ioremap1;
}
pcfg->irq = irq;
 
@@ -150,6 +159,7 @@ static int bman_portal_probe(struct platform_device *pdev)
spin_lock(_lock);
cpu = cpumask_next_zero(-1, _cpus);
if (cpu >= nr_cpu_ids) {
+   __bman_portals_probed = 1;
/* unassigned portal, skip init */
spin_unlock(_lock);
return 0;
@@ -175,6 +185,8 @@ static int bman_portal_probe(struct platform_device *pdev)
 err_ioremap2:
memunmap(pcfg->addr_virt_ce);
 err_ioremap1:
+__bman_portals_probed = -1;
+
return -ENXIO;
 }
 
diff --git a/drivers/soc/fsl/qbman/qman_portal.c 
b/drivers/soc/fsl/qbman/qman_portal.c
index 661c9b234d32..e2186b681d87 100644
--- a/drivers/soc/fsl/qbman/qman_portal.c
+++ b/drivers/soc/fsl/qbman/qman_portal.c
@@ -38,6 +38,7 @@ EXPORT_SYMBOL(qman_dma_portal);
 #define CONFIG_FSL_DPA_PIRQ_FAST  1
 
 static struct cpumask portal_cpus;
+static int __qman_portals_probed;
 /* protect qman global registers and global data shared among portals */
 static DEFINE_SPINLOCK(qman_lock);
 
@@ -220,6 +221,12 @@ static int qman_online_cpu(unsigned int cpu)
return 0;
 }
 
+int qman_portals_probed(void)
+{
+   return __qman_portals_probed;
+}
+EXPORT_SYMBOL_GPL(qman_portals_probed);
+
 static int qman_portal_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -238,8 +245,10 @@ static int qman_portal_probe(struct platform_device *pdev)
}
 
pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL);
-   if (!pcfg)
+   if (!pcfg) {
+   __qman_portals_probed = -1;
return -ENOMEM;
+   }
 
pcfg->dev = dev;
 

[PATCH v2 1/9] soc/fsl/qman: fixup liodns only on ppc targets

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

ARM SoCs use SMMU so the liodn fixup done in the qman driver is no
longer making sense and it also breaks the ICID settings inherited
from u-boot. Do the fixups only for PPC targets.

Signed-off-by: Laurentiu Tudor 
---
 drivers/soc/fsl/qbman/qman_ccsr.c | 2 +-
 drivers/soc/fsl/qbman/qman_priv.h | 9 -
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/fsl/qbman/qman_ccsr.c 
b/drivers/soc/fsl/qbman/qman_ccsr.c
index 109b38de3176..a6bb43007d03 100644
--- a/drivers/soc/fsl/qbman/qman_ccsr.c
+++ b/drivers/soc/fsl/qbman/qman_ccsr.c
@@ -596,7 +596,7 @@ static int qman_init_ccsr(struct device *dev)
 }
 
 #define LIO_CFG_LIODN_MASK 0x0fff
-void qman_liodn_fixup(u16 channel)
+void __qman_liodn_fixup(u16 channel)
 {
static int done;
static u32 liodn_offset;
diff --git a/drivers/soc/fsl/qbman/qman_priv.h 
b/drivers/soc/fsl/qbman/qman_priv.h
index 75a8f905f8f7..04515718cfd9 100644
--- a/drivers/soc/fsl/qbman/qman_priv.h
+++ b/drivers/soc/fsl/qbman/qman_priv.h
@@ -193,7 +193,14 @@ extern struct gen_pool *qm_cgralloc; /* CGR ID allocator */
 u32 qm_get_pools_sdqcr(void);
 
 int qman_wq_alloc(void);
-void qman_liodn_fixup(u16 channel);
+#ifdef CONFIG_FSL_PAMU
+#define qman_liodn_fixup __qman_liodn_fixup
+#else
+static inline void qman_liodn_fixup(u16 channel)
+{
+}
+#endif
+void __qman_liodn_fixup(u16 channel);
 void qman_set_sdest(u16 channel, unsigned int cpu_idx);
 
 struct qman_portal *qman_create_affine_portal(
-- 
2.17.1

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


[PATCH v2 4/9] fsl/fman: add API to get the device behind a fman port

2019-04-27 Thread laurentiu . tudor
From: Laurentiu Tudor 

Add an API that retrieves the 'struct device' that the specified fman
port probed against. The new API will be used in a subsequent iommu
enablement related patch.

Signed-off-by: Laurentiu Tudor 
Acked-by: Madalin Bucur 
---
 drivers/net/ethernet/freescale/fman/fman_port.c | 14 ++
 drivers/net/ethernet/freescale/fman/fman_port.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c 
b/drivers/net/ethernet/freescale/fman/fman_port.c
index ee82ee1384eb..bd76c9730692 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.c
+++ b/drivers/net/ethernet/freescale/fman/fman_port.c
@@ -1728,6 +1728,20 @@ u32 fman_port_get_qman_channel_id(struct fman_port *port)
 }
 EXPORT_SYMBOL(fman_port_get_qman_channel_id);
 
+/**
+ * fman_port_get_device
+ * port:   Pointer to the FMan port device
+ *
+ * Get the 'struct device' associated to the specified FMan port device
+ *
+ * Return: pointer to associated 'struct device'
+ */
+struct device *fman_port_get_device(struct fman_port *port)
+{
+   return port->dev;
+}
+EXPORT_SYMBOL(fman_port_get_device);
+
 int fman_port_get_hash_result_offset(struct fman_port *port, u32 *offset)
 {
if (port->buffer_offsets.hash_result_offset == ILLEGAL_BASE)
diff --git a/drivers/net/ethernet/freescale/fman/fman_port.h 
b/drivers/net/ethernet/freescale/fman/fman_port.h
index 9dbb69f40121..82f12661a46d 100644
--- a/drivers/net/ethernet/freescale/fman/fman_port.h
+++ b/drivers/net/ethernet/freescale/fman/fman_port.h
@@ -157,4 +157,6 @@ int fman_port_get_tstamp(struct fman_port *port, const void 
*data, u64 *tstamp);
 
 struct fman_port *fman_port_bind(struct device *dev);
 
+struct device *fman_port_get_device(struct fman_port *port);
+
 #endif /* __FMAN_PORT_H */
-- 
2.17.1

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


Re: [RFC PATCH] dma-mapping: create iommu mapping for newly allocated dma coherent mem

2019-04-25 Thread Laurentiu Tudor
Hi Christoph,

On 24.04.2019 17:57, Christoph Hellwig wrote:
> I'd be happy to offload all of the mentioned tasks to you if you
> volunteer.

Alright, I think I mostly got it and can start with the two usb drivers 
you mentioned. Just need a few clarifications, please see inline.

> I think the first step is to move the two USB controller that can only
> DMA to their own BAR off the existing DMA coherent infrastructure.  The
> controllers are already identified using the HCD_LOCAL_MEM flag, so we
> just need to key off that in the hcd_buffer_* routines and call into a

So if HCD_LOCAL_MEM is set I should call into the gen_pool api instead 
of existing dma_{alloc,free}_coherent().

> genalloc that has been fed using the bar, replacing the current
> dma_declare_coherent usage.  Take a look at drivers/pci/p2pdma.c
> for another example of allocating bits of a BAR using genalloc.

Where should I place the reference to the gen_pool? How does local_pool 
in 'struct hcd_usb' sound?

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [RFC PATCH] dma-mapping: create iommu mapping for newly allocated dma coherent mem

2019-04-23 Thread Laurentiu Tudor
Hello,

> -Original Message-
> From: Christoph Hellwig 
> Sent: Monday, April 22, 2019 9:11 PM
> 
> On Mon, Apr 22, 2019 at 07:51:25PM +0300, laurentiu.tu...@nxp.com wrote:
> > From: Laurentiu Tudor 
> >
> > If possible / available call into the DMA API to get a proper iommu
> > mapping and a dma address for the newly allocated coherent dma memory.
> 
> I don't think this is so simple.  The original use case of
> dma_declare_coherent_memory was memory that is local to a device, where
> we copy in data through a MMIO mapping and the device can then access
> it.  This use case still seems to be alive in the ohci-sm501 and
> ohci-tmio drivers.  Going through the iommu in those cases would be
> counter productive.

I had a feeling that I didn't get the whole story and something isn't quite 
right with this patch.  But I'm happy that we have a discussion started on the 
topic and, I must say, I'm very interested in getting to the bottom of it (I 
have some patches enabling SMMU on a couple of NXP chips and depend on 
resolving this).
I'll try to understand what you're planning but in the meantime please let me 
know if you think I can be of any help.

---
Thanks & Best Regards, Laurentiu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[RFC PATCH] dma-mapping: create iommu mapping for newly allocated dma coherent mem

2019-04-22 Thread laurentiu . tudor
From: Laurentiu Tudor 

If possible / available call into the DMA API to get a proper iommu
mapping and a dma address for the newly allocated coherent dma memory.

Signed-off-by: Laurentiu Tudor 
---
 arch/arm/mm/dma-mapping-nommu.c |  3 ++-
 include/linux/dma-mapping.h | 12 ++---
 kernel/dma/coherent.c   | 45 +++--
 kernel/dma/mapping.c|  3 ++-
 4 files changed, 44 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c
index f304b10e23a4..2c42e83a6995 100644
--- a/arch/arm/mm/dma-mapping-nommu.c
+++ b/arch/arm/mm/dma-mapping-nommu.c
@@ -74,7 +74,8 @@ static void arm_nommu_dma_free(struct device *dev, size_t 
size,
dma_direct_free_pages(dev, size, cpu_addr, dma_addr, attrs);
} else {
int ret = dma_release_from_global_coherent(get_order(size),
-  cpu_addr);
+  cpu_addr, size,
+  dma_addr);
 
WARN_ON_ONCE(ret == 0);
}
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 6309a721394b..cb23334608a7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -161,19 +161,21 @@ static inline int is_device_dma_capable(struct device 
*dev)
  */
 int dma_alloc_from_dev_coherent(struct device *dev, ssize_t size,
   dma_addr_t *dma_handle, void **ret);
-int dma_release_from_dev_coherent(struct device *dev, int order, void *vaddr);
+int dma_release_from_dev_coherent(struct device *dev, int order, void *vaddr,
+ ssize_t size, dma_addr_t dma_handle);
 
 int dma_mmap_from_dev_coherent(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, size_t size, int *ret);
 
 void *dma_alloc_from_global_coherent(ssize_t size, dma_addr_t *dma_handle);
-int dma_release_from_global_coherent(int order, void *vaddr);
+int dma_release_from_global_coherent(int order, void *vaddr, ssize_t size,
+dma_addr_t dma_handle);
 int dma_mmap_from_global_coherent(struct vm_area_struct *vma, void *cpu_addr,
  size_t size, int *ret);
 
 #else
 #define dma_alloc_from_dev_coherent(dev, size, handle, ret) (0)
-#define dma_release_from_dev_coherent(dev, order, vaddr) (0)
+#define dma_release_from_dev_coherent(dev, order, vaddr, size, dma_handle) (0)
 #define dma_mmap_from_dev_coherent(dev, vma, vaddr, order, ret) (0)
 
 static inline void *dma_alloc_from_global_coherent(ssize_t size,
@@ -182,7 +184,9 @@ static inline void *dma_alloc_from_global_coherent(ssize_t 
size,
return NULL;
 }
 
-static inline int dma_release_from_global_coherent(int order, void *vaddr)
+static inline int dma_release_from_global_coherent(int order, void *vaddr
+  ssize_t size,
+  dma_addr_t dma_handle)
 {
return 0;
 }
diff --git a/kernel/dma/coherent.c b/kernel/dma/coherent.c
index 29fd6590dc1e..b40439d6feaa 100644
--- a/kernel/dma/coherent.c
+++ b/kernel/dma/coherent.c
@@ -135,13 +135,15 @@ void dma_release_declared_memory(struct device *dev)
 }
 EXPORT_SYMBOL(dma_release_declared_memory);
 
-static void *__dma_alloc_from_coherent(struct dma_coherent_mem *mem,
-   ssize_t size, dma_addr_t *dma_handle)
+static void *__dma_alloc_from_coherent(struct device *dev,
+  struct dma_coherent_mem *mem,
+  ssize_t size, dma_addr_t *dma_handle)
 {
int order = get_order(size);
unsigned long flags;
int pageno;
void *ret;
+   const struct dma_map_ops *ops = dev ? get_dma_ops(dev) : NULL;
 
spin_lock_irqsave(>spinlock, flags);
 
@@ -155,10 +157,16 @@ static void *__dma_alloc_from_coherent(struct 
dma_coherent_mem *mem,
/*
 * Memory was found in the coherent area.
 */
-   *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
ret = mem->virt_base + (pageno << PAGE_SHIFT);
spin_unlock_irqrestore(>spinlock, flags);
memset(ret, 0, size);
+   if (ops && ops->map_resource)
+   *dma_handle = ops->map_resource(dev,
+   mem->device_base +
+   (pageno << PAGE_SHIFT),
+   size, DMA_BIDIRECTIONAL, 0);
+   else
+   *dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
return ret;
 err:
spin_unlock_irqrestore(>spinlock, flags);
@@ -187,7 +195,7 @@ int dma_alloc_from_dev_coherent(struct device *dev, ssize_t 
size,

RE: [PATCH 02/13] soc/fsl/bman: map FBPR area in the iommu

2019-04-19 Thread Laurentiu Tudor
Hi Robin,

> -Original Message-
> From: Robin Murphy 
> Sent: Friday, March 29, 2019 4:51 PM
> 
> On 29/03/2019 14:00, laurentiu.tu...@nxp.com wrote:
> > From: Laurentiu Tudor 
> >
> > Add a one-to-one iommu mapping for bman private data memory (FBPR).
> > This is required for BMAN to work without faults behind an iommu.
> >
> > Signed-off-by: Laurentiu Tudor 
> > ---
> >   drivers/soc/fsl/qbman/bman_ccsr.c | 11 +++
> >   1 file changed, 11 insertions(+)
> >
> > diff --git a/drivers/soc/fsl/qbman/bman_ccsr.c
> b/drivers/soc/fsl/qbman/bman_ccsr.c
> > index 7c3cc968053c..b209c79511bb 100644
> > --- a/drivers/soc/fsl/qbman/bman_ccsr.c
> > +++ b/drivers/soc/fsl/qbman/bman_ccsr.c
> > @@ -29,6 +29,7 @@
> >*/
> >
> >   #include "bman_priv.h"
> > +#include 
> >
> >   u16 bman_ip_rev;
> >   EXPORT_SYMBOL(bman_ip_rev);
> > @@ -178,6 +179,7 @@ static int fsl_bman_probe(struct platform_device
> *pdev)
> > int ret, err_irq;
> > struct device *dev = >dev;
> > struct device_node *node = dev->of_node;
> > +   struct iommu_domain *domain;
> > struct resource *res;
> > u16 id, bm_pool_cnt;
> > u8 major, minor;
> > @@ -225,6 +227,15 @@ static int fsl_bman_probe(struct platform_device
> *pdev)
> >
> > dev_dbg(dev, "Allocated FBPR 0x%llx 0x%zx\n", fbpr_a, fbpr_sz);
> >
> > +   /* Create an 1-to-1 iommu mapping for FBPR area */
> > +   domain = iommu_get_domain_for_dev(dev);
> 
> If that's expected to be the default domain that you're grabbing, then
> this is *incredibly* fragile. There's nothing to stop the IOVA that you
> forcibly map from being automatically allocated later and causing some
> other DMA mapping to fail noisily and unexpectedly. Furthermore, have
> you tried this with "iommu.passthrough=1"?
> 
> That said, I really don't understand what's going on here anyway :/
> 
> As far as I can tell from qbman_init_private_mem(), fbpr_a comes from
> dma_alloc_coherent() and thus would already be a mapped IOVA - isn't
> this the stuff that Roy converted to nicely use shared-dma-pool regions
> a while ago?
> 

Finally found some time to look into this, sorry for the delay. It seems that 
on the code path taken in our case (dma_alloc_coherent() -> dma_alloc_attrs() 
-> dma_alloc_from_dev_coherent() -> __dma_alloc_from_coherent()) there's no 
call into the iommu layer, thus no mapping in the smmu. I plan to come up with 
a RFC patch early next week so we have something concrete to discuss on.

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


  1   2   >