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

2022-05-13 Thread Lorenzo Pieralisi
[with Christoph's correct email address]

On Tue, May 10, 2022 at 09:07:00AM +0100, Robin Murphy wrote:
> On 2022-05-10 08:23, Shameerali Kolothum Thodi wrote:
> > Hi Joerg/Robin,
> > 
> > I think this series is now ready to be merged. Could you please let
> > me know if there is anything missing.
> 
> Fine by me - these patches have had enough review and testing now that
> even if anything else did come up, I think it would be better done as
> follow-up work on the merged code.

Given the ACPICA dependency I believe it is best for this series
to go via the ACPI tree, right ?

I assume there are all the required ACKs for that to happen.

Thanks,
Lorenzo

> Cheers,
> Robin.
> 
> > 
> > Thanks,
> > Shameer
> > 
> > > -Original Message-
> > > From: Guohanjun (Hanjun Guo)
> > > Sent: 05 May 2022 02:24
> > > To: Shameerali Kolothum Thodi ;
> > > linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> > > iommu@lists.linux-foundation.org
> > > Cc: Linuxarm ; lorenzo.pieral...@arm.com;
> > > j...@8bytes.org; robin.mur...@arm.com; w...@kernel.org; wanghuiqiang
> > > ; steven.pr...@arm.com;
> > > sami.muja...@arm.com; j...@solid-run.com; eric.au...@redhat.com;
> > > laurentiu.tu...@nxp.com; h...@infradead.org
> > > Subject: Re: [PATCH v12 0/9] ACPI/IORT: Support for IORT RMR node
> > > 
> > > On 2022/5/4 0:33, Shameer Kolothum wrote:
> > > > Hi
> > > > 
> > > > v11 --> v12
> > > > -Minor fix in patch #4 to address the issue reported by the kernel 
> > > > test
> > > robot.
> > > > -Added R-by tags by Christoph(patch #1) and Lorenzo(patch #4).
> > > > -Added T-by from Steve to all relevant patches. Many thanks!.
> > > > 
> > > > Please note, this series has a dependency on the ACPICA header patch
> > > > here[1].
> > > 
> > > Tested on a Kunpeng920 server machine with SMMUv3, the 3408iMR RAID
> > > controller card works as expected,
> > > 
> > > Tested-by: Hanjun Guo 
> > > 
> > > Thanks
> > > Hanjun
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2022-05-13 Thread Lorenzo Pieralisi
On Tue, May 10, 2022 at 09:07:00AM +0100, Robin Murphy wrote:
> On 2022-05-10 08:23, Shameerali Kolothum Thodi wrote:
> > Hi Joerg/Robin,
> > 
> > I think this series is now ready to be merged. Could you please let
> > me know if there is anything missing.
> 
> Fine by me - these patches have had enough review and testing now that
> even if anything else did come up, I think it would be better done as
> follow-up work on the merged code.

Given the ACPICA dependency I believe it is best for this series
to go via the ACPI tree, right ?

I assume there are all the required ACKs for that to happen.

Thanks,
Lorenzo

> Cheers,
> Robin.
> 
> > 
> > Thanks,
> > Shameer
> > 
> > > -Original Message-
> > > From: Guohanjun (Hanjun Guo)
> > > Sent: 05 May 2022 02:24
> > > To: Shameerali Kolothum Thodi ;
> > > linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> > > iommu@lists.linux-foundation.org
> > > Cc: Linuxarm ; lorenzo.pieral...@arm.com;
> > > j...@8bytes.org; robin.mur...@arm.com; w...@kernel.org; wanghuiqiang
> > > ; steven.pr...@arm.com;
> > > sami.muja...@arm.com; j...@solid-run.com; eric.au...@redhat.com;
> > > laurentiu.tu...@nxp.com; h...@infradead.org
> > > Subject: Re: [PATCH v12 0/9] ACPI/IORT: Support for IORT RMR node
> > > 
> > > On 2022/5/4 0:33, Shameer Kolothum wrote:
> > > > Hi
> > > > 
> > > > v11 --> v12
> > > > -Minor fix in patch #4 to address the issue reported by the kernel 
> > > > test
> > > robot.
> > > > -Added R-by tags by Christoph(patch #1) and Lorenzo(patch #4).
> > > > -Added T-by from Steve to all relevant patches. Many thanks!.
> > > > 
> > > > Please note, this series has a dependency on the ACPICA header patch
> > > > here[1].
> > > 
> > > Tested on a Kunpeng920 server machine with SMMUv3, the 3408iMR RAID
> > > controller card works as expected,
> > > 
> > > Tested-by: Hanjun Guo 
> > > 
> > > Thanks
> > > Hanjun
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v11 4/9] ACPI/IORT: Add support to retrieve IORT RMR reserved regions

2022-04-26 Thread Lorenzo Pieralisi
On Fri, Apr 22, 2022 at 05:29:02PM +0100, Shameer Kolothum wrote:
> Parse through the IORT RMR nodes and populate the reserve region list
> corresponding to a given IOMMU and device(optional). Also, go through
> the ID mappings of the RMR node and retrieve all the SIDs associated
> with it.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 290 ++
>  include/linux/iommu.h |   8 ++
>  2 files changed, 298 insertions(+)

Reviewed-by: Lorenzo Pieralisi 

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index cd5d1d7823cb..5be6e8ecca38 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -788,6 +788,293 @@ void acpi_configure_pmsi_domain(struct device *dev)
>  }
>  
>  #ifdef CONFIG_IOMMU_API
> +static void iort_rmr_free(struct device *dev,
> +   struct iommu_resv_region *region)
> +{
> + struct iommu_iort_rmr_data *rmr_data;
> +
> + rmr_data = container_of(region, struct iommu_iort_rmr_data, rr);
> + kfree(rmr_data->sids);
> + kfree(rmr_data);
> +}
> +
> +struct iommu_iort_rmr_data *iort_rmr_alloc(struct acpi_iort_rmr_desc 
> *rmr_desc,
> +int prot, enum iommu_resv_type type,
> +u32 *sids, u32 num_sids)
> +{
> + struct iommu_iort_rmr_data *rmr_data;
> + struct iommu_resv_region *region;
> + u32 *sids_copy;
> + u64 addr = rmr_desc->base_address, size = rmr_desc->length;
> +
> + rmr_data = kmalloc(sizeof(*rmr_data), GFP_KERNEL);
> + if (!rmr_data)
> + return NULL;
> +
> + /* Create a copy of SIDs array to associate with this rmr_data */
> + sids_copy = kmemdup(sids, num_sids * sizeof(*sids), GFP_KERNEL);
> + if (!sids_copy) {
> + kfree(rmr_data);
> + return NULL;
> + }
> + rmr_data->sids = sids_copy;
> + rmr_data->num_sids = num_sids;
> +
> + 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);
> + }
> +
> + region = _data->rr;
> + INIT_LIST_HEAD(>list);
> + region->start = addr;
> + region->length = size;
> + region->prot = prot;
> + region->type = type;
> + region->free = iort_rmr_free;
> +
> + return rmr_data;
> +}
> +
> +static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc,
> + u32 count)
> +{
> + int i, j;
> +
> + for (i = 0; i < count; i++) {
> + u64 end, start = desc[i].base_address, length = desc[i].length;
> +
> + if (!length) {
> + pr_err(FW_BUG "RMR descriptor[0x%llx] with zero length, 
> continue anyway\n",
> +start);
> + continue;
> + }
> +
> + end = start + length - 1;
> +
> + /* Check for address overlap */
> + for (j = i + 1; j < count; j++) {
> + u64 e_start = desc[j].base_address;
> + u64 e_end = e_start + desc[j].length - 1;
> +
> + if (start <= e_end && end >= e_start)
> + pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] 
> overlaps, continue anyway\n",
> +start, end);
> + }
> + }
> +}
> +
> +/*
> + * Please note, we will keep the already allocated RMR reserve
> + * regions in case of a memory allocation failure.
> + */
> +static void iort_get_rmrs(struct acpi_iort_node *node,
> +   struct acpi_iort_node *smmu,
> +   u32 *sids, u32 num_sids,
> +   struct list_head *head)
> +{
> + struct acpi_iort_rmr *rmr = (struct acpi_iort_rmr *)node->node_data;
> + struct acpi_iort_rmr_desc *rmr_desc;
> + int i;
> +
> + rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, node,
> + rmr->rmr_offset);
> +
> + iort_rmr_desc_check_overlap(rmr_desc, rmr->rmr_count);
&g

Re: [PATCH v9 04/11] ACPI/IORT: Provide a generic helper to retrieve reserve regions

2022-04-06 Thread Lorenzo Pieralisi
On Mon, Apr 04, 2022 at 01:42:02PM +0100, Shameer Kolothum wrote:
> Currently IORT provides a helper to retrieve HW MSI reserve regions.
> Change this to a generic helper to retrieve any IORT related reserve
> regions. This will be useful when we add support for RMR nodes in
> subsequent patches.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 23 +++
>  drivers/iommu/dma-iommu.c |  2 +-
>  include/linux/acpi_iort.h |  4 ++--
>  3 files changed, 18 insertions(+), 11 deletions(-)

Reviewed-by: Lorenzo Pieralisi  # for ACPI
IORT

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index c5ebb2be9a19..63acc3c5b275 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -830,16 +830,13 @@ static struct acpi_iort_node 
> *iort_get_msi_resv_iommu(struct device *dev)
>   return NULL;
>  }
>  
> -/**
> - * iort_iommu_msi_get_resv_regions - Reserved region driver helper
> - *   for HW MSI regions.
> - * @dev: Device from iommu_get_resv_regions()
> - * @head: Reserved region list from iommu_get_resv_regions()
> - *
> +/*
> + * Retrieve platform specific HW MSI reserve regions.
>   * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
>   * associated with the device are the HW MSI reserved regions.
>   */
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> +static void
> +iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
>  {
>   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>   struct acpi_iort_its_group *its;
> @@ -888,6 +885,16 @@ void iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>   }
>  }
>  
> +/**
> + * iort_iommu_get_resv_regions - Generic helper to retrieve reserved regions.
> + * @dev: Device from iommu_get_resv_regions()
> + * @head: Reserved region list from iommu_get_resv_regions()
> + */
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
> +{
> + iort_iommu_msi_get_resv_regions(dev, head);
> +}
> +
>  static inline bool iort_iommu_driver_enabled(u8 type)
>  {
>   switch (type) {
> @@ -1052,7 +1059,7 @@ int iort_iommu_configure_id(struct device *dev, const 
> u32 *id_in)
>  }
>  
>  #else
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  { }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 09f6e1c0f9c0..93d76b666888 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -384,7 +384,7 @@ void iommu_dma_get_resv_regions(struct device *dev, 
> struct list_head *list)
>  {
>  
>   if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
> - iort_iommu_msi_get_resv_regions(dev, list);
> + iort_iommu_get_resv_regions(dev, list);
>  
>  }
>  EXPORT_SYMBOL(iommu_dma_get_resv_regions);
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index a8198b83753d..e5d2de9caf7f 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -36,7 +36,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
>  /* IOMMU interface */
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
>  #else
>  static inline void acpi_iort_init(void) { }
> @@ -52,7 +52,7 @@ static inline int iort_dma_get_ranges(struct device *dev, 
> u64 *size)
>  static inline int iort_iommu_configure_id(struct device *dev, const u32 
> *id_in)
>  { return -ENODEV; }
>  static inline
> -void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
>  { }
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
> -- 
> 2.25.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v9 01/11] ACPI/IORT: Add temporary RMR node flag definitions

2022-04-06 Thread Lorenzo Pieralisi
On Mon, Apr 04, 2022 at 01:41:59PM +0100, Shameer Kolothum wrote:
> IORT rev E.d introduces more details into the RMR node Flags
> field. Add temporary definitions to describe and access these
> Flags field until ACPICA header is updated to support E.d.
> 
> This patch can be reverted once the include/acpi/actbl2.h has
> all the relevant definitions.
> 
> Signed-off-by: Shameer Kolothum 
> ---
> Please find the ACPICA E.d related changes pull request here,
> https://github.com/acpica/acpica/pull/765
> 
> This is now merged to acpica:master.

I assume we can drop this patch when ACPICA Linuxized patches hit
Rafael's tree.

> ---
>  drivers/acpi/arm64/iort.c | 24 
>  1 file changed, 24 insertions(+)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index f2f8f05662de..fd06cf43ba31 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -25,6 +25,30 @@
>  #define IORT_IOMMU_TYPE  ((1 << ACPI_IORT_NODE_SMMU) |   \
>   (1 << ACPI_IORT_NODE_SMMU_V3))
>  
> +/*
> + * The following RMR related definitions are temporary and
> + * can be removed once ACPICA headers support IORT rev E.d
> + */
> +#ifndef ACPI_IORT_RMR_REMAP_PERMITTED
> +#define ACPI_IORT_RMR_REMAP_PERMITTED(1)
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ACCESS_PRIVILEGE
> +#define ACPI_IORT_RMR_ACCESS_PRIVILEGE   (1 << 1)
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ACCESS_ATTRIBUTES
> +#define ACPI_IORT_RMR_ACCESS_ATTRIBUTES(flags)   (((flags) >> 2) & 0xFF)
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ATTR_DEVICE_GRE
> +#define ACPI_IORT_RMR_ATTR_DEVICE_GRE0x03
> +#endif
> +
> +#ifndef ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB
> +#define ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB0x05
> +#endif
> +
>  struct iort_its_msi_chip {
>   struct list_headlist;
>   struct fwnode_handle*fw_node;
> -- 
> 2.25.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v9 07/11] ACPI/IORT: Add a helper to retrieve RMR info directly

2022-04-06 Thread Lorenzo Pieralisi
On Mon, Apr 04, 2022 at 01:42:05PM +0100, Shameer Kolothum wrote:
> This will provide a way for SMMU drivers to retrieve StreamIDs
> associated with IORT RMR nodes and use that to set bypass settings
> for those IDs.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 29 +
>  include/linux/acpi_iort.h |  8 
>  2 files changed, 37 insertions(+)

Reviewed-by: Lorenzo Pieralisi 

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 1147387cfddb..fb2b0163c27d 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -1402,6 +1402,35 @@ int iort_dma_get_ranges(struct device *dev, u64 *size)
>   return nc_dma_get_range(dev, size);
>  }
>  
> +/**
> + * iort_get_rmr_sids - Retrieve IORT RMR node reserved regions with
> + * associated StreamIDs information.
> + * @iommu_fwnode: fwnode associated with IOMMU
> + * @head: Resereved region list
> + */
> +void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +struct list_head *head)
> +{
> + iort_iommu_rmr_get_resv_regions(iommu_fwnode, NULL, head);
> +}
> +EXPORT_SYMBOL_GPL(iort_get_rmr_sids);
> +
> +/**
> + * iort_put_rmr_sids - Free all the memory allocated for RMR reserved 
> regions.
> + * @iommu_fwnode: fwnode associated with IOMMU
> + * @head: Resereved region list
> + */
> +void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +struct list_head *head)
> +{
> + struct iommu_resv_region *entry, *next;
> +
> + iort_iommu_put_resv_regions(NULL, head);
> + list_for_each_entry_safe(entry, next, head, list)
> + kfree(entry);
> +}
> +EXPORT_SYMBOL_GPL(iort_put_rmr_sids);
> +
>  static void __init acpi_iort_register_irq(int hwirq, const char *name,
> int trigger,
> struct resource *res)
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index eb3c28853110..774b8bc16573 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -33,6 +33,10 @@ struct irq_domain *iort_get_device_domain(struct device 
> *dev, u32 id,
> enum irq_domain_bus_token bus_token);
>  void acpi_configure_pmsi_domain(struct device *dev);
>  int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
> +void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +struct list_head *head);
> +void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
> +struct list_head *head);
>  /* IOMMU interface */
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> @@ -47,6 +51,10 @@ static inline struct irq_domain *iort_get_device_domain(
>   struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
>  { return NULL; }
>  static inline void acpi_configure_pmsi_domain(struct device *dev) { }
> +static inline
> +void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head 
> *head) { }
> +static inline
> +void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode, struct list_head 
> *head) { }
>  /* IOMMU interface */
>  static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
>  { return -ENODEV; }
> -- 
> 2.25.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v9 06/11] ACPI/IORT: Add support to retrieve IORT RMR reserved regions

2022-04-06 Thread Lorenzo Pieralisi
On Mon, Apr 04, 2022 at 01:42:04PM +0100, Shameer Kolothum wrote:
> Parse through the IORT RMR nodes and populate the reserve region list
> corresponding to a given IOMMU and device(optional). Also, go through
> the ID mappings of the RMR node and retrieve all the SIDs associated
> with it.
> 
> Now that we have this support, update iommu_dma_get/_put_resv_regions()
> paths to include the RMR reserve regions.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 275 ++
>  drivers/iommu/dma-iommu.c |   3 +
>  include/linux/acpi_iort.h |   4 +
>  3 files changed, 282 insertions(+)

Very minor style comment below, regardless:

Reviewed-by: Lorenzo Pieralisi  # for ACPI
IORT

> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 63acc3c5b275..1147387cfddb 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -812,6 +812,259 @@ void acpi_configure_pmsi_domain(struct device *dev)
>  }
>  
>  #ifdef CONFIG_IOMMU_API
> +static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 
> count)
> +{
> + int i, j;
> +
> + for (i = 0; i < count; i++) {
> + u64 end, start = desc[i].base_address, length = desc[i].length;
> +
> + if (!length) {
> + pr_err(FW_BUG "RMR descriptor[0x%llx] with zero length, 
> continue anyway\n",
> +start);
> + continue;
> + }
> +
> + end = start + length - 1;
> +
> + /* Check for address overlap */
> + for (j = i + 1; j < count; j++) {
> + u64 e_start = desc[j].base_address;
> + u64 e_end = e_start + desc[j].length - 1;
> +
> + if (start <= e_end && end >= e_start)
> + pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] 
> overlaps, continue anyway\n",
> +start, end);
> + }
> + }
> +}
> +
> +/*
> + * Please note, we will keep the already allocated RMR reserve
> + * regions in case of a memory allocation failure.
> + */
> +static void iort_get_rmrs(struct acpi_iort_node *node,
> +   struct acpi_iort_node *smmu,
> +   u32 *sids, u32 num_sids,
> +   struct list_head *head)
> +{
> + struct acpi_iort_rmr *rmr = (struct acpi_iort_rmr *)node->node_data;
> + struct acpi_iort_rmr_desc *rmr_desc;
> + int i;
> +
> + rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, 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;
> + u32  *sids_copy;
> + 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 & ACPI_IORT_RMR_REMAP_PERMITTED)
> + type = IOMMU_RESV_DIRECT_RELAXABLE;
> + else
> + type = IOMMU_RESV_DIRECT;
> +
> + if (rmr->flags & ACPI_IORT_RMR_ACCESS_PRIVILEGE)
> + prot |= IOMMU_PRIV;
> +
> + /* Attributes 0x00 - 0x03 represents device memory */
> + if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) <=
> + ACPI_IORT_RMR_ATTR_DEVICE_GRE)
> + prot |= IOMMU_MMIO;
> + else if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) ==
> + ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB)
> + prot |= IOMMU_CACHE;
> +
> + /* Create a copy of SIDs array to associate with this resv 
> region */
> + sids_copy = kmemdup(sids, num_sids * sizeof(*s

Re: [PATCH v9 03/11] ACPI/IORT: Make iort_iommu_msi_get_resv_regions() return void

2022-04-06 Thread Lorenzo Pieralisi
On Mon, Apr 04, 2022 at 01:42:01PM +0100, Shameer Kolothum wrote:
> At present iort_iommu_msi_get_resv_regions() returns the number of
> MSI reserved regions on success and there are no users for this.
> The reserved region list will get populated anyway for platforms
> that require the HW MSI region reservation. Hence, change the
> function to return void instead.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 26 ++
>  include/linux/acpi_iort.h |  6 +++---
>  2 files changed, 13 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index fd06cf43ba31..c5ebb2be9a19 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -832,25 +832,23 @@ static struct acpi_iort_node 
> *iort_get_msi_resv_iommu(struct device *dev)
>  
>  /**
>   * iort_iommu_msi_get_resv_regions - Reserved region driver helper
> + *   for HW MSI regions.

Very minor but is this a spurious change ?

>   * @dev: Device from iommu_get_resv_regions()
>   * @head: Reserved region list from iommu_get_resv_regions()
>   *
> - * Returns: Number of msi reserved regions on success (0 if platform
> - *  doesn't require the reservation or no associated msi regions),
> - *  appropriate error value otherwise. The ITS interrupt translation
> - *  spaces (ITS_base + SZ_64K, SZ_64K) associated with the device
> - *  are the msi reserved regions.
> + * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
> + * associated with the device are the HW MSI reserved regions.
>   */
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
>  {
>   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>   struct acpi_iort_its_group *its;
>   struct acpi_iort_node *iommu_node, *its_node = NULL;
> - int i, resv = 0;
> + int i;
>  
>   iommu_node = iort_get_msi_resv_iommu(dev);
>   if (!iommu_node)
> - return 0;
> + return;
>  
>   /*
>* Current logic to reserve ITS regions relies on HW topologies
> @@ -870,7 +868,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>   }
>  
>   if (!its_node)
> - return 0;
> + return;
>  
>   /* Move to ITS specific data */
>   its = (struct acpi_iort_its_group *)its_node->node_data;
> @@ -884,14 +882,10 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>  
>   region = iommu_alloc_resv_region(base + SZ_64K, SZ_64K,
>prot, IOMMU_RESV_MSI);
> - if (region) {
> + if (region)
>   list_add_tail(>list, head);
> - resv++;
> - }
>   }
>   }
> -
> - return (resv == its->its_count) ? resv : -ENODEV;
>  }
>  
>  static inline bool iort_iommu_driver_enabled(u8 type)
> @@ -1058,8 +1052,8 @@ int iort_iommu_configure_id(struct device *dev, const 
> u32 *id_in)
>  }
>  
>  #else
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> -{ return 0; }
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> +{ }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
>  #endif
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index f1f0842a2cb2..a8198b83753d 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -36,7 +36,7 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
>  /* IOMMU interface */
>  int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
>  #else
>  static inline void acpi_iort_init(void) { }
> @@ -52,8 +52,8 @@ static inline int iort_dma_get_ranges(struct device *dev, 
> u64 *size)
>  static inline int iort_iommu_configure_id(struct device *dev, const u32 
> *id_in)
>  { return -ENODEV; }
>  static inline
> -int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> -{ return 0; }
> +void iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
> +{ }
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
>  { return PHYS_ADDR_MAX; }
> -- 
> 2.25.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 00/11] ACPI/IORT: Support for IORT RMR node

2022-03-14 Thread Lorenzo Pieralisi
On Mon, Mar 14, 2022 at 11:43:51AM +0100, Ard Biesheuvel wrote:
> On Mon, 14 Mar 2022 at 11:37, Eric Auger  wrote:
> >
> > Hi Robin
> >
> > On 3/11/22 11:34 AM, Robin Murphy wrote:
> > > On 2022-03-11 08:19, Eric Auger wrote:
> > >> Hi guys,
> > >>
> > >> On 2/21/22 4:43 PM, Shameer Kolothum wrote:
> > >>> Hi,
> > >>>
> > >>> Since we now have an updated verion[0] of IORT spec(E.d) which
> > >>> addresses the memory attributes issues discussed here [1],
> > >>> this series now make use of it.
> > >>>
> > >>> The pull request for ACPICA E.d related changes are already
> > >>> raised and can be found here,
> > >>> https://github.com/acpica/acpica/pull/752
> > >>>
> > >>> v7 --> v8
> > >>>- Patch #1 has temp definitions for RMR related changes till
> > >>>  the ACPICA header changes are part of kernel.
> > >>>- No early parsing of RMR node info and is only parsed at the
> > >>>  time of use.
> > >>>- Changes to the RMR get/put API format compared to the
> > >>>  previous version.
> > >>>- Support for RMR descriptor shared by multiple stream IDs.
> > >>>
> > >>> Please take a look and let me know your thoughts.
> > >>>
> > >>> Thanks,
> > >>> Shameer
> > >>> [0] https://developer.arm.com/documentation/den0049/ed/
> > >> I still have a question on the IORT E.d spec (unrelated to this series).
> > >>
> > >> The spec mandates that if RMR nodes are presented in the IORT,
> > >> _DSM function #5 for the PCIe host bridge ACPI device object must return
> > >> 0, indicating the OS must honour the PCI config that the FW computed at
> > >> boot time.
> > >>
> > >> However implementing this _DSM #5 as above is known to prevent PCI
> > >> devices with IO ports from working, on aarch64 linux.
> > >>
> > >> "
> > >> The reason is that EFI creates I/O port mappings below
> > >>  0x1000 (in fact, at 0). However Linux, for legacy reasons, does not
> > >>  support I/O ports <= 0x1000 on PCI, so the I/O assignment
> > >> created by EFI
> > >>  is rejected.
> > >>  EFI creates the mappings primarily for itself, and up until
> > >> DSM #5
> > >>  started to be enforced, all PCI resource allocations that
> > >> existed at
> > >>  boot were ignored by Linux and recreated from scratch.
> > >> "
> > >>
> > >> This is an excerpt of a qemu commit message that reverted the _DMS #5
> > >> change (Revert "acpi/gpex: Inform os to keep firmware resource map").
> > >> Has the situation changed since July 2021 (ie. has UEFI been reworked?).
> > >> [+ Ard]
> > >
> > > FWIW I wasn't aware of that, but if it's an issue then it will need to
> > > be fixed in Linux or UEFI's PCI resource code (arguably if UEFI has
> > > already allocated from the bottom of I/O space then Linux should be
> > > safe to assume that there are no legacy PC I/O resources to worry
> > > about). The DSM is required to prevent bus numbers being reassigned,
> > > because if that happens then any PCI StreamIDs referenced in IORT may
> > > suddenly become meaningless and the association of root complex nodes
> > > and RMRs to physical hardware lost.
> >
> > Thank you for confirming and explaining the need for DSM #5. Ard, please
> > could you confirm that the incompatibility with PCI devices with IO
> > ports is still there?
> >
> 
> Yes, and this needs to be fixed in Linux. The firmware complies with
> the pertinent specifications, and it is Linux that deviates from this
> for legacy reasons.
> 
> IIRC, this came up on the mailing list at some point, and one of the
> issues is that I/O port 0x0 is mistaken for 'no resource' or some
> other exceptional case like that, so even if we fix the arbitrary
> limit of 0x1000, we may still run into trouble when devices uses I/O
> port 0x0.

Yes, I need to go back to that thread to sort this out.

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


Re: [PATCH v8 03/11] ACPI/IORT: Add helper functions to parse RMR nodes

2022-02-24 Thread Lorenzo Pieralisi
On Mon, Feb 21, 2022 at 03:43:36PM +, Shameer Kolothum wrote:
> The helper functions here parse through the IORT RMR nodes and
> populate a reserved region list  corresponding to a given iommu
> and device(optional). These also go through the ID mappings of
> the RMR node and retrieves all the SIDs associated with a RMR
> descriptor.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 225 ++
>  1 file changed, 225 insertions(+)

I have very minor comments - I would ask Robin to ack the updated
flags management.

Functions should be introduced where they are used, this patch
is not bisectable:

drivers/acpi/arm64/iort.c:1028:13: warning: ‘iort_find_rmrs’ defined but not 
used [-Wunused-function]
 1028 | static void iort_find_rmrs(struct acpi_iort_node *iommu, struct device 
*dev,

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 0730c4dbb700..05da9ebff50a 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -830,6 +830,231 @@ static struct acpi_iort_node 
> *iort_get_msi_resv_iommu(struct device *dev)
>   return NULL;
>  }
>  
> +static void iort_rmr_desc_check_overlap(struct acpi_iort_rmr_desc *desc, u32 
> count)
> +{
> + int i, j;
> +
> + for (i = 0; i < count; i++) {
> + u64 end, start = desc[i].base_address, length = desc[i].length;
> +
> + end = start + length - 1;

We could probably check for length != 0, the kernel is not there to
validate firmware but this would not hurt either.

> +
> + /* Check for address overlap */
> + for (j = i + 1; j < count; j++) {
> + u64 e_start = desc[j].base_address;
> + u64 e_end = e_start + desc[j].length - 1;
> +
> + if (start <= e_end && end >= e_start)
> + pr_err(FW_BUG "RMR descriptor[0x%llx - 0x%llx] 
> overlaps, continue anyway\n",
> +start, end);
> + }
> + }
> +}
> +
> +/*
> + * Please note, we will keep the already allocated RMR reserve
> + * regions in case of a memory allocation failure.
> + */
> +static void iort_rmr_get_resv_regions(struct acpi_iort_node *node,
> +   struct acpi_iort_node *smmu,
> +   u32 *sids, u32 num_sids,
> +   struct list_head *head)
> +{
> + struct acpi_iort_rmr *rmr = (struct acpi_iort_rmr *)node->node_data;
> + struct acpi_iort_rmr_desc *rmr_desc;
> + int i;
> +
> + rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, 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;
> + u32  *sids_copy;
> + 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 & ACPI_IORT_RMR_REMAP_PERMITTED)
> + type = IOMMU_RESV_DIRECT_RELAXABLE;
> + else
> + type = IOMMU_RESV_DIRECT;
> +
> + if (rmr->flags & ACPI_IORT_RMR_ACCESS_PRIVILEGE)
> + prot |= IOMMU_PRIV;
> +
> + /* Attributes 0x00 - 0x03 represents device memory */
> + if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) <=
> + ACPI_IORT_RMR_ATTR_DEVICE_GRE)
> + prot |= IOMMU_MMIO;
> + else if (ACPI_IORT_RMR_ACCESS_ATTRIBUTES(rmr->flags) ==
> + ACPI_IORT_RMR_ATTR_NORMAL)
> + prot |= IOMMU_CACHE;
> +
> + /* Create a copy of sids array to associate with this resv 
> region */
> + sids_copy = kmemdup(sids, num_sids * sizeof(*sids), GFP_KERNEL);
> + if (!sids_copy)
> + return;
> +
> + region = iommu_alloc_resv_region(addr, size, prot, type);
> + if (!region) {
> + kfree(sids_copy);
> + return;
> + }
> +
> + region->fw_data.rmr.sids = sids_copy;
> + region->fw_data.rmr.num_sids = 

Re: [PATCH v8 05/11] ACPI/IORT: Add a helper to retrieve RMR memory regions

2022-02-23 Thread Lorenzo Pieralisi
On Mon, Feb 21, 2022 at 03:43:38PM +, Shameer Kolothum wrote:
> Add helper functions (iort_iommu_get/put_rmrs()) that
> retrieves/releases RMR memory descriptors associated
> with a given IOMMU. This will be used by IOMMU drivers
> to set up necessary mappings.
> 
> Invoke it from the generic iommu helper functions.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 56 +++
>  drivers/iommu/dma-iommu.c |  4 +++
>  include/linux/acpi_iort.h | 14 ++
>  3 files changed, 74 insertions(+)

I would squash this patch with the previous one - at least the
iommu_dma_get/put_rmrs() are actually used in the patch that is
adding them.

Lorenzo

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 05da9ebff50a..b2c959c72fb2 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -1055,6 +1055,57 @@ static void iort_find_rmrs(struct acpi_iort_node 
> *iommu, struct device *dev,
>   }
>  }
>  
> +/**
> + * iort_iommu_dma_put_rmrs - Free any memory associated with RMRs.
> + * @iommu_fwnode: fwnode associated with IOMMU
> + * @head: Resereved region list
> + *
> + * This function go through the provided reserved region list and
> + * free up memory associated with RMR entries and delete them from
> + * the list.
> + */
> +void iort_iommu_put_rmrs(struct fwnode_handle *iommu_fwnode,
> +  struct list_head *head)
> +{
> + struct iommu_resv_region *e, *tmp;
> +
> + /*
> +  * RMR entries will have mem allocated for fw_data.rmr.sids.
> +  * Free the mem and delete the node.
> +  */
> + list_for_each_entry_safe(e, tmp, head, list) {
> + if (e->fw_data.rmr.sids) {
> + kfree(e->fw_data.rmr.sids);
> + list_del(>list);
> + kfree(e);
> + }
> + }
> +}
> +
> +/**
> + *
> + * iort_iommu_dma_get_rmrs - Retrieve Reserved Memory Regions(RMRs) 
> associated
> + *  with a given IOMMU and dev.
> + * @iommu_fwnode: fwnode associated with IOMMU
> + * @dev: Device associated with RMR(Optional)
> + * @list: RMR list to be populated
> + *
> + * This function populates the RMR list associated with a given IOMMU and
> + * dev(if provided). If dev is NULL, the function populates all the RMRs
> + * associated with the given IOMMU.
> + */
> +void iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode, struct device 
> *dev,
> +  struct list_head *head)
> +{
> + struct acpi_iort_node *iommu;
> +
> + iommu = iort_get_iort_node(iommu_fwnode);
> + if (!iommu)
> + return;
> +
> + iort_find_rmrs(iommu, dev, head);
> +}
> +
>  /**
>   * iort_iommu_msi_get_resv_regions - Reserved region driver helper
>   * @dev: Device from iommu_get_resv_regions()
> @@ -1287,6 +1338,11 @@ int iort_iommu_msi_get_resv_regions(struct device 
> *dev, struct list_head *head)
>  { return 0; }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
> +void iort_iommu_get_rmrs(struct fwnode_handle *fwnode, struct device *dev,
> +  struct list_head *head)
> +{ }
> +void iort_iommu_put_rmrs(struct fwnode_handle *fwnode, struct list_head 
> *head)
> +{ }
>  #endif
>  
>  static int nc_dma_get_range(struct device *dev, u64 *size)
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 65ab01d5128b..b33e4df85de1 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -382,12 +382,16 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
>  void iommu_dma_get_rmrs(struct fwnode_handle *iommu_fwnode, struct device 
> *dev,
>   struct list_head *list)
>  {
> + if (!is_of_node(iommu_fwnode))
> + iort_iommu_get_rmrs(iommu_fwnode, dev, list);
>  }
>  EXPORT_SYMBOL(iommu_dma_get_rmrs);
>  
>  void iommu_dma_put_rmrs(struct fwnode_handle *iommu_fwnode,
>   struct list_head *list)
>  {
> + if (!is_of_node(iommu_fwnode))
> + iort_iommu_put_rmrs(iommu_fwnode, list);
>  }
>  EXPORT_SYMBOL(iommu_dma_put_rmrs);
>  
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index f1f0842a2cb2..212f7f178ec3 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -38,6 +38,10 @@ int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
>  int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
> +void iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode, struct device 
> *dev,
> +  struct list_head *list);
> +void iort_iommu_put_rmrs(struct fwnode_handle *iommu_fwnode,
> +  struct list_head *list);
>  #else
>  static inline void acpi_iort_init(void) { }
>  static inline u32 

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

2021-12-08 Thread Lorenzo Pieralisi
On Tue, Oct 12, 2021 at 10:00:24AM +0200, Jon Nettleton wrote:
> On Mon, Oct 11, 2021 at 4:04 PM Robin Murphy  wrote:
> >
> > On 2021-10-09 08:06, Jon Nettleton wrote:
> > [...]
> > >>> + 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;
> > >>> + }
> > >>
> > >> I'm not sure we ever got a definitive answer to this - does DPAA2
> > >> actually go wrong if we use IOMMU_MMIO here? I'd still much prefer to
> > >> make the fewest possible assumptions, since at this point it's basically
> > >> just a stop-gap until we can fix the spec. It's become clear that we
> > >> can't reliably rely on guessing attributes, so I'm not too fussed about
> > >> theoretical cases that currently don't work (due to complete lack of RMR
> > >> support) continuing to not work for the moment, as long as we can make
> > >> the real-world cases we actually have work at all. Anything which only
> > >> affects performance I'd rather leave until firmware can tell us what to 
> > >> do.
> > >
> > > Well it isn't DPAA2, it is FSL_MC_BUS that fails with IOMMU_MMIO
> > > mappings.  DPAA2 is just one connected device.
> >
> > Apologies if I'm being overly loose with terminology there - my point of
> > reference for this hardware is documentation for the old LS2080A, where
> > the "DPAA2 Reference Manual" gives a strong impression that the MC is a
> > component belonging to the overall DPAA2 architecture. Either way it
> > technically stands to reason that the other DPAA2 components would only
> > be usable if the MC itself works (unless I've been holding a major
> > misconception about that for years as well).
> >
> > In the context of this discussion, please consider any reference I may
> > make to bits of NXP's hardware to be shorthand for "the thing for which
> > NXP have a vested interest in IORT RMRs".
> 
> Ultimately the spec doesn't mention what IOMMU properties the regions
> should have.

It will have to and that's what we are working on.

> Even marking them as IOMMU_READ/WRITE is as much of an assumption as
> using IOMMU_MMIO or IOMMU_CACHE. It just seems IOMMU_MMIO is the most
> popular since all the examples use it for MSI doorbells in the
> documentation.

We don't merge code based on assumptions that can easily break because
the specifications don't contemplate the details that are required.

> I am interested why this concern is only being brought up at this point
> on a patchset that has been on the mailing list for 8+ months? 

See above. We don't merge code that we know can break and is based on
assumptions, we need to update the IORT specifications to make them
cover all the use cases - in a predictable way - and that's what we are
working on.

> This is based on a spec that has existed from Arm since 2020 with the
> most recent revisions published in Feb 2021.  The lack of RMR support
> in the kernel is affecting real world products, and the ability for
> SystemReady ES certified systems from just fully working with recent
> distributions.

I answered above - if you have any questions please ask them, here,
as far as Linux code is concerned.

I understand this is taking a long time, it is also helping us
understand all the possible use cases and how to cover them in
a way that is maintainable in the long run.

Thanks,
Lorenzo

> Even worse, is that without this patchset customers are forced to jump
> through hoops to purposefully re-enable smmu bypass making their
> systems less secure.
> 
> How is this a good experience for customers of SystemReady hardware
> when for any mainline distribution to work the first thing they have
> to do is make their system less secure?
> 
> -Jon
> 
> >
> > Thanks,
> > Robin.
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


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

2021-08-05 Thread Lorenzo Pieralisi
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_ ?

Thanks,
Lorenzo

> +
> + 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,
> +  iort_node->length);
> + }
> +}
>  
>  static void __init iort_init_platform_devices(void)
>  {
> @@ -1636,6 +1767,7 @@ void __init acpi_iort_init(void)
>   }
>  
>   iort_init_platform_devices();
> + iort_parse_rmr();
>  }
>  
>  #ifdef CONFIG_ZONE_DMA
> -- 
> 2.17.1
> 
___
iommu 

Re: [PATCH v7 4/9] ACPI/IORT: Add a helper to retrieve RMR memory regions

2021-08-05 Thread Lorenzo Pieralisi
On Thu, Aug 05, 2021 at 09:07:19AM +0100, Shameer Kolothum wrote:
> Add a helper function (iort_iommu_get_rmrs()) that retrieves RMR
> memory descriptors associated with a given IOMMU. This will be used
> by IOMMU drivers to setup necessary mappings.
> 
> Invoke it from the generic helper iommu_dma_get_rmrs().
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 38 ++
>  drivers/iommu/dma-iommu.c |  4 
>  include/linux/acpi_iort.h |  7 +++
>  3 files changed, 49 insertions(+)

Reviewed-by: Lorenzo Pieralisi 

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index d76ba46ebe67..3c32d62e63b6 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -809,6 +809,42 @@ static struct acpi_iort_node 
> *iort_get_msi_resv_iommu(struct device *dev)
>   return NULL;
>  }
>  
> +/**
> + * iort_iommu_get_rmrs() - Helper to retrieve RMR info associated with IOMMU
> + * @iommu_fwnode: fwnode for the IOMMU
> + * @head: RMR list head to be populated
> + *
> + * Returns: 0 on success, <0 failure. Please note, we will keep the already
> + *  allocated RMR reserve regions in case of a kmemdup()
> + *  failure.
> + */
> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
> + struct list_head *head)
> +{
> + struct iommu_resv_region *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) {
> + struct iommu_resv_region *region;
> +
> + if (e->fw_data.rmr.smmu != iommu)
> + continue;
> +
> + region = kmemdup(e, sizeof(*region), GFP_KERNEL);
> + if (region) {
> + list_add_tail(>list, head);
> + rmrs++;
> + }
> + }
> +
> + return (rmrs == 0) ? -ENODEV : 0;
> +}
> +
>  /**
>   * iort_iommu_msi_get_resv_regions - Reserved region driver helper
>   * @dev: Device from iommu_get_resv_regions()
> @@ -1041,6 +1077,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>  { return 0; }
>  int iort_iommu_configure_id(struct device *dev, const u32 *input_id)
>  { return -ENODEV; }
> +int iort_iommu_get_rmrs(struct fwnode_handle *fwnode, struct list_head *head)
> +{ return -ENODEV; }
>  #endif
>  
>  static int nc_dma_get_range(struct device *dev, u64 *size)
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 2fa2445e9070..1b6e27475279 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -185,6 +185,9 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
>  int iommu_dma_get_rmrs(struct fwnode_handle *iommu_fwnode,
>  struct list_head *list)
>  {
> + if (!is_of_node(iommu_fwnode))
> + return iort_iommu_get_rmrs(iommu_fwnode, list);
> +
>   return -EINVAL;
>  }
>  EXPORT_SYMBOL(iommu_dma_get_rmrs);
> @@ -200,6 +203,7 @@ EXPORT_SYMBOL(iommu_dma_get_rmrs);
>  void iommu_dma_put_rmrs(struct fwnode_handle *iommu_fwnode,
>   struct list_head *list)
>  {
> + generic_iommu_put_resv_regions(iommu_fwnode->dev, list);
>  }
>  EXPORT_SYMBOL(iommu_dma_put_rmrs);
>  
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index f1f0842a2cb2..d8c030c103f5 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -38,6 +38,8 @@ int iort_dma_get_ranges(struct device *dev, u64 *size);
>  int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
>  int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
> + struct list_head *list);
>  #else
>  static inline void acpi_iort_init(void) { }
>  static inline u32 iort_msi_map_id(struct device *dev, u32 id)
> @@ -57,6 +59,11 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
>  { return PHYS_ADDR_MAX; }
> +
> +static inline
> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
> + struct list_head *list)
> +{ return -ENODEV; }
>  #endif
>  
>  #endif /* __ACPI_IORT_H__ */
> -- 
> 2.17.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 1/8] ACPI/IORT: Add support for RMR node parsing

2021-06-03 Thread Lorenzo Pieralisi
On Thu, May 13, 2021 at 02:45:43PM +0100, Shameer Kolothum wrote:
> Add support for parsing RMR node information from ACPI.
> Find associated stream id and smmu node info from the
> RMR node and populate a linked list with RMR memory
> descriptors.

"Add support for parsing RMR node information from ACPI.

Find the associated streamid and SMMU node info from the
RMR node and populate a linked list with RMR memory
descriptors."

> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 104 +-
>  1 file changed, 103 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 3912a1f6058e..fea1ffaedf3b 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -40,6 +40,19 @@ struct iort_fwnode {
>  static LIST_HEAD(iort_fwnode_list);
>  static DEFINE_SPINLOCK(iort_fwnode_lock);
>  
> +/*
> + * One entry for IORT RMR.
> + */
> +struct iort_rmr_entry {
> + struct list_head list;
> + u32 sid;
> + struct acpi_iort_node *smmu;
> + struct acpi_iort_rmr_desc *rmr_desc;
> + u32 flags;
> +};
> +
> +static LIST_HEAD(iort_rmr_list); /* list of RMR regions from ACPI */
> +
>  /**
>   * iort_set_fwnode() - Create iort_fwnode and use it to register
>   *  iommu data in the iort_fwnode_list
> @@ -393,7 +406,8 @@ static struct acpi_iort_node *iort_node_get_id(struct 
> acpi_iort_node *node,
>   if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
>   node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ||
>   node->type == ACPI_IORT_NODE_SMMU_V3 ||
> - node->type == ACPI_IORT_NODE_PMCG) {
> + node->type == ACPI_IORT_NODE_PMCG ||
> + node->type == ACPI_IORT_NODE_RMR) {
>   *id_out = map->output_base;
>   return parent;
>   }
> @@ -1660,6 +1674,91 @@ static void __init iort_enable_acs(struct 
> acpi_iort_node *iort_node)
>  #else
>  static inline void iort_enable_acs(struct acpi_iort_node *iort_node) { }
>  #endif
> +static int iort_rmr_desc_valid(struct acpi_iort_rmr_desc *desc, u32 count)
> +{
> + int i, j;
> +
> + for (i = 0; i < count; i++) {
> + u64 end, start = desc[i].base_address, length = desc[i].length;
> +
> + if (!IS_ALIGNED(start, SZ_64K) || !IS_ALIGNED(length, SZ_64K))
> + return -EINVAL;
> +
> + end = start + length - 1;
> +
> + /* Check for address overlap */
> + for (j = i + 1; j < count; j++) {
> + u64 e_start = desc[j].base_address;
> + u64 e_end = e_start + desc[j].length - 1;
> +
> + if (start <= e_end && end >= e_start)
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int __init iort_parse_rmr(struct acpi_iort_node *iort_node)
> +{
> + struct acpi_iort_node *smmu;
> + struct iort_rmr_entry *e;
> + struct acpi_iort_rmr *rmr;
> + struct acpi_iort_rmr_desc *rmr_desc;
> + u32 map_count = iort_node->mapping_count;
> + u32  sid;
   ^
Remove one space.

> + int i, ret = 0;
> +
> + if (iort_node->type != ACPI_IORT_NODE_RMR)
> + return 0;
> +
> + if (!iort_node->mapping_offset || map_count != 1) {
> + pr_err(FW_BUG "Invalid ID mapping, skipping RMR node %p\n",
> +iort_node);
> + return -EINVAL;
> + }
> +
> + /* 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 -EINVAL;
> + }
> +
> + /* 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 -EINVAL;
> + }
> +
> + rmr_desc = ACPI_ADD_PTR(struct acpi_iort_rmr_desc, iort_node,
> + rmr->rmr_offset);
> +
> + ret = iort_rmr_desc_valid(rmr_desc, rmr->rmr_count);
> + if (ret) {
> + pr_err(FW_BUG "Invalid RMR descriptor[%d] for node %p, 
> skipping...\n",
> +i, iort_node);
> + return ret;
> + }
> +
> + for (i = 0; i < rmr->rmr_count; i++, rmr_desc++) {
> + e = kmalloc(sizeof(*e), GFP_KERNEL);
> + if (!e)
> + return -ENOMEM;
> +
> + e->sid = sid;
> + e->smmu = smmu;
> + e->rmr_desc = rmr_desc;
> + e->flags = rmr->flags;
> +
> + list_add_tail(>list, _rmr_list);
> + }
> +
> + return 0;
> +}
>  
>  static void __init 

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

2021-06-03 Thread Lorenzo Pieralisi
On Thu, May 13, 2021 at 02:45:45PM +0100, 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

"Add a helper function (iort_iommu_get_rmrs()) that retrieves RMR memory
descriptors associated with a given IOMMU. This will be used by IOMMU
drivers to setup necessary mappings.

Invoke it from the generic helper iommu_dma_get_rmrs()."

> interface.
> 
> Signed-off-by: Shameer Kolothum 
> ---
>  drivers/acpi/arm64/iort.c | 40 +++
>  drivers/iommu/dma-iommu.c |  3 +++
>  include/linux/acpi_iort.h |  7 +++
>  3 files changed, 50 insertions(+)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index fea1ffaedf3b..6ca88c38987a 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,43 @@ static inline int iort_add_device_replay(struct device 
> *dev)
>   return err;
>  }
>  
> +/**
> + * iort_iommu_get_rmrs - Helper to retrieve RMR info associated with IOMMU

iort_iommu_get_rmrs()

please check other functions comments in the patchset.

> + * @iommu: fwnode for the IOMMU

Does not match the parameter.

> + * @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;
> +
> + iommu = iort_get_iort_node(iommu_fwnode);
> + if (!iommu)
> + return -EINVAL;
> +
> + list_for_each_entry(e, _rmr_list, list) {
> + struct acpi_iort_rmr_desc *rmr_desc;
> + struct iommu_rmr *rmr;
> +
> + if (e->smmu != iommu)
> + continue;
> +
> + rmr_desc = e->rmr_desc;
> + rmr = iommu_dma_alloc_rmr(rmr_desc->base_address,
> +   rmr_desc->length, e->sid,
> +   e->flags);
> + if (!rmr)
> + return -ENOMEM;

I suppose it is OK to leave the already allocated regions allocated
on -ENOMEM.

Probably worth clarifying it in the function comment.

Lorenzo

> +
> + list_add_tail(>list, head);
> + }
> +
> + return 0;
> +}
> +
>  /**
>   * iort_iommu_msi_get_resv_regions - Reserved region driver helper
>   * @dev: Device from iommu_get_resv_regions()
> @@ -1108,6 +1146,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>  const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
>   const u32 *input_id)
>  { return NULL; }
> +int iort_iommu_get_rmrs(struct fwnode_handle *fwnode, struct list_head *head)
> +{ return -ENODEV; }
>  #endif
>  
>  static int nc_dma_get_range(struct device *dev, u64 *size)
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 674bd8815159..2d9caf548a32 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -203,6 +203,9 @@ EXPORT_SYMBOL(iommu_dma_get_resv_regions);
>  int iommu_dma_get_rmrs(struct fwnode_handle *iommu_fwnode,
>  struct list_head *list)
>  {
> + if (!is_of_node(iommu_fwnode))
> + return iort_iommu_get_rmrs(iommu_fwnode, list);
> +
>   return -EINVAL;
>  }
>  EXPORT_SYMBOL(iommu_dma_get_rmrs);
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 1a12baa58e40..e8c45fa59531 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -39,6 +39,8 @@ const struct iommu_ops *iort_iommu_configure_id(struct 
> device *dev,
>   const u32 *id_in);
>  int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
>  phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
> + struct list_head *list);
>  #else
>  static inline void acpi_iort_init(void) { }
>  static inline u32 iort_msi_map_id(struct device *dev, u32 id)
> @@ -59,6 +61,11 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
> struct list_head *head)
>  
>  static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
>  { return PHYS_ADDR_MAX; }
> +
> +static inline
> +int iort_iommu_get_rmrs(struct fwnode_handle *iommu_fwnode,
> + struct list_head *list)
> +{ return -ENODEV; }
>  #endif
>  
>  #endif /* __ACPI_IORT_H__ */
> -- 
> 2.17.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v14 09/10] ACPI/IORT: Enable stall support for platform devices

2021-04-06 Thread Lorenzo Pieralisi
On Thu, Apr 01, 2021 at 05:47:18PM +0200, Jean-Philippe Brucker wrote:
> Copy the "Stall supported" bit, that tells whether a named component
> supports stall, into the dma-can-stall device property.
> 
> Acked-by: Jonathan Cameron 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/acpi/arm64/iort.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)

Acked-by: Lorenzo Pieralisi 

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 3912a1f6058e..0828f70cb782 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -968,13 +968,15 @@ static int iort_pci_iommu_init(struct pci_dev *pdev, 
> u16 alias, void *data)
>  static void iort_named_component_init(struct device *dev,
> struct acpi_iort_node *node)
>  {
> - struct property_entry props[2] = {};
> + struct property_entry props[3] = {};
>   struct acpi_iort_named_component *nc;
>  
>   nc = (struct acpi_iort_named_component *)node->node_data;
>   props[0] = PROPERTY_ENTRY_U32("pasid-num-bits",
> FIELD_GET(ACPI_IORT_NC_PASID_BITS,
>   nc->node_flags));
> + if (nc->node_flags & ACPI_IORT_NC_STALL_SUPPORTED)
> + props[1] = PROPERTY_ENTRY_BOOL("dma-can-stall");
>  
>   if (device_add_properties(dev, props))
>   dev_warn(dev, "Could not add device properties\n");
> -- 
> 2.31.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v2 1/8] ACPICA: IORT: Update for revision E

2021-03-24 Thread Lorenzo Pieralisi
On Tue, Mar 23, 2021 at 06:51:44PM +, Kaneda, Erik wrote:
> 
> 
> > -Original Message-
> > From: Lorenzo Pieralisi 
> > Sent: Tuesday, March 23, 2021 8:54 AM
> > To: Kaneda, Erik 
> > Cc: Shameerali Kolothum Thodi ;
> > linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> > iommu@lists.linux-foundation.org; de...@acpica.org; Moore, Robert
> > ; Linuxarm ;
> > steven.pr...@arm.com; sami.muja...@arm.com; robin.mur...@arm.com;
> > wanghuiqiang 
> > Subject: Re: [RFC PATCH v2 1/8] ACPICA: IORT: Update for revision E
> > 
> > On Mon, Mar 22, 2021 at 09:57:58PM +, Kaneda, Erik wrote:
> > >
> > >
> > > > -Original Message-
> > > > From: Shameerali Kolothum Thodi
> > > > 
> > > > Sent: Monday, March 22, 2021 3:36 AM
> > > > To: Kaneda, Erik ; linux-arm-
> > > > ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> > iommu@lists.linux-
> > > > foundation.org; de...@acpica.org; Lorenzo Pieralisi
> > > > ; Moore, Robert
> > 
> > > > Cc: Linuxarm ; steven.pr...@arm.com;
> > > > sami.muja...@arm.com; robin.mur...@arm.com; wanghuiqiang
> > > > 
> > > > Subject: [Devel] Re: [RFC PATCH v2 1/8] ACPICA: IORT: Update for
> > revision E
> > > >
> > > > [+]
> > > >
> > > > Hi Erik,
> > > >
> > > > As this is now just merged ino acpica-master and based on the discussion
> > we
> > > > had here,
> > > >
> > > > https://github.com/acpica/acpica/pull/638
> > > >
> > > > I had a discussion with ARM folks(Lorenzo) in the 
> > > > linaro-open-discussions
> > call
> > > > and
> > > > can confirm that the IORT Revision E is not the final specification and 
> > > > has
> > > > some issues
> > > > which is now corrected in the latest E.b revision[1]. Also there are no
> > current
> > > > users
> > > > for the Rev E and it may not be a good idea to push this version into 
> > > > the
> > Linux
> > > > kernel
> > > > or elsewhere.
> > > >
> > > > So could you please revert the merge and I am planning to work on the
> > E.b
> > > > soon.
> > > Hi,
> > >
> > > > Please let me know if I need to explicitly send a revert pull request 
> > > > or not.
> > >
> > > Please send a revert pull request and I'll remember to not submit 
> > > Linux-ize
> > the IORT patches.
> > >
> > > From all of the activity that I've seen with the IORT specification,
> > > it looks like this table is nontrivial to design and maintain. The
> > > difficulty I have with the table is that I do not understand which
> > > table revisions are in active use.
> > 
> Hi Lorenzo,
> 
> > Possibly all of them in firmware in the field - I am not sure what you
> > are asking though; if you can elaborate I'd be grateful.
> 
> Yes, I'd be happy to explain.
> 
> The ACPICA project contains code that provides definitions for ACPI tables. 
> After each release of this project, the codebase gets translated to a Linux 
> style syntax and relevant patches are submitted to Linux so that it can use 
> these table definitions in their driver codebase. From ACPICA's perspective, 
> the code providing these definitions are used to implement a 
> compiler/disassembler called iASL. This tool disassembles table definitions 
> so that the user doesn't have to open a hex editor to decipher ACPI tables. 
> Our goal with iASL is to be able to disassemble as many ACPI tables as 
> possible to give users the ability to compile and debug ACPI tables.
> 
> Out of the 60+ tables that we support, IORT has been tricky to maintain. 
> There are revisions A-E and we have received pull requests from engineers 
> from ARM or companies that work with ARM. We are grateful of their 
> contributions but some of these pull requests have broken support for earlier 
> versions of IORT. In addition, we sometimes receive communication from people 
> like Shameer saying that revision E does not currently have users. This 
> leaves Bob and I very confused about which revisions we should be focused on 
> supporting in iASL.
> 
> We need your help in understanding which versions of IORT should be supported 
> by iASL as well as Linux.
> 
> I hope this helps.. Let me know if you need me to clarify anything that I've 
> written.

Yes, it does, it is my question that wasn't 

Re: [RFC PATCH v2 1/8] ACPICA: IORT: Update for revision E

2021-03-23 Thread Lorenzo Pieralisi
On Mon, Mar 22, 2021 at 09:57:58PM +, Kaneda, Erik wrote:
> 
> 
> > -Original Message-
> > From: Shameerali Kolothum Thodi
> > 
> > Sent: Monday, March 22, 2021 3:36 AM
> > To: Kaneda, Erik ; linux-arm-
> > ker...@lists.infradead.org; linux-a...@vger.kernel.org; iommu@lists.linux-
> > foundation.org; de...@acpica.org; Lorenzo Pieralisi
> > ; Moore, Robert 
> > Cc: Linuxarm ; steven.pr...@arm.com;
> > sami.muja...@arm.com; robin.mur...@arm.com; wanghuiqiang
> > 
> > Subject: [Devel] Re: [RFC PATCH v2 1/8] ACPICA: IORT: Update for revision E
> > 
> > [+]
> > 
> > Hi Erik,
> > 
> > As this is now just merged ino acpica-master and based on the discussion we
> > had here,
> > 
> > https://github.com/acpica/acpica/pull/638
> > 
> > I had a discussion with ARM folks(Lorenzo) in the linaro-open-discussions 
> > call
> > and
> > can confirm that the IORT Revision E is not the final specification and has
> > some issues
> > which is now corrected in the latest E.b revision[1]. Also there are no 
> > current
> > users
> > for the Rev E and it may not be a good idea to push this version into the 
> > Linux
> > kernel
> > or elsewhere.
> > 
> > So could you please revert the merge and I am planning to work on the E.b
> > soon.
> Hi,
> 
> > Please let me know if I need to explicitly send a revert pull request or 
> > not.
> 
> Please send a revert pull request and I'll remember to not submit Linux-ize 
> the IORT patches.
> 
> From all of the activity that I've seen with the IORT specification,
> it looks like this table is nontrivial to design and maintain. The
> difficulty I have with the table is that I do not understand which
> table revisions are in active use.

Possibly all of them in firmware in the field - I am not sure what you
are asking though; if you can elaborate I'd be grateful.

> So my question is this: which IORT revisions are being actively used?

See above.

Thanks,
Lorenzo

> 
> Thanks,
> Erik
> > 
> > Thanks,
> > Shameer
> > 
> > 1. https://developer.arm.com/documentation/den0049/latest/
> > 
> > > -Original Message-
> > > From: iommu [mailto:iommu-boun...@lists.linux-foundation.org] On
> > Behalf Of
> > > Shameer Kolothum
> > > Sent: 19 November 2020 12:12
> > > To: linux-arm-ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> > > iommu@lists.linux-foundation.org; de...@acpica.org
> > > Cc: Linuxarm ; steven.pr...@arm.com;
> > Guohanjun
> > > (Hanjun Guo) ; sami.muja...@arm.com;
> > > robin.mur...@arm.com; wanghuiqiang 
> > > Subject: [RFC PATCH v2 1/8] ACPICA: IORT: Update for revision E
> > >
> > > IORT revision E contains a few additions like,
> > >     -Added an identifier field in the node descriptors to aid table
> > >      cross-referencing.
> > >     -Introduced the Reserved Memory Range(RMR) node. This is used
> > >      to describe memory ranges that are used by endpoints and requires
> > >      a unity mapping in SMMU.
> > > -Introduced a flag in the RC node to express support for PRI.
> > >
> > > Signed-off-by: Shameer Kolothum
> > 
> > > ---
> > >  include/acpi/actbl2.h | 25 +++--
> > >  1 file changed, 19 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index
> > > ec66779cb193..274fce7b5c01 100644
> > > --- a/include/acpi/actbl2.h
> > > +++ b/include/acpi/actbl2.h
> > > @@ -68,7 +68,7 @@
> > >   * IORT - IO Remapping Table
> > >   *
> > >   * Conforms to "IO Remapping Table System Software on ARM Platforms",
> > > - * Document number: ARM DEN 0049D, March 2018
> > > + * Document number: ARM DEN 0049E, June 2020
> > >   *
> > >
> > >
> > **
> > **
> > > **/
> > >
> > > @@ -86,7 +86,8 @@ struct acpi_iort_node {
> > >   u8 type;
> > >   u16 length;
> > >   u8 revision;
> > > - u32 reserved;
> > > + u16 reserved;
> > > + u16 identifier;
> > >   u32 mapping_count;
> > >   u32 mapping_offset;
> > >   char node_data[1];
> > > @@ -100,7 +101,8 @@ enum acpi_iort_node_type {
> > >   ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
> > >   ACPI_IORT_NODE_SMMU = 0x03,
> > >   ACPI_IORT_NODE_SMMU_V3 = 0x04,

Re: [PATCH v4 0/2] VMD MSI Remapping Bypass

2021-03-22 Thread Lorenzo Pieralisi
On Wed, 10 Feb 2021 09:13:13 -0700, Jon Derrick wrote:
> The Intel Volume Management Device acts similar to a PCI-to-PCI bridge in that
> it changes downstream devices' requester-ids to its own. As VMD supports PCIe
> devices, it has its own MSI-X table and transmits child device MSI-X by
> remapping child device MSI-X and handling like a demultiplexer.
> 
> Some newer VMD devices (Icelake Server) have an option to bypass the VMD MSI-X
> remapping table. This allows for better performance scaling as the child 
> device
> MSI-X won't be limited by VMD's MSI-X count and IRQ handler.
> 
> [...]

Applied to pci/vmd, thanks!

[1/2] iommu/vt-d: Use Real PCI DMA device for IRTE
  https://git.kernel.org/lpieralisi/pci/c/9b4a824b88
[2/2] PCI: vmd: Disable MSI-X remapping when possible
  https://git.kernel.org/lpieralisi/pci/c/ee81ee84f8

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


Re: [PATCH v4 0/2] VMD MSI Remapping Bypass

2021-03-18 Thread Lorenzo Pieralisi
On Thu, Mar 18, 2021 at 10:07:38AM +0100, j...@8bytes.org wrote:
> On Wed, Mar 17, 2021 at 07:14:17PM +, Derrick, Jonathan wrote:
> > Gentle reminder, for v5.13 ?
> 
> This should go through the PCI tree, Bjorn?

I will start queuing code next week, noted.

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


Re: [PATCH v4 6/7] arm64: mm: Set ZONE_DMA size based on early IORT scan

2020-10-27 Thread Lorenzo Pieralisi
On Wed, Oct 21, 2020 at 02:34:36PM +0200, Nicolas Saenz Julienne wrote:
> From: Ard Biesheuvel 
> 
> We recently introduced a 1 GB sized ZONE_DMA to cater for platforms
> incorporating masters that can address less than 32 bits of DMA, in
> particular the Raspberry Pi 4, which has 4 or 8 GB of DRAM, but has
> peripherals that can only address up to 1 GB (and its PCIe host
> bridge can only access the bottom 3 GB)
> 
> Instructing the DMA layer about these limitations is straight-forward,
> even though we had to fix some issues regarding memory limits set in
> the IORT for named components, and regarding the handling of ACPI _DMA
> methods. However, the DMA layer also needs to be able to allocate
> memory that is guaranteed to meet those DMA constraints, for bounce
> buffering as well as allocating the backing for consistent mappings.
> 
> This is why the 1 GB ZONE_DMA was introduced recently. Unfortunately,
> it turns out the having a 1 GB ZONE_DMA as well as a ZONE_DMA32 causes
> problems with kdump, and potentially in other places where allocations
> cannot cross zone boundaries. Therefore, we should avoid having two
> separate DMA zones when possible.
> 
> So let's do an early scan of the IORT, and only create the ZONE_DMA
> if we encounter any devices that need it. This puts the burden on
> the firmware to describe such limitations in the IORT, which may be
> redundant (and less precise) if _DMA methods are also being provided.
> However, it should be noted that this situation is highly unusual for
> arm64 ACPI machines. Also, the DMA subsystem still gives precedence to
> the _DMA method if implemented, and so we will not lose the ability to
> perform streaming DMA outside the ZONE_DMA if the _DMA method permits
> it.
> 
> Cc: Jeremy Linton 
> Cc: Lorenzo Pieralisi 
> Cc: Nicolas Saenz Julienne 
> Cc: Rob Herring 
> Cc: Christoph Hellwig 
> Cc: Robin Murphy 
> Cc: Hanjun Guo 
> Cc: Sudeep Holla 
> Cc: Anshuman Khandual 
> Signed-off-by: Ard Biesheuvel 
> [nsaenz: Rebased, removed documentation change and add declaration in 
> acpi_iort.h]
> Signed-off-by: Nicolas Saenz Julienne 
> 
> ---
> 
> Changes since v3:
>  - Use min_not_zero()
>  - Check ACPI revision
>  - Remove unnecessary #ifdef in zone_sizes_init()
> 
>  arch/arm64/mm/init.c  |  3 ++-
>  drivers/acpi/arm64/iort.c | 52 +++
>  include/linux/acpi_iort.h |  4 +++
>  3 files changed, 58 insertions(+), 1 deletion(-)

Acked-by: Lorenzo Pieralisi 

> diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
> index 94e38f99748b..f5d4f85506e4 100644
> --- a/arch/arm64/mm/init.c
> +++ b/arch/arm64/mm/init.c
> @@ -29,6 +29,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  #include 
> @@ -190,7 +191,7 @@ static void __init zone_sizes_init(unsigned long min, 
> unsigned long max)
>  
>  #ifdef CONFIG_ZONE_DMA
>   dt_zone_dma_bits = ilog2(of_dma_get_max_cpu_address(NULL));
> - zone_dma_bits = min(32U, dt_zone_dma_bits);
> + zone_dma_bits = min3(32U, dt_zone_dma_bits, 
> acpi_iort_get_zone_dma_size());
>   arm64_dma_phys_limit = max_zone_phys(zone_dma_bits);
>   max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
>  #endif
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 9929ff50c0c0..05fe4a076bab 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -1718,3 +1718,55 @@ void __init acpi_iort_init(void)
>  
>   iort_init_platform_devices();
>  }
> +
> +#ifdef CONFIG_ZONE_DMA
> +/*
> + * Check the IORT whether any devices exist whose DMA mask is < 32 bits.
> + * If so, return the smallest value encountered, or 32 otherwise.
> + */
> +unsigned int __init acpi_iort_get_zone_dma_size(void)
> +{
> + struct acpi_table_iort *iort;
> + struct acpi_iort_node *node, *end;
> + acpi_status status;
> + u8 limit = 32;
> + int i;
> +
> + if (acpi_disabled)
> + return limit;
> +
> + status = acpi_get_table(ACPI_SIG_IORT, 0,
> + (struct acpi_table_header **));
> + if (ACPI_FAILURE(status))
> + return limit;
> +
> + node = ACPI_ADD_PTR(struct acpi_iort_node, iort, iort->node_offset);
> + end = ACPI_ADD_PTR(struct acpi_iort_node, iort, iort->header.length);
> +
> + for (i = 0; i < iort->node_count; i++) {
> + if (node >= end)
> + break;
> +
> + switch (node->type) {
> + struct acpi_iort_named_component *ncomp;
> + struct acpi_iort_root_complex *rc;
> +
> + 

Re: [PATCH v3 7/8] arm64: mm: Set ZONE_DMA size based on early IORT scan

2020-10-15 Thread Lorenzo Pieralisi
On Wed, Oct 14, 2020 at 09:12:09PM +0200, Nicolas Saenz Julienne wrote:

[...]

> +unsigned int __init acpi_iort_get_zone_dma_size(void)
> +{
> + struct acpi_table_iort *iort;
> + struct acpi_iort_node *node, *end;
> + acpi_status status;
> + u8 limit = 32;
> + int i;
> +
> + if (acpi_disabled)
> + return limit;
> +
> + status = acpi_get_table(ACPI_SIG_IORT, 0,
> + (struct acpi_table_header **));
> + if (ACPI_FAILURE(status))
> + return limit;
> +
> + node = ACPI_ADD_PTR(struct acpi_iort_node, iort, iort->node_offset);
> + end = ACPI_ADD_PTR(struct acpi_iort_node, iort, iort->header.length);
> +
> + for (i = 0; i < iort->node_count; i++) {
> + if (node >= end)
> + break;
> +
> + switch (node->type) {
> + struct acpi_iort_named_component *ncomp;
> + struct acpi_iort_root_complex *rc;
> +
> + case ACPI_IORT_NODE_NAMED_COMPONENT:
> + ncomp = (struct acpi_iort_named_component 
> *)node->node_data;
> + if (ncomp->memory_address_limit)
> + limit = min(limit, ncomp->memory_address_limit);
> + break;
> +
> + case ACPI_IORT_NODE_PCI_ROOT_COMPLEX:
> + rc = (struct acpi_iort_root_complex *)node->node_data;
> + if (rc->memory_address_limit)

You need to add a node revision check here, see rc_dma_get_range() in
drivers/acpi/arm64/iort.c, otherwise we may be reading junk data
in older IORT tables - acpica structures are always referring to the
latest specs.

Thanks,
Lorenzo

> + limit = min(limit, rc->memory_address_limit);
> + break;
> + }
> + node = ACPI_ADD_PTR(struct acpi_iort_node, node, node->length);
> + }
> + acpi_put_table(>header);
> + return limit;
> +}
> +#endif
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 20a32120bb88..7d2e184f0d4d 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -38,6 +38,7 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 
> *size);
>  const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
>   const u32 *id_in);
>  int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
> +unsigned int acpi_iort_get_zone_dma_size(void);
>  #else
>  static inline void acpi_iort_init(void) { }
>  static inline u32 iort_msi_map_id(struct device *dev, u32 id)
> @@ -55,6 +56,9 @@ static inline const struct iommu_ops 
> *iort_iommu_configure_id(
>  static inline
>  int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head)
>  { return 0; }
> +
> +static inline unsigned int acpi_iort_get_zone_dma_size(void)
> +{ return 32; }
>  #endif
>  
>  #endif /* __ACPI_IORT_H__ */
> -- 
> 2.28.0
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/4] of/fdt: Update zone_dma_bits when running in bcm2711

2020-10-09 Thread Lorenzo Pieralisi
On Fri, Oct 09, 2020 at 11:13:59AM +0200, Ard Biesheuvel wrote:
> On Fri, 9 Oct 2020 at 10:36, Nicolas Saenz Julienne
>  wrote:
> >
> > On Fri, 2020-10-09 at 09:37 +0200, Ard Biesheuvel wrote:
> > > On Fri, 9 Oct 2020 at 09:11, Christoph Hellwig  wrote:
> > > > On Thu, Oct 08, 2020 at 12:05:25PM +0200, Nicolas Saenz Julienne wrote:
> > > > > Sadly I just realised that the series is incomplete, we have RPi4 
> > > > > users that
> > > > > want to boot unsing ACPI, and this series would break things for 
> > > > > them. I'll
> > > > > have a word with them to see what we can do for their use-case.
> > > >
> > > > Stupid question:  why do these users insist on a totally unsuitable
> > > > interface? And why would we as Linux developers care to support such
> > > > a aims?
> > >
> > > The point is really whether we want to revert changes in Linux that
> > > made both DT and ACPI boot work without quirks on RPi4.
> >
> > Well, and broke a big amount of devices that were otherwise fine.
> >
> 
> Yeah that was unfortunate.
> 
> > > Having to check the RPi4 compatible string or OEM id in core init code is
> > > awful, regardless of whether you boot via ACPI or via DT.
> > >
> > > The problem with this hardware is that it uses a DMA mask which is
> > > narrower than 32, and the arm64 kernel is simply not set up to deal
> > > with that at all. On DT, we have DMA ranges properties and the likes
> > > to describe such limitations, on ACPI we have _DMA methods as well as
> > > DMA range attributes in the IORT, both of which are now handled
> > > correctly. So all the information is there, we just have to figure out
> > > how to consume it early on.
> >
> > Is it worth the effort just for a single board? I don't know about ACPI but
> > parsing dma-ranges that early at boot time is not trivial. My intuition 
> > tells
> > me that it'd be even harder for ACPI, being a more complex data structure.
> >
> 
> Yes, it will be harder, especially for the _DMA methods.
> 
> > > Interestingly, this limitation always existed in the SoC, but it
> > > wasn't until they started shipping it with more than 1 GB of DRAM that
> > > it became a problem. This means issues like this could resurface in
> > > the future with existing SoCs when they get shipped with more memory,
> > > and so I would prefer fixing this in a generic way.
> >
> > Actually what I proposed here is pretty generic. Specially from arm64's
> > perspective. We call early_init_dt_scan(), which sets up zone_dma_bits 
> > based on
> > whatever it finds in DT. Both those operations are architecture independent.
> > arm64 arch code doesn't care about the logic involved in ascertaining
> > zone_dma_bits. I get that the last step isn't generic. But it's all setup 
> > so as
> > to make it as such whenever it's worth the effort.
> >
> 
> The problem is that, while we are providing a full description of the
> SoC's capabilities, we short circuit this by inserting knowledge into
> the code (that is shared between all DT architectures) that
> "brcm,bcm2711" is special, and needs a DMA zone override.
> 
> I think for ACPI boot, we might be able to work around this by cold
> plugging the memory above 1 GB, but I have to double check whether it
> won't get pulled into ZONE_DMA32 anyway (unless anyone can answer that
> for me here from the top of their head)

Is this information that we can infer from IORT nodes and make it
generic (ie make a DMA limit out of all IORT nodes allowed ranges) ?

We can move this check to IORT code and call it from arm64 if it
can be made to work.

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


Re: [RFC 0/3] iommu: Reserved regions for IOVAs beyond dma_mask and iommu aperture

2020-10-05 Thread Lorenzo Pieralisi
[+Christoph]

On Tue, Sep 29, 2020 at 12:18:49PM -0600, Alex Williamson wrote:
> On Tue, 29 Sep 2020 09:18:22 +0200
> Auger Eric  wrote:
> 
> > Hi all,
> > 
> > [also correcting some outdated email addresses + adding Lorenzo in cc]
> > 
> > On 9/29/20 12:42 AM, Alex Williamson wrote:
> > > On Mon, 28 Sep 2020 21:50:34 +0200
> > > Eric Auger  wrote:
> > >   
> > >> VFIO currently exposes the usable IOVA regions through the
> > >> VFIO_IOMMU_GET_INFO ioctl / VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE
> > >> capability. However it fails to take into account the dma_mask
> > >> of the devices within the container. The top limit currently is
> > >> defined by the iommu aperture.  
> > > 
> > > I think that dma_mask is traditionally a DMA API interface for a device
> > > driver to indicate to the DMA layer which mappings are accessible to the
> > > device.  On the other hand, vfio makes use of the IOMMU API where the
> > > driver is in userspace.  That userspace driver has full control of the
> > > IOVA range of the device, therefore dma_mask is mostly irrelevant to
> > > vfio.  I think the issue you're trying to tackle is that the IORT code
> > > is making use of the dma_mask to try to describe a DMA address
> > > limitation imposed by the PCI root bus, living between the endpoint
> > > device and the IOMMU.  Therefore, if the IORT code is exposing a
> > > topology or system imposed device limitation, this seems much more akin
> > > to something like an MSI reserved range, where it's not necessarily the
> > > device or the IOMMU with the limitation, but something that sits
> > > between them.  
> > 
> > First I think I failed to explain the context. I worked on NVMe
> > passthrough on ARM. The QEMU NVMe backend uses VFIO to program the
> > physical device. The IOVA allocator there currently uses an IOVA range
> > within [0x1, 1ULL << 39]. This IOVA layout rather is arbitrary if I
> > understand correctly.
> 
> 39 bits is the minimum available on some VT-d systems, so it was
> probably considered a reasonable minimum address width to consider.
> 
> > I noticed we rapidly get some VFIO MAP DMA
> > failures because the allocated IOVA collide with the ARM MSI reserved
> > IOVA window [0x800, 0x810]. Since  9b77e5c79840 ("vfio/type1:
> > Check reserved region conflict and update iova list"), such VFIO MAP DMA
> > attempts to map IOVAs belonging to host reserved IOVA windows fail. So,
> > by using the VFIO_IOMMU_GET_INFO ioctl /
> > VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE I can change the IOVA allocator to
> > avoid allocating within this range and others. While working on this, I
> > tried to automatically compute the min/max IOVAs and change the
> > arbitrary [0x1, 1ULL << 39]. My SMMUv2 supports up to 48b so
> > naturally the max IOVA was computed as 1ULL << 48. The QEMU NVMe backend
> > allocates at the bottom and at the top of the range. I noticed the use
> > case was not working as soon as the top IOVA was more than 1ULL << 42.
> > And then we noticed the dma_mask was set to 42 by using
> > cat  /sys/bus/pci/devices/0005:01:00.0/dma_mask_bits. So my
> > interpretation is the dma_mask was somehow containing the info the
> > device couldn't handle IOVAs beyond a certain limit.
> 
> I see that there are both OF and ACPI hooks in pci_dma_configure() and
> both modify dev->dma_mask, which is what pci-sysfs is exposing here,
> but I'm not convinced this even does what it's intended to do.  The
> driver core calls this via the bus->dma_configure callback before
> probing a driver, but then what happens when the driver calls
> pci_set_dma_mask()?  This is just a wrapper for dma_set_mask() and I
> don't see anywhere that would take into account the existing
> dev->dma_mask.  It seems for example that pci_dma_configure() could
> produce a 42 bit mask as we have here, then the driver could override
> that with anything that the dma_ops.dma_supported() callback finds
> acceptable, and I don't see any instances where the current
> dev->dma_mask is considered.  Am I overlooking something? 

I don't think so but Christoph and Robin can provide more input on
this - it is a long story.

ACPI and OF bindings set a default dma_mask (and dev->bus_dma_limit),
this does not prevent a driver from overriding the dev->dma_mask but DMA
mapping code still takes into account the dev->bus_dma_limit.

This may help:

git log -p 03bfdc31176c

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


Re: [PATCH v11 00/11] PCI: brcmstb: enable PCIe for STB chips

2020-09-08 Thread Lorenzo Pieralisi
On Mon, Sep 07, 2020 at 11:29:06AM -0700, Florian Fainelli wrote:
> 
> 
> On 9/7/2020 10:43 AM, Jim Quinlan wrote:
> > On Mon, Sep 7, 2020 at 5:16 AM Lorenzo Pieralisi
> >  wrote:
> > > 
> > > On Thu, Aug 27, 2020 at 09:29:59AM -0400, Jim Quinlan wrote:
> > > > On Thu, Aug 27, 2020 at 2:35 AM Christoph Hellwig  wrote:
> > > > > 
> > > > > On Tue, Aug 25, 2020 at 10:40:27AM -0700, Florian Fainelli wrote:
> > > > > > Hi,
> > > > > > 
> > > > > > On 8/24/2020 12:30 PM, Jim Quinlan wrote:
> > > > > > > 
> > > > > > > Patchset Summary:
> > > > > > > Enhance a PCIe host controller driver.  Because of its 
> > > > > > > unusual design
> > > > > > > we are foced to change dev->dma_pfn_offset into a more 
> > > > > > > general role
> > > > > > > allowing multiple offsets.  See the 'v1' notes below for more 
> > > > > > > info.
> > > > > > 
> > > > > > We are version 11 and counting, and it is not clear to me whether 
> > > > > > there is
> > > > > > any chance of getting these patches reviewed and hopefully merged 
> > > > > > for the
> > > > > > 5.10 merge window.
> > > > > > 
> > > > > > There are a lot of different files being touched, so what would be 
> > > > > > the
> > > > > > ideal way of routing those changes towards inclusion?
> > > > > 
> > > > > FYI, I offered to take the dma-mapping bits through the dma-mapping 
> > > > > tree.
> > > > > I have a bit of a backlog, but plan to review and if Jim is ok with 
> > > > > that
> > > > > apply the current version.
> > > > Sounds good to me.
> > > 
> > > Hi Jim,
> > > 
> > > is the dependency now solved ? Should we review/take this series as
> > > is for v5.10 through the PCI tree ?
> > Hello Lorenzo,
> > 
> > We are still working out a regression with the DMA offset commit on
> > the RaspberryPi.  Nicolas has found the root cause and we are now
> > devising a solution.
> 
> Maybe we can parallelize the PCIe driver review while the DMA changes
> are being worked on in Christoph's branch. Lorenzo, are you fine with
> the PCIe changes proper?

I will have a look - the main contentious point was about the DMA
changes - if Christoph is happy with them I am OK with them
too - I hope there is not anything controversial in the host
bridge driver itself but I will look into it.

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


Re: [PATCH v11 00/11] PCI: brcmstb: enable PCIe for STB chips

2020-09-07 Thread Lorenzo Pieralisi
On Thu, Aug 27, 2020 at 09:29:59AM -0400, Jim Quinlan wrote:
> On Thu, Aug 27, 2020 at 2:35 AM Christoph Hellwig  wrote:
> >
> > On Tue, Aug 25, 2020 at 10:40:27AM -0700, Florian Fainelli wrote:
> > > Hi,
> > >
> > > On 8/24/2020 12:30 PM, Jim Quinlan wrote:
> > >>
> > >> Patchset Summary:
> > >>Enhance a PCIe host controller driver.  Because of its unusual design
> > >>we are foced to change dev->dma_pfn_offset into a more general role
> > >>allowing multiple offsets.  See the 'v1' notes below for more info.
> > >
> > > We are version 11 and counting, and it is not clear to me whether there is
> > > any chance of getting these patches reviewed and hopefully merged for the
> > > 5.10 merge window.
> > >
> > > There are a lot of different files being touched, so what would be the
> > > ideal way of routing those changes towards inclusion?
> >
> > FYI, I offered to take the dma-mapping bits through the dma-mapping tree.
> > I have a bit of a backlog, but plan to review and if Jim is ok with that
> > apply the current version.
> Sounds good to me.

Hi Jim,

is the dependency now solved ? Should we review/take this series as
is for v5.10 through the PCI tree ?

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


Re: [patch V2 34/46] PCI/MSI: Make arch_.*_msi_irq[s] fallbacks selectable

2020-08-28 Thread Lorenzo Pieralisi
On Thu, Aug 27, 2020 at 01:20:40PM -0500, Bjorn Helgaas wrote:

[...]

> And I can't figure out what's special about tegra, rcar, and xilinx
> that makes them need it as well.  Is there something I could grep for
> to identify them?  Is there a way to convert them so they don't need
> it?

I think DT binding and related firmware support are needed to setup the
MSI IRQ domains correctly, there is nothing special about tegra, rcar
and xilinx AFAIK (well, all native host controllers MSI handling is
*special* just to be polite but let's gloss over this for the time
being).

struct msi_controller, to answer the first question.

I have doubts about pci_mvebu too, they do allocate an msi_controller
but without methods so it looks pretty much useless.

Hyper-V code too seems questionable, maybe there is room for more
clean-ups.

Lorenzo

> > --- a/include/linux/msi.h
> > +++ b/include/linux/msi.h
> > @@ -193,17 +193,38 @@ void pci_msi_mask_irq(struct irq_data *d
> >  void pci_msi_unmask_irq(struct irq_data *data);
> >  
> >  /*
> > - * The arch hooks to setup up msi irqs. Those functions are
> > - * implemented as weak symbols so that they /can/ be overriden by
> > - * architecture specific code if needed.
> > + * The arch hooks to setup up msi irqs. Default functions are implemented
> 
> s/msi/MSI/ to match the one below.
> 
> > + * as weak symbols so that they /can/ be overriden by architecture specific
> > + * code if needed. These hooks must be enabled by the architecture or by
> > + * drivers which depend on them via msi_controller based MSI handling.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


VFIO/IOMMU/PCI MC at LPC20 - Call for Topics

2020-08-04 Thread Lorenzo Pieralisi
Hi all,

following up the LPC20 blog announcement:

https://www.linuxplumbersconf.org/blog/2020/vfio-iommu-pci-microconference-accepted-into-2020-linux-plumbers-conference/

The call for topics for the VFIO/IOMMU/PCI microconference at LPC20 is
now open, the LPC20 entry below provides a list of possible topics but
you should feel free to submit topics of interest that you would like to
discuss with maintainers and developers of the respective subsystems.

https://www.linuxplumbersconf.org/event/7/page/80-accepted-microconferences#vfio-cr

Please do reach out for any other piece of information we can help with.

Looking forward to receiving your submissions !

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


Re: [PATCH v2 05/12] ACPI/IORT: Add an input ID to acpi_dma_configure()

2020-07-28 Thread Lorenzo Pieralisi
On Wed, Jul 15, 2020 at 10:13:26AM +0100, Lorenzo Pieralisi wrote:
> On Thu, Jul 09, 2020 at 10:35:14AM +0100, Lorenzo Pieralisi wrote:
> > On Fri, Jun 19, 2020 at 09:20:06AM +0100, Lorenzo Pieralisi wrote:
> > > Some HW devices are created as child devices of proprietary busses,
> > > that have a bus specific policy defining how the child devices
> > > wires representing the devices ID are translated into IOMMU and
> > > IRQ controllers device IDs.
> > > 
> > > Current IORT code provides translations for:
> > > 
> > > - PCI devices, where the device ID is well identified at bus level
> > >   as the requester ID (RID)
> > > - Platform devices that are endpoint devices where the device ID is
> > >   retrieved from the ACPI object IORT mappings (Named components single
> > >   mappings). A platform device is represented in IORT as a named
> > >   component node
> > > 
> > > For devices that are child devices of proprietary busses the IORT
> > > firmware represents the bus node as a named component node in IORT
> > > and it is up to that named component node to define in/out bus
> > > specific ID translations for the bus child devices that are
> > > allocated and created in a bus specific manner.
> > > 
> > > In order to make IORT ID translations available for proprietary
> > > bus child devices, the current ACPI (and IORT) code must be
> > > augmented to provide an additional ID parameter to acpi_dma_configure()
> > > representing the child devices input ID. This ID is bus specific
> > > and it is retrieved in bus specific code.
> > > 
> > > By adding an ID parameter to acpi_dma_configure(), the IORT
> > > code can map the child device ID to an IOMMU stream ID through
> > > the IORT named component representing the bus in/out ID mappings.
> > > 
> > > Signed-off-by: Lorenzo Pieralisi 
> > > Cc: Will Deacon 
> > > Cc: Hanjun Guo 
> > > Cc: Sudeep Holla 
> > > Cc: Catalin Marinas 
> > > Cc: Robin Murphy 
> > > Cc: "Rafael J. Wysocki" 
> > > ---
> > >  drivers/acpi/arm64/iort.c | 59 +--
> > >  drivers/acpi/scan.c   |  8 --
> > >  include/acpi/acpi_bus.h   |  9 --
> > >  include/linux/acpi.h  |  7 +
> > >  include/linux/acpi_iort.h |  7 +++--
> > >  5 files changed, 67 insertions(+), 23 deletions(-)
> > 
> > Hi Rafael,
> > 
> > just to ask if the ACPI core changes in this patch are OK with you,
> > thank you very much.
> 
> Hi Rafael,
> 
> are you OK with ACPI core changes in this patch ?
> 
> Please let me know, thanks.

Hi Rafael,

gentle ping, I think we are missing v5.9, we would need your feedback
on this please.

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


Re: [PATCH v2 00/12] ACPI/OF: Upgrade MSI/IOMMU ID mapping APIs

2020-07-20 Thread Lorenzo Pieralisi
On Fri, Jun 19, 2020 at 09:20:01AM +0100, Lorenzo Pieralisi wrote:
> This series is a v2 of a previous posting:
> 
> v1 -> v2
> 
> - Removed _rid() wrappers
> - Fixed !CONFIG_ACPI compilation issue
> - Converted of_pci_iommu_init() to use of_iommu_configure_dev_id()
> 
> v1: 
> https://lore.kernel.org/linux-arm-kernel/20200521130008.8266-1-lorenzo.pieral...@arm.com/
> 
> Original cover letter
> -
> 
> Firmware bindings provided in the ACPI IORT table[1] and device tree
> bindings define rules to carry out input/output ID mappings - ie
> retrieving an IOMMU/MSI controller input ID for a device with a given
> ID.
> 
> At the moment these firmware bindings are used exclusively for PCI
> devices and their requester ID to IOMMU/MSI id mapping but there is
> nothing PCI specific in the ACPI and devicetree bindings that prevent
> the firmware and kernel from using the firmware bindings to traslate
> device IDs for any bus that requires its devices to carry out
> input/output id translations.
> 
> The Freescale FSL bus is an example whereby the input/output ID
> translation kernel code put in place for PCI can be reused for devices
> attached to the bus that are not PCI devices.
> 
> This series updates the kernel code to make the MSI/IOMMU input/output
> ID translation PCI agnostic and apply the resulting changes to the
> device ID space provided by the Freescale FSL bus.
> 
> [1] 
> http://infocenter.arm.com/help/topic/com.arm.doc.den0049d/DEN0049D_IO_Remapping_Table.pdf
> 
> Cc: Rob Herring 
> Cc: "Rafael J. Wysocki" 
> Cc: "Joerg Roedel 
> Cc: Hanjun Guo 
> Cc: Bjorn Helgaas 
> Cc: Sudeep Holla 
> Cc: Robin Murphy 
> Cc: Catalin Marinas 
> Cc: Will Deacon 
> Cc: Marc Zyngier 
> 
> Diana Craciun (2):
>   of/irq: make of_msi_map_get_device_domain() bus agnostic
>   bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver
> 
> Laurentiu Tudor (1):
>   dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus
> 
> Lorenzo Pieralisi (8):
>   ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for
> NC
>   ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
>   ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
>   ACPI/IORT: Remove useless PCI bus walk
>   ACPI/IORT: Add an input ID to acpi_dma_configure()
>   of/iommu: Make of_map_rid() PCI agnostic
>   of/device: Add input id to of_dma_configure()
>   of/irq: Make of_msi_map_rid() PCI bus agnostic
> 
> Makarand Pawagi (1):
>   bus: fsl-mc: Add ACPI support for fsl-mc
> 
>  .../devicetree/bindings/misc/fsl,qoriq-mc.txt |  50 +++-
>  drivers/acpi/arm64/iort.c | 108 --
>  drivers/acpi/scan.c   |   8 +-
>  drivers/bus/fsl-mc/dprc-driver.c  |  31 ++---
>  drivers/bus/fsl-mc/fsl-mc-bus.c   |  79 +
>  drivers/bus/fsl-mc/fsl-mc-msi.c   |  36 --
>  drivers/bus/fsl-mc/fsl-mc-private.h   |   6 +-
>  drivers/iommu/of_iommu.c  |  81 +++--
>  drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c   | 105 ++---
>  drivers/of/base.c |  42 +++
>  drivers/of/device.c   |   8 +-
>  drivers/of/irq.c  |  34 +++---
>  drivers/pci/msi.c |   9 +-
>  include/acpi/acpi_bus.h   |   9 +-
>  include/linux/acpi.h  |   7 ++
>  include/linux/acpi_iort.h |  20 ++--
>  include/linux/of.h|   4 +-
>  include/linux/of_device.h |  16 ++-
>  include/linux/of_iommu.h  |   6 +-
>  include/linux/of_irq.h|  13 ++-
>  20 files changed, 451 insertions(+), 221 deletions(-)

Hi guys,

I think this series is ready for upstream (there are two ACKs missing
from Rafael on patch (5) and Bjorn on patch (3) - I asked for them), it
touches lots of subsystems so I am not really sure what's the best way
to pull it, more so given that it is also late in the cycle (I do think
it is best to merge it via a single tree, it does not make sense to
split it up in my opinion).

Please let me know.

Thanks,
Lorenzo
___
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-15 Thread Lorenzo Pieralisi
On Thu, Jul 09, 2020 at 10:52:52AM +, Makarand Pawagi wrote:

[...]

> >  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_PORTAL,
> > >> _io); @@ -903,11 +930,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) {
> > >> @@ -934,6 +963,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;
> > > Makarand, this looks a bit weird. Is there really a reason for it?
> >  Can you clarify please so that we can reach a conclusion on this 
> >  matter ?
> > 
> > >>> Laurentiu, can you clarify what exactly is the doubt here? Are you
> > >>> asking about
> > >> fwnode assignment from pdev to mc_bus_dev?
> > >> Yes. I remember that a while ago I tested without this fwnode
> > >> assignment and didn't encounter any issues. Maybe we can just drop it?
> > > Did you tested with PHY changes? Because this is needed for MAC driver,
> > where it needs the mc bus node.
> > 
> > Maybe it worth a comment or maybe have it in a different patch?
> > 
> Since this change 

Re: [PATCH v2 03/12] ACPI/IORT: Make iort_msi_map_rid() PCI agnostic

2020-07-15 Thread Lorenzo Pieralisi
On Fri, Jun 19, 2020 at 09:20:04AM +0100, Lorenzo Pieralisi wrote:
> There is nothing PCI specific in iort_msi_map_rid().
> 
> Rename the function using a bus protocol agnostic name,
> iort_msi_map_id(), and convert current callers to it.
> 
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Will Deacon 
> Cc: Hanjun Guo 
> Cc: Bjorn Helgaas 
> Cc: Sudeep Holla 
> Cc: Catalin Marinas 
> Cc: Robin Murphy 
> Cc: "Rafael J. Wysocki" 
> ---
>  drivers/acpi/arm64/iort.c | 12 ++--
>  drivers/pci/msi.c |  2 +-

Hi Bjorn,

please let me know if you are OK with this change, thanks.

Lorenzo

>  include/linux/acpi_iort.h |  6 +++---
>  3 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 902e2aaca946..53f9ef515089 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -568,22 +568,22 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
> device *dev)
>  }
>  
>  /**
> - * iort_msi_map_rid() - Map a MSI requester ID for a device
> + * iort_msi_map_id() - Map a MSI input ID for a device
>   * @dev: The device for which the mapping is to be done.
> - * @req_id: The device requester ID.
> + * @input_id: The device input ID.
>   *
> - * Returns: mapped MSI RID on success, input requester ID otherwise
> + * Returns: mapped MSI ID on success, input ID otherwise
>   */
> -u32 iort_msi_map_rid(struct device *dev, u32 req_id)
> +u32 iort_msi_map_id(struct device *dev, u32 input_id)
>  {
>   struct acpi_iort_node *node;
>   u32 dev_id;
>  
>   node = iort_find_dev_node(dev);
>   if (!node)
> - return req_id;
> + return input_id;
>  
> - iort_node_map_id(node, req_id, _id, IORT_MSI_TYPE);
> + iort_node_map_id(node, input_id, _id, IORT_MSI_TYPE);
>   return dev_id;
>  }
>  
> diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
> index 74a91f52ecc0..77f48b95e277 100644
> --- a/drivers/pci/msi.c
> +++ b/drivers/pci/msi.c
> @@ -1536,7 +1536,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain 
> *domain, struct pci_dev *pdev)
>  
>   of_node = irq_domain_get_of_node(domain);
>   rid = of_node ? of_msi_map_rid(>dev, of_node, rid) :
> - iort_msi_map_rid(>dev, rid);
> + iort_msi_map_id(>dev, rid);
>  
>   return rid;
>  }
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 08ec6bd2297f..e51425e083da 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -28,7 +28,7 @@ void iort_deregister_domain_token(int trans_id);
>  struct fwnode_handle *iort_find_domain_token(int trans_id);
>  #ifdef CONFIG_ACPI_IORT
>  void acpi_iort_init(void);
> -u32 iort_msi_map_rid(struct device *dev, u32 req_id);
> +u32 iort_msi_map_id(struct device *dev, u32 id);
>  struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
> enum irq_domain_bus_token bus_token);
>  void acpi_configure_pmsi_domain(struct device *dev);
> @@ -39,8 +39,8 @@ const struct iommu_ops *iort_iommu_configure(struct device 
> *dev);
>  int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
> *head);
>  #else
>  static inline void acpi_iort_init(void) { }
> -static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
> -{ return req_id; }
> +static inline u32 iort_msi_map_id(struct device *dev, u32 id)
> +{ return id; }
>  static inline struct irq_domain *iort_get_device_domain(
>   struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
>  { return NULL; }
> -- 
> 2.26.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 05/12] ACPI/IORT: Add an input ID to acpi_dma_configure()

2020-07-15 Thread Lorenzo Pieralisi
On Thu, Jul 09, 2020 at 10:35:14AM +0100, Lorenzo Pieralisi wrote:
> On Fri, Jun 19, 2020 at 09:20:06AM +0100, Lorenzo Pieralisi wrote:
> > Some HW devices are created as child devices of proprietary busses,
> > that have a bus specific policy defining how the child devices
> > wires representing the devices ID are translated into IOMMU and
> > IRQ controllers device IDs.
> > 
> > Current IORT code provides translations for:
> > 
> > - PCI devices, where the device ID is well identified at bus level
> >   as the requester ID (RID)
> > - Platform devices that are endpoint devices where the device ID is
> >   retrieved from the ACPI object IORT mappings (Named components single
> >   mappings). A platform device is represented in IORT as a named
> >   component node
> > 
> > For devices that are child devices of proprietary busses the IORT
> > firmware represents the bus node as a named component node in IORT
> > and it is up to that named component node to define in/out bus
> > specific ID translations for the bus child devices that are
> > allocated and created in a bus specific manner.
> > 
> > In order to make IORT ID translations available for proprietary
> > bus child devices, the current ACPI (and IORT) code must be
> > augmented to provide an additional ID parameter to acpi_dma_configure()
> > representing the child devices input ID. This ID is bus specific
> > and it is retrieved in bus specific code.
> > 
> > By adding an ID parameter to acpi_dma_configure(), the IORT
> > code can map the child device ID to an IOMMU stream ID through
> > the IORT named component representing the bus in/out ID mappings.
> > 
> > Signed-off-by: Lorenzo Pieralisi 
> > Cc: Will Deacon 
> > Cc: Hanjun Guo 
> > Cc: Sudeep Holla 
> > Cc: Catalin Marinas 
> > Cc: Robin Murphy 
> > Cc: "Rafael J. Wysocki" 
> > ---
> >  drivers/acpi/arm64/iort.c | 59 +--
> >  drivers/acpi/scan.c   |  8 --
> >  include/acpi/acpi_bus.h   |  9 --
> >  include/linux/acpi.h  |  7 +
> >  include/linux/acpi_iort.h |  7 +++--
> >  5 files changed, 67 insertions(+), 23 deletions(-)
> 
> Hi Rafael,
> 
> just to ask if the ACPI core changes in this patch are OK with you,
> thank you very much.

Hi Rafael,

are you OK with ACPI core changes in this patch ?

Please let me know, thanks.

Lorenzo

> Lorenzo
> 
> > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> > index 421c6976ab81..ec782e4a0fe4 100644
> > --- a/drivers/acpi/arm64/iort.c
> > +++ b/drivers/acpi/arm64/iort.c
> > @@ -978,19 +978,54 @@ static void iort_named_component_init(struct device 
> > *dev,
> >nc->node_flags);
> >  }
> >  
> > +static int iort_nc_iommu_map(struct device *dev, struct acpi_iort_node 
> > *node)
> > +{
> > +   struct acpi_iort_node *parent;
> > +   int err = -ENODEV, i = 0;
> > +   u32 streamid = 0;
> > +
> > +   do {
> > +
> > +   parent = iort_node_map_platform_id(node, ,
> > +  IORT_IOMMU_TYPE,
> > +  i++);
> > +
> > +   if (parent)
> > +   err = iort_iommu_xlate(dev, parent, streamid);
> > +   } while (parent && !err);
> > +
> > +   return err;
> > +}
> > +
> > +static int iort_nc_iommu_map_id(struct device *dev,
> > +   struct acpi_iort_node *node,
> > +   const u32 *in_id)
> > +{
> > +   struct acpi_iort_node *parent;
> > +   u32 streamid;
> > +
> > +   parent = iort_node_map_id(node, *in_id, , IORT_IOMMU_TYPE);
> > +   if (parent)
> > +   return iort_iommu_xlate(dev, parent, streamid);
> > +
> > +   return -ENODEV;
> > +}
> > +
> > +
> >  /**
> > - * iort_iommu_configure - Set-up IOMMU configuration for a device.
> > + * iort_iommu_configure_id - Set-up IOMMU configuration for a device.
> >   *
> >   * @dev: device to configure
> > + * @id_in: optional input id const value pointer
> >   *
> >   * Returns: iommu_ops pointer on configuration success
> >   *  NULL on configuration failure
> >   */
> > -const struct iommu_ops *iort_iommu_configure(struct device *dev)
> > +const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
> > +   const u32 *id_in)
> >  {
> > -

Re: [PATCH v2 05/12] ACPI/IORT: Add an input ID to acpi_dma_configure()

2020-07-09 Thread Lorenzo Pieralisi
On Fri, Jun 19, 2020 at 09:20:06AM +0100, Lorenzo Pieralisi wrote:
> Some HW devices are created as child devices of proprietary busses,
> that have a bus specific policy defining how the child devices
> wires representing the devices ID are translated into IOMMU and
> IRQ controllers device IDs.
> 
> Current IORT code provides translations for:
> 
> - PCI devices, where the device ID is well identified at bus level
>   as the requester ID (RID)
> - Platform devices that are endpoint devices where the device ID is
>   retrieved from the ACPI object IORT mappings (Named components single
>   mappings). A platform device is represented in IORT as a named
>   component node
> 
> For devices that are child devices of proprietary busses the IORT
> firmware represents the bus node as a named component node in IORT
> and it is up to that named component node to define in/out bus
> specific ID translations for the bus child devices that are
> allocated and created in a bus specific manner.
> 
> In order to make IORT ID translations available for proprietary
> bus child devices, the current ACPI (and IORT) code must be
> augmented to provide an additional ID parameter to acpi_dma_configure()
> representing the child devices input ID. This ID is bus specific
> and it is retrieved in bus specific code.
> 
> By adding an ID parameter to acpi_dma_configure(), the IORT
> code can map the child device ID to an IOMMU stream ID through
> the IORT named component representing the bus in/out ID mappings.
> 
> Signed-off-by: Lorenzo Pieralisi 
> Cc: Will Deacon 
> Cc: Hanjun Guo 
> Cc: Sudeep Holla 
> Cc: Catalin Marinas 
> Cc: Robin Murphy 
> Cc: "Rafael J. Wysocki" 
> ---
>  drivers/acpi/arm64/iort.c | 59 +--
>  drivers/acpi/scan.c   |  8 --
>  include/acpi/acpi_bus.h   |  9 --
>  include/linux/acpi.h  |  7 +
>  include/linux/acpi_iort.h |  7 +++--
>  5 files changed, 67 insertions(+), 23 deletions(-)

Hi Rafael,

just to ask if the ACPI core changes in this patch are OK with you,
thank you very much.

Lorenzo

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 421c6976ab81..ec782e4a0fe4 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -978,19 +978,54 @@ static void iort_named_component_init(struct device 
> *dev,
>  nc->node_flags);
>  }
>  
> +static int iort_nc_iommu_map(struct device *dev, struct acpi_iort_node *node)
> +{
> + struct acpi_iort_node *parent;
> + int err = -ENODEV, i = 0;
> + u32 streamid = 0;
> +
> + do {
> +
> + parent = iort_node_map_platform_id(node, ,
> +IORT_IOMMU_TYPE,
> +i++);
> +
> + if (parent)
> + err = iort_iommu_xlate(dev, parent, streamid);
> + } while (parent && !err);
> +
> + return err;
> +}
> +
> +static int iort_nc_iommu_map_id(struct device *dev,
> + struct acpi_iort_node *node,
> + const u32 *in_id)
> +{
> + struct acpi_iort_node *parent;
> + u32 streamid;
> +
> + parent = iort_node_map_id(node, *in_id, , IORT_IOMMU_TYPE);
> + if (parent)
> + return iort_iommu_xlate(dev, parent, streamid);
> +
> + return -ENODEV;
> +}
> +
> +
>  /**
> - * iort_iommu_configure - Set-up IOMMU configuration for a device.
> + * iort_iommu_configure_id - Set-up IOMMU configuration for a device.
>   *
>   * @dev: device to configure
> + * @id_in: optional input id const value pointer
>   *
>   * Returns: iommu_ops pointer on configuration success
>   *  NULL on configuration failure
>   */
> -const struct iommu_ops *iort_iommu_configure(struct device *dev)
> +const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
> + const u32 *id_in)
>  {
> - struct acpi_iort_node *node, *parent;
> + struct acpi_iort_node *node;
>   const struct iommu_ops *ops;
> - u32 streamid = 0;
>   int err = -ENODEV;
>  
>   /*
> @@ -1019,21 +1054,13 @@ const struct iommu_ops *iort_iommu_configure(struct 
> device *dev)
>   if (fwspec && iort_pci_rc_supports_ats(node))
>   fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
>   } else {
> - int i = 0;
> -
>   node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
> iort_match_node_callback, dev);
>   if (!node)

Re: [PATCH v2 01/12] ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for NC

2020-07-09 Thread Lorenzo Pieralisi
On Thu, Jul 02, 2020 at 04:22:00PM +0800, Hanjun Guo wrote:
> Hi Robin,
> 
> On 2020/7/2 0:12, Robin Murphy wrote:
> > On 2020-06-30 14:04, Hanjun Guo wrote:
> > > On 2020/6/30 18:24, Lorenzo Pieralisi wrote:
> > > > On Tue, Jun 30, 2020 at 11:06:41AM +0800, Hanjun Guo wrote:
> > > > 
> > > > [...]
> > > > 
> > > > > > For devices that aren't described in the DSDT - IORT translations
> > > > > > are determined by their ACPI parent device. Do you see/Have you
> > > > > > found any issue with this approach ?
> > > > > 
> > > > > The spec says "Describes the IO relationships between devices
> > > > > represented in the ACPI namespace.", and in section 3.1.1.3 Named
> > > > > component node, it says:
> > > > 
> > > > PCI devices aren't necessarily described in the ACPI namespace and we
> > > > still use IORT to describe them - through the RC node.
> > > > 
> > > > > "Named component nodes are used to describe devices that are also
> > > > > included in the Differentiated System Description Table (DSDT). See
> > > > > [ACPI]."
> > > > > 
> > > > > So from my understanding, the IORT spec for now, can only do ID
> > > > > translations for devices in the DSDT.
> > > > 
> > > > I think you can read this multiple ways but this patch does not
> > > > change this concept. What changes, is applying parent's node IORT
> > > > mapping to child nodes with no associated DSDT nodes, it is the
> > > > same thing we do with PCI and the _DMA method - we could update
> > > > the wording in the specs if that clarifies but I don't think this
> > > > deliberately disregards the specifications.
> > > 
> > > I agree, but it's better to update the wording of the spec.
> > > 
> > > > 
> > > > > > > For a platform device, if I use its parent's full path name for
> > > > > > > its named component entry, then it will match, but this will 
> > > > > > > violate
> > > > > > > the IORT spec.
> > > > > > 
> > > > > > Can you elaborate on this please I don't get the point you
> > > > > > are making.
> > > > > 
> > > > > For example, device A is not described in DSDT so can't represent
> > > > > as a NC node in IORT. Device B can be described in DSDT and it
> > > > > is the parent of device A, so device B can be represented in IORT
> > > > > with memory access properties and node flags with Substream width
> > > > > and Stall supported info.
> > > > > 
> > > > > When we trying to translate device A's ID, we reuse all the memory
> > > > > access properties and node flags from its parent (device B), but
> > > > > will it the same?
> > > > 
> > > > I assume so why wouldn't it be ? Why would be describe them in
> > > > a parent-child relationship if that's not how the system looks like
> > > > in HW ?
> > > 
> > > The point I'm making is that I'm not sure all the memory access and
> > > stall properties are the same for the parent and the device itself.
> > 
> > Is that even a valid case though? The principal thing we want to
> > accommodate here is when device B *is* the one accessing memory, either
> > because it is a bridge with device A sat behind it, or because device A
> > is actually just some logical function or subset of physical device B.
> 
> Thanks for the clarify, for CCA attributes, child device should be the
> same as its parent and that was written in the ACPI spec, so it's better
> to make it clear for other properties in the spec as well.
> 
> > 
> > If the topology is such that device A is a completely independent device
> > with its own path to memory such that it could have different
> > properties, I would expect that it *should* be described in DSDT, and I
> > can't easily think of a good reason why it wouldn't be. I'm also
> > struggling to imagine how it might even have an ID that had to be
> > interpreted in the context of device B if it wasn't one of the cases
> > above :/
> > 
> > I don't doubt that people could - or maybe even have - come up with crap
> > DSDT bindings that don't represent the hardware sufficiently accurately,
> > but I'm not sure that should be IORT's problem...
> 
> As I said in previous email, I'm not against this patch, and seems
> have no regressions for platforms that using named component node
> such as D05/D06 (I will test it shortly to make sure), but it's better
> to update the wording of the spec (even after this patch set is merged).

Have you managed to test this series ?

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


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

2020-07-09 Thread Lorenzo Pieralisi
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_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 %

Re: [PATCH v2 01/12] ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for NC

2020-06-30 Thread Lorenzo Pieralisi
On Tue, Jun 30, 2020 at 11:06:41AM +0800, Hanjun Guo wrote:

[...]

> > For devices that aren't described in the DSDT - IORT translations
> > are determined by their ACPI parent device. Do you see/Have you
> > found any issue with this approach ?
> 
> The spec says "Describes the IO relationships between devices
> represented in the ACPI namespace.", and in section 3.1.1.3 Named
> component node, it says:

PCI devices aren't necessarily described in the ACPI namespace and we
still use IORT to describe them - through the RC node.

> "Named component nodes are used to describe devices that are also
> included in the Differentiated System Description Table (DSDT). See
> [ACPI]."
> 
> So from my understanding, the IORT spec for now, can only do ID
> translations for devices in the DSDT.

I think you can read this multiple ways but this patch does not
change this concept. What changes, is applying parent's node IORT
mapping to child nodes with no associated DSDT nodes, it is the
same thing we do with PCI and the _DMA method - we could update
the wording in the specs if that clarifies but I don't think this
deliberately disregards the specifications.

> > > For a platform device, if I use its parent's full path name for
> > > its named component entry, then it will match, but this will violate
> > > the IORT spec.
> > 
> > Can you elaborate on this please I don't get the point you
> > are making.
> 
> For example, device A is not described in DSDT so can't represent
> as a NC node in IORT. Device B can be described in DSDT and it
> is the parent of device A, so device B can be represented in IORT
> with memory access properties and node flags with Substream width
> and Stall supported info.
> 
> When we trying to translate device A's ID, we reuse all the memory
> access properties and node flags from its parent (device B), but
> will it the same?

I assume so why wouldn't it be ? Why would be describe them in
a parent-child relationship if that's not how the system looks like
in HW ?

Do you have a specific example in mind that we should be aware of ?

> So the IORT spec don't support this, at least it's pretty vague
> I think.

I think that's a matter of wording, it can be updated if it needs be,
reach out if you see any issue with the current approach please.

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


Re: [PATCH v2 01/12] ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for NC

2020-06-29 Thread Lorenzo Pieralisi
On Mon, Jun 29, 2020 at 12:24:43PM +0800, Hanjun Guo wrote:
> Hi Lorenzo,
> 
> On 2020/6/19 16:20, Lorenzo Pieralisi wrote:
> > When the iort_match_node_callback is invoked for a named component
> > the match should be executed upon a device with an ACPI companion.
> > 
> > For devices with no ACPI companion set-up the ACPI device tree must be
> > walked in order to find the first parent node with a companion set and
> > check the parent node against the named component entry to check whether
> > there is a match and therefore an IORT node describing the in/out ID
> > translation for the device has been found.
> > 
> > Signed-off-by: Lorenzo Pieralisi 
> > Cc: Will Deacon 
> > Cc: Hanjun Guo 
> > Cc: Sudeep Holla 
> > Cc: Catalin Marinas 
> > Cc: Robin Murphy 
> > Cc: "Rafael J. Wysocki" 
> > ---
> >   drivers/acpi/arm64/iort.c | 20 ++--
> >   1 file changed, 18 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> > index 28a6b387e80e..5eee81758184 100644
> > --- a/drivers/acpi/arm64/iort.c
> > +++ b/drivers/acpi/arm64/iort.c
> > @@ -264,15 +264,31 @@ static acpi_status iort_match_node_callback(struct 
> > acpi_iort_node *node,
> > if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
> > struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
> > -   struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
> > +   struct acpi_device *adev;
> > struct acpi_iort_named_component *ncomp;
> > +   struct device *nc_dev = dev;
> > +
> > +   /*
> > +* Walk the device tree to find a device with an
> > +* ACPI companion; there is no point in scanning
> > +* IORT for a device matching a named component if
> > +* the device does not have an ACPI companion to
> > +* start with.
> > +*/
> > +   do {
> > +   adev = ACPI_COMPANION(nc_dev);
> > +   if (adev)
> > +   break;
> > +
> > +   nc_dev = nc_dev->parent;
> > +   } while (nc_dev);
> 
> I'm lost here, we need the ACPI_COMPANION (the same as
> to_acpi_device_node()) of the device, but why do we need to go
> up to find the parent node?

For devices that aren't described in the DSDT - IORT translations
are determined by their ACPI parent device. Do you see/Have you
found any issue with this approach ?

> For a platform device, if I use its parent's full path name for
> its named component entry, then it will match, but this will violate
> the IORT spec.

Can you elaborate on this please I don't get the point you
are making.

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


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

2020-06-19 Thread Lorenzo Pieralisi
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_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_PORTAL, _io);
@@ -903,11 +930,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,
+   

[PATCH v2 10/12] of/irq: Make of_msi_map_rid() PCI bus agnostic

2020-06-19 Thread Lorenzo Pieralisi
There is nothing PCI bus specific in the of_msi_map_rid()
implementation other than the requester ID tag for the input
ID space. Rename requester ID to a more generic ID so that
the translation code can be used by all busses that require
input/output ID translations.

No functional change intended.

Signed-off-by: Lorenzo Pieralisi 
Cc: Bjorn Helgaas 
Cc: Rob Herring 
Cc: Marc Zyngier 
---
 drivers/of/irq.c   | 28 ++--
 drivers/pci/msi.c  |  2 +-
 include/linux/of_irq.h |  8 
 3 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 1005e4f349ef..25d17b8a1a1a 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -576,43 +576,43 @@ void __init of_irq_init(const struct of_device_id 
*matches)
}
 }
 
-static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
-   u32 rid_in)
+static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
+   u32 id_in)
 {
struct device *parent_dev;
-   u32 rid_out = rid_in;
+   u32 id_out = id_in;
 
/*
 * Walk up the device parent links looking for one with a
 * "msi-map" property.
 */
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
-   if (!of_map_id(parent_dev->of_node, rid_in, "msi-map",
-   "msi-map-mask", np, _out))
+   if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
+   "msi-map-mask", np, _out))
break;
-   return rid_out;
+   return id_out;
 }
 
 /**
- * of_msi_map_rid - Map a MSI requester ID for a device.
+ * of_msi_map_id - Map a MSI ID for a device.
  * @dev: device for which the mapping is to be done.
  * @msi_np: device node of the expected msi controller.
- * @rid_in: unmapped MSI requester ID for the device.
+ * @id_in: unmapped MSI ID for the device.
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
- * property.  If found, apply the mapping to @rid_in.
+ * property.  If found, apply the mapping to @id_in.
  *
- * Returns the mapped MSI requester ID.
+ * Returns the mapped MSI ID.
  */
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in)
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
 {
-   return __of_msi_map_rid(dev, _np, rid_in);
+   return __of_msi_map_id(dev, _np, id_in);
 }
 
 /**
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
- * @rid: Requester ID for the device.
+ * @id: Device ID.
  * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
@@ -625,7 +625,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct 
device *dev, u32 id,
 {
struct device_node *np = NULL;
 
-   __of_msi_map_rid(dev, , id);
+   __of_msi_map_id(dev, , id);
return irq_find_matching_host(np, bus_token);
 }
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index b4bfe0b03b2d..19aeadb22f11 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1535,7 +1535,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, 
struct pci_dev *pdev)
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
 
of_node = irq_domain_get_of_node(domain);
-   rid = of_node ? of_msi_map_rid(>dev, of_node, rid) :
+   rid = of_node ? of_msi_map_id(>dev, of_node, rid) :
iort_msi_map_id(>dev, rid);
 
return rid;
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 7142a3722758..e8b78139f78c 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -55,7 +55,7 @@ extern struct irq_domain *of_msi_map_get_device_domain(struct 
device *dev,
u32 id,
u32 bus_token);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in);
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
@@ -93,10 +93,10 @@ static inline struct irq_domain 
*of_msi_map_get_device_domain(struct device *dev
 static inline void of_msi_configure(struct device *dev, struct device_node *np)
 {
 }
-static inline u32 of_msi_map_rid(struct device *dev,
-struct device_node *msi_np, u32 rid_in)
+static inline u32 of_msi_map_id(struct device *dev,
+struct device_node *msi_np, u32 id_in)
 {
-   return rid_in;
+   return id_in;
 }
 #endif
 
-- 
2.26.1

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


[PATCH v2 09/12] of/irq: make of_msi_map_get_device_domain() bus agnostic

2020-06-19 Thread Lorenzo Pieralisi
From: Diana Craciun 

of_msi_map_get_device_domain() is PCI specific but it need not be and
can be easily changed to be bus agnostic in order to be used by other
busses by adding an IRQ domain bus token as an input parameter.

Signed-off-by: Diana Craciun 
Signed-off-by: Lorenzo Pieralisi 
Acked-by: Bjorn Helgaas# pci/msi.c
Cc: Bjorn Helgaas 
Cc: Rob Herring 
Cc: Marc Zyngier 
---
 drivers/of/irq.c   | 8 +---
 drivers/pci/msi.c  | 2 +-
 include/linux/of_irq.h | 5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index d632bc5b3a2d..1005e4f349ef 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -613,18 +613,20 @@ u32 of_msi_map_rid(struct device *dev, struct device_node 
*msi_np, u32 rid_in)
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
  * @rid: Requester ID for the device.
+ * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
  * property.
  *
  * Returns: the MSI domain for this device (or NULL on failure)
  */
-struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
+struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
+   u32 bus_token)
 {
struct device_node *np = NULL;
 
-   __of_msi_map_rid(dev, , rid);
-   return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+   __of_msi_map_rid(dev, , id);
+   return irq_find_matching_host(np, bus_token);
 }
 
 /**
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 77f48b95e277..b4bfe0b03b2d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1556,7 +1556,7 @@ struct irq_domain *pci_msi_get_device_domain(struct 
pci_dev *pdev)
u32 rid = pci_dev_id(pdev);
 
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
-   dom = of_msi_map_get_device_domain(>dev, rid);
+   dom = of_msi_map_get_device_domain(>dev, rid, DOMAIN_BUS_PCI_MSI);
if (!dom)
dom = iort_get_device_domain(>dev, rid,
 DOMAIN_BUS_PCI_MSI);
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 1214cabb2247..7142a3722758 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -52,7 +52,8 @@ extern struct irq_domain *of_msi_get_domain(struct device 
*dev,
struct device_node *np,
enum irq_domain_bus_token token);
 extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
-  u32 rid);
+   u32 id,
+   u32 bus_token);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
 u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 #else
@@ -85,7 +86,7 @@ static inline struct irq_domain *of_msi_get_domain(struct 
device *dev,
return NULL;
 }
 static inline struct irq_domain *of_msi_map_get_device_domain(struct device 
*dev,
- u32 rid)
+   u32 id, u32 bus_token)
 {
return NULL;
 }
-- 
2.26.1

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


[PATCH v2 11/12] bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver

2020-06-19 Thread Lorenzo Pieralisi
From: Diana Craciun 

The DPRC driver is not taking into account the msi-map property
and assumes that the icid is the same as the stream ID. Although
this assumption is correct, generalize the code to include a
translation between icid and streamID.

Furthermore do not just copy the MSI domain from parent (for child
containers), but use the information provided by the msi-map property.

If the msi-map property is missing from the device tree retain the old
behaviour for backward compatibility ie the child DPRC objects
inherit the MSI domain from the parent.

Signed-off-by: Diana Craciun 
---
 drivers/bus/fsl-mc/dprc-driver.c| 31 ++---
 drivers/bus/fsl-mc/fsl-mc-bus.c |  4 +--
 drivers/bus/fsl-mc/fsl-mc-msi.c | 31 +
 drivers/bus/fsl-mc/fsl-mc-private.h |  6 ++--
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 15 +-
 5 files changed, 47 insertions(+), 40 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index c8b1c3842c1a..189bff2115a8 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -592,6 +592,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
bool mc_io_created = false;
bool msi_domain_set = false;
u16 major_ver, minor_ver;
+   struct irq_domain *mc_msi_domain;
 
if (!is_fsl_mc_bus_dprc(mc_dev))
return -EINVAL;
@@ -621,31 +622,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
return error;
 
mc_io_created = true;
+   }
 
-   /*
-* Inherit parent MSI domain:
-*/
-   dev_set_msi_domain(_dev->dev,
-  dev_get_msi_domain(parent_dev));
-   msi_domain_set = true;
+   mc_msi_domain = fsl_mc_find_msi_domain(_dev->dev);
+   if (!mc_msi_domain) {
+   dev_warn(_dev->dev,
+"WARNING: MC bus without interrupt support\n");
} else {
-   /*
-* This is a root DPRC
-*/
-   struct irq_domain *mc_msi_domain;
-
-   if (dev_is_fsl_mc(parent_dev))
-   return -EINVAL;
-
-   error = fsl_mc_find_msi_domain(parent_dev,
-  _msi_domain);
-   if (error < 0) {
-   dev_warn(_dev->dev,
-"WARNING: MC bus without interrupt support\n");
-   } else {
-   dev_set_msi_domain(_dev->dev, mc_msi_domain);
-   msi_domain_set = true;
-   }
+   dev_set_msi_domain(_dev->dev, mc_msi_domain);
+   msi_domain_set = true;
}
 
error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 8ead3f0238f2..824ff77bbe86 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -370,8 +370,8 @@ EXPORT_SYMBOL_GPL(fsl_mc_get_version);
 /**
  * fsl_mc_get_root_dprc - function to traverse to the root dprc
  */
-static void fsl_mc_get_root_dprc(struct device *dev,
-struct device **root_dprc_dev)
+void fsl_mc_get_root_dprc(struct device *dev,
+struct device **root_dprc_dev)
 {
if (!dev) {
*root_dprc_dev = NULL;
diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 8b9c66d7c4ff..e7bbff445a83 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -177,23 +177,30 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct 
fwnode_handle *fwnode,
return domain;
 }
 
-int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
-  struct irq_domain **mc_msi_domain)
+struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
 {
-   struct irq_domain *msi_domain;
-   struct device_node *mc_of_node = mc_platform_dev->of_node;
+   struct irq_domain *msi_domain = NULL;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
 
-   msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
-  DOMAIN_BUS_FSL_MC_MSI);
-   if (!msi_domain) {
-   pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
-  mc_of_node);
+   msi_domain = of_msi_map_get_device_domain(dev, mc_dev->icid,
+ DOMAIN_BUS_FSL_MC_MSI);
 
-   return -ENOENT;
+   /*
+* if the msi-map property is missing assume that all the
+* child containers inherit the domain from the parent
+*/
+   if (!msi_domain) {
+   struct device *root_dprc_dev;
+   struct device *bus_dev;
+
+   

[PATCH v2 05/12] ACPI/IORT: Add an input ID to acpi_dma_configure()

2020-06-19 Thread Lorenzo Pieralisi
Some HW devices are created as child devices of proprietary busses,
that have a bus specific policy defining how the child devices
wires representing the devices ID are translated into IOMMU and
IRQ controllers device IDs.

Current IORT code provides translations for:

- PCI devices, where the device ID is well identified at bus level
  as the requester ID (RID)
- Platform devices that are endpoint devices where the device ID is
  retrieved from the ACPI object IORT mappings (Named components single
  mappings). A platform device is represented in IORT as a named
  component node

For devices that are child devices of proprietary busses the IORT
firmware represents the bus node as a named component node in IORT
and it is up to that named component node to define in/out bus
specific ID translations for the bus child devices that are
allocated and created in a bus specific manner.

In order to make IORT ID translations available for proprietary
bus child devices, the current ACPI (and IORT) code must be
augmented to provide an additional ID parameter to acpi_dma_configure()
representing the child devices input ID. This ID is bus specific
and it is retrieved in bus specific code.

By adding an ID parameter to acpi_dma_configure(), the IORT
code can map the child device ID to an IOMMU stream ID through
the IORT named component representing the bus in/out ID mappings.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 59 +--
 drivers/acpi/scan.c   |  8 --
 include/acpi/acpi_bus.h   |  9 --
 include/linux/acpi.h  |  7 +
 include/linux/acpi_iort.h |  7 +++--
 5 files changed, 67 insertions(+), 23 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 421c6976ab81..ec782e4a0fe4 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -978,19 +978,54 @@ static void iort_named_component_init(struct device *dev,
   nc->node_flags);
 }
 
+static int iort_nc_iommu_map(struct device *dev, struct acpi_iort_node *node)
+{
+   struct acpi_iort_node *parent;
+   int err = -ENODEV, i = 0;
+   u32 streamid = 0;
+
+   do {
+
+   parent = iort_node_map_platform_id(node, ,
+  IORT_IOMMU_TYPE,
+  i++);
+
+   if (parent)
+   err = iort_iommu_xlate(dev, parent, streamid);
+   } while (parent && !err);
+
+   return err;
+}
+
+static int iort_nc_iommu_map_id(struct device *dev,
+   struct acpi_iort_node *node,
+   const u32 *in_id)
+{
+   struct acpi_iort_node *parent;
+   u32 streamid;
+
+   parent = iort_node_map_id(node, *in_id, , IORT_IOMMU_TYPE);
+   if (parent)
+   return iort_iommu_xlate(dev, parent, streamid);
+
+   return -ENODEV;
+}
+
+
 /**
- * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ * iort_iommu_configure_id - Set-up IOMMU configuration for a device.
  *
  * @dev: device to configure
+ * @id_in: optional input id const value pointer
  *
  * Returns: iommu_ops pointer on configuration success
  *  NULL on configuration failure
  */
-const struct iommu_ops *iort_iommu_configure(struct device *dev)
+const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
+   const u32 *id_in)
 {
-   struct acpi_iort_node *node, *parent;
+   struct acpi_iort_node *node;
const struct iommu_ops *ops;
-   u32 streamid = 0;
int err = -ENODEV;
 
/*
@@ -1019,21 +1054,13 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
if (fwspec && iort_pci_rc_supports_ats(node))
fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
} else {
-   int i = 0;
-
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
  iort_match_node_callback, dev);
if (!node)
return NULL;
 
-   do {
-   parent = iort_node_map_platform_id(node, ,
-  IORT_IOMMU_TYPE,
-  i++);
-
-   if (parent)
-   err = iort_iommu_xlate(dev, parent, streamid);
-   } while (parent && !err);
+   err = id_in ? iort_nc_iommu_map_id(dev, node, id_in) :
+ iort_nc_iommu_map(dev, node);
 
if (!err)
iort_named_component_init(dev, node);
@@ -1058,6 +1085,7 @@ const struct iommu_ops *

[PATCH v2 06/12] of/iommu: Make of_map_rid() PCI agnostic

2020-06-19 Thread Lorenzo Pieralisi
There is nothing PCI specific (other than the RID - requester ID)
in the of_map_rid() implementation, so the same function can be
reused for input/output IDs mapping for other busses just as well.

Rename the RID instances/names to a generic "id" tag.

No functionality change intended.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Joerg Roedel 
Cc: Robin Murphy 
Cc: Marc Zyngier 
---
 drivers/iommu/of_iommu.c |  4 ++--
 drivers/of/base.c| 42 
 drivers/of/irq.c |  2 +-
 include/linux/of.h   |  4 ++--
 4 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 20738aacac89..016316244737 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -129,7 +129,7 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 
alias, void *data)
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_rid(info->np, alias, "iommu-map", "iommu-map-mask",
+   err = of_map_id(info->np, alias, "iommu-map", "iommu-map-mask",
 _spec.np, iommu_spec.args);
if (err)
return err == -ENODEV ? NO_IOMMU : err;
@@ -145,7 +145,7 @@ static int of_fsl_mc_iommu_init(struct fsl_mc_device 
*mc_dev,
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
+   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
 "iommu-map-mask", _spec.np,
 iommu_spec.args);
if (err)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ae03b1218b06..ea44fea99813 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2201,15 +2201,15 @@ int of_find_last_cache_level(unsigned int cpu)
 }
 
 /**
- * of_map_rid - Translate a requester ID through a downstream mapping.
+ * of_map_id - Translate an ID through a downstream mapping.
  * @np: root complex device node.
- * @rid: device requester ID to map.
+ * @id: device ID to map.
  * @map_name: property name of the map to use.
  * @map_mask_name: optional property name of the mask to use.
  * @target: optional pointer to a target device node.
  * @id_out: optional pointer to receive the translated ID.
  *
- * Given a device requester ID, look up the appropriate implementation-defined
+ * Given a device ID, look up the appropriate implementation-defined
  * platform ID and/or the target device which receives transactions on that
  * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
  * @id_out may be NULL if only the other is required. If @target points to
@@ -2219,11 +2219,11 @@ int of_find_last_cache_level(unsigned int cpu)
  *
  * Return: 0 on success or a standard error code on failure.
  */
-int of_map_rid(struct device_node *np, u32 rid,
+int of_map_id(struct device_node *np, u32 id,
   const char *map_name, const char *map_mask_name,
   struct device_node **target, u32 *id_out)
 {
-   u32 map_mask, masked_rid;
+   u32 map_mask, masked_id;
int map_len;
const __be32 *map = NULL;
 
@@ -2235,7 +2235,7 @@ int of_map_rid(struct device_node *np, u32 rid,
if (target)
return -ENODEV;
/* Otherwise, no map implies no translation */
-   *id_out = rid;
+   *id_out = id;
return 0;
}
 
@@ -2255,22 +2255,22 @@ int of_map_rid(struct device_node *np, u32 rid,
if (map_mask_name)
of_property_read_u32(np, map_mask_name, _mask);
 
-   masked_rid = map_mask & rid;
+   masked_id = map_mask & id;
for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
struct device_node *phandle_node;
-   u32 rid_base = be32_to_cpup(map + 0);
+   u32 id_base = be32_to_cpup(map + 0);
u32 phandle = be32_to_cpup(map + 1);
u32 out_base = be32_to_cpup(map + 2);
-   u32 rid_len = be32_to_cpup(map + 3);
+   u32 id_len = be32_to_cpup(map + 3);
 
-   if (rid_base & ~map_mask) {
-   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
ignores rid-base (0x%x)\n",
+   if (id_base & ~map_mask) {
+   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
ignores id-base (0x%x)\n",
np, map_name, map_name,
-   map_mask, rid_base);
+   map_mask, id_base);
return -EFAULT;
}
 
-   if (masked_rid < rid_base || masked_rid >= rid_base + rid_len)
+   if (masked_id < id_base || masked_id >= i

[PATCH v2 04/12] ACPI/IORT: Remove useless PCI bus walk

2020-06-19 Thread Lorenzo Pieralisi
The PCI bus domain number (used in the iort_match_node_callback() -
pci_domain_nr() call) is cascaded through the PCI bus hierarchy at PCI
bus enumeration time, therefore there is no need in iort_find_dev_node()
to walk the PCI bus upwards to grab the root bus to be passed to
iort_scan_node(), the device->bus PCI bus pointer will do.

Remove this useless code.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 53f9ef515089..421c6976ab81 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -558,10 +558,7 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
  iort_match_node_callback, dev);
}
 
-   /* Find a PCI root bus */
pbus = to_pci_dev(dev)->bus;
-   while (!pci_is_root_bus(pbus))
-   pbus = pbus->parent;
 
return iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
  iort_match_node_callback, >dev);
-- 
2.26.1

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


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

2020-06-19 Thread Lorenzo Pieralisi
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.
In addition, deprecate msi-parent property which no longer makes sense
now that we support translating the MSIs.

Signed-off-by: Laurentiu Tudor 
Signed-off-by: Diana Craciun 
Cc: Rob Herring 
---
 .../devicetree/bindings/misc/fsl,qoriq-mc.txt | 50 ---
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt 
b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
index 9134e9bcca56..ebd329181c14 100644
--- a/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
+++ b/Documentation/devicetree/bindings/misc/fsl,qoriq-mc.txt
@@ -28,6 +28,16 @@ Documentation/devicetree/bindings/iommu/iommu.txt.
 For arm-smmu binding, see:
 Documentation/devicetree/bindings/iommu/arm,smmu.yaml.
 
+The MSI writes are accompanied by sideband data which is derived from the ICID.
+The msi-map property is used to associate the devices with both the ITS
+controller and the sideband data which accompanies the writes.
+
+For generic MSI bindings, see
+Documentation/devicetree/bindings/interrupt-controller/msi.txt.
+
+For GICv3 and GIC ITS bindings, see:
+Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml.
+
 Required properties:
 
 - compatible
@@ -49,11 +59,6 @@ Required properties:
 region may not be present in some scenarios, such
 as in the device tree presented to a virtual machine.
 
-- msi-parent
-Value type: 
-Definition: Must be present and point to the MSI controller node
-handling message interrupts for the MC.
-
 - ranges
 Value type: 
 Definition: A standard property.  Defines the mapping between the child
@@ -119,6 +124,28 @@ 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 msi-specifier
+  data.
+
+  The property is an arbitrary number of tuples of
+  (icid-base,gic-its,msi-base,length).
+
+  Any ICID in the interval [icid-base, icid-base + length) is
+  associated with the listed GIC ITS, with the msi-specifier
+  (i - icid-base + msi-base).
+
+Deprecated properties:
+
+- msi-parent
+Value type: 
+Definition: Describes the MSI controller node handling message
+interrupts for the MC. When there is no translation
+between the ICID and deviceID this property can be used
+to describe the MSI controller used by the devices on the
+mc-bus.
+The use of this property for mc-bus is deprecated. Please
+use msi-map.
+
 Example:
 
 smmu: iommu@500 {
@@ -128,13 +155,24 @@ 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 */
   <0x 0x0834 0 0x4>; /* MC control reg */
-msi-parent = <>;
 /* define map for ICIDs 23-64 */
 iommu-map = <23  23 41>;
+/* define msi map for ICIDs 23-64 */
+msi-map = <23  23 41>;
 #address-cells = <3>;
 #size-cells = <1>;
 
-- 
2.26.1

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


[PATCH v2 07/12] of/device: Add input id to of_dma_configure()

2020-06-19 Thread Lorenzo Pieralisi
Devices sitting on proprietary busses have a device ID space that
is owned by the respective bus and related firmware bindings. In order
to let the generic OF layer handle the input translations to
an IOMMU id, for such busses the current of_dma_configure() interface
should be extended in order to allow the bus layer to provide the
device input id parameter - that is retrieved/assigned in bus
specific code and firmware.

Augment of_dma_configure() to add an optional input_id parameter,
leaving current functionality unchanged.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Robin Murphy 
Cc: Joerg Roedel 
Cc: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c |  4 +-
 drivers/iommu/of_iommu.c| 81 ++---
 drivers/of/device.c |  8 ++--
 include/linux/of_device.h   | 16 ++-
 include/linux/of_iommu.h|  6 ++-
 5 files changed, 70 insertions(+), 45 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 40526da5c6a6..8ead3f0238f2 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -118,11 +118,13 @@ 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 fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   u32 input_id = mc_dev->icid;
 
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
 
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 016316244737..e505b9130a1c 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -118,46 +118,66 @@ static int of_iommu_xlate(struct device *dev,
return ret;
 }
 
-struct of_pci_iommu_alias_info {
-   struct device *dev;
-   struct device_node *np;
-};
-
-static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
+static int of_iommu_configure_dev_id(struct device_node *master_np,
+struct device *dev,
+const u32 *id)
 {
-   struct of_pci_iommu_alias_info *info = data;
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_id(info->np, alias, "iommu-map", "iommu-map-mask",
-_spec.np, iommu_spec.args);
+   err = of_map_id(master_np, *id, "iommu-map",
+"iommu-map-mask", _spec.np,
+iommu_spec.args);
if (err)
return err == -ENODEV ? NO_IOMMU : err;
 
-   err = of_iommu_xlate(info->dev, _spec);
+   err = of_iommu_xlate(dev, _spec);
of_node_put(iommu_spec.np);
return err;
 }
 
-static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev,
-   struct device_node *master_np)
+static int of_iommu_configure_dev(struct device_node *master_np,
+ struct device *dev)
 {
-   struct of_phandle_args iommu_spec = { .args_count = 1 };
-   int err;
-
-   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
-"iommu-map-mask", _spec.np,
-iommu_spec.args);
-   if (err)
-   return err == -ENODEV ? NO_IOMMU : err;
+   struct of_phandle_args iommu_spec;
+   int err = NO_IOMMU, idx = 0;
+
+   while (!of_parse_phandle_with_args(master_np, "iommus",
+  "#iommu-cells",
+  idx, _spec)) {
+   err = of_iommu_xlate(dev, _spec);
+   of_node_put(iommu_spec.np);
+   idx++;
+   if (err)
+   break;
+   }
 
-   err = of_iommu_xlate(_dev->dev, _spec);
-   of_node_put(iommu_spec.np);
return err;
 }
 
+struct of_pci_iommu_alias_info {
+   struct device *dev;
+   struct device_node *np;
+};
+
+static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
+{
+   struct of_pci_iommu_alias_info *info = data;
+   u32 input_id = alias;
+
+   return of_iommu_configure_dev_id(info->np, info->dev, _id);
+}
+
+static int of_iommu_configure_device(struct device_node *master_np,
+struct device *dev, const u32 *id)
+{
+   return (id) ? of_iommu_configure_dev_id(master_np, dev, id) :
+ of_iommu_configure_dev(master_np, dev);
+}
+
 const struct iommu_ops *of_iommu_configure(struct device *dev,
-  struct device_node *master_np)
+   

[PATCH v2 02/12] ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic

2020-06-19 Thread Lorenzo Pieralisi
iort_get_device_domain() is PCI specific but it need not be,
since it can be used to retrieve IRQ domain nexus of any kind
by adding an irq_domain_bus_token input to it.

Make it PCI agnostic by also renaming the requestor ID input
to a more generic ID name.

Signed-off-by: Lorenzo Pieralisi 
Acked-by: Bjorn Helgaas# pci/msi.c
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Bjorn Helgaas 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 14 +++---
 drivers/pci/msi.c |  3 ++-
 include/linux/acpi_iort.h |  7 ---
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 5eee81758184..902e2aaca946 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -550,7 +550,6 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
node = iort_get_iort_node(dev->fwnode);
if (node)
return node;
-
/*
 * if not, then it should be a platform device defined in
 * DSDT/SSDT (with Named Component node in IORT)
@@ -641,13 +640,13 @@ static int __maybe_unused iort_find_its_base(u32 its_id, 
phys_addr_t *base)
 /**
  * iort_dev_find_its_id() - Find the ITS identifier for a device
  * @dev: The device.
- * @req_id: Device's requester ID
+ * @id: Device's ID
  * @idx: Index of the ITS identifier list.
  * @its_id: ITS identifier.
  *
  * Returns: 0 on success, appropriate error value otherwise
  */
-static int iort_dev_find_its_id(struct device *dev, u32 req_id,
+static int iort_dev_find_its_id(struct device *dev, u32 id,
unsigned int idx, int *its_id)
 {
struct acpi_iort_its_group *its;
@@ -657,7 +656,7 @@ static int iort_dev_find_its_id(struct device *dev, u32 
req_id,
if (!node)
return -ENXIO;
 
-   node = iort_node_map_id(node, req_id, NULL, IORT_MSI_TYPE);
+   node = iort_node_map_id(node, id, NULL, IORT_MSI_TYPE);
if (!node)
return -ENXIO;
 
@@ -680,19 +679,20 @@ static int iort_dev_find_its_id(struct device *dev, u32 
req_id,
  *
  * Returns: the MSI domain for this device, NULL otherwise
  */
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+ enum irq_domain_bus_token bus_token)
 {
struct fwnode_handle *handle;
int its_id;
 
-   if (iort_dev_find_its_id(dev, req_id, 0, _id))
+   if (iort_dev_find_its_id(dev, id, 0, _id))
return NULL;
 
handle = iort_find_domain_token(its_id);
if (!handle)
return NULL;
 
-   return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
+   return irq_find_matching_fwnode(handle, bus_token);
 }
 
 static void iort_set_device_domain(struct device *dev,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 6b43a5455c7a..74a91f52ecc0 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1558,7 +1558,8 @@ struct irq_domain *pci_msi_get_device_domain(struct 
pci_dev *pdev)
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
dom = of_msi_map_get_device_domain(>dev, rid);
if (!dom)
-   dom = iort_get_device_domain(>dev, rid);
+   dom = iort_get_device_domain(>dev, rid,
+DOMAIN_BUS_PCI_MSI);
return dom;
 }
 #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 8e7e2ec37f1b..08ec6bd2297f 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -29,7 +29,8 @@ struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+ enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
@@ -40,8 +41,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
struct list_head *head);
 static inline void acpi_iort_init(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
-static inline struct irq_domain *iort_get_device_domain(struct device *dev,
-   u32 req_id)
+static inline struct irq_domain *iort_get_device_domain(
+   struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
 static inline void acpi_configure_pmsi_domain(struct device *dev) { }
 /* IOMMU i

[PATCH v2 00/12] ACPI/OF: Upgrade MSI/IOMMU ID mapping APIs

2020-06-19 Thread Lorenzo Pieralisi
This series is a v2 of a previous posting:

v1 -> v2

- Removed _rid() wrappers
- Fixed !CONFIG_ACPI compilation issue
- Converted of_pci_iommu_init() to use of_iommu_configure_dev_id()

v1: 
https://lore.kernel.org/linux-arm-kernel/20200521130008.8266-1-lorenzo.pieral...@arm.com/

Original cover letter
-

Firmware bindings provided in the ACPI IORT table[1] and device tree
bindings define rules to carry out input/output ID mappings - ie
retrieving an IOMMU/MSI controller input ID for a device with a given
ID.

At the moment these firmware bindings are used exclusively for PCI
devices and their requester ID to IOMMU/MSI id mapping but there is
nothing PCI specific in the ACPI and devicetree bindings that prevent
the firmware and kernel from using the firmware bindings to traslate
device IDs for any bus that requires its devices to carry out
input/output id translations.

The Freescale FSL bus is an example whereby the input/output ID
translation kernel code put in place for PCI can be reused for devices
attached to the bus that are not PCI devices.

This series updates the kernel code to make the MSI/IOMMU input/output
ID translation PCI agnostic and apply the resulting changes to the
device ID space provided by the Freescale FSL bus.

[1] 
http://infocenter.arm.com/help/topic/com.arm.doc.den0049d/DEN0049D_IO_Remapping_Table.pdf

Cc: Rob Herring 
Cc: "Rafael J. Wysocki" 
Cc: "Joerg Roedel 
Cc: Hanjun Guo 
Cc: Bjorn Helgaas 
Cc: Sudeep Holla 
Cc: Robin Murphy 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Marc Zyngier 

Diana Craciun (2):
  of/irq: make of_msi_map_get_device_domain() bus agnostic
  bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver

Laurentiu Tudor (1):
  dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus

Lorenzo Pieralisi (8):
  ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for
NC
  ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
  ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
  ACPI/IORT: Remove useless PCI bus walk
  ACPI/IORT: Add an input ID to acpi_dma_configure()
  of/iommu: Make of_map_rid() PCI agnostic
  of/device: Add input id to of_dma_configure()
  of/irq: Make of_msi_map_rid() PCI bus agnostic

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

 .../devicetree/bindings/misc/fsl,qoriq-mc.txt |  50 +++-
 drivers/acpi/arm64/iort.c | 108 --
 drivers/acpi/scan.c   |   8 +-
 drivers/bus/fsl-mc/dprc-driver.c  |  31 ++---
 drivers/bus/fsl-mc/fsl-mc-bus.c   |  79 +
 drivers/bus/fsl-mc/fsl-mc-msi.c   |  36 --
 drivers/bus/fsl-mc/fsl-mc-private.h   |   6 +-
 drivers/iommu/of_iommu.c  |  81 +++--
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c   | 105 ++---
 drivers/of/base.c |  42 +++
 drivers/of/device.c   |   8 +-
 drivers/of/irq.c  |  34 +++---
 drivers/pci/msi.c |   9 +-
 include/acpi/acpi_bus.h   |   9 +-
 include/linux/acpi.h  |   7 ++
 include/linux/acpi_iort.h |  20 ++--
 include/linux/of.h|   4 +-
 include/linux/of_device.h |  16 ++-
 include/linux/of_iommu.h  |   6 +-
 include/linux/of_irq.h|  13 ++-
 20 files changed, 451 insertions(+), 221 deletions(-)

-- 
2.26.1

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


[PATCH v2 01/12] ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for NC

2020-06-19 Thread Lorenzo Pieralisi
When the iort_match_node_callback is invoked for a named component
the match should be executed upon a device with an ACPI companion.

For devices with no ACPI companion set-up the ACPI device tree must be
walked in order to find the first parent node with a companion set and
check the parent node against the named component entry to check whether
there is a match and therefore an IORT node describing the in/out ID
translation for the device has been found.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 28a6b387e80e..5eee81758184 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -264,15 +264,31 @@ static acpi_status iort_match_node_callback(struct 
acpi_iort_node *node,
 
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
-   struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
+   struct acpi_device *adev;
struct acpi_iort_named_component *ncomp;
+   struct device *nc_dev = dev;
+
+   /*
+* Walk the device tree to find a device with an
+* ACPI companion; there is no point in scanning
+* IORT for a device matching a named component if
+* the device does not have an ACPI companion to
+* start with.
+*/
+   do {
+   adev = ACPI_COMPANION(nc_dev);
+   if (adev)
+   break;
+
+   nc_dev = nc_dev->parent;
+   } while (nc_dev);
 
if (!adev)
goto out;
 
status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, );
if (ACPI_FAILURE(status)) {
-   dev_warn(dev, "Can't get device full path name\n");
+   dev_warn(nc_dev, "Can't get device full path name\n");
goto out;
}
 
-- 
2.26.1

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


[PATCH v2 03/12] ACPI/IORT: Make iort_msi_map_rid() PCI agnostic

2020-06-19 Thread Lorenzo Pieralisi
There is nothing PCI specific in iort_msi_map_rid().

Rename the function using a bus protocol agnostic name,
iort_msi_map_id(), and convert current callers to it.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Bjorn Helgaas 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 12 ++--
 drivers/pci/msi.c |  2 +-
 include/linux/acpi_iort.h |  6 +++---
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 902e2aaca946..53f9ef515089 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -568,22 +568,22 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
 }
 
 /**
- * iort_msi_map_rid() - Map a MSI requester ID for a device
+ * iort_msi_map_id() - Map a MSI input ID for a device
  * @dev: The device for which the mapping is to be done.
- * @req_id: The device requester ID.
+ * @input_id: The device input ID.
  *
- * Returns: mapped MSI RID on success, input requester ID otherwise
+ * Returns: mapped MSI ID on success, input ID otherwise
  */
-u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+u32 iort_msi_map_id(struct device *dev, u32 input_id)
 {
struct acpi_iort_node *node;
u32 dev_id;
 
node = iort_find_dev_node(dev);
if (!node)
-   return req_id;
+   return input_id;
 
-   iort_node_map_id(node, req_id, _id, IORT_MSI_TYPE);
+   iort_node_map_id(node, input_id, _id, IORT_MSI_TYPE);
return dev_id;
 }
 
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 74a91f52ecc0..77f48b95e277 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1536,7 +1536,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, 
struct pci_dev *pdev)
 
of_node = irq_domain_get_of_node(domain);
rid = of_node ? of_msi_map_rid(>dev, of_node, rid) :
-   iort_msi_map_rid(>dev, rid);
+   iort_msi_map_id(>dev, rid);
 
return rid;
 }
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 08ec6bd2297f..e51425e083da 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -28,7 +28,7 @@ void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
-u32 iort_msi_map_rid(struct device *dev, u32 req_id);
+u32 iort_msi_map_id(struct device *dev, u32 id);
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
  enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
@@ -39,8 +39,8 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev);
 int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
*head);
 #else
 static inline void acpi_iort_init(void) { }
-static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
-{ return req_id; }
+static inline u32 iort_msi_map_id(struct device *dev, u32 id)
+{ return id; }
 static inline struct irq_domain *iort_get_device_domain(
struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
-- 
2.26.1

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


Re: arm64 iommu groups issue

2020-06-12 Thread Lorenzo Pieralisi
On Mon, Feb 17, 2020 at 12:08:48PM +, John Garry wrote:
> > > 
> > > Right, and even worse is that it relies on the port driver even
> > > existing at all.
> > > 
> > > All this iommu group assignment should be taken outside device
> > > driver probe paths.
> > > 
> > > However we could still consider device links for sync'ing the SMMU
> > > and each device probing.
> > 
> > Yes, we should get that for DT now thanks to the of_devlink stuff, but
> > cooking up some equivalent for IORT might be worthwhile.
> 
> It doesn't solve this problem, but at least we could remove the iommu_ops
> check in iort_iommu_xlate().
> 
> We would need to carve out a path from pci_device_add() or even device_add()
> to solve all cases.
> 
> > 
> > > > Another thought that crosses my mind is that when pci_device_group()
> > > > walks up to the point of ACS isolation and doesn't find an existing
> > > > group, it can still infer that everything it walked past *should* be put
> > > > in the same group it's then eventually going to return. Unfortunately I
> > > > can't see an obvious way for it to act on that knowledge, though, since
> > > > recursive iommu_probe_device() is unlikely to end well.
> > > 
> 
> [...]
> 
> > > And this looks to be the reason for which current
> > > iommu_bus_init()->bus_for_each_device(..., add_iommu_group) fails
> > > also.
> > 
> > Of course, just adding a 'correct' add_device replay without the
> > of_xlate process doesn't help at all. No wonder this looked suspiciously
> > simpler than where the first idea left off...
> > 
> > (on reflection, the core of this idea seems to be recycling the existing
> > iommu_bus_init walk rather than building up a separate "waiting list",
> > while forgetting that that wasn't the difficult part of the original
> > idea anyway)
> 
> We could still use a bus walk to add the group per iommu, but we would need
> an additional check to ensure the device is associated with the IOMMU.
> 
> > 
> > > On this current code mentioned, the principle of this seems wrong to
> > > me - we call bus_for_each_device(..., add_iommu_group) for the first
> > > SMMU in the system which probes, but we attempt to add_iommu_group()
> > > for all devices on the bus, even though the SMMU for that device may
> > > yet to have probed.
> > 
> > Yes, iommu_bus_init() is one of the places still holding a
> > deeply-ingrained assumption that the ops go live for all IOMMU instances
> > at once, which is what warranted the further replay in
> > of_iommu_configure() originally. Moving that out of
> > of_platform_device_create() to support probe deferral is where the
> > trouble really started.
> 
> I'm not too familiar with the history here, but could this be reverted now
> with the introduction of of_devlink stuff?

Hi John,

have we managed to reach a consensus on this thread on how to solve
the issue ? Asking because this thread seems stalled - I am keen on
getting it fixed.

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


Re: [PATCH 10/12] of/irq: Make of_msi_map_rid() PCI bus agnostic

2020-06-04 Thread Lorenzo Pieralisi
On Thu, May 21, 2020 at 05:17:27PM -0600, Rob Herring wrote:
> On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
>  wrote:
> >
> > There is nothing PCI bus specific in the of_msi_map_rid()
> > implementation other than the requester ID tag for the input
> > ID space. Rename requester ID to a more generic ID so that
> > the translation code can be used by all busses that require
> > input/output ID translations.
> >
> > Leave a wrapper function of_msi_map_rid() in place to keep
> > existing PCI code mapping requester ID syntactically unchanged.
> >
> > No functional change intended.
> >
> > Signed-off-by: Lorenzo Pieralisi 
> > Cc: Rob Herring 
> > Cc: Marc Zyngier 
> > ---
> >  drivers/of/irq.c   | 28 ++--
> >  include/linux/of_irq.h | 14 --
> >  2 files changed, 26 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/of/irq.c b/drivers/of/irq.c
> > index 48a40326984f..25d17b8a1a1a 100644
> > --- a/drivers/of/irq.c
> > +++ b/drivers/of/irq.c
> > @@ -576,43 +576,43 @@ void __init of_irq_init(const struct of_device_id 
> > *matches)
> > }
> >  }
> >
> > -static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
> > -   u32 rid_in)
> > +static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
> > +   u32 id_in)
> >  {
> > struct device *parent_dev;
> > -   u32 rid_out = rid_in;
> > +   u32 id_out = id_in;
> >
> > /*
> >  * Walk up the device parent links looking for one with a
> >  * "msi-map" property.
> >  */
> > for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
> > -   if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map",
> > -   "msi-map-mask", np, _out))
> > +   if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
> > +   "msi-map-mask", np, _out))
> > break;
> > -   return rid_out;
> > +   return id_out;
> >  }
> >
> >  /**
> > - * of_msi_map_rid - Map a MSI requester ID for a device.
> > + * of_msi_map_id - Map a MSI ID for a device.
> >   * @dev: device for which the mapping is to be done.
> >   * @msi_np: device node of the expected msi controller.
> > - * @rid_in: unmapped MSI requester ID for the device.
> > + * @id_in: unmapped MSI ID for the device.
> >   *
> >   * Walk up the device hierarchy looking for devices with a "msi-map"
> > - * property.  If found, apply the mapping to @rid_in.
> > + * property.  If found, apply the mapping to @id_in.
> >   *
> > - * Returns the mapped MSI requester ID.
> > + * Returns the mapped MSI ID.
> >   */
> > -u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 
> > rid_in)
> > +u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 
> > id_in)
> >  {
> > -   return __of_msi_map_rid(dev, _np, rid_in);
> > +   return __of_msi_map_id(dev, _np, id_in);
> >  }
> >
> >  /**
> >   * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI 
> > domain
> >   * @dev: device for which the mapping is to be done.
> > - * @rid: Requester ID for the device.
> > + * @id: Device ID.
> >   * @bus_token: Bus token
> >   *
> >   * Walk up the device hierarchy looking for devices with a "msi-map"
> > @@ -625,7 +625,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct 
> > device *dev, u32 id,
> >  {
> > struct device_node *np = NULL;
> >
> > -   __of_msi_map_rid(dev, , id);
> > +   __of_msi_map_id(dev, , id);
> > return irq_find_matching_host(np, bus_token);
> >  }
> >
> > diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
> > index 7142a3722758..cf9cb1e545ce 100644
> > --- a/include/linux/of_irq.h
> > +++ b/include/linux/of_irq.h
> > @@ -55,7 +55,12 @@ extern struct irq_domain 
> > *of_msi_map_get_device_domain(struct device *dev,
> > u32 id,
> > u32 bus_token);
> >  extern void of_msi_configure(struct device *dev, struct device_node *np);
> > -u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 
> > rid_in);
> > +u32 of_msi_

Re: [PATCH 07/12] of/device: Add input id to of_dma_configure()

2020-06-04 Thread Lorenzo Pieralisi
On Thu, May 21, 2020 at 05:02:20PM -0600, Rob Herring wrote:
> On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
>  wrote:
> >
> > Devices sitting on proprietary busses have a device ID space that
> > is owned by the respective bus and related firmware bindings. In order
> > to let the generic OF layer handle the input translations to
> > an IOMMU id, for such busses the current of_dma_configure() interface
> > should be extended in order to allow the bus layer to provide the
> > device input id parameter - that is retrieved/assigned in bus
> > specific code and firmware.
> >
> > Augment of_dma_configure() to add an optional input_id parameter,
> > leaving current functionality unchanged.
> >
> > Signed-off-by: Lorenzo Pieralisi 
> > Cc: Rob Herring 
> > Cc: Robin Murphy 
> > Cc: Joerg Roedel 
> > Cc: Laurentiu Tudor 
> > ---
> >  drivers/bus/fsl-mc/fsl-mc-bus.c |  4 ++-
> >  drivers/iommu/of_iommu.c| 53 +
> >  drivers/of/device.c |  8 +++--
> >  include/linux/of_device.h   | 16 --
> >  include/linux/of_iommu.h|  6 ++--
> >  5 files changed, 60 insertions(+), 27 deletions(-)
> >
> > diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c 
> > b/drivers/bus/fsl-mc/fsl-mc-bus.c
> > index 40526da5c6a6..8ead3f0238f2 100644
> > --- a/drivers/bus/fsl-mc/fsl-mc-bus.c
> > +++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
> > @@ -118,11 +118,13 @@ 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 fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
> > +   u32 input_id = mc_dev->icid;
> >
> > while (dev_is_fsl_mc(dma_dev))
> > dma_dev = dma_dev->parent;
> >
> > -   return of_dma_configure(dev, dma_dev->of_node, 0);
> > +   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
> >  }
> >
> >  static ssize_t modalias_show(struct device *dev, struct device_attribute 
> > *attr,
> > diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> > index ad96b87137d6..4516d5bf6cc9 100644
> > --- a/drivers/iommu/of_iommu.c
> > +++ b/drivers/iommu/of_iommu.c
> > @@ -139,25 +139,53 @@ 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)
> > +static int of_iommu_configure_dev_id(struct device_node *master_np,
> > +struct device *dev,
> > +const u32 *id)
> 
> Should have read this patch before #6. I guess you could still make
> of_pci_iommu_init() call
> of_iommu_configure_dev_id.

Yes that makes sense, I will update it.

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


Re: [PATCH 06/12] of/iommu: Make of_map_rid() PCI agnostic

2020-06-04 Thread Lorenzo Pieralisi
On Thu, May 21, 2020 at 04:47:19PM -0600, Rob Herring wrote:
> On Thu, May 21, 2020 at 7:00 AM Lorenzo Pieralisi
>  wrote:
> >
> > There is nothing PCI specific (other than the RID - requester ID)
> > in the of_map_rid() implementation, so the same function can be
> > reused for input/output IDs mapping for other busses just as well.
> >
> > Rename the RID instances/names to a generic "id" tag and provide
> > an of_map_rid() wrapper function so that we can leave the existing
> > (and legitimate) callers unchanged.
> 
> It's not all that clear to a casual observer that RID is a PCI thing,
> so I don't know that keeping it buys much. And there's only 3 callers.

Yes I agree - I think we can remove the _rid interface.

> > No functionality change intended.
> >
> > Signed-off-by: Lorenzo Pieralisi 
> > Cc: Rob Herring 
> > Cc: Joerg Roedel 
> > Cc: Robin Murphy 
> > Cc: Marc Zyngier 
> > ---
> >  drivers/iommu/of_iommu.c |  2 +-
> >  drivers/of/base.c| 42 
> >  include/linux/of.h   | 17 +++-
> >  3 files changed, 38 insertions(+), 23 deletions(-)
> >
> > diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
> > index 20738aacac89..ad96b87137d6 100644
> > --- a/drivers/iommu/of_iommu.c
> > +++ b/drivers/iommu/of_iommu.c
> > @@ -145,7 +145,7 @@ static int of_fsl_mc_iommu_init(struct fsl_mc_device 
> > *mc_dev,
> > struct of_phandle_args iommu_spec = { .args_count = 1 };
> > int err;
> >
> > -   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
> > +   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
> 
> I'm not sure this is an improvement because I'd refactor this function
> and of_pci_iommu_init() into a single function:
> 
> of_bus_iommu_init(struct device *dev, struct device_node *np, u32 id)
> 
> Then of_pci_iommu_init() becomes:
> 
> of_pci_iommu_init()
> {
>   return of_bus_iommu_init(info->dev, info->np, alias);
> }
> 
> And replace of_fsl_mc_iommu_init call with:
> err = of_bus_iommu_init(dev, master_np, to_fsl_mc_device(dev)->icid);

I will follow up on this on patch 7.

> >  "iommu-map-mask", _spec.np,
> >  iommu_spec.args);
> > if (err)
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index ae03b1218b06..e000e17bd602 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -2201,15 +2201,15 @@ int of_find_last_cache_level(unsigned int cpu)
> >  }
> >
> >  /**
> > - * of_map_rid - Translate a requester ID through a downstream mapping.
> > + * of_map_id - Translate a requester ID through a downstream mapping.
> 
> Still a requester ID?

Fixed, thanks.

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


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

2020-05-22 Thread Lorenzo Pieralisi
On Fri, May 22, 2020 at 05:32:02AM +, Makarand Pawagi wrote:

[...]

> > Subject: Re: [PATCH 12/12] bus: fsl-mc: Add ACPI support for fsl-mc
> > 
> > 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.
> > 
>  
> Will you be able to correct this or should I post another patch?

I will update it.

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


[PATCH 06/12] of/iommu: Make of_map_rid() PCI agnostic

2020-05-21 Thread Lorenzo Pieralisi
There is nothing PCI specific (other than the RID - requester ID)
in the of_map_rid() implementation, so the same function can be
reused for input/output IDs mapping for other busses just as well.

Rename the RID instances/names to a generic "id" tag and provide
an of_map_rid() wrapper function so that we can leave the existing
(and legitimate) callers unchanged.

No functionality change intended.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Joerg Roedel 
Cc: Robin Murphy 
Cc: Marc Zyngier 
---
 drivers/iommu/of_iommu.c |  2 +-
 drivers/of/base.c| 42 
 include/linux/of.h   | 17 +++-
 3 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 20738aacac89..ad96b87137d6 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -145,7 +145,7 @@ static int of_fsl_mc_iommu_init(struct fsl_mc_device 
*mc_dev,
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_rid(master_np, mc_dev->icid, "iommu-map",
+   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
 "iommu-map-mask", _spec.np,
 iommu_spec.args);
if (err)
diff --git a/drivers/of/base.c b/drivers/of/base.c
index ae03b1218b06..e000e17bd602 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -2201,15 +2201,15 @@ int of_find_last_cache_level(unsigned int cpu)
 }
 
 /**
- * of_map_rid - Translate a requester ID through a downstream mapping.
+ * of_map_id - Translate a requester ID through a downstream mapping.
  * @np: root complex device node.
- * @rid: device requester ID to map.
+ * @id: device ID to map.
  * @map_name: property name of the map to use.
  * @map_mask_name: optional property name of the mask to use.
  * @target: optional pointer to a target device node.
  * @id_out: optional pointer to receive the translated ID.
  *
- * Given a device requester ID, look up the appropriate implementation-defined
+ * Given a device ID, look up the appropriate implementation-defined
  * platform ID and/or the target device which receives transactions on that
  * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
  * @id_out may be NULL if only the other is required. If @target points to
@@ -2219,11 +2219,11 @@ int of_find_last_cache_level(unsigned int cpu)
  *
  * Return: 0 on success or a standard error code on failure.
  */
-int of_map_rid(struct device_node *np, u32 rid,
+int of_map_id(struct device_node *np, u32 id,
   const char *map_name, const char *map_mask_name,
   struct device_node **target, u32 *id_out)
 {
-   u32 map_mask, masked_rid;
+   u32 map_mask, masked_id;
int map_len;
const __be32 *map = NULL;
 
@@ -2235,7 +2235,7 @@ int of_map_rid(struct device_node *np, u32 rid,
if (target)
return -ENODEV;
/* Otherwise, no map implies no translation */
-   *id_out = rid;
+   *id_out = id;
return 0;
}
 
@@ -2255,22 +2255,22 @@ int of_map_rid(struct device_node *np, u32 rid,
if (map_mask_name)
of_property_read_u32(np, map_mask_name, _mask);
 
-   masked_rid = map_mask & rid;
+   masked_id = map_mask & id;
for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
struct device_node *phandle_node;
-   u32 rid_base = be32_to_cpup(map + 0);
+   u32 id_base = be32_to_cpup(map + 0);
u32 phandle = be32_to_cpup(map + 1);
u32 out_base = be32_to_cpup(map + 2);
-   u32 rid_len = be32_to_cpup(map + 3);
+   u32 id_len = be32_to_cpup(map + 3);
 
-   if (rid_base & ~map_mask) {
-   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
ignores rid-base (0x%x)\n",
+   if (id_base & ~map_mask) {
+   pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) 
ignores id-base (0x%x)\n",
np, map_name, map_name,
-   map_mask, rid_base);
+   map_mask, id_base);
return -EFAULT;
}
 
-   if (masked_rid < rid_base || masked_rid >= rid_base + rid_len)
+   if (masked_id < id_base || masked_id >= id_base + id_len)
continue;
 
phandle_node = of_find_node_by_phandle(phandle);
@@ -2288,20 +2288,20 @@ int of_map_rid(struct device_node *np, u32 rid,
}
 
if (id_out)
-   *id_out = masked_rid - rid_base + out_base;
+   *id_out = masked_id - id_base + out_base;
 
- 

[PATCH 04/12] ACPI/IORT: Remove useless PCI bus walk

2020-05-21 Thread Lorenzo Pieralisi
The PCI bus domain number (used in the iort_match_node_callback() -
pci_domain_nr() call) is cascaded through the PCI bus hierarchy at PCI
bus enumeration time, therefore there is no need in iort_find_dev_node()
to walk the PCI bus upwards to grab the root bus to be passed to
iort_scan_node(), the device->bus PCI bus pointer will do.

Remove this useless code.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index f346a785e0b5..ae9e1089d954 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -575,10 +575,7 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
  iort_match_node_callback, dev);
}
 
-   /* Find a PCI root bus */
pbus = to_pci_dev(dev)->bus;
-   while (!pci_is_root_bus(pbus))
-   pbus = pbus->parent;
 
return iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
  iort_match_node_callback, >dev);
-- 
2.26.1

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


[PATCH 03/12] ACPI/IORT: Make iort_msi_map_rid() PCI agnostic

2020-05-21 Thread Lorenzo Pieralisi
There is nothing PCI specific in iort_msi_map_rid(). Make it
a generic function, iort_msi_map_id() and provide a stub
for iort_msi_map_rid() on top of it to keep current users
unchanged.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 12 ++--
 include/linux/acpi_iort.h | 12 ++--
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 8f2a961c1364..f346a785e0b5 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -585,22 +585,22 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
 }
 
 /**
- * iort_msi_map_rid() - Map a MSI requester ID for a device
+ * iort_msi_map_id() - Map a MSI input ID for a device
  * @dev: The device for which the mapping is to be done.
- * @req_id: The device requester ID.
+ * @input_id: The device input ID.
  *
- * Returns: mapped MSI RID on success, input requester ID otherwise
+ * Returns: mapped MSI ID on success, input ID otherwise
  */
-u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+u32 iort_msi_map_id(struct device *dev, u32 input_id)
 {
struct acpi_iort_node *node;
u32 dev_id;
 
node = iort_find_dev_node(dev);
if (!node)
-   return req_id;
+   return input_id;
 
-   iort_node_map_id(node, req_id, _id, IORT_MSI_TYPE);
+   iort_node_map_id(node, input_id, _id, IORT_MSI_TYPE);
return dev_id;
 }
 
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 08ec6bd2297f..8c71f92b92ef 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -28,7 +28,11 @@ void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
-u32 iort_msi_map_rid(struct device *dev, u32 req_id);
+u32 iort_msi_map_id(struct device *dev, u32 id);
+static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
+{
+   return iort_msi_map_id(dev, req_id);
+}
 struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
  enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
@@ -39,8 +43,12 @@ const struct iommu_ops *iort_iommu_configure(struct device 
*dev);
 int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head 
*head);
 #else
 static inline void acpi_iort_init(void) { }
+static inline u32 iort_msi_map_id(struct device *dev, u32 id)
+{ return id; }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
-{ return req_id; }
+{
+   return iort_msi_map_id(dev, req_id);
+}
 static inline struct irq_domain *iort_get_device_domain(
struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
-- 
2.26.1

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


[PATCH 05/12] ACPI/IORT: Add an input ID to acpi_dma_configure()

2020-05-21 Thread Lorenzo Pieralisi
Some HW devices are created as child devices of proprietary busses,
that have a bus specific policy definining how the child devices
wires representing the devices ID are translated into IOMMU and
IRQ controllers device IDs.

Current IORT code provides translations for:

- PCI devices, where the device ID is well identified at bus level
  as the requester ID (RID)
- Platform devices that are endpoint devices where the device ID is
  retrieved from the ACPI object IORT mappings (Named components single
  mappings). A platform device is represented in IORT as a named
  component node

For devices that are child devices of proprietary busses the IORT
firmware represents the bus node as a named component node in IORT
and it is up to that named component node to define in/out bus
specific ID translations for the bus child devices that are
allocated and created in a bus specific manner.

In order to make IORT ID translations available for proprietary
bus child devices, the current ACPI (and IORT) code must be
augmented to provide an additional ID parameter to acpi_dma_configure()
representing the child devices input ID. This ID is bus specific
and it is retrieved in bus specific code.

By adding an ID parameter to acpi_dma_configure(), the IORT
code can map the child device ID to an IOMMU stream id through
the IORT named component representing the bus in/out ID mappings.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 59 +--
 drivers/acpi/scan.c   |  8 --
 include/acpi/acpi_bus.h   |  9 --
 include/linux/acpi.h  |  7 +
 include/linux/acpi_iort.h |  7 +++--
 5 files changed, 67 insertions(+), 23 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index ae9e1089d954..270c1a0cdeff 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1004,19 +1004,54 @@ static void iort_named_component_init(struct device 
*dev,
   nc->node_flags);
 }
 
+static int iort_nc_iommu_map(struct device *dev, struct acpi_iort_node *node)
+{
+   struct acpi_iort_node *parent;
+   int err = -ENODEV, i = 0;
+   u32 streamid = 0;
+
+   do {
+
+   parent = iort_node_map_platform_id(node, ,
+  IORT_IOMMU_TYPE,
+  i++);
+
+   if (parent)
+   err = iort_iommu_xlate(dev, parent, streamid);
+   } while (parent && !err);
+
+   return err;
+}
+
+static int iort_nc_iommu_map_id(struct device *dev,
+   struct acpi_iort_node *node,
+   const u32 *in_id)
+{
+   struct acpi_iort_node *parent;
+   u32 streamid;
+
+   parent = iort_node_map_id(node, *in_id, , IORT_IOMMU_TYPE);
+   if (parent)
+   return iort_iommu_xlate(dev, parent, streamid);
+
+   return -ENODEV;
+}
+
+
 /**
- * iort_iommu_configure - Set-up IOMMU configuration for a device.
+ * iort_iommu_configure_id - Set-up IOMMU configuration for a device.
  *
  * @dev: device to configure
+ * @id_in: optional input id const value pointer
  *
  * Returns: iommu_ops pointer on configuration success
  *  NULL on configuration failure
  */
-const struct iommu_ops *iort_iommu_configure(struct device *dev)
+const struct iommu_ops *iort_iommu_configure_id(struct device *dev,
+   const u32 *id_in)
 {
-   struct acpi_iort_node *node, *parent;
+   struct acpi_iort_node *node;
const struct iommu_ops *ops;
-   u32 streamid = 0;
int err = -ENODEV;
 
/*
@@ -1045,21 +1080,13 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
if (fwspec && iort_pci_rc_supports_ats(node))
fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
} else {
-   int i = 0;
-
node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
  iort_match_node_callback, dev);
if (!node)
return NULL;
 
-   do {
-   parent = iort_node_map_platform_id(node, ,
-  IORT_IOMMU_TYPE,
-  i++);
-
-   if (parent)
-   err = iort_iommu_xlate(dev, parent, streamid);
-   } while (parent && !err);
+   err = id_in ? iort_nc_iommu_map_id(dev, node, id_in) :
+ iort_nc_iommu_map(dev, node);
 
if (!err)
iort_named_component_init(dev, node);
@@ -1084,6 +,7 @@ const struct iommu_ops *

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

2020-05-21 Thread Lorenzo Pieralisi
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 
---
 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_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_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_PORTAL, _io);
@@ -903,11 +930,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,
+   

[PATCH 00/12] ACPI/OF: Upgrade MSI/IOMMU ID mapping APIs

2020-05-21 Thread Lorenzo Pieralisi
Firmware bindings provided in the ACPI IORT table[1] and device tree
bindings define rules to carry out input/output ID mappings - ie
retrieving an IOMMU/MSI controller input ID for a device with a given
ID.

At the moment these firmware bindings are used exclusively for PCI
devices and their requester ID to IOMMU/MSI id mapping but there is
nothing PCI specific in the ACPI and devicetree bindings that prevent
the firmware and kernel from using the firmware bindings to traslate
device IDs for any bus that requires its devices to carry out
input/output id translations.

The Freescale FSL bus is an example whereby the input/output ID
translation kernel code put in place for PCI can be reused for devices
attached to the bus that are not PCI devices.

This series updates the kernel code to make the MSI/IOMMU input/output
ID translation PCI agnostic and apply the resulting changes to the
device ID space provided by the Freescale FSL bus.

[1] 
http://infocenter.arm.com/help/topic/com.arm.doc.den0049d/DEN0049D_IO_Remapping_Table.pdf

Cc: Rob Herring 
Cc: "Rafael J. Wysocki" 
Cc: "Joerg Roedel 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Robin Murphy 
Cc: Catalin Marinas 
Cc: Will Deacon 
Cc: Marc Zyngier 

Diana Craciun (3):
  of/irq: make of_msi_map_get_device_domain() bus agnostic
  bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver
  bus: fsl-mc: Add ACPI support for fsl-mc

Laurentiu Tudor (1):
  dt-bindings: arm: fsl: Add msi-map device-tree binding for fsl-mc bus

Lorenzo Pieralisi (8):
  ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for
NC
  ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic
  ACPI/IORT: Make iort_msi_map_rid() PCI agnostic
  ACPI/IORT: Remove useless PCI bus walk
  ACPI/IORT: Add an input ID to acpi_dma_configure()
  of/iommu: Make of_map_rid() PCI agnostic
  of/device: Add input id to of_dma_configure()
  of/irq: Make of_msi_map_rid() PCI bus agnostic

 .../devicetree/bindings/misc/fsl,qoriq-mc.txt |  30 -
 drivers/acpi/arm64/iort.c | 108 --
 drivers/acpi/scan.c   |   8 +-
 drivers/bus/fsl-mc/dprc-driver.c  |  31 ++---
 drivers/bus/fsl-mc/fsl-mc-bus.c   |  79 +
 drivers/bus/fsl-mc/fsl-mc-msi.c   |  36 --
 drivers/bus/fsl-mc/fsl-mc-private.h   |   6 +-
 drivers/iommu/of_iommu.c  |  53 ++---
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c   |  88 +-
 drivers/of/base.c |  42 +++
 drivers/of/device.c   |   8 +-
 drivers/of/irq.c  |  34 +++---
 drivers/pci/msi.c |   5 +-
 include/acpi/acpi_bus.h   |   9 +-
 include/linux/acpi.h  |   7 ++
 include/linux/acpi_iort.h |  26 +++--
 include/linux/of.h|  17 ++-
 include/linux/of_device.h |  16 ++-
 include/linux/of_iommu.h  |   6 +-
 include/linux/of_irq.h|  19 ++-
 20 files changed, 451 insertions(+), 177 deletions(-)

-- 
2.26.1

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


[PATCH 10/12] of/irq: Make of_msi_map_rid() PCI bus agnostic

2020-05-21 Thread Lorenzo Pieralisi
There is nothing PCI bus specific in the of_msi_map_rid()
implementation other than the requester ID tag for the input
ID space. Rename requester ID to a more generic ID so that
the translation code can be used by all busses that require
input/output ID translations.

Leave a wrapper function of_msi_map_rid() in place to keep
existing PCI code mapping requester ID syntactically unchanged.

No functional change intended.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Marc Zyngier 
---
 drivers/of/irq.c   | 28 ++--
 include/linux/of_irq.h | 14 --
 2 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 48a40326984f..25d17b8a1a1a 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -576,43 +576,43 @@ void __init of_irq_init(const struct of_device_id 
*matches)
}
 }
 
-static u32 __of_msi_map_rid(struct device *dev, struct device_node **np,
-   u32 rid_in)
+static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
+   u32 id_in)
 {
struct device *parent_dev;
-   u32 rid_out = rid_in;
+   u32 id_out = id_in;
 
/*
 * Walk up the device parent links looking for one with a
 * "msi-map" property.
 */
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
-   if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map",
-   "msi-map-mask", np, _out))
+   if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
+   "msi-map-mask", np, _out))
break;
-   return rid_out;
+   return id_out;
 }
 
 /**
- * of_msi_map_rid - Map a MSI requester ID for a device.
+ * of_msi_map_id - Map a MSI ID for a device.
  * @dev: device for which the mapping is to be done.
  * @msi_np: device node of the expected msi controller.
- * @rid_in: unmapped MSI requester ID for the device.
+ * @id_in: unmapped MSI ID for the device.
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
- * property.  If found, apply the mapping to @rid_in.
+ * property.  If found, apply the mapping to @id_in.
  *
- * Returns the mapped MSI requester ID.
+ * Returns the mapped MSI ID.
  */
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in)
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
 {
-   return __of_msi_map_rid(dev, _np, rid_in);
+   return __of_msi_map_id(dev, _np, id_in);
 }
 
 /**
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
- * @rid: Requester ID for the device.
+ * @id: Device ID.
  * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
@@ -625,7 +625,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct 
device *dev, u32 id,
 {
struct device_node *np = NULL;
 
-   __of_msi_map_rid(dev, , id);
+   __of_msi_map_id(dev, , id);
return irq_find_matching_host(np, bus_token);
 }
 
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 7142a3722758..cf9cb1e545ce 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -55,7 +55,12 @@ extern struct irq_domain 
*of_msi_map_get_device_domain(struct device *dev,
u32 id,
u32 bus_token);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
+u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in);
+static inline u32 of_msi_map_rid(struct device *dev,
+struct device_node *msi_np, u32 rid_in)
+{
+   return of_msi_map_id(dev, msi_np, rid_in);
+}
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
@@ -93,10 +98,15 @@ static inline struct irq_domain 
*of_msi_map_get_device_domain(struct device *dev
 static inline void of_msi_configure(struct device *dev, struct device_node *np)
 {
 }
+static inline u32 of_msi_map_id(struct device *dev,
+struct device_node *msi_np, u32 id_in)
+{
+   return id_in;
+}
 static inline u32 of_msi_map_rid(struct device *dev,
 struct device_node *msi_np, u32 rid_in)
 {
-   return rid_in;
+   return of_msi_map_id(dev, msi_np, rid_in);
 }
 #endif
 
-- 
2.26.1

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


[PATCH 08/12] of/irq: make of_msi_map_get_device_domain() bus agnostic

2020-05-21 Thread Lorenzo Pieralisi
From: Diana Craciun 

of_msi_map_get_device_domain() is PCI specific but it need not be and
can be easily changed to be bus agnostic in order to be used by other
busses by adding an IRQ domain bus token as an input parameter.

Signed-off-by: Diana Craciun 
Signed-off-by: Lorenzo Pieralisi 
Cc: Bjorn Helgaas 
Cc: Rob Herring 
Cc: Marc Zyngier 
---
 drivers/of/irq.c   | 8 +---
 drivers/pci/msi.c  | 2 +-
 include/linux/of_irq.h | 5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index a296eaf52a5b..48a40326984f 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -613,18 +613,20 @@ u32 of_msi_map_rid(struct device *dev, struct device_node 
*msi_np, u32 rid_in)
  * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
  * @dev: device for which the mapping is to be done.
  * @rid: Requester ID for the device.
+ * @bus_token: Bus token
  *
  * Walk up the device hierarchy looking for devices with a "msi-map"
  * property.
  *
  * Returns: the MSI domain for this device (or NULL on failure)
  */
-struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid)
+struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
+   u32 bus_token)
 {
struct device_node *np = NULL;
 
-   __of_msi_map_rid(dev, , rid);
-   return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI);
+   __of_msi_map_rid(dev, , id);
+   return irq_find_matching_host(np, bus_token);
 }
 
 /**
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 74a91f52ecc0..9532e1d12d3f 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1556,7 +1556,7 @@ struct irq_domain *pci_msi_get_device_domain(struct 
pci_dev *pdev)
u32 rid = pci_dev_id(pdev);
 
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
-   dom = of_msi_map_get_device_domain(>dev, rid);
+   dom = of_msi_map_get_device_domain(>dev, rid, DOMAIN_BUS_PCI_MSI);
if (!dom)
dom = iort_get_device_domain(>dev, rid,
 DOMAIN_BUS_PCI_MSI);
diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h
index 1214cabb2247..7142a3722758 100644
--- a/include/linux/of_irq.h
+++ b/include/linux/of_irq.h
@@ -52,7 +52,8 @@ extern struct irq_domain *of_msi_get_domain(struct device 
*dev,
struct device_node *np,
enum irq_domain_bus_token token);
 extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
-  u32 rid);
+   u32 id,
+   u32 bus_token);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
 u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 #else
@@ -85,7 +86,7 @@ static inline struct irq_domain *of_msi_get_domain(struct 
device *dev,
return NULL;
 }
 static inline struct irq_domain *of_msi_map_get_device_domain(struct device 
*dev,
- u32 rid)
+   u32 id, u32 bus_token)
 {
return NULL;
 }
-- 
2.26.1

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


[PATCH 02/12] ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic

2020-05-21 Thread Lorenzo Pieralisi
iort_get_device_domain() is PCI specific but it need not be,
since it can be used to retrieve IRQ domain nexus of any kind
by adding an irq_domain_bus_token input to it.

Make it PCI agnostic by also renaming the requestor ID input
to a more generic ID name.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Bjorn Helgaas 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
Cc: Marc Zyngier 
---
 drivers/acpi/arm64/iort.c | 14 +++---
 drivers/pci/msi.c |  3 ++-
 include/linux/acpi_iort.h |  7 ---
 3 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 7cfd77b5e6e8..8f2a961c1364 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -567,7 +567,6 @@ static struct acpi_iort_node *iort_find_dev_node(struct 
device *dev)
node = iort_get_iort_node(dev->fwnode);
if (node)
return node;
-
/*
 * if not, then it should be a platform device defined in
 * DSDT/SSDT (with Named Component node in IORT)
@@ -658,13 +657,13 @@ static int __maybe_unused iort_find_its_base(u32 its_id, 
phys_addr_t *base)
 /**
  * iort_dev_find_its_id() - Find the ITS identifier for a device
  * @dev: The device.
- * @req_id: Device's requester ID
+ * @id: Device's ID
  * @idx: Index of the ITS identifier list.
  * @its_id: ITS identifier.
  *
  * Returns: 0 on success, appropriate error value otherwise
  */
-static int iort_dev_find_its_id(struct device *dev, u32 req_id,
+static int iort_dev_find_its_id(struct device *dev, u32 id,
unsigned int idx, int *its_id)
 {
struct acpi_iort_its_group *its;
@@ -674,7 +673,7 @@ static int iort_dev_find_its_id(struct device *dev, u32 
req_id,
if (!node)
return -ENXIO;
 
-   node = iort_node_map_id(node, req_id, NULL, IORT_MSI_TYPE);
+   node = iort_node_map_id(node, id, NULL, IORT_MSI_TYPE);
if (!node)
return -ENXIO;
 
@@ -697,19 +696,20 @@ static int iort_dev_find_its_id(struct device *dev, u32 
req_id,
  *
  * Returns: the MSI domain for this device, NULL otherwise
  */
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id)
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+ enum irq_domain_bus_token bus_token)
 {
struct fwnode_handle *handle;
int its_id;
 
-   if (iort_dev_find_its_id(dev, req_id, 0, _id))
+   if (iort_dev_find_its_id(dev, id, 0, _id))
return NULL;
 
handle = iort_find_domain_token(its_id);
if (!handle)
return NULL;
 
-   return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI);
+   return irq_find_matching_fwnode(handle, bus_token);
 }
 
 static void iort_set_device_domain(struct device *dev,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 6b43a5455c7a..74a91f52ecc0 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1558,7 +1558,8 @@ struct irq_domain *pci_msi_get_device_domain(struct 
pci_dev *pdev)
pci_for_each_dma_alias(pdev, get_msi_id_cb, );
dom = of_msi_map_get_device_domain(>dev, rid);
if (!dom)
-   dom = iort_get_device_domain(>dev, rid);
+   dom = iort_get_device_domain(>dev, rid,
+DOMAIN_BUS_PCI_MSI);
return dom;
 }
 #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 8e7e2ec37f1b..08ec6bd2297f 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -29,7 +29,8 @@ struct fwnode_handle *iort_find_domain_token(int trans_id);
 #ifdef CONFIG_ACPI_IORT
 void acpi_iort_init(void);
 u32 iort_msi_map_rid(struct device *dev, u32 req_id);
-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
+struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
+ enum irq_domain_bus_token bus_token);
 void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
@@ -40,8 +41,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
struct list_head *head);
 static inline void acpi_iort_init(void) { }
 static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id)
 { return req_id; }
-static inline struct irq_domain *iort_get_device_domain(struct device *dev,
-   u32 req_id)
+static inline struct irq_domain *iort_get_device_domain(
+   struct device *dev, u32 id, enum irq_domain_bus_token bus_token)
 { return NULL; }
 static inline void acpi_configure_pmsi_domain(struct device *dev) { }
 /* IOMMU interface */
-- 
2.26.1

___

[PATCH 01/12] ACPI/IORT: Make iort_match_node_callback walk the ACPI namespace for NC

2020-05-21 Thread Lorenzo Pieralisi
When the iort_match_node_callback is invoked for a named component
the match should be executed upon a device with an ACPI companion.

For devices with no ACPI companion set-up the ACPI device tree must be
walked in order to find the first parent node with a companion set and
check the parent node against the named component entry to check whether
there is a match and therefore an IORT node describing the in/out ID
translation for the device has been found.

Signed-off-by: Lorenzo Pieralisi 
Cc: Will Deacon 
Cc: Hanjun Guo 
Cc: Sudeep Holla 
Cc: Catalin Marinas 
Cc: Robin Murphy 
Cc: "Rafael J. Wysocki" 
---
 drivers/acpi/arm64/iort.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 7d04424189df..7cfd77b5e6e8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -264,15 +264,31 @@ static acpi_status iort_match_node_callback(struct 
acpi_iort_node *node,
 
if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
-   struct acpi_device *adev = to_acpi_device_node(dev->fwnode);
+   struct acpi_device *adev;
struct acpi_iort_named_component *ncomp;
+   struct device *nc_dev = dev;
+
+   /*
+* Walk the device tree to find a device with an
+* ACPI companion; there is no point in scanning
+* IORT for a device matching a named component if
+* the device does not have an ACPI companion to
+* start with.
+*/
+   do {
+   adev = ACPI_COMPANION(nc_dev);
+   if (adev)
+   break;
+
+   nc_dev = nc_dev->parent;
+   } while (nc_dev);
 
if (!adev)
goto out;
 
status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, );
if (ACPI_FAILURE(status)) {
-   dev_warn(dev, "Can't get device full path name\n");
+   dev_warn(nc_dev, "Can't get device full path name\n");
goto out;
}
 
-- 
2.26.1

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


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

2020-05-21 Thread Lorenzo Pieralisi
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).
+
+  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 = <>;
 /* define map for ICIDs 23-64 */
 iommu-map = <23  23 41>;
+/* define msi map for ICIDs 23-64 */
+msi-map = <23  23 41>;
 #address-cells = <3>;
 #size-cells = <1>;
 
-- 
2.26.1

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


[PATCH 11/12] bus/fsl-mc: Refactor the MSI domain creation in the DPRC driver

2020-05-21 Thread Lorenzo Pieralisi
From: Diana Craciun 

The DPRC driver is not taking into account the msi-map property
and assumes that the icid is the same as the stream ID. Although
this assumption is correct, generalize the code to include a
translation between icid and streamID.

Furthermore do not just copy the MSI domain from parent (for child
containers), but use the information provided by the msi-map property.

If the msi-map property is missing from the device tree retain the old
behaviour for backward compatibility ie the child DPRC objects
inherit the MSI domain from the parent.

Signed-off-by: Diana Craciun 
---
 drivers/bus/fsl-mc/dprc-driver.c| 31 ++---
 drivers/bus/fsl-mc/fsl-mc-bus.c |  4 +--
 drivers/bus/fsl-mc/fsl-mc-msi.c | 31 +
 drivers/bus/fsl-mc/fsl-mc-private.h |  6 ++--
 drivers/irqchip/irq-gic-v3-its-fsl-mc-msi.c | 15 +-
 5 files changed, 47 insertions(+), 40 deletions(-)

diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index c8b1c3842c1a..189bff2115a8 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -592,6 +592,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
bool mc_io_created = false;
bool msi_domain_set = false;
u16 major_ver, minor_ver;
+   struct irq_domain *mc_msi_domain;
 
if (!is_fsl_mc_bus_dprc(mc_dev))
return -EINVAL;
@@ -621,31 +622,15 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
return error;
 
mc_io_created = true;
+   }
 
-   /*
-* Inherit parent MSI domain:
-*/
-   dev_set_msi_domain(_dev->dev,
-  dev_get_msi_domain(parent_dev));
-   msi_domain_set = true;
+   mc_msi_domain = fsl_mc_find_msi_domain(_dev->dev);
+   if (!mc_msi_domain) {
+   dev_warn(_dev->dev,
+"WARNING: MC bus without interrupt support\n");
} else {
-   /*
-* This is a root DPRC
-*/
-   struct irq_domain *mc_msi_domain;
-
-   if (dev_is_fsl_mc(parent_dev))
-   return -EINVAL;
-
-   error = fsl_mc_find_msi_domain(parent_dev,
-  _msi_domain);
-   if (error < 0) {
-   dev_warn(_dev->dev,
-"WARNING: MC bus without interrupt support\n");
-   } else {
-   dev_set_msi_domain(_dev->dev, mc_msi_domain);
-   msi_domain_set = true;
-   }
+   dev_set_msi_domain(_dev->dev, mc_msi_domain);
+   msi_domain_set = true;
}
 
error = dprc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 8ead3f0238f2..824ff77bbe86 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -370,8 +370,8 @@ EXPORT_SYMBOL_GPL(fsl_mc_get_version);
 /**
  * fsl_mc_get_root_dprc - function to traverse to the root dprc
  */
-static void fsl_mc_get_root_dprc(struct device *dev,
-struct device **root_dprc_dev)
+void fsl_mc_get_root_dprc(struct device *dev,
+struct device **root_dprc_dev)
 {
if (!dev) {
*root_dprc_dev = NULL;
diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 8b9c66d7c4ff..e7bbff445a83 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -177,23 +177,30 @@ struct irq_domain *fsl_mc_msi_create_irq_domain(struct 
fwnode_handle *fwnode,
return domain;
 }
 
-int fsl_mc_find_msi_domain(struct device *mc_platform_dev,
-  struct irq_domain **mc_msi_domain)
+struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
 {
-   struct irq_domain *msi_domain;
-   struct device_node *mc_of_node = mc_platform_dev->of_node;
+   struct irq_domain *msi_domain = NULL;
+   struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
 
-   msi_domain = of_msi_get_domain(mc_platform_dev, mc_of_node,
-  DOMAIN_BUS_FSL_MC_MSI);
-   if (!msi_domain) {
-   pr_err("Unable to find fsl-mc MSI domain for %pOF\n",
-  mc_of_node);
+   msi_domain = of_msi_map_get_device_domain(dev, mc_dev->icid,
+ DOMAIN_BUS_FSL_MC_MSI);
 
-   return -ENOENT;
+   /*
+* if the msi-map property is missing assume that all the
+* child containers inherit the domain from the parent
+*/
+   if (!msi_domain) {
+   struct device *root_dprc_dev;
+   struct device *bus_dev;
+
+   

[PATCH 07/12] of/device: Add input id to of_dma_configure()

2020-05-21 Thread Lorenzo Pieralisi
Devices sitting on proprietary busses have a device ID space that
is owned by the respective bus and related firmware bindings. In order
to let the generic OF layer handle the input translations to
an IOMMU id, for such busses the current of_dma_configure() interface
should be extended in order to allow the bus layer to provide the
device input id parameter - that is retrieved/assigned in bus
specific code and firmware.

Augment of_dma_configure() to add an optional input_id parameter,
leaving current functionality unchanged.

Signed-off-by: Lorenzo Pieralisi 
Cc: Rob Herring 
Cc: Robin Murphy 
Cc: Joerg Roedel 
Cc: Laurentiu Tudor 
---
 drivers/bus/fsl-mc/fsl-mc-bus.c |  4 ++-
 drivers/iommu/of_iommu.c| 53 +
 drivers/of/device.c |  8 +++--
 include/linux/of_device.h   | 16 --
 include/linux/of_iommu.h|  6 ++--
 5 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 40526da5c6a6..8ead3f0238f2 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -118,11 +118,13 @@ 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 fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
+   u32 input_id = mc_dev->icid;
 
while (dev_is_fsl_mc(dma_dev))
dma_dev = dma_dev->parent;
 
-   return of_dma_configure(dev, dma_dev->of_node, 0);
+   return of_dma_configure_id(dev, dma_dev->of_node, 0, _id);
 }
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index ad96b87137d6..4516d5bf6cc9 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -139,25 +139,53 @@ 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)
+static int of_iommu_configure_dev_id(struct device_node *master_np,
+struct device *dev,
+const u32 *id)
 {
struct of_phandle_args iommu_spec = { .args_count = 1 };
int err;
 
-   err = of_map_id(master_np, mc_dev->icid, "iommu-map",
+   err = of_map_id(master_np, *id, "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);
+   err = of_iommu_xlate(dev, _spec);
of_node_put(iommu_spec.np);
return err;
 }
 
+static int of_iommu_configure_dev(struct device_node *master_np,
+ struct device *dev)
+{
+   struct of_phandle_args iommu_spec;
+   int err = NO_IOMMU, idx = 0;
+
+   while (!of_parse_phandle_with_args(master_np, "iommus",
+  "#iommu-cells",
+  idx, _spec)) {
+   err = of_iommu_xlate(dev, _spec);
+   of_node_put(iommu_spec.np);
+   idx++;
+   if (err)
+   break;
+   }
+
+   return err;
+}
+
+static int of_iommu_configure_device(struct device_node *master_np,
+struct device *dev, const u32 *id)
+{
+   return (id) ? of_iommu_configure_dev_id(master_np, dev, id) :
+ of_iommu_configure_dev(master_np, dev);
+}
+
 const struct iommu_ops *of_iommu_configure(struct device *dev,
-  struct device_node *master_np)
+  struct device_node *master_np,
+  const u32 *id)
 {
const struct iommu_ops *ops = NULL;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
@@ -188,21 +216,8 @@ 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;
-
-   while (!of_parse_phandle_with_args(master_np, "iommus",
-  "#iommu-cells",
-  idx, _spec)) {
-   err = of_iommu_xlate(dev, _spec);
-   of_node_put(iommu_spec.np);
-

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

2020-04-23 Thread Lorenzo Pieralisi
On Thu, Apr 23, 2020 at 09:56:54AM +, Makarand Pawagi wrote:

[...]

> > > 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?
> > 
> > Assuming you mean the DPRC devices rather than the MC itself, then yes; in 
> > that
> > sense it's exactly the same as how we treat dynamically-discovered PCI 
> > devices.
> > 
> > >   * 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.
> > 
> > Wrong - last time I looked, what that firmware actually manages are
> > *ICIDs* for the devices, not SMMU Stream IDs or GIC Device IDs; what DT/ACPI
> > specifies is a translation from ICID to Stream ID/Device ID. The ICID is 
> > very much
> > the requester/input ID for that translation. Yes, in practice the 
> > "translation" is
> > effectively always a trivial identity mapping, but conceptually it most 
> > definitely
> > exists. Yes, the subtlety is incredibly easy to overlook because it's 
> > basically
> > drawing a distinction between one end of some wires vs. the other end, but 
> > it
> > matters.
> > 
> > (and of course "trivial 1:1 translation" isn't even true in the case of SMMU
> > Stream ID values, since IIRC they are really composed of 5 different 
> > inputs, only
> > one of which is (part of) the incoming ICID)
> > 
> > >   * 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?
> > 
> > If it represents a unique ICID allocated to the MC itself, then sure, it 
> > simply goes
> > through the mapping like anything else. Just like a PCI host bridge owns
> > requester ID 0:0.0 and thus whatever Stream ID/Device ID that might map to.
> > 
> > If (for the sake of argument, because AIUI everything is an ICID in this 
> > particular
> > case) it's some hard-wired thing that exists in Stream ID/Device ID space 
> > only,
> > then it's a little trickier, but still in scope. In DT we have a lovely 
> > distinction
> > between between "originating from the node" and "translated through the
> > node", e.g. "msi-parent" vs.
> > "msi-map"; IORT is not quite as clear-cut, but there are at least a few 
> > options. If
> > the valid input ID space is smaller than 32 bits, then the "Named Component 
> > as
> > bridge" binding could simply define special out-of-range values to 
> > represent IDs
> > originating from the bridge itself, such that the NC driver knows what to 
> > do and
> > from IORT's point of view everything is just a normal mapping. Alternatively
> > there's already the example of SMMUv3 where we can have a mix of the normal
> > mappings from Stream ID to Device ID for the upstream masters plus a single
> > mapping for the SMMU's own Device ID - admittedly that depends on the
> > additional SMMUv3-specific Device ID Mapping Index property, but if 
> > necessary
> > it might be workable to have a de-facto interface for NCs that only 
> > considers
> > single mappings when configuring the NC itself, and only considers normal
> > mappings when configuring its children. Or maybe define a new mapping flag 
> > or
> > NC property if there's a real need to specify such a situation 
> > unambiguously at
> > the IORT level.
> > 
> > >   * 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?
> > 
> > I won't speak for Lorenzo or claim we've agreed on an approach at all (not 
> > least
> > because in all honesty we haven't really discussed it beyond these various 
> > email
> > threads), but FWIW my vision is that ultimately the DT/ACPI code would 
> > expose
> > a *_dma_configure() interface that takes an optional input ID, or (perhaps 
> > more
> > likely) an explicit pair of interfaces for "configure this regular device" 
> > and
> > "configure this device based on this 'host' device and this ID", and it 
> > becomes
> > the bus code's responsibility to pass the right device(s) and deal with 
> > multiple IDs
> > (i.e. for starters all the PCI alias stuff goes back to the PCI code where 
> > it really
> > should be, rather than having multiple copies of magic PCI awareness deep
> > down in DT/ACPI code).
> > 
> > Robin.
>  
> Hi Lorenzo, Robin,


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

2020-04-15 Thread Lorenzo Pieralisi
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 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 see

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

2020-04-15 Thread Lorenzo Pieralisi
On Wed, Apr 15, 2020 at 05:42:03AM +, Makarand Pawagi wrote:
> 
> 
> > -Original Message-
> > From: Lorenzo Pieralisi 
> > Sent: Tuesday, April 14, 2020 8:02 PM
> > To: Laurentiu Tudor 
> > Cc: linux-ker...@vger.kernel.org; iommu@lists.linux-foundation.org; 
> > linux-arm-
> > ker...@lists.infradead.org; linux-a...@vger.kernel.org;
> > robin.mur...@arm.com; ard.biesheu...@linaro.org; Ioana Ciornei
> > ; Diana Madalina Craciun (OSS)
> > ; m...@kernel.org; j...@solid-run.com; Pankaj
> > Bansal ; Makarand Pawagi
> > ; Calvin Johnson ;
> > Varun Sethi ; Cristi Sovaiala ;
> > stuart.yo...@arm.com; jeremy.lin...@arm.com; j...@8bytes.org;
> > t...@linutronix.de; ja...@lakedaemon.net
> > Subject: [EXT] Re: [RFC PATCH 1/4] bus: fsl-mc: add custom .dma_configure
> > implementation
> > 
> > Caution: EXT Email
> > 
> > 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()).
> > 
> 
> That would help.
> 
> > Would that be enough to enable IORT "normal" mappings in the MC bus named
> > components ?
> > 
> 
> But still the question remain unanswered that how we are going to represent 
> MC? As Platform device with single ID mapping flag?

No, "normal" mappings, that's what I wrote above and it is not a
platform device it is a named component in ACPI/IORT terms.

Thanks,
Lorenzo
___
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-04-14 Thread Lorenzo Pieralisi
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 ?

Thanks,
Lorenzo
___
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 Lorenzo Pieralisi
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 - the streamid are injected directly here
bypassing OF/IORT bindings translations altogether. Am I reading this
code correctly ?

Thanks,
Lorenzo

> + 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 v5 3/7] PCI: Introduce pci_real_dma_dev()

2020-01-23 Thread Lorenzo Pieralisi
On Wed, Jan 22, 2020 at 03:12:59PM -0600, Bjorn Helgaas wrote:
> On Tue, Jan 21, 2020 at 06:37:47AM -0700, Jon Derrick wrote:
> > The current DMA alias implementation requires the aliased device be on
> > the same PCI bus as the requester ID. This introduces an arch-specific
> > mechanism to point to another PCI device when doing mapping and
> > PCI DMA alias search. The default case returns the actual device.
> > 
> > CC: Christoph Hellwig 
> > Signed-off-by: Jon Derrick 
> 
> Acked-by: Bjorn Helgaas 
> 
> Looks like a nice cleanup to me.
> 
> Lorenzo, let me know if you want me to take this.

Hi Bjorn,

I think it makes sense for you to take the series given that
it is mostly core/x86 changes. FWIW I Acked the relevant patch
(6) even though Jon forgot to carry it to v5.

Thanks,
Lorenzo

> >  arch/x86/pci/common.c | 10 ++
> >  drivers/pci/pci.c | 19 ++-
> >  drivers/pci/search.c  |  6 ++
> >  include/linux/pci.h   |  1 +
> >  4 files changed, 35 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
> > index 1e59df0..fe21a5c 100644
> > --- a/arch/x86/pci/common.c
> > +++ b/arch/x86/pci/common.c
> > @@ -736,3 +736,13 @@ int pci_ext_cfg_avail(void)
> > else
> > return 0;
> >  }
> > +
> > +#if IS_ENABLED(CONFIG_VMD)
> > +struct pci_dev *pci_real_dma_dev(struct pci_dev *dev)
> > +{
> > +   if (is_vmd(dev->bus))
> > +   return to_pci_sysdata(dev->bus)->vmd_dev;
> > +
> > +   return dev;
> > +}
> > +#endif
> > diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> > index 581b177..36d24f2 100644
> > --- a/drivers/pci/pci.c
> > +++ b/drivers/pci/pci.c
> > @@ -6048,7 +6048,9 @@ bool pci_devs_are_dma_aliases(struct pci_dev *dev1, 
> > struct pci_dev *dev2)
> > return (dev1->dma_alias_mask &&
> > test_bit(dev2->devfn, dev1->dma_alias_mask)) ||
> >(dev2->dma_alias_mask &&
> > -   test_bit(dev1->devfn, dev2->dma_alias_mask));
> > +   test_bit(dev1->devfn, dev2->dma_alias_mask)) ||
> > +  pci_real_dma_dev(dev1) == dev2 ||
> > +  pci_real_dma_dev(dev2) == dev1;
> >  }
> >  
> >  bool pci_device_is_present(struct pci_dev *pdev)
> > @@ -6072,6 +6074,21 @@ void pci_ignore_hotplug(struct pci_dev *dev)
> >  }
> >  EXPORT_SYMBOL_GPL(pci_ignore_hotplug);
> >  
> > +/**
> > + * pci_real_dma_dev - Get PCI DMA device for PCI device
> > + * @dev: the PCI device that may have a PCI DMA alias
> > + *
> > + * Permits the platform to provide architecture-specific functionality to
> > + * devices needing to alias DMA to another PCI device on another PCI bus. 
> > If
> > + * the PCI device is on the same bus, it is recommended to use
> > + * pci_add_dma_alias(). This is the default implementation. Architecture
> > + * implementations can override this.
> > + */
> > +struct pci_dev __weak *pci_real_dma_dev(struct pci_dev *dev)
> > +{
> > +   return dev;
> > +}
> > +
> >  resource_size_t __weak pcibios_default_alignment(void)
> >  {
> > return 0;
> > diff --git a/drivers/pci/search.c b/drivers/pci/search.c
> > index e4dbdef..2061672 100644
> > --- a/drivers/pci/search.c
> > +++ b/drivers/pci/search.c
> > @@ -32,6 +32,12 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
> > struct pci_bus *bus;
> > int ret;
> >  
> > +   /*
> > +* The device may have an explicit alias requester ID for DMA where the
> > +* requester is on another PCI bus.
> > +*/
> > +   pdev = pci_real_dma_dev(pdev);
> > ret = fn(pdev, pci_dev_id(pdev), data);
> > if (ret)
> > return ret;
> > diff --git a/include/linux/pci.h b/include/linux/pci.h
> > index 930fab2..3840a54 100644
> > --- a/include/linux/pci.h
> > +++ b/include/linux/pci.h
> > @@ -1202,6 +1202,7 @@ u32 pcie_bandwidth_available(struct pci_dev *dev, 
> > struct pci_dev **limiting_dev,
> >  int pci_select_bars(struct pci_dev *dev, unsigned long flags);
> >  bool pci_device_is_present(struct pci_dev *pdev);
> >  void pci_ignore_hotplug(struct pci_dev *dev);
> > +struct pci_dev *pci_real_dma_dev(struct pci_dev *dev);
> >  
> >  int __printf(6, 7) pci_request_irq(struct pci_dev *dev, unsigned int nr,
> > irq_handler_t handler, irq_handler_t thread_fn, void *dev_id,
> > -- 
> > 1.8.3.1
> > 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 0/7] Clean up VMD DMA Map Ops

2020-01-20 Thread Lorenzo Pieralisi
On Sun, Jan 19, 2020 at 11:25:23PM +0100, Christoph Hellwig wrote:
> This series looks good to me (modulo the one minor nitpick which isn't
> all that important):
> 
> Reviewed-by: Christoph Hellwig 

Hi Bjorn,

are you picking this up ? I can merge it too but since it is mostly
x86 changes I reckon you should take it, I acked patch (6) to that
end.

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


Re: [PATCH v4 6/7] PCI: vmd: Stop overriding dma_map_ops

2020-01-20 Thread Lorenzo Pieralisi
On Fri, Jan 17, 2020 at 09:27:28AM -0700, Jon Derrick wrote:
> Devices on the VMD domain use the VMD endpoint's requester ID and have
> been relying on the VMD endpoint's DMA operations. The problem with this
> was that VMD domain devices would use the VMD endpoint's attributes when
> doing DMA and IOMMU mapping. We can be smarter about this by only using
> the VMD endpoint when mapping and providing the correct child device's
> attributes during DMA operations.
> 
> This patch removes the dma_map_ops redirect.
> 
> Signed-off-by: Jon Derrick 
> ---
>  drivers/pci/controller/Kconfig |   1 -
>  drivers/pci/controller/vmd.c   | 150 
> -
>  2 files changed, 151 deletions(-)

Acked-by: Lorenzo Pieralisi 

> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index 918e283..20bf00f 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -239,7 +239,6 @@ config PCIE_TANGO_SMP8759
>  
>  config VMD
>   depends on PCI_MSI && X86_64 && SRCU
> - select X86_DEV_DMA_OPS
>   tristate "Intel Volume Management Device Driver"
>   ---help---
> Adds support for the Intel Volume Management Device (VMD). VMD is a
> diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
> index d67ad56..fe1acb0 100644
> --- a/drivers/pci/controller/vmd.c
> +++ b/drivers/pci/controller/vmd.c
> @@ -98,9 +98,6 @@ struct vmd_dev {
>   struct irq_domain   *irq_domain;
>   struct pci_bus  *bus;
>   u8  busn_start;
> -
> - struct dma_map_ops  dma_ops;
> - struct dma_domain   dma_domain;
>  };
>  
>  static inline struct vmd_dev *vmd_from_bus(struct pci_bus *bus)
> @@ -295,151 +292,6 @@ static void vmd_set_desc(msi_alloc_info_t *arg, struct 
> msi_desc *desc)
>   .chip   = _msi_controller,
>  };
>  
> -/*
> - * VMD replaces the requester ID with its own.  DMA mappings for devices in a
> - * VMD domain need to be mapped for the VMD, not the device requiring
> - * the mapping.
> - */
> -static struct device *to_vmd_dev(struct device *dev)
> -{
> - struct pci_dev *pdev = to_pci_dev(dev);
> - struct vmd_dev *vmd = vmd_from_bus(pdev->bus);
> -
> - return >dev->dev;
> -}
> -
> -static void *vmd_alloc(struct device *dev, size_t size, dma_addr_t *addr,
> -gfp_t flag, unsigned long attrs)
> -{
> - return dma_alloc_attrs(to_vmd_dev(dev), size, addr, flag, attrs);
> -}
> -
> -static void vmd_free(struct device *dev, size_t size, void *vaddr,
> -  dma_addr_t addr, unsigned long attrs)
> -{
> - return dma_free_attrs(to_vmd_dev(dev), size, vaddr, addr, attrs);
> -}
> -
> -static int vmd_mmap(struct device *dev, struct vm_area_struct *vma,
> - void *cpu_addr, dma_addr_t addr, size_t size,
> - unsigned long attrs)
> -{
> - return dma_mmap_attrs(to_vmd_dev(dev), vma, cpu_addr, addr, size,
> - attrs);
> -}
> -
> -static int vmd_get_sgtable(struct device *dev, struct sg_table *sgt,
> -void *cpu_addr, dma_addr_t addr, size_t size,
> -unsigned long attrs)
> -{
> - return dma_get_sgtable_attrs(to_vmd_dev(dev), sgt, cpu_addr, addr, size,
> - attrs);
> -}
> -
> -static dma_addr_t vmd_map_page(struct device *dev, struct page *page,
> -unsigned long offset, size_t size,
> -enum dma_data_direction dir,
> -unsigned long attrs)
> -{
> - return dma_map_page_attrs(to_vmd_dev(dev), page, offset, size, dir,
> - attrs);
> -}
> -
> -static void vmd_unmap_page(struct device *dev, dma_addr_t addr, size_t size,
> -enum dma_data_direction dir, unsigned long attrs)
> -{
> - dma_unmap_page_attrs(to_vmd_dev(dev), addr, size, dir, attrs);
> -}
> -
> -static int vmd_map_sg(struct device *dev, struct scatterlist *sg, int nents,
> -   enum dma_data_direction dir, unsigned long attrs)
> -{
> - return dma_map_sg_attrs(to_vmd_dev(dev), sg, nents, dir, attrs);
> -}
> -
> -static void vmd_unmap_sg(struct device *dev, struct scatterlist *sg, int 
> nents,
> -  enum dma_data_direction dir, unsigned long attrs)
> -{
> - dma_unmap_sg_attrs(to_vmd_dev(dev), sg, nents, dir, attrs);
> -}
> -
> -static void vmd_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
> - size_t size, enum dma_data_direction dir)
> -{
> -  

Re: [PATCH v3 0/5] Clean up VMD DMA Map Ops

2020-01-13 Thread Lorenzo Pieralisi
On Mon, Jan 13, 2020 at 12:01:13PM -0600, Bjorn Helgaas wrote:
> On Mon, Jan 13, 2020 at 05:13:38PM +, Derrick, Jonathan wrote:
> > On Mon, 2020-01-13 at 12:08 +, Lorenzo Pieralisi wrote:
> > > On Fri, Jan 10, 2020 at 10:21:08AM -0700, Jon Derrick wrote:
> > > > v2 Set: 
> > > > https://lore.kernel.org/linux-iommu/1578580256-3483-1-git-send-email-jonathan.derr...@intel.com/T/#t
> > > > v1 Set: 
> > > > https://lore.kernel.org/linux-iommu/20200107134125.gd30...@8bytes.org/T/#t
> > > > 
> > > > VMD currently works with VT-d enabled by pointing DMA and IOMMU actions 
> > > > at the
> > > > VMD endpoint. The problem with this approach is that the VMD endpoint's
> > > > device-specific attributes, such as the DMA Mask Bits, are used instead.
> > > > 
> > > > This set cleans up VMD by removing the override that redirects DMA map
> > > > operations to the VMD endpoint. Instead it introduces a new DMA alias 
> > > > mechanism
> > > > into the existing DMA alias infrastructure.
> > > > 
> > > > v1 added a pointer in struct pci_dev that pointed to the DMA alias' 
> > > > struct
> > > > pci_dev and did the necessary DMA alias and IOMMU modifications.
> > > > 
> > > > v2 introduced a new weak function to reference the 'Direct DMA Alias', 
> > > > and
> > > > removed the need to add a pointer in struct device or pci_dev. Weak 
> > > > functions
> > > > are generally frowned upon when it's a single architecture 
> > > > implementation, so I
> > > > am open to alternatives.
> > > > 
> > > > v3 references the pci_dev rather than the struct device for the PCI
> > > > 'Direct DMA Alias' (pci_direct_dma_alias()). This revision also allows
> > > > pci_for_each_dma_alias() to call any DMA aliases for the Direct DMA 
> > > > alias
> > > > device, though I don't expect the VMD endpoint to need intra-bus DMA 
> > > > aliases.
> > > > 
> > > > Changes from v2:
> > > > Uses struct pci_dev for PCI Device 'Direct DMA aliasing' 
> > > > (pci_direct_dma_alias)
> > > > Allows pci_for_each_dma_alias to iterate over the alias mask of the 
> > > > 'Direct DMA alias'
> > > > 
> > > > Changes from v1:
> > > > Removed 1/5 & 2/5 misc fix patches that were merged
> > > > Uses Christoph's staging/cleanup patches
> > > > Introduce weak function rather than including pointer in struct device 
> > > > or pci_dev.
> > > > 
> > > > Based on Joerg's next:
> > > > https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git/
> > > > 
> > > > Jon Derrick (5):
> > > >   x86/pci: Add a to_pci_sysdata helper
> > > >   x86/PCI: Expose VMD's PCI Device in pci_sysdata
> > > >   PCI: Introduce pci_direct_dma_alias()
> > > >   PCI: vmd: Stop overriding dma_map_ops
> > > >   x86/pci: Remove X86_DEV_DMA_OPS
> > > > 
> > > >  arch/x86/Kconfig   |   3 -
> > > >  arch/x86/include/asm/device.h  |  10 ---
> > > >  arch/x86/include/asm/pci.h |  31 -
> > > >  arch/x86/pci/common.c  |  45 ++--
> > > >  drivers/iommu/intel-iommu.c|  18 +++--
> > > >  drivers/pci/controller/Kconfig |   1 -
> > > >  drivers/pci/controller/vmd.c   | 152 
> > > > +
> > > >  drivers/pci/pci.c  |  19 +-
> > > >  drivers/pci/search.c   |   7 ++
> > > >  include/linux/pci.h|   1 +
> > > >  10 files changed, 61 insertions(+), 226 deletions(-)
> > > 
> > > Jon, Christoph,
> > > 
> > > AFAICS this series supersedes/overrides:
> > > 
> > > https://patchwork.kernel.org/patch/4831/
> > > 
> > > Please let me know if that's correct, actually I was waiting to
> > > see consensus on the patch above but if this series supersedes
> > > it I would drop it from the PCI review queue.
> > > 
> > > Thanks,
> > > Lorenzo
> > 
> > It does supercede it (with Christoph's blessing). By the way, I have
> > been basing on Joerg's repo  due to the v1/RFC IOMMU modifcations. As
> > there's more pci work at this point, should I base it on Bjorn's repo
> > instead?
> 
> In general if I'm going to apply something, I prefer it based on my
> "master" branch unless there's a reason to the contrary.  I think
> Lorenzo works pretty much the same way.
> 
> Lorenzo will probably handle this series, but I applied it
> experimentally to check out the brace thing, and it applied fine to my
> "master" branch.  So I think everything's fine as-is.

I think it is mostly x86+core PCI code, VMD code is mostly deletions
so I think you can take it, let me know, I can ACK the VMD changes
straight away.

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


Re: [PATCH v3 0/5] Clean up VMD DMA Map Ops

2020-01-13 Thread Lorenzo Pieralisi
On Fri, Jan 10, 2020 at 10:21:08AM -0700, Jon Derrick wrote:
> v2 Set: 
> https://lore.kernel.org/linux-iommu/1578580256-3483-1-git-send-email-jonathan.derr...@intel.com/T/#t
> v1 Set: 
> https://lore.kernel.org/linux-iommu/20200107134125.gd30...@8bytes.org/T/#t
> 
> VMD currently works with VT-d enabled by pointing DMA and IOMMU actions at the
> VMD endpoint. The problem with this approach is that the VMD endpoint's
> device-specific attributes, such as the DMA Mask Bits, are used instead.
> 
> This set cleans up VMD by removing the override that redirects DMA map
> operations to the VMD endpoint. Instead it introduces a new DMA alias 
> mechanism
> into the existing DMA alias infrastructure.
> 
> v1 added a pointer in struct pci_dev that pointed to the DMA alias' struct
> pci_dev and did the necessary DMA alias and IOMMU modifications.
> 
> v2 introduced a new weak function to reference the 'Direct DMA Alias', and
> removed the need to add a pointer in struct device or pci_dev. Weak functions
> are generally frowned upon when it's a single architecture implementation, so 
> I
> am open to alternatives.
> 
> v3 references the pci_dev rather than the struct device for the PCI
> 'Direct DMA Alias' (pci_direct_dma_alias()). This revision also allows
> pci_for_each_dma_alias() to call any DMA aliases for the Direct DMA alias
> device, though I don't expect the VMD endpoint to need intra-bus DMA aliases.
> 
> Changes from v2:
> Uses struct pci_dev for PCI Device 'Direct DMA aliasing' 
> (pci_direct_dma_alias)
> Allows pci_for_each_dma_alias to iterate over the alias mask of the 'Direct 
> DMA alias'
> 
> Changes from v1:
> Removed 1/5 & 2/5 misc fix patches that were merged
> Uses Christoph's staging/cleanup patches
> Introduce weak function rather than including pointer in struct device or 
> pci_dev.
> 
> Based on Joerg's next:
> https://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git/
> 
> Jon Derrick (5):
>   x86/pci: Add a to_pci_sysdata helper
>   x86/PCI: Expose VMD's PCI Device in pci_sysdata
>   PCI: Introduce pci_direct_dma_alias()
>   PCI: vmd: Stop overriding dma_map_ops
>   x86/pci: Remove X86_DEV_DMA_OPS
> 
>  arch/x86/Kconfig   |   3 -
>  arch/x86/include/asm/device.h  |  10 ---
>  arch/x86/include/asm/pci.h |  31 -
>  arch/x86/pci/common.c  |  45 ++--
>  drivers/iommu/intel-iommu.c|  18 +++--
>  drivers/pci/controller/Kconfig |   1 -
>  drivers/pci/controller/vmd.c   | 152 
> +
>  drivers/pci/pci.c  |  19 +-
>  drivers/pci/search.c   |   7 ++
>  include/linux/pci.h|   1 +
>  10 files changed, 61 insertions(+), 226 deletions(-)

Jon, Christoph,

AFAICS this series supersedes/overrides:

https://patchwork.kernel.org/patch/4831/

Please let me know if that's correct, actually I was waiting to
see consensus on the patch above but if this series supersedes
it I would drop it from the PCI review queue.

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


Re: [PATCH] iommu/arm-smmu: support SMMU module probing from the IORT

2019-11-25 Thread Lorenzo Pieralisi
On Fri, Nov 22, 2019 at 06:41:25PM +0100, Ard Biesheuvel wrote:
> Add support for SMMU drivers built as modules to the ACPI/IORT device
> probing path, by deferring the probe of the master if the SMMU driver is
> known to exist but has not been loaded yet. Given that the IORT code
> registers a platform device for each SMMU that it discovers, we can
> easily trigger the udev based autoloading of the SMMU drivers by making
> the platform device identifier part of the module alias.
> 
> Signed-off-by: Ard Biesheuvel 
> ---
>  drivers/acpi/arm64/iort.c   | 4 ++--
>  drivers/iommu/arm-smmu-v3.c | 1 +
>  drivers/iommu/arm-smmu.c| 1 +
>  3 files changed, 4 insertions(+), 2 deletions(-)

I think it is best if Will picks this up and add it to the
series that modularize the SMMU drivers:

Acked-by: Lorenzo Pieralisi 

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 5a7551d060f2..a696457a9b11 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -850,9 +850,9 @@ static inline bool iort_iommu_driver_enabled(u8 type)
>  {
>   switch (type) {
>   case ACPI_IORT_NODE_SMMU_V3:
> - return IS_BUILTIN(CONFIG_ARM_SMMU_V3);
> + return IS_ENABLED(CONFIG_ARM_SMMU_V3);
>   case ACPI_IORT_NODE_SMMU:
> - return IS_BUILTIN(CONFIG_ARM_SMMU);
> + return IS_ENABLED(CONFIG_ARM_SMMU);
>   default:
>   pr_warn("IORT node type %u does not describe an SMMU\n", type);
>   return false;
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 7669beafc493..bf6a1e8eb9b0 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -3733,4 +3733,5 @@ module_platform_driver(arm_smmu_driver);
>  
>  MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
>  MODULE_AUTHOR("Will Deacon ");
> +MODULE_ALIAS("platform:arm-smmu-v3");
>  MODULE_LICENSE("GPL v2");
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index d55acc48aee3..db5106b0955b 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -2292,4 +2292,5 @@ module_platform_driver(arm_smmu_driver);
>  
>  MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
>  MODULE_AUTHOR("Will Deacon ");
> +MODULE_ALIAS("platform:arm-smmu");
>  MODULE_LICENSE("GPL v2");
> -- 
> 2.20.1
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 0/7] iommu: Permit modular builds of ARM SMMU[v3] drivers

2019-11-04 Thread Lorenzo Pieralisi
On Fri, Nov 01, 2019 at 02:26:05PM -0700, Saravana Kannan wrote:
> On Fri, Nov 1, 2019 at 5:28 AM Lorenzo Pieralisi
>  wrote:
> >
> > On Fri, Nov 01, 2019 at 12:41:48PM +0100, Jean-Philippe Brucker wrote:
> >
> > [...]
> >
> > > > > I'm also wondering about ACPI support.
> > > >
> > > > I'd love to add ACPI support too, but I have zero knowledge of ACPI.
> > > > I'd be happy to help anyone who wants to add ACPI support that allows
> > > > ACPI to add device links.
> > >
> > > It's not as generic as device-tree, each vendor has their own table to
> > > describe the IOMMU topology. I don't see a nice way to transpose the
> > > add_links() callback there. Links need to be created either in a common
> > > path (iommu_probe_device()) or in the APCI IORT driver.
> >
> > We can create a generic stub that calls into respective firmware
> > handling paths (eg iort_dma_setup() in acpi_dma_configure()).
> >
> > There are three arches booting with ACPI so stubbing it out in
> > specific firmware handlers is not such a big deal, less generic
> > sure, but not catastrophically bad.
> 
> Ok, good to know.
> 
> > Obviously this works for IOMMU masters links
> 
> It's unclear to me what you are referring to here and it's throwing me
> off on the rest of the email.
> 
> Did you mean to say "IOMMU master's links"? As in the bus masters
> whose accesses go through IOMMUs? And "links" as in device links?
> 
> OR
> 
> Do you mean device links from bus master devices to IOMMUs here?

I meant associating endpoints devices to the IOMMU they are connected
to.

In DT you do it through "iommus", "iommu-map" properties, in ACPI
it is arch specific, doable nonetheless through ACPI (IORT on ARM)
static tables data.

> > - for resources
> > dependencies (eg power domains) it deserves some thought, keeping in
> > mind that IOMMUs are static table entries in ACPI and not device objects
> > so they are not even capable of expressing eg power resources and
> > suchlike.
> 
> If you can reword this sentence for me with more context or split it
> into separate sentences, I'd appreciate that very much. I'd help me
> understand this better and allow me to try to help out.

In ACPI (at least on ARM but on x86 I suspect that's the same story with
the DMAR table) an SMMU is presented in FW as an entry in a static
table (eg IORT on ARM). I noticed that your patch series takes into
account for instance eg clock dependencies in DT; this way the OS knows
the clock(s) the SMMU depends on to be activated.

In ACPI there is not a notion of "clock" (hopefully - unless someone
sneaked that in using _DSD properties) but rather every device in the
ACPI namespace (which is part of tables containing code that needs the
ACPI interpreter to be used such as SSDT/DSDT - it is AML code) has ACPI
objects describing power resources (ie ACPI specification 6.3, 7.2).

The SMMU, since it is not itself an ACPI object in the ACPI namespace
but rather an entry in a static ACPI table (IORT on ARM), can't have
PowerResource object in it which means that at the moment there is no
way you can detect a dependency on other power resources to be ON to
build the device links you require to sort out the probe dependencies,
which I *assume* that's the reason why you require to detect
clock dependencies in DT.

Maybe it is not even needed at all but in case it is I was giving
a heads-up to say that clocks (or rather an all encompassing "power
resource" dependency) dependencies in ACPI to build an SMMU as
a module are not straightforward and most certainly will require
firmware specifications updates.

*Hopefully* in the short term all you need to detect is how endpoint
devices are connected to an IOMMU and build device links to describe
that probe dependency, if we need to throw power management into
the picture there is more work to be done.

I hope that's clearer, if it is not please let me know and I will
try to be more precise.

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


Re: [PATCH 0/7] iommu: Permit modular builds of ARM SMMU[v3] drivers

2019-11-01 Thread Lorenzo Pieralisi
On Fri, Nov 01, 2019 at 12:41:48PM +0100, Jean-Philippe Brucker wrote:

[...]

> > > I'm also wondering about ACPI support.
> > 
> > I'd love to add ACPI support too, but I have zero knowledge of ACPI.
> > I'd be happy to help anyone who wants to add ACPI support that allows
> > ACPI to add device links.
> 
> It's not as generic as device-tree, each vendor has their own table to
> describe the IOMMU topology. I don't see a nice way to transpose the
> add_links() callback there. Links need to be created either in a common
> path (iommu_probe_device()) or in the APCI IORT driver.

We can create a generic stub that calls into respective firmware
handling paths (eg iort_dma_setup() in acpi_dma_configure()).

There are three arches booting with ACPI so stubbing it out in
specific firmware handlers is not such a big deal, less generic
sure, but not catastrophically bad.

Obviously this works for IOMMU masters links - for resources
dependencies (eg power domains) it deserves some thought, keeping in
mind that IOMMUs are static table entries in ACPI and not device objects
so they are not even capable of expressing eg power resources and
suchlike.

Long story short: adding IOMMU masters links in ACPI should be
reasonably simple, everything else requires further thought.

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


VFIO/IOMMU/PCI Linux Plumbers 2019 MC - Call for Topics

2019-07-10 Thread Lorenzo Pieralisi
Hi,

following the official LPC19 VFIO/IOMMU/PCI microconference acceptance
notification:

https://www.linuxplumbersconf.org/blog/2019/vfio-iommu-pci-microconference-accepted-into-2019-linux-plumbers-conference/

I am sending out a call for sessions proposals open to all developers
interested/involved in Linux kernel VFIO/IOMMU/PCI development.

The LPC19 blog page provides a list of topics that we put forward for
the microconference submission:

https://www.linuxplumbersconf.org/blog/2019/vfio-iommu-pci-microconference-accepted-into-2019-linux-plumbers-conference/

The blog page is there to provide a list of topics that we considered key
and it should not be considered final, actually it is a starting point to
define a possible schedule structure.

Session proposals for the LPC19 VFIO/IOMMU/PCI microconference are warmly
encouraged and can be submitted here through the common Call for Proposals
LPC19 web page (please choose VFIO/IOMMU/PCI MC topic in the "Track" submenu):

https://www.linuxplumbersconf.org/event/4/abstracts/

Anyone involved in VFIO/IOMMU/PCI kernel development, if you wish to add
sessions and attend the microconference consider yourself welcome, for any
questions just reply to this thread or drop me a line.

Looking forward to meeting you all in Lisbon for this interesting track !

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


Re: [PATCH v1 0/3] PCIe and AR8151 on APQ8098/MSM8998

2019-06-11 Thread Lorenzo Pieralisi
On Thu, Mar 28, 2019 at 05:59:48PM +0100, Marc Gonzalez wrote:
> Hello everyone,
> 
> After a lot of poking, I am finally able to use the AR8151 ethernet on the 
> APQ8098 board.
> The magic bits are the iommu-map prop and the PCIE20_PARF_BDF_TRANSLATE_N 
> setup.
> 
> The WIP thread is archived here:
> https://marc.info/?t=15505953924=1=2
> 
> 
> Marc Gonzalez (3):
>   PCI: qcom: Setup PCIE20_PARF_BDF_TRANSLATE_N
>   arm64: dts: qcom: msm8998: Add PCIe SMMU node
>   arm64: dts: qcom: msm8998: Add PCIe PHY and RC nodes
> 
>  arch/arm64/boot/dts/qcom/msm8998.dtsi  | 93 ++
>  drivers/pci/controller/dwc/pcie-qcom.c |  4 ++
>  2 files changed, 97 insertions(+)

Marc,

what's the plan with this series ? Please let me know so that
I can handle it correctly in the PCI patch queue, I am not
sure by reading comments it has evolved much since posting.

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


Re: [PATCH v6 3/3] PCI: iproc: Add sorted dma ranges resource entries to host bridge

2019-05-07 Thread Lorenzo Pieralisi
On Mon, May 06, 2019 at 04:12:08PM -0500, Bjorn Helgaas wrote:
> On Fri, May 03, 2019 at 07:35:34PM +0530, Srinath Mannam wrote:
> > The IPROC host controller allows only a subset of physical address space
> > as target of inbound PCI memory transactions addresses.
> > 
> > PCIe devices memory transactions targeting memory regions that
> > are not allowed for inbound transactions in the host controller
> > are rejected by the host controller and cannot reach the upstream
> > buses.
> > 
> > Firmware device tree description defines the DMA ranges that are
> > addressable by devices DMA transactions; parse the device tree
> > dma-ranges property and add its ranges to the PCI host bridge dma_ranges
> > list; the iova_reserve_pci_windows() call in the driver will reserve the
> > IOVA address ranges that are not addressable (ie memory holes in the
> > dma-ranges set) so that they are not allocated to PCI devices for DMA
> > transfers.
> > 
> > All allowed address ranges are listed in dma-ranges DT parameter.
> > 
> > Example:
> > 
> > dma-ranges = < \
> >   0x4300 0x00 0x8000 0x00 0x8000 0x00 0x8000 \
> >   0x4300 0x08 0x 0x08 0x 0x08 0x \
> >   0x4300 0x80 0x 0x80 0x 0x40 0x>
> > 
> > In the above example of dma-ranges, memory address from
> > 
> > 0x0 - 0x8000,
> > 0x1 - 0x8,
> > 0x10 - 0x80 and
> > 0x100 - 0x.
> > 
> > are not allowed to be used as inbound addresses.
> > 
> > Based-on-patch-by: Oza Pawandeep 
> > Signed-off-by: Srinath Mannam 
> > [lorenzo.pieral...@arm.com: updated commit log]
> > Signed-off-by: Lorenzo Pieralisi 
> > Reviewed-by: Oza Pawandeep 
> > Reviewed-by: Eric Auger 
> > ---
> >  drivers/pci/controller/pcie-iproc.c | 44 
> > -
> >  1 file changed, 43 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/pci/controller/pcie-iproc.c 
> > b/drivers/pci/controller/pcie-iproc.c
> > index c20fd6b..94ba5c0 100644
> > --- a/drivers/pci/controller/pcie-iproc.c
> > +++ b/drivers/pci/controller/pcie-iproc.c
> > @@ -1146,11 +1146,43 @@ static int iproc_pcie_setup_ib(struct iproc_pcie 
> > *pcie,
> > return ret;
> >  }
> >  
> > +static int
> > +iproc_pcie_add_dma_range(struct device *dev, struct list_head *resources,
> > +struct of_pci_range *range)
> 
> Just FYI, I cherry-picked these commits from Lorenzo's branch to fix
> the formatting of this prototype to match the rest of the file, e.g.:

Thank you, I noticed too but I forgot to update it before merging
v6 from the list.

Thanks,
Lorenzo

> >  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
> > ...
> >  static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v6 0/3] PCIe Host request to reserve IOVA

2019-05-03 Thread Lorenzo Pieralisi
On Fri, May 03, 2019 at 07:35:31PM +0530, Srinath Mannam wrote:
> This patch set will reserve IOVA addresses for DMA memory holes.
> 
> The IPROC host controller allows only a few ranges of physical address
> as inbound PCI addresses which are listed through dma-ranges DT property.
> Added dma_ranges list field of PCI host bridge structure to hold these
> allowed inbound address ranges in sorted order.
> 
> Process this list and reserve IOVA addresses that are not present in its
> resource entries (ie DMA memory holes) to prevent allocating IOVA
> addresses that cannot be allocated as inbound addresses.
> 
> This patch set is based on Linux-5.1-rc3.
> 
> Changes from v5:
>   - Addressed Robin Murphy, Lorenzo review comments.
> - Error handling in dma ranges list processing.
> - Used commit messages given by Lorenzo to all patches.
> 
> Changes from v4:
>   - Addressed Bjorn, Robin Murphy and Auger Eric review comments.
> - Commit message modification.
> - Change DMA_BIT_MASK to "~(dma_addr_t)0".
> 
> Changes from v3:
>   - Addressed Robin Murphy review comments.
> - pcie-iproc: parse dma-ranges and make sorted resource list.
> - dma-iommu: process list and reserve gaps between entries
> 
> Changes from v2:
>   - Patch set rebased to Linux-5.0-rc2
> 
> Changes from v1:
>   - Addressed Oza review comments.
> 
> Srinath Mannam (3):
>   PCI: Add dma_ranges window list
>   iommu/dma: Reserve IOVA for PCIe inaccessible DMA address
>   PCI: iproc: Add sorted dma ranges resource entries to host bridge
> 
>  drivers/iommu/dma-iommu.c   | 35 ++---
>  drivers/pci/controller/pcie-iproc.c | 44 
> -
>  drivers/pci/probe.c |  3 +++
>  include/linux/pci.h |  1 +
>  4 files changed, 79 insertions(+), 4 deletions(-)

I have applied the series to pci/iova-dma-ranges, targeting v5.2,
thanks.

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


Re: [PATCH v5 2/3] iommu/dma: Reserve IOVA for PCIe inaccessible DMA address

2019-05-03 Thread Lorenzo Pieralisi
On Fri, May 03, 2019 at 10:53:23AM +0530, Srinath Mannam wrote:
> Hi Robin, Lorenzo,
> 
> Thanks for review and guidance.
> AFAIU, conclusion of discussion is, to return error if dma-ranges list
> is not sorted.
> 
> So that, Can I send a new patch with below change to return error if
> dma-ranges list is not sorted?

You can but I can't guarantee it will make it for v5.2.

We will have to move the DT parsing and dma list ranges creation
to core code anyway because I want this to work by construction,
so even if we manage to make v5.2 you will have to do that.

I pushed a branch out:

not-to-merge/iova-dma-ranges

where I rewrote all commit logs and I am not willing to do it again
so please use them for your v6 posting if you manage to make it
today.

Lorenzo

> -static void iova_reserve_pci_windows(struct pci_dev *dev,
> +static int iova_reserve_pci_windows(struct pci_dev *dev,
> struct iova_domain *iovad)
>  {
> struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
> @@ -227,11 +227,15 @@ static void iova_reserve_pci_windows(struct pci_dev 
> *dev,
> resource_list_for_each_entry(window, >dma_ranges) {
> end = window->res->start - window->offset;
>  resv_iova:
> -   if (end - start) {
> +   if (end > start) {
> lo = iova_pfn(iovad, start);
> hi = iova_pfn(iovad, end);
> reserve_iova(iovad, lo, hi);
> +   } else {
> +   dev_err(>dev, "Unsorted dma_ranges list\n");
> +   return -EINVAL;
> }
> +
> 
> Please provide your inputs if any more changes required. Thank you,
> 
> Regards,
> Srinath.
> 
> On Thu, May 2, 2019 at 7:45 PM Robin Murphy  wrote:
> >
> > On 02/05/2019 14:06, Lorenzo Pieralisi wrote:
> > > On Thu, May 02, 2019 at 12:27:02PM +0100, Robin Murphy wrote:
> > >> Hi Lorenzo,
> > >>
> > >> On 02/05/2019 12:01, Lorenzo Pieralisi wrote:
> > >>> On Wed, May 01, 2019 at 11:06:25PM +0530, Srinath Mannam wrote:
> > >>>> dma_ranges field of PCI host bridge structure has resource entries in
> > >>>> sorted order of address range given through dma-ranges DT property. 
> > >>>> This
> > >>>> list is the accessible DMA address range. So that this resource list 
> > >>>> will
> > >>>> be processed and reserve IOVA address to the inaccessible address 
> > >>>> holes in
> > >>>> the list.
> > >>>>
> > >>>> This method is similar to PCI IO resources address ranges reserving in
> > >>>> IOMMU for each EP connected to host bridge.
> > >>>>
> > >>>> Signed-off-by: Srinath Mannam 
> > >>>> Based-on-patch-by: Oza Pawandeep 
> > >>>> Reviewed-by: Oza Pawandeep 
> > >>>> Acked-by: Robin Murphy 
> > >>>> ---
> > >>>>drivers/iommu/dma-iommu.c | 19 +++
> > >>>>1 file changed, 19 insertions(+)
> > >>>>
> > >>>> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> > >>>> index 77aabe6..da94844 100644
> > >>>> --- a/drivers/iommu/dma-iommu.c
> > >>>> +++ b/drivers/iommu/dma-iommu.c
> > >>>> @@ -212,6 +212,7 @@ static void iova_reserve_pci_windows(struct 
> > >>>> pci_dev *dev,
> > >>>>struct pci_host_bridge *bridge = 
> > >>>> pci_find_host_bridge(dev->bus);
> > >>>>struct resource_entry *window;
> > >>>>unsigned long lo, hi;
> > >>>> +  phys_addr_t start = 0, end;
> > >>>>resource_list_for_each_entry(window, >windows) {
> > >>>>if (resource_type(window->res) != IORESOURCE_MEM)
> > >>>> @@ -221,6 +222,24 @@ static void iova_reserve_pci_windows(struct 
> > >>>> pci_dev *dev,
> > >>>>hi = iova_pfn(iovad, window->res->end - 
> > >>>> window->offset);
> > >>>>reserve_iova(iovad, lo, hi);
> > >>>>}
> > >>>> +
> > >>>> +  /* Get reserved DMA windows from host bridge */
> > >>>> +  resource_list_for_each_entry(window, >dma_ranges) {
> > >>>
> > >&g

Re: [PATCH v5 2/3] iommu/dma: Reserve IOVA for PCIe inaccessible DMA address

2019-05-02 Thread Lorenzo Pieralisi
On Thu, May 02, 2019 at 12:27:02PM +0100, Robin Murphy wrote:
> Hi Lorenzo,
> 
> On 02/05/2019 12:01, Lorenzo Pieralisi wrote:
> > On Wed, May 01, 2019 at 11:06:25PM +0530, Srinath Mannam wrote:
> > > dma_ranges field of PCI host bridge structure has resource entries in
> > > sorted order of address range given through dma-ranges DT property. This
> > > list is the accessible DMA address range. So that this resource list will
> > > be processed and reserve IOVA address to the inaccessible address holes in
> > > the list.
> > > 
> > > This method is similar to PCI IO resources address ranges reserving in
> > > IOMMU for each EP connected to host bridge.
> > > 
> > > Signed-off-by: Srinath Mannam 
> > > Based-on-patch-by: Oza Pawandeep 
> > > Reviewed-by: Oza Pawandeep 
> > > Acked-by: Robin Murphy 
> > > ---
> > >   drivers/iommu/dma-iommu.c | 19 +++
> > >   1 file changed, 19 insertions(+)
> > > 
> > > diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> > > index 77aabe6..da94844 100644
> > > --- a/drivers/iommu/dma-iommu.c
> > > +++ b/drivers/iommu/dma-iommu.c
> > > @@ -212,6 +212,7 @@ static void iova_reserve_pci_windows(struct pci_dev 
> > > *dev,
> > >   struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
> > >   struct resource_entry *window;
> > >   unsigned long lo, hi;
> > > + phys_addr_t start = 0, end;
> > >   resource_list_for_each_entry(window, >windows) {
> > >   if (resource_type(window->res) != IORESOURCE_MEM)
> > > @@ -221,6 +222,24 @@ static void iova_reserve_pci_windows(struct pci_dev 
> > > *dev,
> > >   hi = iova_pfn(iovad, window->res->end - window->offset);
> > >   reserve_iova(iovad, lo, hi);
> > >   }
> > > +
> > > + /* Get reserved DMA windows from host bridge */
> > > + resource_list_for_each_entry(window, >dma_ranges) {
> > 
> > If this list is not sorted it seems to me the logic in this loop is
> > broken and you can't rely on callers to sort it because it is not a
> > written requirement and it is not enforced (you know because you
> > wrote the code but any other developer is not supposed to guess
> > it).
> > 
> > Can't we rewrite this loop so that it does not rely on list
> > entries order ?
> 
> The original idea was that callers should be required to provide a sorted
> list, since it keeps things nice and simple...

I understand, if it was self-contained in driver code that would be fine
but in core code with possible multiple consumers this must be
documented/enforced, somehow.

> > I won't merge this series unless you sort it, no pun intended.
> > 
> > Lorenzo
> > 
> > > + end = window->res->start - window->offset;
> 
> ...so would you consider it sufficient to add
> 
>   if (end < start)
>   dev_err(...);

We should also revert any IOVA reservation we did prior to this
error, right ?

Anyway, I think it is best to ensure it *is* sorted.

> here, plus commenting the definition of pci_host_bridge::dma_ranges
> that it must be sorted in ascending order?

I don't think that commenting dma_ranges would help much, I am more
keen on making it work by construction.

> [ I guess it might even make sense to factor out the parsing and list
> construction from patch #3 into an of_pci core helper from the beginning, so
> that there's even less chance of another driver reimplementing it
> incorrectly in future. ]

This makes sense IMO and I would like to take this approach if you
don't mind.

Either this or we move the whole IOVA reservation and dma-ranges
parsing into PCI IProc.

> Failing that, although I do prefer the "simple by construction"
> approach, I'd have no objection to just sticking a list_sort() call in
> here instead, if you'd rather it be entirely bulletproof.

I think what you outline above is a sensible way forward - if we
miss the merge window so be it.

Thanks,
Lorenzo

> Robin.
> 
> > > +resv_iova:
> > > + if (end - start) {
> > > + lo = iova_pfn(iovad, start);
> > > + hi = iova_pfn(iovad, end);
> > > + reserve_iova(iovad, lo, hi);
> > > + }
> > > + start = window->res->end - window->offset + 1;
> > > + /* If window is last entry */
> > > + if (window->node.next == >dma_ranges &&
> > > + end != ~(dma_addr_t)0) {
> > > + end = ~(dma_addr_t)0;
> > > + goto resv_iova;
> > > + }
> > > + }
> > >   }
> > >   static int iova_reserve_iommu_regions(struct device *dev,
> > > -- 
> > > 2.7.4
> > > 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 2/3] iommu/dma: Reserve IOVA for PCIe inaccessible DMA address

2019-05-02 Thread Lorenzo Pieralisi
On Wed, May 01, 2019 at 11:06:25PM +0530, Srinath Mannam wrote:
> dma_ranges field of PCI host bridge structure has resource entries in
> sorted order of address range given through dma-ranges DT property. This
> list is the accessible DMA address range. So that this resource list will
> be processed and reserve IOVA address to the inaccessible address holes in
> the list.
> 
> This method is similar to PCI IO resources address ranges reserving in
> IOMMU for each EP connected to host bridge.
> 
> Signed-off-by: Srinath Mannam 
> Based-on-patch-by: Oza Pawandeep 
> Reviewed-by: Oza Pawandeep 
> Acked-by: Robin Murphy 
> ---
>  drivers/iommu/dma-iommu.c | 19 +++
>  1 file changed, 19 insertions(+)
> 
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 77aabe6..da94844 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -212,6 +212,7 @@ static void iova_reserve_pci_windows(struct pci_dev *dev,
>   struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
>   struct resource_entry *window;
>   unsigned long lo, hi;
> + phys_addr_t start = 0, end;
>  
>   resource_list_for_each_entry(window, >windows) {
>   if (resource_type(window->res) != IORESOURCE_MEM)
> @@ -221,6 +222,24 @@ static void iova_reserve_pci_windows(struct pci_dev *dev,
>   hi = iova_pfn(iovad, window->res->end - window->offset);
>   reserve_iova(iovad, lo, hi);
>   }
> +
> + /* Get reserved DMA windows from host bridge */
> + resource_list_for_each_entry(window, >dma_ranges) {

If this list is not sorted it seems to me the logic in this loop is
broken and you can't rely on callers to sort it because it is not a
written requirement and it is not enforced (you know because you
wrote the code but any other developer is not supposed to guess
it).

Can't we rewrite this loop so that it does not rely on list
entries order ?

I won't merge this series unless you sort it, no pun intended.

Lorenzo

> + end = window->res->start - window->offset;
> +resv_iova:
> + if (end - start) {
> + lo = iova_pfn(iovad, start);
> + hi = iova_pfn(iovad, end);
> + reserve_iova(iovad, lo, hi);
> + }
> + start = window->res->end - window->offset + 1;
> + /* If window is last entry */
> + if (window->node.next == >dma_ranges &&
> + end != ~(dma_addr_t)0) {
> + end = ~(dma_addr_t)0;
> + goto resv_iova;
> + }
> + }
>  }
>  
>  static int iova_reserve_iommu_regions(struct device *dev,
> -- 
> 2.7.4
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 3/3] PCI: iproc: Add sorted dma ranges resource entries to host bridge

2019-05-01 Thread Lorenzo Pieralisi
On Fri, Apr 12, 2019 at 08:43:35AM +0530, Srinath Mannam wrote:
> IPROC host has the limitation that it can use only those address ranges
> given by dma-ranges property as inbound address. So that the memory
> address holes in dma-ranges should be reserved to allocate as DMA address.
> 
> Inbound address of host accessed by PCIe devices will not be translated
> before it comes to IOMMU or directly to PE.

What does that mean "directly to PE" ?

IIUC all you want to say is that there is no entity translating
PCI memory transactions addresses before they it the PCI host
controller inbound regions address decoder.

> But the limitation of this host is, access to few address ranges are
> ignored. So that IOVA ranges for these address ranges have to be
> reserved.
> 
> All allowed address ranges are listed in dma-ranges DT parameter. These
> address ranges are converted as resource entries and listed in sorted
> order add added to dma_ranges list of PCI host bridge structure.
> 
> Ex:
> dma-ranges = < \
>   0x4300 0x00 0x8000 0x00 0x8000 0x00 0x8000 \
>   0x4300 0x08 0x 0x08 0x 0x08 0x \
>   0x4300 0x80 0x 0x80 0x 0x40 0x>
> 
> In the above example of dma-ranges, memory address from
> 0x0 - 0x8000,
> 0x1 - 0x8,
> 0x10 - 0x80 and
> 0x100 - 0x.
> are not allowed to use as inbound addresses.
> 
> Signed-off-by: Srinath Mannam 
> Based-on-patch-by: Oza Pawandeep 
> Reviewed-by: Oza Pawandeep 
> ---
>  drivers/pci/controller/pcie-iproc.c | 44 
> -
>  1 file changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/pci/controller/pcie-iproc.c 
> b/drivers/pci/controller/pcie-iproc.c
> index c20fd6b..94ba5c0 100644
> --- a/drivers/pci/controller/pcie-iproc.c
> +++ b/drivers/pci/controller/pcie-iproc.c
> @@ -1146,11 +1146,43 @@ static int iproc_pcie_setup_ib(struct iproc_pcie 
> *pcie,
>   return ret;
>  }
>  
> +static int
> +iproc_pcie_add_dma_range(struct device *dev, struct list_head *resources,
> +  struct of_pci_range *range)
> +{
> + struct resource *res;
> + struct resource_entry *entry, *tmp;
> + struct list_head *head = resources;
> +
> + res = devm_kzalloc(dev, sizeof(struct resource), GFP_KERNEL);
> + if (!res)
> + return -ENOMEM;
> +
> + resource_list_for_each_entry(tmp, resources) {
> + if (tmp->res->start < range->cpu_addr)
> + head = >node;
> + }
> +
> + res->start = range->cpu_addr;
> + res->end = res->start + range->size - 1;
> +
> + entry = resource_list_create_entry(res, 0);
> + if (!entry)
> + return -ENOMEM;
> +
> + entry->offset = res->start - range->cpu_addr;
> + resource_list_add(entry, head);
> +
> + return 0;
> +}
> +
>  static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
>  {
> + struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
>   struct of_pci_range range;
>   struct of_pci_range_parser parser;
>   int ret;
> + LIST_HEAD(resources);
>  
>   /* Get the dma-ranges from DT */
>   ret = of_pci_dma_range_parser_init(, pcie->dev->of_node);
> @@ -1158,13 +1190,23 @@ static int iproc_pcie_map_dma_ranges(struct 
> iproc_pcie *pcie)
>   return ret;
>  
>   for_each_of_pci_range(, ) {
> + ret = iproc_pcie_add_dma_range(pcie->dev,
> +,
> +);
> + if (ret)
> + goto out;
>   /* Each range entry corresponds to an inbound mapping region */
>   ret = iproc_pcie_setup_ib(pcie, , IPROC_PCIE_IB_MAP_MEM);
>   if (ret)
> - return ret;
> + goto out;
>   }
>  
> + list_splice_init(, >dma_ranges);
> +
>   return 0;
> +out:
> + pci_free_resource_list();
> + return ret;
>  }
>  
>  static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
> -- 
> 2.7.4
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 0/3] PCIe Host request to reserve IOVA

2019-05-01 Thread Lorenzo Pieralisi
On Wed, May 01, 2019 at 02:20:56PM +0100, Robin Murphy wrote:
> On 2019-05-01 1:55 pm, Bjorn Helgaas wrote:
> > On Wed, May 01, 2019 at 12:30:38PM +0100, Lorenzo Pieralisi wrote:
> > > On Fri, Apr 12, 2019 at 08:43:32AM +0530, Srinath Mannam wrote:
> > > > Few SOCs have limitation that their PCIe host can't allow few inbound
> > > > address ranges. Allowed inbound address ranges are listed in dma-ranges
> > > > DT property and this address ranges are required to do IOVA mapping.
> > > > Remaining address ranges have to be reserved in IOVA mapping.
> > > > 
> > > > PCIe Host driver of those SOCs has to list resource entries of allowed
> > > > address ranges given in dma-ranges DT property in sorted order. This
> > > > sorted list of resources will be processed and reserve IOVA address for
> > > > inaccessible address holes while initializing IOMMU domain.
> > > > 
> > > > This patch set is based on Linux-5.0-rc2.
> > > > 
> > > > Changes from v3:
> > > >- Addressed Robin Murphy review comments.
> > > >  - pcie-iproc: parse dma-ranges and make sorted resource list.
> > > >  - dma-iommu: process list and reserve gaps between entries
> > > > 
> > > > Changes from v2:
> > > >- Patch set rebased to Linux-5.0-rc2
> > > > 
> > > > Changes from v1:
> > > >- Addressed Oza review comments.
> > > > 
> > > > Srinath Mannam (3):
> > > >PCI: Add dma_ranges window list
> > > >iommu/dma: Reserve IOVA for PCIe inaccessible DMA address
> > > >PCI: iproc: Add sorted dma ranges resource entries to host bridge
> > > > 
> > > >   drivers/iommu/dma-iommu.c   | 19 
> > > >   drivers/pci/controller/pcie-iproc.c | 44 
> > > > -
> > > >   drivers/pci/probe.c |  3 +++
> > > >   include/linux/pci.h |  1 +
> > > >   4 files changed, 66 insertions(+), 1 deletion(-)
> > > 
> > > Bjorn, Joerg,
> > > 
> > > this series should not affect anything in the mainline other than its
> > > consumer (ie patch 3); if that's the case should we consider it for v5.2
> > > and if yes how are we going to merge it ?
> > 
> > I acked the first one
> > 
> > Robin reviewed the second
> > (https://lore.kernel.org/lkml/e6c812d6-0cad-4cfd-defd-d7ec427a6...@arm.com)
> > (though I do agree with his comment about DMA_BIT_MASK()), Joerg was OK
> > with it if Robin was
> > (https://lore.kernel.org/lkml/20190423145721.gh29...@8bytes.org).
> > 
> > Eric reviewed the third (and pointed out a typo).
> > 
> > My Kconfiggery never got fully answered -- it looks to me as though it's
> > possible to build pcie-iproc without the DMA hole support, and I thought
> > the whole point of this series was to deal with those holes
> > (https://lore.kernel.org/lkml/20190418234241.gf126...@google.com).  I would
> > have expected something like making pcie-iproc depend on IOMMU_SUPPORT.
> > But Srinath didn't respond to that, so maybe it's not an issue and it
> > should only affect pcie-iproc anyway.
> 
> Hmm, I'm sure I had at least half-written a reply on that point, but I
> can't seem to find it now... anyway, the gist is that these inbound
> windows are generally set up to cover the physical address ranges of DRAM
> and anything else that devices might need to DMA to. Thus if you're not
> using an IOMMU, the fact that devices can't access the gaps in between
> doesn't matter because there won't be anything there anyway; it only
> needs mitigating if you do use an IOMMU and start giving arbitrary
> non-physical addresses to the endpoint.

So basically there is no strict IOMMU_SUPPORT dependency.

> > So bottom line, I'm fine with merging it for v5.2.  Do you want to merge
> > it, Lorenzo, or ...?
> 
> This doesn't look like it will conflict with the other DMA ops and MSI
> mapping changes currently in-flight for iommu-dma, so I have no
> objection to it going through the PCI tree for 5.2.

I will update the DMA_BIT_MASK() according to your review and fix the
typo Eric pointed out and push out a branch - we shall see if we can
include it for v5.2.

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


Re: [PATCH v4 0/3] PCIe Host request to reserve IOVA

2019-05-01 Thread Lorenzo Pieralisi
On Fri, Apr 12, 2019 at 08:43:32AM +0530, Srinath Mannam wrote:
> Few SOCs have limitation that their PCIe host can't allow few inbound
> address ranges. Allowed inbound address ranges are listed in dma-ranges
> DT property and this address ranges are required to do IOVA mapping.
> Remaining address ranges have to be reserved in IOVA mapping.
> 
> PCIe Host driver of those SOCs has to list resource entries of allowed
> address ranges given in dma-ranges DT property in sorted order. This
> sorted list of resources will be processed and reserve IOVA address for
> inaccessible address holes while initializing IOMMU domain.
> 
> This patch set is based on Linux-5.0-rc2.
> 
> Changes from v3:
>   - Addressed Robin Murphy review comments.
> - pcie-iproc: parse dma-ranges and make sorted resource list.
> - dma-iommu: process list and reserve gaps between entries
> 
> Changes from v2:
>   - Patch set rebased to Linux-5.0-rc2
> 
> Changes from v1:
>   - Addressed Oza review comments.
> 
> Srinath Mannam (3):
>   PCI: Add dma_ranges window list
>   iommu/dma: Reserve IOVA for PCIe inaccessible DMA address
>   PCI: iproc: Add sorted dma ranges resource entries to host bridge
> 
>  drivers/iommu/dma-iommu.c   | 19 
>  drivers/pci/controller/pcie-iproc.c | 44 
> -
>  drivers/pci/probe.c |  3 +++
>  include/linux/pci.h |  1 +
>  4 files changed, 66 insertions(+), 1 deletion(-)

Bjorn, Joerg,

this series should not affect anything in the mainline other than its
consumer (ie patch 3); if that's the case should we consider it for v5.2
and if yes how are we going to merge it ?

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


Re: [PATCH v3 3/9] ACPI/IORT: Check ATS capability in root complex nodes

2019-04-18 Thread Lorenzo Pieralisi
On Wed, Apr 17, 2019 at 07:24:42PM +0100, Jean-Philippe Brucker wrote:
> Root complex node in IORT has a bit telling whether it supports ATS or
> not. Store this bit in the IOMMU fwspec when setting up a device, so it
> can be accessed later by an IOMMU driver. In the future we'll probably
> want to store this bit at the host bridge or SMMU rather than in each
> endpoint.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/acpi/arm64/iort.c | 11 +++
>  include/linux/iommu.h |  4 
>  2 files changed, 15 insertions(+)

For the IORT portion:

Acked-by: Lorenzo Pieralisi 

> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index e48894e002ba..4000902e57f0 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -1028,6 +1028,14 @@ void iort_dma_setup(struct device *dev, u64 *dma_addr, 
> u64 *dma_size)
>   dev_dbg(dev, "dma_pfn_offset(%#08llx)\n", offset);
>  }
>  
> +static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)
> +{
> + struct acpi_iort_root_complex *pci_rc;
> +
> + pci_rc = (struct acpi_iort_root_complex *)node->node_data;
> + return pci_rc->ats_attribute & ACPI_IORT_ATS_SUPPORTED;
> +}
> +
>  /**
>   * iort_iommu_configure - Set-up IOMMU configuration for a device.
>   *
> @@ -1063,6 +1071,9 @@ const struct iommu_ops *iort_iommu_configure(struct 
> device *dev)
>   info.node = node;
>   err = pci_for_each_dma_alias(to_pci_dev(dev),
>iort_pci_iommu_init, );
> +
> + if (!err && iort_pci_rc_supports_ats(node))
> + dev->iommu_fwspec->flags |= IOMMU_FWSPEC_PCI_RC_ATS;
>   } else {
>   int i = 0;
>  
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index 480921dfbadf..51ab006d348e 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -446,6 +446,7 @@ struct iommu_fwspec {
>   const struct iommu_ops  *ops;
>   struct fwnode_handle*iommu_fwnode;
>   void*iommu_priv;
> + u32 flags;
>   unsigned intnum_ids;
>   u32 ids[1];
>  };
> @@ -458,6 +459,9 @@ struct iommu_sva {
>   const struct iommu_sva_ops  *ops;
>  };
>  
> +/* ATS is supported */
> +#define IOMMU_FWSPEC_PCI_RC_ATS  (1 << 0)
> +
>  int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
> const struct iommu_ops *ops);
>  void iommu_fwspec_free(struct device *dev);
> -- 
> 2.21.0
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 2/2] PCI: iproc: Add PCIe 32bit outbound memory configuration

2019-02-12 Thread Lorenzo Pieralisi
On Tue, Feb 05, 2019 at 10:27:01AM +0530, Srinath Mannam wrote:
> Add configuration to support IPROC PCIe host controller outbound memory
> window mapping with SOC address range inside 4GB boundary, which is 32 bit
> AXI address.

I do not understand what this means, explain it to me and rewrite the
commit log accordingly.

What does this solve ? Why do we need this patch or rephrased, what
is missing in the current driver ?

> Signed-off-by: Srinath Mannam 
> Signed-off-by: Abhishek Shah 
> Signed-off-by: Ray Jui 
> Reviewed-by: Scott Branden 
> Reviewed-by: Vikram Prakash 

Review tags should be given on public mailing lists, these ones seem
to come from non-public review cycles in which case you must drop
them.

>  drivers/pci/controller/pcie-iproc.c | 21 +++--
>  1 file changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-iproc.c 
> b/drivers/pci/controller/pcie-iproc.c
> index b882255..080f142 100644
> --- a/drivers/pci/controller/pcie-iproc.c
> +++ b/drivers/pci/controller/pcie-iproc.c
> @@ -955,8 +955,25 @@ static int iproc_pcie_setup_ob(struct iproc_pcie *pcie, 
> u64 axi_addr,
>   resource_size_t window_size =
>   ob_map->window_sizes[size_idx] * SZ_1M;
>  
> - if (size < window_size)
> - continue;
> + /*
> +  * Keep iterating until we reach the last window and
> +  * with the minimal window size at index zero. In this
> +  * case, we take a compromise by mapping it using the
> +  * minimum window size that can be supported

See above, I do not understand clearly what this means.

Lorenzo

> +  */
> + if (size < window_size) {
> + if (size_idx > 0 || window_idx > 0)
> + continue;
> +
> + /*
> +  * For the corner case of reaching the minimal
> +  * window size that can be supported on the
> +  * last window
> +  */
> + axi_addr = ALIGN_DOWN(axi_addr, window_size);
> + pci_addr = ALIGN_DOWN(pci_addr, window_size);
> + size = window_size;
> + }
>  
>   if (!IS_ALIGNED(axi_addr, window_size) ||
>   !IS_ALIGNED(pci_addr, window_size)) {
> -- 
> 2.7.4
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2 1/2] PCI: iproc: Add CRS check in config read

2019-02-12 Thread Lorenzo Pieralisi
On Tue, Feb 05, 2019 at 10:27:00AM +0530, Srinath Mannam wrote:
> In the current implementation, config read output data 0x0001 is
> assumed as CRS completion. But sometimes 0x0001 can be a valid data.
> 
> IPROC PCIe host controller has a register to show config read request
> status flags like SC, UR, CRS and CA. So that extra check is added to
> confirm the CRS using status flags before reissue config read.
> 
> Signed-off-by: Srinath Mannam 
> Reviewed-by: Ray Jui 
> ---
>  drivers/pci/controller/pcie-iproc.c | 23 +--
>  1 file changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/pcie-iproc.c 
> b/drivers/pci/controller/pcie-iproc.c
> index c20fd6b..b882255 100644
> --- a/drivers/pci/controller/pcie-iproc.c
> +++ b/drivers/pci/controller/pcie-iproc.c
> @@ -60,6 +60,10 @@
>  #define APB_ERR_EN_SHIFT 0
>  #define APB_ERR_EN   BIT(APB_ERR_EN_SHIFT)
>  
> +#define CFG_RD_SUCCESS   0
> +#define CFG_RD_UR1
> +#define CFG_RD_CRS   2
> +#define CFG_RD_CA3
>  #define CFG_RETRY_STATUS 0x0001
>  #define CFG_RETRY_STATUS_TIMEOUT_US  50 /* 500 milliseconds */
>  
> @@ -289,6 +293,9 @@ enum iproc_pcie_reg {
>   IPROC_PCIE_IARR4,
>   IPROC_PCIE_IMAP4,
>  
> + /* config read status */
> + IPROC_PCIE_CFG_RD_STATUS,
> +
>   /* link status */
>   IPROC_PCIE_LINK_STATUS,
>  
> @@ -350,6 +357,7 @@ static const u16 iproc_pcie_reg_paxb_v2[] = {
>   [IPROC_PCIE_IMAP3]  = 0xe08,
>   [IPROC_PCIE_IARR4]  = 0xe68,
>   [IPROC_PCIE_IMAP4]  = 0xe70,
> + [IPROC_PCIE_CFG_RD_STATUS]  = 0xee0,

So, with the *current* code, on controllers that does not support this
register you won't be able to get any HW whose config space register
value reads 0x0001 to work, is that correct ?

Lorenzo

>   [IPROC_PCIE_LINK_STATUS]= 0xf0c,
>   [IPROC_PCIE_APB_ERR_EN] = 0xf40,
>  };
> @@ -474,10 +482,12 @@ static void __iomem *iproc_pcie_map_ep_cfg_reg(struct 
> iproc_pcie *pcie,
>   return (pcie->base + offset);
>  }
>  
> -static unsigned int iproc_pcie_cfg_retry(void __iomem *cfg_data_p)
> +static unsigned int iproc_pcie_cfg_retry(struct iproc_pcie *pcie,
> +  void __iomem *cfg_data_p)
>  {
>   int timeout = CFG_RETRY_STATUS_TIMEOUT_US;
>   unsigned int data;
> + u32 status;
>  
>   /*
>* As per PCIe spec r3.1, sec 2.3.2, CRS Software Visibility only
> @@ -498,6 +508,15 @@ static unsigned int iproc_pcie_cfg_retry(void __iomem 
> *cfg_data_p)
>*/
>   data = readl(cfg_data_p);
>   while (data == CFG_RETRY_STATUS && timeout--) {
> + /*
> +  * CRS state is set in CFG_RD status register
> +  * This will handle the case where CFG_RETRY_STATUS is
> +  * valid config data.
> +  */
> + status = iproc_pcie_read_reg(pcie, IPROC_PCIE_CFG_RD_STATUS);
> + if (status != CFG_RD_CRS)
> + return data;
> +
>   udelay(1);
>   data = readl(cfg_data_p);
>   }
> @@ -576,7 +595,7 @@ static int iproc_pcie_config_read(struct pci_bus *bus, 
> unsigned int devfn,
>   if (!cfg_data_p)
>   return PCIBIOS_DEVICE_NOT_FOUND;
>  
> - data = iproc_pcie_cfg_retry(cfg_data_p);
> + data = iproc_pcie_cfg_retry(pcie, cfg_data_p);
>  
>   *val = data;
>   if (size <= 2)
> -- 
> 2.7.4
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices

2018-11-21 Thread Lorenzo Pieralisi
On Tue, Nov 20, 2018 at 10:43:35PM +0100, Rafael J. Wysocki wrote:
> On Friday, November 16, 2018 11:57:38 AM CET Lorenzo Pieralisi wrote:
> > On Thu, Nov 15, 2018 at 07:33:54PM +, mario.limoncie...@dell.com wrote:
> > > 
> > > 
> > > > -Original Message-
> > > > From: Mika Westerberg 
> > > > Sent: Thursday, November 15, 2018 1:01 PM
> > > > To: Lorenzo Pieralisi
> > > > Cc: Lukas Wunner; iommu@lists.linux-foundation.org; Joerg Roedel; David
> > > > Woodhouse; Lu Baolu; Ashok Raj; Bjorn Helgaas; Rafael J. Wysocki; Jacob 
> > > > jun Pan;
> > > > Andreas Noever; Michael Jamet; Yehezkel Bernat; Christian Kellner; 
> > > > Limonciello,
> > > > Mario; Anthony Wong; linux-a...@vger.kernel.org; 
> > > > linux-...@vger.kernel.org; linux-
> > > > ker...@vger.kernel.org
> > > > Subject: Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices
> > > > 
> > > > 
> > > > [EXTERNAL EMAIL]
> > > > 
> > > > On Thu, Nov 15, 2018 at 05:46:08PM +, Lorenzo Pieralisi wrote:
> > > > > Do you really need to parse it if the dev->is_thunderbolt check is 
> > > > > enough ?
> > > > 
> > > > Yes, we need to parse it one way or another. dev->is_thunderbolt is
> > > > based on heuristics which do not apply anymore when the thing gets
> > > > integrated in the SoC.
> > > > 
> > > > The _DSD is there already (on existing systems) and is being used by
> > > > Windows so I don't understand why we cannot take advantage of it? Every
> > > > new system with Thunderbolt ports will have it.
> > 
> > We have different opinions on this, there is no point in me reiterating
> > it over and over, I am against the approach taken to solve this problem
> > first in defining the bindings outside the ACPI specifications and
> > second by acquiescing to what has been done so that it will be done
> > over and over again.
> 
> Arguably, however, we are on the receiving end of things here and even if
> we don't use this binding, that won't buy us anything (but it will introduce
> a fair amount of disappointment among both users and OEMs).
> 
> If Windows uses it, then systems will ship with it regardless of what Linux
> does with it, so your "acquiescing to what has been done" argument leads to
> nowhere in this particular case.  It's just a matter of whether or not
> Linux will provide the same level of functionality as Windows with respect
> to this and IMO it would be impractical to refuse to do that for purely
> formal reasons.
> 
> > I will raise the point in the appropriate forum, it is up to Bjorn
> > and Rafael to decide on this patch.
> 
> For the record, my opinion is that there's a little choice on whether
> or not to use this extra information that firmware is willing to give
> us.  It could be defined in a better way and so on, but since it is in
> use anyway, we really have nothing to gain by refusing to use it.

AFAIK PCI firmware bindings should go into PCI firmware specifications,
not Microsoft webpages.

If we deviate from this model there is no way to tell whether that extra
information is right or wrong, it is not necessarily about this patch,
it is about changing the way these bindings are deployed in future
systems.

> Now, where the handling of it belongs to is a separate matter that should be
> decided on its own.

I think that the way these bindings were deployed is wrong, I agree this
is not the right forum to discuss that though. What you will do with
this patch is not my call anyway, I just expressed my opinion.

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


Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices

2018-11-16 Thread Lorenzo Pieralisi
On Thu, Nov 15, 2018 at 07:33:54PM +, mario.limoncie...@dell.com wrote:
> 
> 
> > -Original Message-
> > From: Mika Westerberg 
> > Sent: Thursday, November 15, 2018 1:01 PM
> > To: Lorenzo Pieralisi
> > Cc: Lukas Wunner; iommu@lists.linux-foundation.org; Joerg Roedel; David
> > Woodhouse; Lu Baolu; Ashok Raj; Bjorn Helgaas; Rafael J. Wysocki; Jacob jun 
> > Pan;
> > Andreas Noever; Michael Jamet; Yehezkel Bernat; Christian Kellner; 
> > Limonciello,
> > Mario; Anthony Wong; linux-a...@vger.kernel.org; linux-...@vger.kernel.org; 
> > linux-
> > ker...@vger.kernel.org
> > Subject: Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices
> > 
> > 
> > [EXTERNAL EMAIL]
> > 
> > On Thu, Nov 15, 2018 at 05:46:08PM +, Lorenzo Pieralisi wrote:
> > > Do you really need to parse it if the dev->is_thunderbolt check is enough 
> > > ?
> > 
> > Yes, we need to parse it one way or another. dev->is_thunderbolt is
> > based on heuristics which do not apply anymore when the thing gets
> > integrated in the SoC.
> > 
> > The _DSD is there already (on existing systems) and is being used by
> > Windows so I don't understand why we cannot take advantage of it? Every
> > new system with Thunderbolt ports will have it.

We have different opinions on this, there is no point in me reiterating
it over and over, I am against the approach taken to solve this problem
first in defining the bindings outside the ACPI specifications and
second by acquiescing to what has been done so that it will be done
over and over again.

I will raise the point in the appropriate forum, it is up to Bjorn
and Rafael to decide on this patch.

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


Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices

2018-11-15 Thread Lorenzo Pieralisi
On Thu, Nov 15, 2018 at 02:16:27PM +0200, Mika Westerberg wrote:
> On Thu, Nov 15, 2018 at 01:07:36PM +0100, Lukas Wunner wrote:
> > On Thu, Nov 15, 2018 at 01:37:37PM +0200, Mika Westerberg wrote:
> > > On Thu, Nov 15, 2018 at 11:13:56AM +, Lorenzo Pieralisi wrote:
> > > > I have strong objections to the way these bindings have been forced upon
> > > > everybody; if that's the way *generic* ACPI bindings are specified I
> > > > wonder why there still exists an ACPI specification and related working
> > > > group.
> > > > 
> > > > I personally (but that's Bjorn and Rafael choice) think that this is
> > > > not a change that belongs in PCI core, ACPI bindings are ill-defined
> > > > and device tree bindings are non-existing.
> > > 
> > > Any idea where should I put it then? These systems are already out there
> > > and we need to support them one way or another.
> > 
> > I suppose those are all Thunderbolt, so could be handled by the
> > existing ->is_thunderbolt bit?
> > 
> > It was said in this thread that ->is_external is more generic in
> > that it could also be used on PCIe slots, however that use case
> > doesn't appear to lend itself to the "plug in while laptop owner
> > is getting coffee" attack.  To access PCIe slots on a server you
> > normally need access to a data center.  On a desktop, you usually
> > have to open the case, by which time the coffee may already have
> > been fetched.  So frankly the binding seems a bit over-engineered
> > to me and yet another thing that BIOS writers may get wrong.
> 
> I would not say it should include PCIe slots but there are other cables
> that carry PCIe and I was thinking we could make it to support those as
> well.
> 
> I have no problem using is_thunderbolt here, though if we don't want to
> support non-Thunderbolt external devices this way.
> 
> However, the question here is more that where I should put the _DSD
> parsing code if it is not suitable to be placed inside PCI/ACPI core as
> I've done in this patch? ;-)

Do you really need to parse it if the dev->is_thunderbolt check is enough ?

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


Re: [PATCH 1/4] PCI / ACPI: Identify external PCI devices

2018-11-15 Thread Lorenzo Pieralisi
On Thu, Nov 15, 2018 at 12:22:39PM +0200, Mika Westerberg wrote:
> On Tue, Nov 13, 2018 at 11:45:36AM +0000, Lorenzo Pieralisi wrote:
> > On Tue, Nov 13, 2018 at 01:27:00PM +0200, Mika Westerberg wrote:
> > 
> > [...]
> > 
> > > > To be frank the concept (and Microsoft _DSD bindings) seems a bit vague
> > > > and not thoroughly defined and I would question its detection at
> > > > PCI/ACPI core level, I would hope this can be clarified at ACPI
> > > > specification level, at least.
> > > 
> > > I guess that is the way they envision to use _DSD. Instead of having
> > > single UUID that covers all properties (like what we have with device
> > > properties) they have one UUID per property "class". I certainly hope we
> > > don't need to keep extending prp_guids[] array each time they invent
> > > another "class" of properties.
> > 
> > It is even worse than that. This is a unilateral/obscure change that
> > won't be part of ACPI specifications (I guess it was easier to add a
> > UUID than add this to the ACPI specifications through the AWSG) but it
> > is still supposed to be applicable to ACPI PCI bindings on any
> > platforms/arches; this way of adding bindings does not work and it
> > has to be rectified.
> 
> I agree.
> 
> For the existing property "classes" such as the one here I don't think
> we can do anything. There are systems already with these included in
> their ACPI tables.
> 
> I wonder if you have any objections regarding this patch?

I have strong objections to the way these bindings have been forced upon
everybody; if that's the way *generic* ACPI bindings are specified I
wonder why there still exists an ACPI specification and related working
group.

I personally (but that's Bjorn and Rafael choice) think that this is
not a change that belongs in PCI core, ACPI bindings are ill-defined
and device tree bindings are non-existing.

At the very least Microsoft should be asked to publish and discuss
these bindings within the ACPI and UEFI forums.

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


  1   2   3   4   >