Skip to content

Commit a6a4c7e

Browse files
committed
iommu: Add probe_device() and release_device() call-backs
Add call-backs to 'struct iommu_ops' as an alternative to the add_device() and remove_device() call-backs, which will be removed when all drivers are converted. The new call-backs will not setup IOMMU groups and domains anymore, so also add a probe_finalize() call-back where the IOMMU driver can do per-device setup work which require the device to be set up with a group and a domain. Signed-off-by: Joerg Roedel <[email protected]> Tested-by: Marek Szyprowski <[email protected]> Acked-by: Marek Szyprowski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent 57bd2c2 commit a6a4c7e

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

drivers/iommu/iommu.c

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,36 @@ static void dev_iommu_free(struct device *dev)
174174
dev->iommu = NULL;
175175
}
176176

177+
static int __iommu_probe_device(struct device *dev)
178+
{
179+
const struct iommu_ops *ops = dev->bus->iommu_ops;
180+
struct iommu_device *iommu_dev;
181+
struct iommu_group *group;
182+
int ret;
183+
184+
iommu_dev = ops->probe_device(dev);
185+
if (IS_ERR(iommu_dev))
186+
return PTR_ERR(iommu_dev);
187+
188+
dev->iommu->iommu_dev = iommu_dev;
189+
190+
group = iommu_group_get_for_dev(dev);
191+
if (!IS_ERR(group)) {
192+
ret = PTR_ERR(group);
193+
goto out_release;
194+
}
195+
iommu_group_put(group);
196+
197+
iommu_device_link(iommu_dev, dev);
198+
199+
return 0;
200+
201+
out_release:
202+
ops->release_device(dev);
203+
204+
return ret;
205+
}
206+
177207
int iommu_probe_device(struct device *dev)
178208
{
179209
const struct iommu_ops *ops = dev->bus->iommu_ops;
@@ -191,10 +221,17 @@ int iommu_probe_device(struct device *dev)
191221
goto err_free_dev_param;
192222
}
193223

194-
ret = ops->add_device(dev);
224+
if (ops->probe_device)
225+
ret = __iommu_probe_device(dev);
226+
else
227+
ret = ops->add_device(dev);
228+
195229
if (ret)
196230
goto err_module_put;
197231

232+
if (ops->probe_finalize)
233+
ops->probe_finalize(dev);
234+
198235
return 0;
199236

200237
err_module_put:
@@ -204,17 +241,31 @@ int iommu_probe_device(struct device *dev)
204241
return ret;
205242
}
206243

244+
static void __iommu_release_device(struct device *dev)
245+
{
246+
const struct iommu_ops *ops = dev->bus->iommu_ops;
247+
248+
iommu_device_unlink(dev->iommu->iommu_dev, dev);
249+
250+
iommu_group_remove_device(dev);
251+
252+
ops->release_device(dev);
253+
}
254+
207255
void iommu_release_device(struct device *dev)
208256
{
209257
const struct iommu_ops *ops = dev->bus->iommu_ops;
210258

211-
if (dev->iommu_group)
259+
if (!dev->iommu)
260+
return;
261+
262+
if (ops->release_device)
263+
__iommu_release_device(dev);
264+
else if (dev->iommu_group)
212265
ops->remove_device(dev);
213266

214-
if (dev->iommu) {
215-
module_put(ops->owner);
216-
dev_iommu_free(dev);
217-
}
267+
module_put(ops->owner);
268+
dev_iommu_free(dev);
218269
}
219270

220271
static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,

include/linux/iommu.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,10 @@ struct iommu_iotlb_gather {
225225
* @iova_to_phys: translate iova to physical address
226226
* @add_device: add device to iommu grouping
227227
* @remove_device: remove device from iommu grouping
228+
* @probe_device: Add device to iommu driver handling
229+
* @release_device: Remove device from iommu driver handling
230+
* @probe_finalize: Do final setup work after the device is added to an IOMMU
231+
* group and attached to the groups domain
228232
* @device_group: find iommu group for a particular device
229233
* @domain_get_attr: Query domain attributes
230234
* @domain_set_attr: Change domain attributes
@@ -275,6 +279,9 @@ struct iommu_ops {
275279
phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova);
276280
int (*add_device)(struct device *dev);
277281
void (*remove_device)(struct device *dev);
282+
struct iommu_device *(*probe_device)(struct device *dev);
283+
void (*release_device)(struct device *dev);
284+
void (*probe_finalize)(struct device *dev);
278285
struct iommu_group *(*device_group)(struct device *dev);
279286
int (*domain_get_attr)(struct iommu_domain *domain,
280287
enum iommu_attr attr, void *data);
@@ -375,6 +382,7 @@ struct iommu_fault_param {
375382
*
376383
* @fault_param: IOMMU detected device fault reporting data
377384
* @fwspec: IOMMU fwspec data
385+
* @iommu_dev: IOMMU device this device is linked to
378386
* @priv: IOMMU Driver private data
379387
*
380388
* TODO: migrate other per device data pointers under iommu_dev_data, e.g.
@@ -384,6 +392,7 @@ struct dev_iommu {
384392
struct mutex lock;
385393
struct iommu_fault_param *fault_param;
386394
struct iommu_fwspec *fwspec;
395+
struct iommu_device *iommu_dev;
387396
void *priv;
388397
};
389398

0 commit comments

Comments
 (0)