diff mbox series

[v5,1/2] ACPI/IORT: Add ITS address regions reservation helper

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

Commit Message

Shameerali Kolothum Thodi Aug. 1, 2017, 10:49 a.m. UTC
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.

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(-)

-- 
1.9.1


--
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

Comments

Robin Murphy Aug. 4, 2017, 4:57 p.m. UTC | #1
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(&region->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
Shameerali Kolothum Thodi Aug. 7, 2017, 8:21 a.m. UTC | #2
> -----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
Lorenzo Pieralisi Aug. 7, 2017, 5:09 p.m. UTC | #3
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
Shameerali Kolothum Thodi Aug. 8, 2017, 9:49 a.m. UTC | #4
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 mbox series

Patch

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(&region->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__ */