Message ID | 20170801104913.71912-2-shameerali.kolothum.thodi@huawei.com |
---|---|
State | Superseded |
Headers | show |
Series | iommu/smmu-v3: Workaround for hisilicon 161010801 erratum(reserve HW MSI) | expand |
On 01/08/17 11:49, Shameer Kolothum wrote: > On some platforms ITS address regions have to be excluded from normal > IOVA allocation in that they are detected and decoded in a HW specific > way by system components and so they cannot be considered normal IOVA > address space. > > Add an helper function that retrieves ITS address regions through IORT > device <-> ITS mappings and reserves it so that these regions will not > be translated by IOMMU and will be excluded from IOVA allocations. I've just realised that we no longer seem to have a check that ensures the regions are only reserved on platforms that need it - if not, then we're going to break everything else that does have an ITS behind SMMU translation as expected. It feels like IORT should know enough to be able to make that decision internally, but if not (or if it would be hideous to do so), then I guess my idea for patch #2 was a bust and we probably do need to go back to calling directly from the SMMU driver based on the SMMU model. Robin. > Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com> > [lorenzo.pieralisi@arm.com: updated commit log/added comments] > Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> > --- > drivers/acpi/arm64/iort.c | 95 ++++++++++++++++++++++++++++++++++++++-- > drivers/irqchip/irq-gic-v3-its.c | 3 +- > include/linux/acpi_iort.h | 7 ++- > 3 files changed, 100 insertions(+), 5 deletions(-) > > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c > index a3215ee..86b5a51 100644 > --- a/drivers/acpi/arm64/iort.c > +++ b/drivers/acpi/arm64/iort.c > @@ -39,6 +39,7 @@ > struct iort_its_msi_chip { > struct list_head list; > struct fwnode_handle *fw_node; > + phys_addr_t base_addr; > u32 translation_id; > }; > > @@ -136,14 +137,16 @@ typedef acpi_status (*iort_find_node_callback) > static DEFINE_SPINLOCK(iort_msi_chip_lock); > > /** > - * iort_register_domain_token() - register domain token and related ITS ID > - * to the list from where we can get it back later on. > + * iort_register_domain_token() - register domain token along with related > + * ITS ID and base address to the list from where we can get it back later on. > * @trans_id: ITS ID. > + * @base: ITS base address. > * @fw_node: Domain token. > * > * Returns: 0 on success, -ENOMEM if no memory when allocating list element > */ > -int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node) > +int iort_register_domain_token(int trans_id, phys_addr_t base, > + struct fwnode_handle *fw_node) > { > struct iort_its_msi_chip *its_msi_chip; > > @@ -153,6 +156,7 @@ int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node) > > its_msi_chip->fw_node = fw_node; > its_msi_chip->translation_id = trans_id; > + its_msi_chip->base_addr = base; > > spin_lock(&iort_msi_chip_lock); > list_add(&its_msi_chip->list, &iort_msi_chip_list); > @@ -481,6 +485,24 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) > return -ENODEV; > } > > +static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base) > +{ > + struct iort_its_msi_chip *its_msi_chip; > + bool match = false; > + > + spin_lock(&iort_msi_chip_lock); > + list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) { > + if (its_msi_chip->translation_id == its_id) { > + *base = its_msi_chip->base_addr; > + match = true; > + break; > + } > + } > + spin_unlock(&iort_msi_chip_lock); > + > + return match ? 0 : -ENODEV; > +} > + > /** > * iort_dev_find_its_id() - Find the ITS identifier for a device > * @dev: The device. > @@ -639,6 +661,71 @@ int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) > > return err; > } > + > +/** > + * iort_iommu_its_get_resv_regions - Reserved region driver helper > + * @dev: Device from iommu_get_resv_regions() > + * @list: Reserved region list from iommu_get_resv_regions() > + * > + * Returns: Number of reserved regions on success(0 if no associated ITS), > + * appropriate error value otherwise. > + */ > +int iort_iommu_its_get_resv_regions(struct device *dev, struct list_head *head) > +{ > + struct acpi_iort_its_group *its; > + struct acpi_iort_node *node, *its_node = NULL; > + int i, resv = 0; > + > + node = iort_find_dev_node(dev); > + if (!node) > + return -ENODEV; > + > + /* > + * Current logic to reserve ITS regions relies on HW topologies > + * where a given PCI or named component maps its IDs to only one > + * ITS group; if a PCI or named component can map its IDs to > + * different ITS groups through IORT mappings this function has > + * to be reworked to ensure we reserve regions for all ITS groups > + * a given PCI or named component may map IDs to. > + */ > + if (dev_is_pci(dev)) { > + u32 rid; > + > + pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid, &rid); > + its_node = iort_node_map_id(node, rid, NULL, IORT_MSI_TYPE); > + } else { > + for (i = 0; i < node->mapping_count; i++) { > + its_node = iort_node_map_platform_id(node, NULL, > + IORT_MSI_TYPE, i); > + if (its_node) > + break; > + } > + } > + > + if (!its_node) > + return 0; > + > + /* Move to ITS specific data */ > + its = (struct acpi_iort_its_group *)its_node->node_data; > + > + for (i = 0; i < its->its_count; i++) { > + phys_addr_t base; > + > + if (!iort_find_its_base(its->identifiers[i], &base)) { > + int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; > + struct iommu_resv_region *region; > + > + region = iommu_alloc_resv_region(base, SZ_128K, prot, > + IOMMU_RESV_MSI); > + if (region) { > + list_add_tail(®ion->list, head); > + resv++; > + } > + } > + } > + > + return (resv == its->its_count) ? resv : -ENODEV; > +} > #else > static inline > const struct iommu_ops *iort_fwspec_iommu_ops(struct iommu_fwspec *fwspec) > @@ -646,6 +733,8 @@ const struct iommu_ops *iort_fwspec_iommu_ops(struct iommu_fwspec *fwspec) > static inline > int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) > { return 0; } > +int iort_iommu_its_get_resv_regions(struct device *dev, struct list_head *head) > +{ return -ENODEV; } > #endif > > static const struct iommu_ops *iort_iommu_xlate(struct device *dev, > diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c > index 6893287..77322b3 100644 > --- a/drivers/irqchip/irq-gic-v3-its.c > +++ b/drivers/irqchip/irq-gic-v3-its.c > @@ -1928,7 +1928,8 @@ static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header, > return -ENOMEM; > } > > - err = iort_register_domain_token(its_entry->translation_id, dom_handle); > + err = iort_register_domain_token(its_entry->translation_id, res.start, > + dom_handle); > if (err) { > pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n", > &res.start, its_entry->translation_id); > diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h > index 8379d40..d7ed49c 100644 > --- a/include/linux/acpi_iort.h > +++ b/include/linux/acpi_iort.h > @@ -26,7 +26,8 @@ > #define IORT_IRQ_MASK(irq) (irq & 0xffffffffULL) > #define IORT_IRQ_TRIGGER_MASK(irq) ((irq >> 32) & 0xffffffffULL) > > -int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node); > +int iort_register_domain_token(int trans_id, phys_addr_t base, > + struct fwnode_handle *fw_node); > void iort_deregister_domain_token(int trans_id); > struct fwnode_handle *iort_find_domain_token(int trans_id); > #ifdef CONFIG_ACPI_IORT > @@ -38,6 +39,7 @@ > /* IOMMU interface */ > void iort_set_dma_mask(struct device *dev); > const struct iommu_ops *iort_iommu_configure(struct device *dev); > +int iort_iommu_its_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) > @@ -51,6 +53,9 @@ static inline void iort_set_dma_mask(struct device *dev) { } > static inline > const struct iommu_ops *iort_iommu_configure(struct device *dev) > { return NULL; } > +static inline > +int iort_iommu_its_get_resv_regions(struct device *dev, struct list_head *head) > +{ return -ENODEV; } > #endif > > #endif /* __ACPI_IORT_H__ */ > -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> -----Original Message----- > From: Robin Murphy [mailto:robin.murphy@arm.com] > Sent: Friday, August 04, 2017 5:57 PM > To: Shameerali Kolothum Thodi; lorenzo.pieralisi@arm.com; > marc.zyngier@arm.com; sudeep.holla@arm.com; will.deacon@arm.com; > hanjun.guo@linaro.org > Cc: Gabriele Paoloni; John Garry; iommu@lists.linux-foundation.org; linux- > arm-kernel@lists.infradead.org; linux-acpi@vger.kernel.org; > devel@acpica.org; Linuxarm; Wangzhou (B); Guohanjun (Hanjun Guo) > Subject: Re: [PATCH v5 1/2] ACPI/IORT: Add ITS address regions reservation > helper > > On 01/08/17 11:49, Shameer Kolothum wrote: > > On some platforms ITS address regions have to be excluded from normal > > IOVA allocation in that they are detected and decoded in a HW specific > > way by system components and so they cannot be considered normal > IOVA > > address space. > > > > Add an helper function that retrieves ITS address regions through IORT > > device <-> ITS mappings and reserves it so that these regions will not > > be translated by IOMMU and will be excluded from IOVA allocations. > > I've just realised that we no longer seem to have a check that ensures > the regions are only reserved on platforms that need it - if not, then > we're going to break everything else that does have an ITS behind SMMU > translation as expected. Right. I had this doubt, but then my thinking was that we will have the SW_MSI regions for those and will end up using that. But that doesn’t seems to be the case now. > It feels like IORT should know enough to be able to make that decision > internally, but if not (or if it would be hideous to do so), then I > guess my idea for patch #2 was a bust and we probably do need to go back > to calling directly from the SMMU driver based on the SMMU model. It might be possible to do that check inside iort code, but then we have to find the smmu node first and check the model number. I think it will be more cleaner if SMMU driver makes that check and call the iommu_dma_get_msi_resv_regions(). If you are Ok with that I will quickly rework and send out the next version. Thanks, Shameer
On Mon, Aug 07, 2017 at 08:21:40AM +0000, Shameerali Kolothum Thodi wrote: > > > > -----Original Message----- > > From: Robin Murphy [mailto:robin.murphy@arm.com] > > Sent: Friday, August 04, 2017 5:57 PM > > To: Shameerali Kolothum Thodi; lorenzo.pieralisi@arm.com; > > marc.zyngier@arm.com; sudeep.holla@arm.com; will.deacon@arm.com; > > hanjun.guo@linaro.org > > Cc: Gabriele Paoloni; John Garry; iommu@lists.linux-foundation.org; linux- > > arm-kernel@lists.infradead.org; linux-acpi@vger.kernel.org; > > devel@acpica.org; Linuxarm; Wangzhou (B); Guohanjun (Hanjun Guo) > > Subject: Re: [PATCH v5 1/2] ACPI/IORT: Add ITS address regions reservation > > helper > > > > On 01/08/17 11:49, Shameer Kolothum wrote: > > > On some platforms ITS address regions have to be excluded from normal > > > IOVA allocation in that they are detected and decoded in a HW specific > > > way by system components and so they cannot be considered normal > > IOVA > > > address space. > > > > > > Add an helper function that retrieves ITS address regions through IORT > > > device <-> ITS mappings and reserves it so that these regions will not > > > be translated by IOMMU and will be excluded from IOVA allocations. > > > > I've just realised that we no longer seem to have a check that ensures > > the regions are only reserved on platforms that need it - if not, then > > we're going to break everything else that does have an ITS behind SMMU > > translation as expected. > > Right. I had this doubt, but then my thinking was that we will have the SW_MSI > regions for those and will end up using that. But that doesn’t seems > to be the case now. > > > It feels like IORT should know enough to be able to make that decision > > internally, but if not (or if it would be hideous to do so), then I > > guess my idea for patch #2 was a bust and we probably do need to go back > > to calling directly from the SMMU driver based on the SMMU model. > > It might be possible to do that check inside iort code, but then we have to find > the smmu node first and check the model number. I think it will be more > cleaner if SMMU driver makes that check and call the > iommu_dma_get_msi_resv_regions(). +1 on this one - we can do it in IORT but I think it is more logical to have a flag in the SMMU driver (keeping the DT/ACPI fwnode switch in generic IOMMU layer though). Side note I: AFAICS iommu_dma_get_resv_regions() is only used on ARM, if it is not patch 2 would break miserably on arches that do not select IORT - you should rework the return code on !CONFIG_ACPI_IORT configs. Side note II(nit): why not call the function iort_iommu_get_resv_regions() ? Lorenzo > If you are Ok with that I will quickly rework and send out the next version. > > Thanks, > Shameer > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogTG9yZW56byBQaWVyYWxp c2kgW21haWx0bzpsb3JlbnpvLnBpZXJhbGlzaUBhcm0uY29tXQ0KPiBTZW50OiBNb25kYXksIEF1 Z3VzdCAwNywgMjAxNyA2OjA5IFBNDQo+IFRvOiBTaGFtZWVyYWxpIEtvbG90aHVtIFRob2RpDQo+ IENjOiBSb2JpbiBNdXJwaHk7IG1hcmMuenluZ2llckBhcm0uY29tOyBzdWRlZXAuaG9sbGFAYXJt LmNvbTsNCj4gd2lsbC5kZWFjb25AYXJtLmNvbTsgaGFuanVuLmd1b0BsaW5hcm8ub3JnOyBHYWJy aWVsZSBQYW9sb25pOyBKb2huIEdhcnJ5Ow0KPiBMaW51eGFybTsgbGludXgtYWNwaUB2Z2VyLmtl cm5lbC5vcmc7IGlvbW11QGxpc3RzLmxpbnV4LWZvdW5kYXRpb24ub3JnOw0KPiBXYW5nemhvdSAo Qik7IEd1b2hhbmp1biAoSGFuanVuIEd1byk7IGxpbnV4LWFybS0NCj4ga2VybmVsQGxpc3RzLmlu ZnJhZGVhZC5vcmc7IGRldmVsQGFjcGljYS5vcmcNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2NSAx LzJdIEFDUEkvSU9SVDogQWRkIElUUyBhZGRyZXNzIHJlZ2lvbnMgcmVzZXJ2YXRpb24NCj4gaGVs cGVyDQo+IA0KPiBPbiBNb24sIEF1ZyAwNywgMjAxNyBhdCAwODoyMTo0MEFNICswMDAwLCBTaGFt ZWVyYWxpIEtvbG90aHVtIFRob2RpDQo+IHdyb3RlOg0KPiA+DQo+ID4NCj4gPiA+IC0tLS0tT3Jp Z2luYWwgTWVzc2FnZS0tLS0tDQo+ID4gPiBGcm9tOiBSb2JpbiBNdXJwaHkgW21haWx0bzpyb2Jp bi5tdXJwaHlAYXJtLmNvbV0NCj4gPiA+IFNlbnQ6IEZyaWRheSwgQXVndXN0IDA0LCAyMDE3IDU6 NTcgUE0NCj4gPiA+IFRvOiBTaGFtZWVyYWxpIEtvbG90aHVtIFRob2RpOyBsb3JlbnpvLnBpZXJh bGlzaUBhcm0uY29tOw0KPiA+ID4gbWFyYy56eW5naWVyQGFybS5jb207IHN1ZGVlcC5ob2xsYUBh cm0uY29tOyB3aWxsLmRlYWNvbkBhcm0uY29tOw0KPiA+ID4gaGFuanVuLmd1b0BsaW5hcm8ub3Jn DQo+ID4gPiBDYzogR2FicmllbGUgUGFvbG9uaTsgSm9obiBHYXJyeTsgaW9tbXVAbGlzdHMubGlu dXgtZm91bmRhdGlvbi5vcmc7DQo+IGxpbnV4LQ0KPiA+ID4gYXJtLWtlcm5lbEBsaXN0cy5pbmZy YWRlYWQub3JnOyBsaW51eC1hY3BpQHZnZXIua2VybmVsLm9yZzsNCj4gPiA+IGRldmVsQGFjcGlj YS5vcmc7IExpbnV4YXJtOyBXYW5nemhvdSAoQik7IEd1b2hhbmp1biAoSGFuanVuIEd1bykNCj4g PiA+IFN1YmplY3Q6IFJlOiBbUEFUQ0ggdjUgMS8yXSBBQ1BJL0lPUlQ6IEFkZCBJVFMgYWRkcmVz cyByZWdpb25zDQo+IHJlc2VydmF0aW9uDQo+ID4gPiBoZWxwZXINCj4gPiA+DQo+ID4gPiBPbiAw MS8wOC8xNyAxMTo0OSwgU2hhbWVlciBLb2xvdGh1bSB3cm90ZToNCj4gPiA+ID4gT24gc29tZSBw bGF0Zm9ybXMgSVRTIGFkZHJlc3MgcmVnaW9ucyBoYXZlIHRvIGJlIGV4Y2x1ZGVkIGZyb20NCj4g bm9ybWFsDQo+ID4gPiA+IElPVkEgYWxsb2NhdGlvbiBpbiB0aGF0IHRoZXkgYXJlIGRldGVjdGVk IGFuZCBkZWNvZGVkIGluIGEgSFcgc3BlY2lmaWMNCj4gPiA+ID4gd2F5IGJ5IHN5c3RlbSBjb21w b25lbnRzIGFuZCBzbyB0aGV5IGNhbm5vdCBiZSBjb25zaWRlcmVkIG5vcm1hbA0KPiA+ID4gSU9W QQ0KPiA+ID4gPiBhZGRyZXNzIHNwYWNlLg0KPiA+ID4gPg0KPiA+ID4gPiBBZGQgYW4gaGVscGVy IGZ1bmN0aW9uIHRoYXQgcmV0cmlldmVzIElUUyBhZGRyZXNzIHJlZ2lvbnMgdGhyb3VnaCBJT1JU DQo+ID4gPiA+IGRldmljZSA8LT4gSVRTIG1hcHBpbmdzIGFuZCByZXNlcnZlcyBpdCBzbyB0aGF0 IHRoZXNlIHJlZ2lvbnMgd2lsbCBub3QNCj4gPiA+ID4gYmUgdHJhbnNsYXRlZCBieSBJT01NVSBh bmQgd2lsbCBiZSBleGNsdWRlZCBmcm9tIElPVkEgYWxsb2NhdGlvbnMuDQo+ID4gPg0KPiA+ID4g SSd2ZSBqdXN0IHJlYWxpc2VkIHRoYXQgd2Ugbm8gbG9uZ2VyIHNlZW0gdG8gaGF2ZSBhIGNoZWNr IHRoYXQgZW5zdXJlcw0KPiA+ID4gdGhlIHJlZ2lvbnMgYXJlIG9ubHkgcmVzZXJ2ZWQgb24gcGxh dGZvcm1zIHRoYXQgbmVlZCBpdCAtIGlmIG5vdCwgdGhlbg0KPiA+ID4gd2UncmUgZ29pbmcgdG8g YnJlYWsgZXZlcnl0aGluZyBlbHNlIHRoYXQgZG9lcyBoYXZlIGFuIElUUyBiZWhpbmQgU01NVQ0K PiA+ID4gdHJhbnNsYXRpb24gYXMgZXhwZWN0ZWQuDQo+ID4NCj4gPiBSaWdodC4gSSBoYWQgdGhp cyBkb3VidCwgYnV0IHRoZW4gbXkgdGhpbmtpbmcgd2FzIHRoYXQgd2Ugd2lsbCBoYXZlIHRoZQ0K PiBTV19NU0kNCj4gPiByZWdpb25zIGZvciB0aG9zZSBhbmQgd2lsbCBlbmQgdXAgIHVzaW5nIHRo YXQuIEJ1dCB0aGF0IGRvZXNu4oCZdCBzZWVtcw0KPiA+IHRvIGJlIHRoZSBjYXNlIG5vdy4NCj4g Pg0KPiA+ID4gSXQgZmVlbHMgbGlrZSBJT1JUIHNob3VsZCBrbm93IGVub3VnaCB0byBiZSBhYmxl IHRvIG1ha2UgdGhhdCBkZWNpc2lvbg0KPiA+ID4gaW50ZXJuYWxseSwgYnV0IGlmIG5vdCAob3Ig aWYgaXQgd291bGQgYmUgaGlkZW91cyB0byBkbyBzbyksIHRoZW4gSQ0KPiA+ID4gZ3Vlc3MgbXkg aWRlYSBmb3IgcGF0Y2ggIzIgd2FzIGEgYnVzdCBhbmQgd2UgcHJvYmFibHkgZG8gbmVlZCB0byBn bw0KPiBiYWNrDQo+ID4gPiB0byBjYWxsaW5nIGRpcmVjdGx5IGZyb20gdGhlIFNNTVUgZHJpdmVy IGJhc2VkIG9uIHRoZSBTTU1VIG1vZGVsLg0KPiA+DQo+ID4gSXQgbWlnaHQgYmUgcG9zc2libGUg dG8gZG8gdGhhdCBjaGVjayBpbnNpZGUgaW9ydCBjb2RlLCBidXQgdGhlbiB3ZSBoYXZlIHRvDQo+ IGZpbmQNCj4gPiB0aGUgIHNtbXUgbm9kZSBmaXJzdCBhbmQgY2hlY2sgdGhlIG1vZGVsIG51bWJl ci4gSSB0aGluayBpdCB3aWxsIGJlIG1vcmUNCj4gPiBjbGVhbmVyIGlmIFNNTVUgZHJpdmVyIG1h a2VzIHRoYXQgY2hlY2sgYW5kIGNhbGwgdGhlDQo+ID4gaW9tbXVfZG1hX2dldF9tc2lfcmVzdl9y ZWdpb25zKCkuDQo+IA0KPiArMSBvbiB0aGlzIG9uZSAtIHdlIGNhbiBkbyBpdCBpbiBJT1JUIGJ1 dCBJIHRoaW5rIGl0IGlzIG1vcmUgbG9naWNhbA0KPiB0byBoYXZlIGEgZmxhZyBpbiB0aGUgU01N VSBkcml2ZXIgKGtlZXBpbmcgdGhlIERUL0FDUEkgZndub2RlIHN3aXRjaCBpbg0KPiBnZW5lcmlj IElPTU1VIGxheWVyIHRob3VnaCkuDQoNClBsZWFzZSBmaW5kIFsxXSBmb3IgdGhlIGdlbmVyaWMg aW9tbXUgaGVscGVyIGZ1bmN0aW9uIHdoaWNoIHdpbGwgYmUgY2FsbGVkDQpmcm9tIFNNTVUgZHJp dmVyIGJhc2VkIG9uIHRoZSBtb2RlbC4NCg0KPiBTaWRlIG5vdGUgSTogQUZBSUNTIGlvbW11X2Rt YV9nZXRfcmVzdl9yZWdpb25zKCkgaXMgb25seSB1c2VkIG9uIEFSTSwgaWYNCj4gaXQgaXMgbm90 IHBhdGNoIDIgd291bGQgYnJlYWsgbWlzZXJhYmx5IG9uIGFyY2hlcyB0aGF0IGRvIG5vdCBzZWxl Y3QNCj4gSU9SVCAtIHlvdSBzaG91bGQgcmV3b3JrIHRoZSByZXR1cm4gY29kZSBvbiAhQ09ORklH X0FDUElfSU9SVCBjb25maWdzLg0KDQpZZXMuIEJ1dCBzbyBmYXIgaXQgaXMgb25seSB1c2VkIG9u IEFSTS4gSW4gYW55IHdheSB0aGlzIGZ1bmN0aW9uIGlzIG5vdCBnb2luZyB0byBiZQ0KY2hhbmdl ZCBhbmQgd2lsbCBpbnRyb2R1Y2UgYSBuZXcgaW9tbXVfZG1hX2dldF9tc2lfcmVzdl9yZWdpb25z KCkgZm4gIGFzDQpwcm9wb3NlZCBpbiBbMV0uDQoNClBsZWFzZSB0YWtlIGEgbG9vayBhbmQgbGV0 IG1lIGtub3cuIEkgd2lsbCBzdWJtaXQgdGhlIHNlcmllcyBhZ2FpbiBpZiB0aGlzIGlzIGZpbmUu DQoNClRoYW5rcywNClNoYW1lZXINCg0KWzFdIFRoaXMgd2lsbCByZXBsYWNlIHBhdGNoIDIgYW5k IHdpbGwgYmUgZm9sbG93ZWQgYnkgc21tdSBkcml2ZXIgcGF0Y2ggdG8gaW52b2tlDQppb21tdV9k bWFfZ2V0X21zaV9yZXN2X3JlZ2lvbnMoKSBiYXNlZCBvbiBTTU1VIG1vZGVsLg0KDQotLT44LS0N ClN1YmplY3Q6IFtQQVRDSF0gaW9tbXUvZG1hOiBBZGQgYSBoZWxwZXIgIGZ1bmN0aW9uIHRvIHJl c2VydmUgSFcgTVNJIGFkZHJlc3MgcmVnaW9ucyBmb3IgSU9NTVUgZHJpdmVycw0KDQpJT01NVSBk cml2ZXJzIGNhbiB1c2UgdGhpcyB0byBpbXBsZW1lbnQgdGhlaXIgLmdldF9yZXN2X3JlZ2lvbnMg Y2FsbGJhY2sNCmZvciBIVyBNU0kgc3BlY2lmaWMgcmVzZXJ2YXRpb25zKGUuZy4gQVJNIEdJQ3Yz IElUUyBNU0kgcmVnaW9uKS4NCg0KU2lnbmVkLW9mZi1ieTogU2hhbWVlciBLb2xvdGh1bSA8c2hh bWVlcmFsaS5rb2xvdGh1bS50aG9kaUBodWF3ZWkuY29tPg0KLS0tDQogZHJpdmVycy9pb21tdS9k bWEtaW9tbXUuYyB8IDE5ICsrKysrKysrKysrKysrKysrKysNCiBpbmNsdWRlL2xpbnV4L2RtYS1p b21tdS5oIHwgIDcgKysrKysrKw0KIDIgZmlsZXMgY2hhbmdlZCwgMjYgaW5zZXJ0aW9ucygrKQ0K DQpkaWZmIC0tZ2l0IGEvZHJpdmVycy9pb21tdS9kbWEtaW9tbXUuYyBiL2RyaXZlcnMvaW9tbXUv ZG1hLWlvbW11LmMNCmluZGV4IDlkMWNlYmUuLjk1MmVjZGQgMTAwNjQ0DQotLS0gYS9kcml2ZXJz L2lvbW11L2RtYS1pb21tdS5jDQorKysgYi9kcml2ZXJzL2lvbW11L2RtYS1pb21tdS5jDQpAQCAt MTksNiArMTksNyBAQA0KICAqIGFsb25nIHdpdGggdGhpcyBwcm9ncmFtLiAgSWYgbm90LCBzZWUg PGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+Lg0KICAqLw0KIA0KKyNpbmNsdWRlIDxsaW51 eC9hY3BpX2lvcnQuaD4NCiAjaW5jbHVkZSA8bGludXgvZGV2aWNlLmg+DQogI2luY2x1ZGUgPGxp bnV4L2RtYS1pb21tdS5oPg0KICNpbmNsdWRlIDxsaW51eC9nZnAuaD4NCkBAIC0xOTgsNiArMTk5 LDI0IEBAIHZvaWQgaW9tbXVfZG1hX2dldF9yZXN2X3JlZ2lvbnMoc3RydWN0IGRldmljZSAqZGV2 LCBzdHJ1Y3QgbGlzdF9oZWFkICpsaXN0KQ0KIH0NCiBFWFBPUlRfU1lNQk9MKGlvbW11X2RtYV9n ZXRfcmVzdl9yZWdpb25zKTsNCiANCisvKioNCisgKiBpb21tdV9kbWFfZ2V0X21zaV9yZXN2X3Jl Z2lvbnMgLSBSZXNlcnZlZCByZWdpb24gZHJpdmVyIGhlbHBlcg0KKyAqIEBkZXY6IERldmljZSBm cm9tIGlvbW11X2dldF9yZXN2X3JlZ2lvbnMoKQ0KKyAqIEBsaXN0OiBSZXNlcnZlZCByZWdpb24g bGlzdCBmcm9tIGlvbW11X2dldF9yZXN2X3JlZ2lvbnMoKQ0KKyAqDQorICogSU9NTVUgZHJpdmVy cyBjYW4gdXNlIHRoaXMgdG8gaW1wbGVtZW50IHRoZWlyIC5nZXRfcmVzdl9yZWdpb25zDQorICog Y2FsbGJhY2sgZm9yIEhXIE1TSSBzcGVjaWZpYyByZXNlcnZhdGlvbnMuIEZvciBub3csIHRoaXMg b25seQ0KKyAqIGNvdmVycyBJVFMgTVNJIHJlZ2lvbiByZXNlcnZhdGlvbiB1c2luZyBBQ1BJIElP UlQgaGVscGVyIGZ1bmN0aW9uLg0KKyAqLw0KK2ludCBpb21tdV9kbWFfZ2V0X21zaV9yZXN2X3Jl Z2lvbnMoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgbGlzdF9oZWFkICpsaXN0KQ0KK3sNCisJ aWYgKCFpc19vZl9ub2RlKGRldi0+aW9tbXVfZndzcGVjLT5pb21tdV9md25vZGUpKQ0KKwkJcmV0 dXJuIGlvcnRfaW9tbXVfaXRzX2dldF9yZXN2X3JlZ2lvbnMoZGV2LCBsaXN0KTsNCisNCisJcmV0 dXJuIC1FTk9ERVY7DQorfQ0KK0VYUE9SVF9TWU1CT0woaW9tbXVfZG1hX2dldF9tc2lfcmVzdl9y ZWdpb25zKTsNCisNCiBzdGF0aWMgaW50IGNvb2tpZV9pbml0X2h3X21zaV9yZWdpb24oc3RydWN0 IGlvbW11X2RtYV9jb29raWUgKmNvb2tpZSwNCiAJCXBoeXNfYWRkcl90IHN0YXJ0LCBwaHlzX2Fk ZHJfdCBlbmQpDQogew0KZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvZG1hLWlvbW11LmggYi9p bmNsdWRlL2xpbnV4L2RtYS1pb21tdS5oDQppbmRleCA5MmYyMDgzLi42MDYyZWYwIDEwMDY0NA0K LS0tIGEvaW5jbHVkZS9saW51eC9kbWEtaW9tbXUuaA0KKysrIGIvaW5jbHVkZS9saW51eC9kbWEt aW9tbXUuaA0KQEAgLTc0LDYgKzc0LDggQEAgdm9pZCBpb21tdV9kbWFfdW5tYXBfcmVzb3VyY2Uo c3RydWN0IGRldmljZSAqZGV2LCBkbWFfYWRkcl90IGhhbmRsZSwNCiB2b2lkIGlvbW11X2RtYV9t YXBfbXNpX21zZyhpbnQgaXJxLCBzdHJ1Y3QgbXNpX21zZyAqbXNnKTsNCiB2b2lkIGlvbW11X2Rt YV9nZXRfcmVzdl9yZWdpb25zKHN0cnVjdCBkZXZpY2UgKmRldiwgc3RydWN0IGxpc3RfaGVhZCAq bGlzdCk7DQogDQoraW50IGlvbW11X2RtYV9nZXRfbXNpX3Jlc3ZfcmVnaW9ucyhzdHJ1Y3QgZGV2 aWNlICpkZXYsIHN0cnVjdCBsaXN0X2hlYWQgKmxpc3QpOw0KKw0KICNlbHNlDQogDQogc3RydWN0 IGlvbW11X2RvbWFpbjsNCkBAIC0xMDcsNiArMTA5LDExIEBAIHN0YXRpYyBpbmxpbmUgdm9pZCBp b21tdV9kbWFfZ2V0X3Jlc3ZfcmVnaW9ucyhzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBsaXN0 X2hlDQogew0KIH0NCiANCitzdGF0aWMgaW5saW5lIGludCBpb21tdV9kbWFfZ2V0X21zaV9yZXN2 X3JlZ2lvbnMoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgbGlzdF9oZWFkICpsaXN0KQ0KK3sN CisJcmV0dXJuIC1FTk9ERVY7DQorfQ0KKw0KICNlbmRpZgkvKiBDT05GSUdfSU9NTVVfRE1BICov DQogI2VuZGlmCS8qIF9fS0VSTkVMX18gKi8NCiAjZW5kaWYJLyogX19ETUFfSU9NTVVfSCAqLw0K LS0gDQoxLjkuMQ0K -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index a3215ee..86b5a51 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -39,6 +39,7 @@ struct iort_its_msi_chip { struct list_head list; struct fwnode_handle *fw_node; + phys_addr_t base_addr; u32 translation_id; }; @@ -136,14 +137,16 @@ typedef acpi_status (*iort_find_node_callback) static DEFINE_SPINLOCK(iort_msi_chip_lock); /** - * iort_register_domain_token() - register domain token and related ITS ID - * to the list from where we can get it back later on. + * iort_register_domain_token() - register domain token along with related + * ITS ID and base address to the list from where we can get it back later on. * @trans_id: ITS ID. + * @base: ITS base address. * @fw_node: Domain token. * * Returns: 0 on success, -ENOMEM if no memory when allocating list element */ -int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node) +int iort_register_domain_token(int trans_id, phys_addr_t base, + struct fwnode_handle *fw_node) { struct iort_its_msi_chip *its_msi_chip; @@ -153,6 +156,7 @@ int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node) its_msi_chip->fw_node = fw_node; its_msi_chip->translation_id = trans_id; + its_msi_chip->base_addr = base; spin_lock(&iort_msi_chip_lock); list_add(&its_msi_chip->list, &iort_msi_chip_list); @@ -481,6 +485,24 @@ int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) return -ENODEV; } +static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base) +{ + struct iort_its_msi_chip *its_msi_chip; + bool match = false; + + spin_lock(&iort_msi_chip_lock); + list_for_each_entry(its_msi_chip, &iort_msi_chip_list, list) { + if (its_msi_chip->translation_id == its_id) { + *base = its_msi_chip->base_addr; + match = true; + break; + } + } + spin_unlock(&iort_msi_chip_lock); + + return match ? 0 : -ENODEV; +} + /** * iort_dev_find_its_id() - Find the ITS identifier for a device * @dev: The device. @@ -639,6 +661,71 @@ int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) return err; } + +/** + * iort_iommu_its_get_resv_regions - Reserved region driver helper + * @dev: Device from iommu_get_resv_regions() + * @list: Reserved region list from iommu_get_resv_regions() + * + * Returns: Number of reserved regions on success(0 if no associated ITS), + * appropriate error value otherwise. + */ +int iort_iommu_its_get_resv_regions(struct device *dev, struct list_head *head) +{ + struct acpi_iort_its_group *its; + struct acpi_iort_node *node, *its_node = NULL; + int i, resv = 0; + + node = iort_find_dev_node(dev); + if (!node) + return -ENODEV; + + /* + * Current logic to reserve ITS regions relies on HW topologies + * where a given PCI or named component maps its IDs to only one + * ITS group; if a PCI or named component can map its IDs to + * different ITS groups through IORT mappings this function has + * to be reworked to ensure we reserve regions for all ITS groups + * a given PCI or named component may map IDs to. + */ + if (dev_is_pci(dev)) { + u32 rid; + + pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid, &rid); + its_node = iort_node_map_id(node, rid, NULL, IORT_MSI_TYPE); + } else { + for (i = 0; i < node->mapping_count; i++) { + its_node = iort_node_map_platform_id(node, NULL, + IORT_MSI_TYPE, i); + if (its_node) + break; + } + } + + if (!its_node) + return 0; + + /* Move to ITS specific data */ + its = (struct acpi_iort_its_group *)its_node->node_data; + + for (i = 0; i < its->its_count; i++) { + phys_addr_t base; + + if (!iort_find_its_base(its->identifiers[i], &base)) { + int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; + struct iommu_resv_region *region; + + region = iommu_alloc_resv_region(base, SZ_128K, prot, + IOMMU_RESV_MSI); + if (region) { + list_add_tail(®ion->list, head); + resv++; + } + } + } + + return (resv == its->its_count) ? resv : -ENODEV; +} #else static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct iommu_fwspec *fwspec) @@ -646,6 +733,8 @@ const struct iommu_ops *iort_fwspec_iommu_ops(struct iommu_fwspec *fwspec) static inline int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev) { return 0; } +int iort_iommu_its_get_resv_regions(struct device *dev, struct list_head *head) +{ return -ENODEV; } #endif static const struct iommu_ops *iort_iommu_xlate(struct device *dev, diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 6893287..77322b3 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -1928,7 +1928,8 @@ static int __init gic_acpi_parse_madt_its(struct acpi_subtable_header *header, return -ENOMEM; } - err = iort_register_domain_token(its_entry->translation_id, dom_handle); + err = iort_register_domain_token(its_entry->translation_id, res.start, + dom_handle); if (err) { pr_err("ITS@%pa: Unable to register GICv3 ITS domain token (ITS ID %d) to IORT\n", &res.start, its_entry->translation_id); diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h index 8379d40..d7ed49c 100644 --- a/include/linux/acpi_iort.h +++ b/include/linux/acpi_iort.h @@ -26,7 +26,8 @@ #define IORT_IRQ_MASK(irq) (irq & 0xffffffffULL) #define IORT_IRQ_TRIGGER_MASK(irq) ((irq >> 32) & 0xffffffffULL) -int iort_register_domain_token(int trans_id, struct fwnode_handle *fw_node); +int iort_register_domain_token(int trans_id, phys_addr_t base, + struct fwnode_handle *fw_node); void iort_deregister_domain_token(int trans_id); struct fwnode_handle *iort_find_domain_token(int trans_id); #ifdef CONFIG_ACPI_IORT @@ -38,6 +39,7 @@ /* IOMMU interface */ void iort_set_dma_mask(struct device *dev); const struct iommu_ops *iort_iommu_configure(struct device *dev); +int iort_iommu_its_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) @@ -51,6 +53,9 @@ static inline void iort_set_dma_mask(struct device *dev) { } static inline const struct iommu_ops *iort_iommu_configure(struct device *dev) { return NULL; } +static inline +int iort_iommu_its_get_resv_regions(struct device *dev, struct list_head *head) +{ return -ENODEV; } #endif #endif /* __ACPI_IORT_H__ */