Re: [PATCH v12 0/9] ACPI/IORT: Support for IORT RMR node
[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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
[+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
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
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
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
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()
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
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
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
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()
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()
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
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
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
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
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
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
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
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
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()
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
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
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
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()
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
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
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
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
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
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
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()
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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()
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
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
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
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
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
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()
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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