Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iommu/amd: Add amd_iommu_device_info() function

This function can be used to find out which features
necessary for IOMMUv2 usage are available on a given device.

Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>

+69
+43
drivers/iommu/amd_iommu.c
··· 3565 3565 dev_data->errata |= (1 << erratum); 3566 3566 } 3567 3567 EXPORT_SYMBOL(amd_iommu_enable_device_erratum); 3568 + 3569 + int amd_iommu_device_info(struct pci_dev *pdev, 3570 + struct amd_iommu_device_info *info) 3571 + { 3572 + int max_pasids; 3573 + int pos; 3574 + 3575 + if (pdev == NULL || info == NULL) 3576 + return -EINVAL; 3577 + 3578 + if (!amd_iommu_v2_supported()) 3579 + return -EINVAL; 3580 + 3581 + memset(info, 0, sizeof(*info)); 3582 + 3583 + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS); 3584 + if (pos) 3585 + info->flags |= AMD_IOMMU_DEVICE_FLAG_ATS_SUP; 3586 + 3587 + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); 3588 + if (pos) 3589 + info->flags |= AMD_IOMMU_DEVICE_FLAG_PRI_SUP; 3590 + 3591 + pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); 3592 + if (pos) { 3593 + int features; 3594 + 3595 + max_pasids = 1 << (9 * (amd_iommu_max_glx_val + 1)); 3596 + max_pasids = min(max_pasids, (1 << 20)); 3597 + 3598 + info->flags |= AMD_IOMMU_DEVICE_FLAG_PASID_SUP; 3599 + info->max_pasids = min(pci_max_pasids(pdev), max_pasids); 3600 + 3601 + features = pci_pasid_features(pdev); 3602 + if (features & PCI_PASID_CAP_EXEC) 3603 + info->flags |= AMD_IOMMU_DEVICE_FLAG_EXEC_SUP; 3604 + if (features & PCI_PASID_CAP_PRIV) 3605 + info->flags |= AMD_IOMMU_DEVICE_FLAG_PRIV_SUP; 3606 + } 3607 + 3608 + return 0; 3609 + } 3610 + EXPORT_SYMBOL(amd_iommu_device_info);
+26
include/linux/amd-iommu.h
··· 119 119 extern int amd_iommu_set_invalid_ppr_cb(struct pci_dev *pdev, 120 120 amd_iommu_invalid_ppr_cb cb); 121 121 122 + /** 123 + * amd_iommu_device_info() - Get information about IOMMUv2 support of a 124 + * PCI device 125 + * @pdev: PCI device to query information from 126 + * @info: A pointer to an amd_iommu_device_info structure which will contain 127 + * the information about the PCI device 128 + * 129 + * Returns 0 on success, negative value on error 130 + */ 131 + 132 + #define AMD_IOMMU_DEVICE_FLAG_ATS_SUP 0x1 /* ATS feature supported */ 133 + #define AMD_IOMMU_DEVICE_FLAG_PRI_SUP 0x2 /* PRI feature supported */ 134 + #define AMD_IOMMU_DEVICE_FLAG_PASID_SUP 0x4 /* PASID context supported */ 135 + #define AMD_IOMMU_DEVICE_FLAG_EXEC_SUP 0x8 /* Device may request execution 136 + on memory pages */ 137 + #define AMD_IOMMU_DEVICE_FLAG_PRIV_SUP 0x10 /* Device may request 138 + super-user privileges */ 139 + 140 + struct amd_iommu_device_info { 141 + int max_pasids; 142 + u32 flags; 143 + }; 144 + 145 + extern int amd_iommu_device_info(struct pci_dev *pdev, 146 + struct amd_iommu_device_info *info); 147 + 122 148 #else 123 149 124 150 static inline int amd_iommu_detect(void) { return -ENODEV; }