2019-08-29 11:19:05

by Thierry Reding

[permalink] [raw]
Subject: [PATCH 0/5] iommu: Implement iommu_put_resv_regions_simple()

From: Thierry Reding <[email protected]>

Most IOMMU drivers only need to free the memory allocated for each
reserved region. Instead of open-coding the loop to do this in each
driver, extract the code into a common function that can be used by
all these drivers.

Thierry

Thierry Reding (5):
iommu: Implement iommu_put_resv_regions_simple()
iommu: arm: Use iommu_put_resv_regions_simple()
iommu: amd: Use iommu_put_resv_regions_simple()
iommu: intel: Use iommu_put_resv_regions_simple()
iommu: virt: Use iommu_put_resv_regions_simple()

drivers/iommu/amd_iommu.c | 11 +----------
drivers/iommu/arm-smmu-v3.c | 11 +----------
drivers/iommu/arm-smmu.c | 11 +----------
drivers/iommu/intel-iommu.c | 11 +----------
drivers/iommu/iommu.c | 19 +++++++++++++++++++
drivers/iommu/virtio-iommu.c | 14 +++-----------
include/linux/iommu.h | 2 ++
7 files changed, 28 insertions(+), 51 deletions(-)

--
2.22.0


2019-08-29 11:19:10

by Thierry Reding

[permalink] [raw]
Subject: [PATCH 1/5] iommu: Implement iommu_put_resv_regions_simple()

From: Thierry Reding <[email protected]>

Implement a generic function for removing reserved regions. This can be
used by drivers that don't do anything fancy with these regions other
than allocating memory for them.

Signed-off-by: Thierry Reding <[email protected]>
---
drivers/iommu/iommu.c | 19 +++++++++++++++++++
include/linux/iommu.h | 2 ++
2 files changed, 21 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 0f585b614657..73a2a6b13507 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2170,6 +2170,25 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)
ops->put_resv_regions(dev, list);
}

+/**
+ * iommu_put_resv_regions_simple - Reserved region driver helper
+ * @dev: device for which to free reserved regions
+ * @list: reserved region list for device
+ *
+ * IOMMU drivers can use this to implement their .put_resv_regions() callback
+ * for simple reservations. Memory allocated for each reserved region will be
+ * freed. If an IOMMU driver allocates additional resources per region, it is
+ * going to have to implement a custom callback.
+ */
+void iommu_put_resv_regions_simple(struct device *dev, struct list_head *list)
+{
+ struct iommu_resv_region *entry, *next;
+
+ list_for_each_entry_safe(entry, next, list, list)
+ kfree(entry);
+}
+EXPORT_SYMBOL(iommu_put_resv_regions_simple);
+
struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start,
size_t length, int prot,
enum iommu_resv_type type)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 29bac5345563..d9c91e37ac2e 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -434,6 +434,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain,

extern void iommu_get_resv_regions(struct device *dev, struct list_head *list);
extern void iommu_put_resv_regions(struct device *dev, struct list_head *list);
+extern void iommu_put_resv_regions_simple(struct device *dev,
+ struct list_head *list);
extern int iommu_request_dm_for_dev(struct device *dev);
extern int iommu_request_dma_domain_for_dev(struct device *dev);
extern void iommu_set_default_passthrough(bool cmd_line);
--
2.22.0

2019-08-29 11:19:18

by Thierry Reding

[permalink] [raw]
Subject: [PATCH 3/5] iommu: amd: Use iommu_put_resv_regions_simple()

From: Thierry Reding <[email protected]>

Use the new standard function instead of open-coding it.

Signed-off-by: Thierry Reding <[email protected]>
---
drivers/iommu/amd_iommu.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 04a9f8443344..7d8896d5fab9 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3160,15 +3160,6 @@ static void amd_iommu_get_resv_regions(struct device *dev,
list_add_tail(&region->list, head);
}

-static void amd_iommu_put_resv_regions(struct device *dev,
- struct list_head *head)
-{
- struct iommu_resv_region *entry, *next;
-
- list_for_each_entry_safe(entry, next, head, list)
- kfree(entry);
-}
-
static void amd_iommu_apply_resv_region(struct device *dev,
struct iommu_domain *domain,
struct iommu_resv_region *region)
@@ -3216,7 +3207,7 @@ const struct iommu_ops amd_iommu_ops = {
.remove_device = amd_iommu_remove_device,
.device_group = amd_iommu_device_group,
.get_resv_regions = amd_iommu_get_resv_regions,
- .put_resv_regions = amd_iommu_put_resv_regions,
+ .put_resv_regions = iommu_put_resv_regions_simple,
.apply_resv_region = amd_iommu_apply_resv_region,
.is_attach_deferred = amd_iommu_is_attach_deferred,
.pgsize_bitmap = AMD_IOMMU_PGSIZES,
--
2.22.0

2019-08-29 11:19:21

by Thierry Reding

[permalink] [raw]
Subject: [PATCH 5/5] iommu: virt: Use iommu_put_resv_regions_simple()

From: Thierry Reding <[email protected]>

Use the new standard function instead of open-coding it.

Cc: Jean-Philippe Brucker <[email protected]>
Cc: [email protected]
Signed-off-by: Thierry Reding <[email protected]>
---
drivers/iommu/virtio-iommu.c | 14 +++-----------
1 file changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 3ea9d7682999..bc3c7ab7f996 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -838,14 +838,6 @@ static void viommu_get_resv_regions(struct device *dev, struct list_head *head)
iommu_dma_get_resv_regions(dev, head);
}

-static void viommu_put_resv_regions(struct device *dev, struct list_head *head)
-{
- struct iommu_resv_region *entry, *next;
-
- list_for_each_entry_safe(entry, next, head, list)
- kfree(entry);
-}
-
static struct iommu_ops viommu_ops;
static struct virtio_driver virtio_iommu_drv;

@@ -915,7 +907,7 @@ static int viommu_add_device(struct device *dev)
err_unlink_dev:
iommu_device_unlink(&viommu->iommu, dev);
err_free_dev:
- viommu_put_resv_regions(dev, &vdev->resv_regions);
+ iommu_put_resv_regions_simple(dev, &vdev->resv_regions);
kfree(vdev);

return ret;
@@ -933,7 +925,7 @@ static void viommu_remove_device(struct device *dev)

iommu_group_remove_device(dev);
iommu_device_unlink(&vdev->viommu->iommu, dev);
- viommu_put_resv_regions(dev, &vdev->resv_regions);
+ iommu_put_resv_regions_simple(dev, &vdev->resv_regions);
kfree(vdev);
}

@@ -962,7 +954,7 @@ static struct iommu_ops viommu_ops = {
.remove_device = viommu_remove_device,
.device_group = viommu_device_group,
.get_resv_regions = viommu_get_resv_regions,
- .put_resv_regions = viommu_put_resv_regions,
+ .put_resv_regions = iommu_put_resv_regions_simple,
.of_xlate = viommu_of_xlate,
};

--
2.22.0

2019-08-29 11:19:24

by Thierry Reding

[permalink] [raw]
Subject: [PATCH 4/5] iommu: intel: Use iommu_put_resv_regions_simple()

From: Thierry Reding <[email protected]>

Use the new standard function instead of open-coding it.

Cc: David Woodhouse <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
---
drivers/iommu/intel-iommu.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 4658cda6f3d2..2fe5da41c786 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5386,15 +5386,6 @@ static void intel_iommu_get_resv_regions(struct device *device,
list_add_tail(&reg->list, head);
}

-static void intel_iommu_put_resv_regions(struct device *dev,
- struct list_head *head)
-{
- struct iommu_resv_region *entry, *next;
-
- list_for_each_entry_safe(entry, next, head, list)
- kfree(entry);
-}
-
int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)
{
struct device_domain_info *info;
@@ -5629,7 +5620,7 @@ const struct iommu_ops intel_iommu_ops = {
.add_device = intel_iommu_add_device,
.remove_device = intel_iommu_remove_device,
.get_resv_regions = intel_iommu_get_resv_regions,
- .put_resv_regions = intel_iommu_put_resv_regions,
+ .put_resv_regions = iommu_put_resv_regions_simple,
.apply_resv_region = intel_iommu_apply_resv_region,
.device_group = pci_device_group,
.dev_has_feat = intel_iommu_dev_has_feat,
--
2.22.0

2019-08-29 11:19:49

by Thierry Reding

[permalink] [raw]
Subject: [PATCH 2/5] iommu: arm: Use iommu_put_resv_regions_simple()

From: Thierry Reding <[email protected]>

Use the new standard function instead of open-coding it.

Cc: Will Deacon <[email protected]>
Cc: Robin Murphy <[email protected]>
Signed-off-by: Thierry Reding <[email protected]>
---
drivers/iommu/arm-smmu-v3.c | 11 +----------
drivers/iommu/arm-smmu.c | 11 +----------
2 files changed, 2 insertions(+), 20 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 0ad6d34d1e96..b3b7ca2c057a 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -2263,15 +2263,6 @@ static void arm_smmu_get_resv_regions(struct device *dev,
iommu_dma_get_resv_regions(dev, head);
}

-static void arm_smmu_put_resv_regions(struct device *dev,
- struct list_head *head)
-{
- struct iommu_resv_region *entry, *next;
-
- list_for_each_entry_safe(entry, next, head, list)
- kfree(entry);
-}
-
static struct iommu_ops arm_smmu_ops = {
.capable = arm_smmu_capable,
.domain_alloc = arm_smmu_domain_alloc,
@@ -2289,7 +2280,7 @@ static struct iommu_ops arm_smmu_ops = {
.domain_set_attr = arm_smmu_domain_set_attr,
.of_xlate = arm_smmu_of_xlate,
.get_resv_regions = arm_smmu_get_resv_regions,
- .put_resv_regions = arm_smmu_put_resv_regions,
+ .put_resv_regions = iommu_put_resv_regions_simple,
.pgsize_bitmap = -1UL, /* Restricted during device attach */
};

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index d6fe997e9466..e547b4322bcc 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1724,15 +1724,6 @@ static void arm_smmu_get_resv_regions(struct device *dev,
iommu_dma_get_resv_regions(dev, head);
}

-static void arm_smmu_put_resv_regions(struct device *dev,
- struct list_head *head)
-{
- struct iommu_resv_region *entry, *next;
-
- list_for_each_entry_safe(entry, next, head, list)
- kfree(entry);
-}
-
static struct iommu_ops arm_smmu_ops = {
.capable = arm_smmu_capable,
.domain_alloc = arm_smmu_domain_alloc,
@@ -1750,7 +1741,7 @@ static struct iommu_ops arm_smmu_ops = {
.domain_set_attr = arm_smmu_domain_set_attr,
.of_xlate = arm_smmu_of_xlate,
.get_resv_regions = arm_smmu_get_resv_regions,
- .put_resv_regions = arm_smmu_put_resv_regions,
+ .put_resv_regions = iommu_put_resv_regions_simple,
.pgsize_bitmap = -1UL, /* Restricted during device attach */
};

--
2.22.0

2019-09-03 06:57:05

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 5/5] iommu: virt: Use iommu_put_resv_regions_simple()

I think the subject should say virtio instead of virt.

2019-09-16 10:41:05

by Eric Auger

[permalink] [raw]
Subject: Re: [PATCH 0/5] iommu: Implement iommu_put_resv_regions_simple()

Hi Thierry,

On 8/29/19 1:17 PM, Thierry Reding wrote:
> From: Thierry Reding <[email protected]>
>
> Most IOMMU drivers only need to free the memory allocated for each
> reserved region. Instead of open-coding the loop to do this in each
> driver, extract the code into a common function that can be used by
> all these drivers.

If I am not wrong, all the drivers now use the
iommu_put_resv_regions_simple helper. So we can wonder if the callback
is still relevant?

Thanks

Eric
>
> Thierry
>
> Thierry Reding (5):
> iommu: Implement iommu_put_resv_regions_simple()
> iommu: arm: Use iommu_put_resv_regions_simple()
> iommu: amd: Use iommu_put_resv_regions_simple()
> iommu: intel: Use iommu_put_resv_regions_simple()
> iommu: virt: Use iommu_put_resv_regions_simple()
>
> drivers/iommu/amd_iommu.c | 11 +----------
> drivers/iommu/arm-smmu-v3.c | 11 +----------
> drivers/iommu/arm-smmu.c | 11 +----------
> drivers/iommu/intel-iommu.c | 11 +----------
> drivers/iommu/iommu.c | 19 +++++++++++++++++++
> drivers/iommu/virtio-iommu.c | 14 +++-----------
> include/linux/iommu.h | 2 ++
> 7 files changed, 28 insertions(+), 51 deletions(-)
>

2019-09-18 20:39:57

by Will Deacon

[permalink] [raw]
Subject: Re: [PATCH 1/5] iommu: Implement iommu_put_resv_regions_simple()

On Thu, Aug 29, 2019 at 01:17:48PM +0200, Thierry Reding wrote:
> From: Thierry Reding <[email protected]>
>
> Implement a generic function for removing reserved regions. This can be
> used by drivers that don't do anything fancy with these regions other
> than allocating memory for them.
>
> Signed-off-by: Thierry Reding <[email protected]>
> ---
> drivers/iommu/iommu.c | 19 +++++++++++++++++++
> include/linux/iommu.h | 2 ++
> 2 files changed, 21 insertions(+)
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 0f585b614657..73a2a6b13507 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -2170,6 +2170,25 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)
> ops->put_resv_regions(dev, list);
> }
>
> +/**
> + * iommu_put_resv_regions_simple - Reserved region driver helper
> + * @dev: device for which to free reserved regions
> + * @list: reserved region list for device
> + *
> + * IOMMU drivers can use this to implement their .put_resv_regions() callback
> + * for simple reservations. Memory allocated for each reserved region will be
> + * freed. If an IOMMU driver allocates additional resources per region, it is
> + * going to have to implement a custom callback.
> + */
> +void iommu_put_resv_regions_simple(struct device *dev, struct list_head *list)
> +{
> + struct iommu_resv_region *entry, *next;
> +
> + list_for_each_entry_safe(entry, next, list, list)
> + kfree(entry);
> +}
> +EXPORT_SYMBOL(iommu_put_resv_regions_simple);

Can you call this directly from iommu_put_resv_regions() if the function
pointer in ops is NULL? That would save having to plumb the default callback
into a bunch of drivers.

Will

2019-10-16 15:41:43

by Thierry Reding

[permalink] [raw]
Subject: Re: [PATCH 1/5] iommu: Implement iommu_put_resv_regions_simple()

On Wed, Sep 18, 2019 at 04:37:38PM +0100, Will Deacon wrote:
> On Thu, Aug 29, 2019 at 01:17:48PM +0200, Thierry Reding wrote:
> > From: Thierry Reding <[email protected]>
> >
> > Implement a generic function for removing reserved regions. This can be
> > used by drivers that don't do anything fancy with these regions other
> > than allocating memory for them.
> >
> > Signed-off-by: Thierry Reding <[email protected]>
> > ---
> > drivers/iommu/iommu.c | 19 +++++++++++++++++++
> > include/linux/iommu.h | 2 ++
> > 2 files changed, 21 insertions(+)
> >
> > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> > index 0f585b614657..73a2a6b13507 100644
> > --- a/drivers/iommu/iommu.c
> > +++ b/drivers/iommu/iommu.c
> > @@ -2170,6 +2170,25 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list)
> > ops->put_resv_regions(dev, list);
> > }
> >
> > +/**
> > + * iommu_put_resv_regions_simple - Reserved region driver helper
> > + * @dev: device for which to free reserved regions
> > + * @list: reserved region list for device
> > + *
> > + * IOMMU drivers can use this to implement their .put_resv_regions() callback
> > + * for simple reservations. Memory allocated for each reserved region will be
> > + * freed. If an IOMMU driver allocates additional resources per region, it is
> > + * going to have to implement a custom callback.
> > + */
> > +void iommu_put_resv_regions_simple(struct device *dev, struct list_head *list)
> > +{
> > + struct iommu_resv_region *entry, *next;
> > +
> > + list_for_each_entry_safe(entry, next, list, list)
> > + kfree(entry);
> > +}
> > +EXPORT_SYMBOL(iommu_put_resv_regions_simple);
>
> Can you call this directly from iommu_put_resv_regions() if the function
> pointer in ops is NULL? That would save having to plumb the default callback
> into a bunch of drivers.

I probably could, but I don't think that necessarily improves things.
The reason is that that would cause the helper to get called even if the
driver doesn't support reserved regions. That's likely harmless because
in that case the list of regions passed to it would be empty. However, I
think the current way to do this, where we have to implement both hooks
for ->get_resv_regions() and ->put_resv_regions() is nicely symmetric.

Thierry


Attachments:
(No filename) (2.29 kB)
signature.asc (849.00 B)
Download all attachments