Skip to content

Commit eda8c28

Browse files
hegdevasantjoergroedel
authored andcommitted
iommu/amd: Enable device ATS/PASID/PRI capabilities independently
Introduce helper functions to enable/disable device ATS/PASID/PRI capabilities independently along with the new pasid_enabled and pri_enabled variables in struct iommu_dev_data to keep track, which allows attach_device() and detach_device() to be simplified. Co-developed-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com> Link: https://lore.kernel.org/r/20230921092147.5930-14-vasant.hegde@amd.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 92e2bd5 commit eda8c28

File tree

3 files changed

+120
-89
lines changed

3 files changed

+120
-89
lines changed

drivers/iommu/amd/amd_iommu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ int amd_iommu_pc_get_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
5151
int amd_iommu_pc_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr,
5252
u8 fxn, u64 *value);
5353

54+
/* Device capabilities */
55+
int amd_iommu_pdev_enable_cap_pri(struct pci_dev *pdev);
56+
void amd_iommu_pdev_disable_cap_pri(struct pci_dev *pdev);
57+
5458
int amd_iommu_register_ppr_notifier(struct notifier_block *nb);
5559
int amd_iommu_unregister_ppr_notifier(struct notifier_block *nb);
5660
void amd_iommu_domain_direct_map(struct iommu_domain *dom);

drivers/iommu/amd/amd_iommu_types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,8 @@ struct iommu_dev_data {
815815
u32 flags; /* Holds AMD_IOMMU_DEVICE_FLAG_<*> */
816816
int ats_qdep;
817817
u8 ats_enabled :1; /* ATS state */
818+
u8 pri_enabled :1; /* PRI state */
819+
u8 pasid_enabled:1; /* PASID state */
818820
u8 pri_tlp :1; /* PASID TLB required for
819821
PPR completions */
820822
u8 ppr :1; /* Enable device PPR support */

drivers/iommu/amd/iommu.c

Lines changed: 114 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,113 @@ static u32 pdev_get_caps(struct pci_dev *pdev)
349349
return flags;
350350
}
351351

352+
static inline int pdev_enable_cap_ats(struct pci_dev *pdev)
353+
{
354+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(&pdev->dev);
355+
int ret = -EINVAL;
356+
357+
if (dev_data->ats_enabled)
358+
return 0;
359+
360+
if (amd_iommu_iotlb_sup &&
361+
(dev_data->flags & AMD_IOMMU_DEVICE_FLAG_ATS_SUP)) {
362+
ret = pci_enable_ats(pdev, PAGE_SHIFT);
363+
if (!ret) {
364+
dev_data->ats_enabled = 1;
365+
dev_data->ats_qdep = pci_ats_queue_depth(pdev);
366+
}
367+
}
368+
369+
return ret;
370+
}
371+
372+
static inline void pdev_disable_cap_ats(struct pci_dev *pdev)
373+
{
374+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(&pdev->dev);
375+
376+
if (dev_data->ats_enabled) {
377+
pci_disable_ats(pdev);
378+
dev_data->ats_enabled = 0;
379+
}
380+
}
381+
382+
int amd_iommu_pdev_enable_cap_pri(struct pci_dev *pdev)
383+
{
384+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(&pdev->dev);
385+
int ret = -EINVAL;
386+
387+
if (dev_data->pri_enabled)
388+
return 0;
389+
390+
if (dev_data->flags & AMD_IOMMU_DEVICE_FLAG_PRI_SUP) {
391+
/*
392+
* First reset the PRI state of the device.
393+
* FIXME: Hardcode number of outstanding requests for now
394+
*/
395+
if (!pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32)) {
396+
dev_data->pri_enabled = 1;
397+
dev_data->pri_tlp = pci_prg_resp_pasid_required(pdev);
398+
399+
ret = 0;
400+
}
401+
}
402+
403+
return ret;
404+
}
405+
406+
void amd_iommu_pdev_disable_cap_pri(struct pci_dev *pdev)
407+
{
408+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(&pdev->dev);
409+
410+
if (dev_data->pri_enabled) {
411+
pci_disable_pri(pdev);
412+
dev_data->pri_enabled = 0;
413+
}
414+
}
415+
416+
static inline int pdev_enable_cap_pasid(struct pci_dev *pdev)
417+
{
418+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(&pdev->dev);
419+
int ret = -EINVAL;
420+
421+
if (dev_data->pasid_enabled)
422+
return 0;
423+
424+
if (dev_data->flags & AMD_IOMMU_DEVICE_FLAG_PASID_SUP) {
425+
/* Only allow access to user-accessible pages */
426+
ret = pci_enable_pasid(pdev, 0);
427+
if (!ret)
428+
dev_data->pasid_enabled = 1;
429+
}
430+
431+
return ret;
432+
}
433+
434+
static inline void pdev_disable_cap_pasid(struct pci_dev *pdev)
435+
{
436+
struct iommu_dev_data *dev_data = dev_iommu_priv_get(&pdev->dev);
437+
438+
if (dev_data->pasid_enabled) {
439+
pci_disable_pasid(pdev);
440+
dev_data->pasid_enabled = 0;
441+
}
442+
}
443+
444+
static void pdev_enable_caps(struct pci_dev *pdev)
445+
{
446+
pdev_enable_cap_ats(pdev);
447+
pdev_enable_cap_pasid(pdev);
448+
amd_iommu_pdev_enable_cap_pri(pdev);
449+
450+
}
451+
452+
static void pdev_disable_caps(struct pci_dev *pdev)
453+
{
454+
pdev_disable_cap_ats(pdev);
455+
pdev_disable_cap_pasid(pdev);
456+
amd_iommu_pdev_disable_cap_pri(pdev);
457+
}
458+
352459
/*
353460
* This function checks if the driver got a valid device from the caller to
354461
* avoid dereferencing invalid pointers.
@@ -1777,48 +1884,6 @@ static void do_detach(struct iommu_dev_data *dev_data)
17771884
domain->dev_cnt -= 1;
17781885
}
17791886

1780-
static void pdev_iommuv2_disable(struct pci_dev *pdev)
1781-
{
1782-
pci_disable_ats(pdev);
1783-
pci_disable_pri(pdev);
1784-
pci_disable_pasid(pdev);
1785-
}
1786-
1787-
static int pdev_pri_ats_enable(struct pci_dev *pdev)
1788-
{
1789-
int ret;
1790-
1791-
/* Only allow access to user-accessible pages */
1792-
ret = pci_enable_pasid(pdev, 0);
1793-
if (ret)
1794-
return ret;
1795-
1796-
/* First reset the PRI state of the device */
1797-
ret = pci_reset_pri(pdev);
1798-
if (ret)
1799-
goto out_err_pasid;
1800-
1801-
/* Enable PRI */
1802-
/* FIXME: Hardcode number of outstanding requests for now */
1803-
ret = pci_enable_pri(pdev, 32);
1804-
if (ret)
1805-
goto out_err_pasid;
1806-
1807-
ret = pci_enable_ats(pdev, PAGE_SHIFT);
1808-
if (ret)
1809-
goto out_err_pri;
1810-
1811-
return 0;
1812-
1813-
out_err_pri:
1814-
pci_disable_pri(pdev);
1815-
1816-
out_err_pasid:
1817-
pci_disable_pasid(pdev);
1818-
1819-
return ret;
1820-
}
1821-
18221887
/*
18231888
* If a device is not yet associated with a domain, this function makes the
18241889
* device visible in the domain
@@ -1827,55 +1892,22 @@ static int attach_device(struct device *dev,
18271892
struct protection_domain *domain)
18281893
{
18291894
struct iommu_dev_data *dev_data;
1830-
struct pci_dev *pdev;
18311895
unsigned long flags;
1832-
int ret;
1896+
int ret = 0;
18331897

18341898
spin_lock_irqsave(&domain->lock, flags);
18351899

18361900
dev_data = dev_iommu_priv_get(dev);
18371901

18381902
spin_lock(&dev_data->lock);
18391903

1840-
ret = -EBUSY;
1841-
if (dev_data->domain != NULL)
1904+
if (dev_data->domain != NULL) {
1905+
ret = -EBUSY;
18421906
goto out;
1843-
1844-
if (!dev_is_pci(dev))
1845-
goto skip_ats_check;
1846-
1847-
pdev = to_pci_dev(dev);
1848-
if (domain->flags & PD_IOMMUV2_MASK) {
1849-
struct iommu_domain *def_domain = iommu_get_dma_domain(dev);
1850-
1851-
ret = -EINVAL;
1852-
1853-
/*
1854-
* In case of using AMD_IOMMU_V1 page table mode and the device
1855-
* is enabling for PPR/ATS support (using v2 table),
1856-
* we need to make sure that the domain type is identity map.
1857-
*/
1858-
if ((amd_iommu_pgtable == AMD_IOMMU_V1) &&
1859-
def_domain->type != IOMMU_DOMAIN_IDENTITY) {
1860-
goto out;
1861-
}
1862-
1863-
if (pdev_pasid_supported(dev_data)) {
1864-
if (pdev_pri_ats_enable(pdev) != 0)
1865-
goto out;
1866-
1867-
dev_data->ats_enabled = 1;
1868-
dev_data->ats_qdep = pci_ats_queue_depth(pdev);
1869-
dev_data->pri_tlp = pci_prg_resp_pasid_required(pdev);
1870-
}
1871-
} else if (amd_iommu_iotlb_sup &&
1872-
pci_enable_ats(pdev, PAGE_SHIFT) == 0) {
1873-
dev_data->ats_enabled = 1;
1874-
dev_data->ats_qdep = pci_ats_queue_depth(pdev);
18751907
}
18761908

1877-
skip_ats_check:
1878-
ret = 0;
1909+
if (dev_is_pci(dev))
1910+
pdev_enable_caps(to_pci_dev(dev));
18791911

18801912
do_attach(dev_data, domain);
18811913

@@ -1923,15 +1955,8 @@ static void detach_device(struct device *dev)
19231955

19241956
do_detach(dev_data);
19251957

1926-
if (!dev_is_pci(dev))
1927-
goto out;
1928-
1929-
if (domain->flags & PD_IOMMUV2_MASK && pdev_pasid_supported(dev_data))
1930-
pdev_iommuv2_disable(to_pci_dev(dev));
1931-
else if (dev_data->ats_enabled)
1932-
pci_disable_ats(to_pci_dev(dev));
1933-
1934-
dev_data->ats_enabled = 0;
1958+
if (dev_is_pci(dev))
1959+
pdev_disable_caps(to_pci_dev(dev));
19351960

19361961
out:
19371962
spin_unlock(&dev_data->lock);

0 commit comments

Comments
 (0)