diff options
| -rw-r--r-- | drivers/iommu/amd_iommu.c | 98 | ||||
| -rw-r--r-- | drivers/iommu/amd_iommu_init.c | 10 | ||||
| -rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 24 |
3 files changed, 51 insertions, 81 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index a57e9b749895..658ee39e6569 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
| @@ -76,8 +76,6 @@ LIST_HEAD(hpet_map); | |||
| 76 | * Domain for untranslated devices - only allocated | 76 | * Domain for untranslated devices - only allocated |
| 77 | * if iommu=pt passed on kernel cmd line. | 77 | * if iommu=pt passed on kernel cmd line. |
| 78 | */ | 78 | */ |
| 79 | static struct protection_domain *pt_domain; | ||
| 80 | |||
| 81 | static const struct iommu_ops amd_iommu_ops; | 79 | static const struct iommu_ops amd_iommu_ops; |
| 82 | 80 | ||
| 83 | static ATOMIC_NOTIFIER_HEAD(ppr_notifier); | 81 | static ATOMIC_NOTIFIER_HEAD(ppr_notifier); |
| @@ -96,7 +94,7 @@ struct iommu_dev_data { | |||
| 96 | struct protection_domain *domain; /* Domain the device is bound to */ | 94 | struct protection_domain *domain; /* Domain the device is bound to */ |
| 97 | u16 devid; /* PCI Device ID */ | 95 | u16 devid; /* PCI Device ID */ |
| 98 | bool iommu_v2; /* Device can make use of IOMMUv2 */ | 96 | bool iommu_v2; /* Device can make use of IOMMUv2 */ |
| 99 | bool passthrough; /* Default for device is pt_domain */ | 97 | bool passthrough; /* Device is identity mapped */ |
| 100 | struct { | 98 | struct { |
| 101 | bool enabled; | 99 | bool enabled; |
| 102 | int qdep; | 100 | int qdep; |
| @@ -116,7 +114,6 @@ struct iommu_cmd { | |||
| 116 | struct kmem_cache *amd_iommu_irq_cache; | 114 | struct kmem_cache *amd_iommu_irq_cache; |
| 117 | 115 | ||
| 118 | static void update_domain(struct protection_domain *domain); | 116 | static void update_domain(struct protection_domain *domain); |
| 119 | static int alloc_passthrough_domain(void); | ||
| 120 | static int protection_domain_init(struct protection_domain *domain); | 117 | static int protection_domain_init(struct protection_domain *domain); |
| 121 | 118 | ||
| 122 | /**************************************************************************** | 119 | /**************************************************************************** |
| @@ -2167,15 +2164,17 @@ static int attach_device(struct device *dev, | |||
| 2167 | dev_data = get_dev_data(dev); | 2164 | dev_data = get_dev_data(dev); |
| 2168 | 2165 | ||
| 2169 | if (domain->flags & PD_IOMMUV2_MASK) { | 2166 | if (domain->flags & PD_IOMMUV2_MASK) { |
| 2170 | if (!dev_data->iommu_v2 || !dev_data->passthrough) | 2167 | if (!dev_data->passthrough) |
| 2171 | return -EINVAL; | 2168 | return -EINVAL; |
| 2172 | 2169 | ||
| 2173 | if (pdev_iommuv2_enable(pdev) != 0) | 2170 | if (dev_data->iommu_v2) { |
| 2174 | return -EINVAL; | 2171 | if (pdev_iommuv2_enable(pdev) != 0) |
| 2172 | return -EINVAL; | ||
| 2175 | 2173 | ||
| 2176 | dev_data->ats.enabled = true; | 2174 | dev_data->ats.enabled = true; |
| 2177 | dev_data->ats.qdep = pci_ats_queue_depth(pdev); | 2175 | dev_data->ats.qdep = pci_ats_queue_depth(pdev); |
| 2178 | dev_data->pri_tlp = pci_pri_tlp_required(pdev); | 2176 | dev_data->pri_tlp = pci_pri_tlp_required(pdev); |
| 2177 | } | ||
| 2179 | } else if (amd_iommu_iotlb_sup && | 2178 | } else if (amd_iommu_iotlb_sup && |
| 2180 | pci_enable_ats(pdev, PAGE_SHIFT) == 0) { | 2179 | pci_enable_ats(pdev, PAGE_SHIFT) == 0) { |
| 2181 | dev_data->ats.enabled = true; | 2180 | dev_data->ats.enabled = true; |
| @@ -2221,15 +2220,6 @@ static void __detach_device(struct iommu_dev_data *dev_data) | |||
| 2221 | do_detach(head); | 2220 | do_detach(head); |
| 2222 | 2221 | ||
| 2223 | spin_unlock_irqrestore(&domain->lock, flags); | 2222 | spin_unlock_irqrestore(&domain->lock, flags); |
| 2224 | |||
| 2225 | /* | ||
| 2226 | * If we run in passthrough mode the device must be assigned to the | ||
| 2227 | * passthrough domain if it is detached from any other domain. | ||
| 2228 | * Make sure we can deassign from the pt_domain itself. | ||
| 2229 | */ | ||
| 2230 | if (dev_data->passthrough && | ||
| 2231 | (dev_data->domain == NULL && domain != pt_domain)) | ||
| 2232 | __attach_device(dev_data, pt_domain); | ||
| 2233 | } | 2223 | } |
| 2234 | 2224 | ||
| 2235 | /* | 2225 | /* |
| @@ -2249,7 +2239,7 @@ static void detach_device(struct device *dev) | |||
| 2249 | __detach_device(dev_data); | 2239 | __detach_device(dev_data); |
| 2250 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); | 2240 | write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); |
| 2251 | 2241 | ||
| 2252 | if (domain->flags & PD_IOMMUV2_MASK) | 2242 | if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2) |
| 2253 | pdev_iommuv2_disable(to_pci_dev(dev)); | 2243 | pdev_iommuv2_disable(to_pci_dev(dev)); |
| 2254 | else if (dev_data->ats.enabled) | 2244 | else if (dev_data->ats.enabled) |
| 2255 | pci_disable_ats(to_pci_dev(dev)); | 2245 | pci_disable_ats(to_pci_dev(dev)); |
| @@ -2287,17 +2277,15 @@ static int amd_iommu_add_device(struct device *dev) | |||
| 2287 | 2277 | ||
| 2288 | BUG_ON(!dev_data); | 2278 | BUG_ON(!dev_data); |
| 2289 | 2279 | ||
| 2290 | if (dev_data->iommu_v2) | 2280 | if (iommu_pass_through || dev_data->iommu_v2) |
| 2291 | iommu_request_dm_for_dev(dev); | 2281 | iommu_request_dm_for_dev(dev); |
| 2292 | 2282 | ||
| 2293 | /* Domains are initialized for this device - have a look what we ended up with */ | 2283 | /* Domains are initialized for this device - have a look what we ended up with */ |
| 2294 | domain = iommu_get_domain_for_dev(dev); | 2284 | domain = iommu_get_domain_for_dev(dev); |
| 2295 | if (domain->type == IOMMU_DOMAIN_IDENTITY) { | 2285 | if (domain->type == IOMMU_DOMAIN_IDENTITY) |
| 2296 | dev_data->passthrough = true; | 2286 | dev_data->passthrough = true; |
| 2297 | dev->archdata.dma_ops = &nommu_dma_ops; | 2287 | else |
| 2298 | } else { | ||
| 2299 | dev->archdata.dma_ops = &amd_iommu_dma_ops; | 2288 | dev->archdata.dma_ops = &amd_iommu_dma_ops; |
| 2300 | } | ||
| 2301 | 2289 | ||
| 2302 | out: | 2290 | out: |
| 2303 | iommu_completion_wait(iommu); | 2291 | iommu_completion_wait(iommu); |
| @@ -2862,8 +2850,17 @@ int __init amd_iommu_init_api(void) | |||
| 2862 | 2850 | ||
| 2863 | int __init amd_iommu_init_dma_ops(void) | 2851 | int __init amd_iommu_init_dma_ops(void) |
| 2864 | { | 2852 | { |
| 2853 | swiotlb = iommu_pass_through ? 1 : 0; | ||
| 2865 | iommu_detected = 1; | 2854 | iommu_detected = 1; |
| 2866 | swiotlb = 0; | 2855 | |
| 2856 | /* | ||
| 2857 | * In case we don't initialize SWIOTLB (actually the common case | ||
| 2858 | * when AMD IOMMU is enabled), make sure there are global | ||
| 2859 | * dma_ops set as a fall-back for devices not handled by this | ||
| 2860 | * driver (for example non-PCI devices). | ||
| 2861 | */ | ||
| 2862 | if (!swiotlb) | ||
| 2863 | dma_ops = &nommu_dma_ops; | ||
| 2867 | 2864 | ||
| 2868 | amd_iommu_stats_init(); | 2865 | amd_iommu_stats_init(); |
| 2869 | 2866 | ||
| @@ -2947,21 +2944,6 @@ out_err: | |||
| 2947 | return NULL; | 2944 | return NULL; |
| 2948 | } | 2945 | } |
| 2949 | 2946 | ||
| 2950 | static int alloc_passthrough_domain(void) | ||
| 2951 | { | ||
| 2952 | if (pt_domain != NULL) | ||
| 2953 | return 0; | ||
| 2954 | |||
| 2955 | /* allocate passthrough domain */ | ||
| 2956 | pt_domain = protection_domain_alloc(); | ||
| 2957 | if (!pt_domain) | ||
| 2958 | return -ENOMEM; | ||
| 2959 | |||
| 2960 | pt_domain->mode = PAGE_MODE_NONE; | ||
| 2961 | |||
| 2962 | return 0; | ||
| 2963 | } | ||
| 2964 | |||
| 2965 | static struct iommu_domain *amd_iommu_domain_alloc(unsigned type) | 2947 | static struct iommu_domain *amd_iommu_domain_alloc(unsigned type) |
| 2966 | { | 2948 | { |
| 2967 | struct protection_domain *pdomain; | 2949 | struct protection_domain *pdomain; |
| @@ -3222,33 +3204,6 @@ static const struct iommu_ops amd_iommu_ops = { | |||
| 3222 | * | 3204 | * |
| 3223 | *****************************************************************************/ | 3205 | *****************************************************************************/ |
| 3224 | 3206 | ||
| 3225 | int __init amd_iommu_init_passthrough(void) | ||
| 3226 | { | ||
| 3227 | struct iommu_dev_data *dev_data; | ||
| 3228 | struct pci_dev *dev = NULL; | ||
| 3229 | int ret; | ||
| 3230 | |||
| 3231 | ret = alloc_passthrough_domain(); | ||
| 3232 | if (ret) | ||
| 3233 | return ret; | ||
| 3234 | |||
| 3235 | for_each_pci_dev(dev) { | ||
| 3236 | if (!check_device(&dev->dev)) | ||
| 3237 | continue; | ||
| 3238 | |||
| 3239 | dev_data = get_dev_data(&dev->dev); | ||
| 3240 | dev_data->passthrough = true; | ||
| 3241 | |||
| 3242 | attach_device(&dev->dev, pt_domain); | ||
| 3243 | } | ||
| 3244 | |||
| 3245 | amd_iommu_stats_init(); | ||
| 3246 | |||
| 3247 | pr_info("AMD-Vi: Initialized for Passthrough Mode\n"); | ||
| 3248 | |||
| 3249 | return 0; | ||
| 3250 | } | ||
| 3251 | |||
| 3252 | /* IOMMUv2 specific functions */ | 3207 | /* IOMMUv2 specific functions */ |
| 3253 | int amd_iommu_register_ppr_notifier(struct notifier_block *nb) | 3208 | int amd_iommu_register_ppr_notifier(struct notifier_block *nb) |
| 3254 | { | 3209 | { |
| @@ -3363,7 +3318,12 @@ static int __flush_pasid(struct protection_domain *domain, int pasid, | |||
| 3363 | struct amd_iommu *iommu; | 3318 | struct amd_iommu *iommu; |
| 3364 | int qdep; | 3319 | int qdep; |
| 3365 | 3320 | ||
| 3366 | BUG_ON(!dev_data->ats.enabled); | 3321 | /* |
| 3322 | There might be non-IOMMUv2 capable devices in an IOMMUv2 | ||
| 3323 | * domain. | ||
| 3324 | */ | ||
| 3325 | if (!dev_data->ats.enabled) | ||
| 3326 | continue; | ||
| 3367 | 3327 | ||
| 3368 | qdep = dev_data->ats.qdep; | 3328 | qdep = dev_data->ats.qdep; |
| 3369 | iommu = amd_iommu_rlookup_table[dev_data->devid]; | 3329 | iommu = amd_iommu_rlookup_table[dev_data->devid]; |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index dbda9ae68c5d..a24495eb4e26 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
| @@ -2026,14 +2026,6 @@ static bool detect_ivrs(void) | |||
| 2026 | return true; | 2026 | return true; |
| 2027 | } | 2027 | } |
| 2028 | 2028 | ||
| 2029 | static int amd_iommu_init_dma(void) | ||
| 2030 | { | ||
| 2031 | if (iommu_pass_through) | ||
| 2032 | return amd_iommu_init_passthrough(); | ||
| 2033 | else | ||
| 2034 | return amd_iommu_init_dma_ops(); | ||
| 2035 | } | ||
| 2036 | |||
| 2037 | /**************************************************************************** | 2029 | /**************************************************************************** |
| 2038 | * | 2030 | * |
| 2039 | * AMD IOMMU Initialization State Machine | 2031 | * AMD IOMMU Initialization State Machine |
| @@ -2073,7 +2065,7 @@ static int __init state_next(void) | |||
| 2073 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_INTERRUPTS_EN; | 2065 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_INTERRUPTS_EN; |
| 2074 | break; | 2066 | break; |
| 2075 | case IOMMU_INTERRUPTS_EN: | 2067 | case IOMMU_INTERRUPTS_EN: |
| 2076 | ret = amd_iommu_init_dma(); | 2068 | ret = amd_iommu_init_dma_ops(); |
| 2077 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_DMA_OPS; | 2069 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_DMA_OPS; |
| 2078 | break; | 2070 | break; |
| 2079 | case IOMMU_DMA_OPS: | 2071 | case IOMMU_DMA_OPS: |
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 3465faf1809e..f7b875bb70d4 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
| @@ -132,11 +132,19 @@ static struct device_state *get_device_state(u16 devid) | |||
| 132 | 132 | ||
| 133 | static void free_device_state(struct device_state *dev_state) | 133 | static void free_device_state(struct device_state *dev_state) |
| 134 | { | 134 | { |
| 135 | struct iommu_group *group; | ||
| 136 | |||
| 135 | /* | 137 | /* |
| 136 | * First detach device from domain - No more PRI requests will arrive | 138 | * First detach device from domain - No more PRI requests will arrive |
| 137 | * from that device after it is unbound from the IOMMUv2 domain. | 139 | * from that device after it is unbound from the IOMMUv2 domain. |
| 138 | */ | 140 | */ |
| 139 | iommu_detach_device(dev_state->domain, &dev_state->pdev->dev); | 141 | group = iommu_group_get(&dev_state->pdev->dev); |
| 142 | if (WARN_ON(!group)) | ||
| 143 | return; | ||
| 144 | |||
| 145 | iommu_detach_group(dev_state->domain, group); | ||
| 146 | |||
| 147 | iommu_group_put(group); | ||
| 140 | 148 | ||
| 141 | /* Everything is down now, free the IOMMUv2 domain */ | 149 | /* Everything is down now, free the IOMMUv2 domain */ |
| 142 | iommu_domain_free(dev_state->domain); | 150 | iommu_domain_free(dev_state->domain); |
| @@ -731,6 +739,7 @@ EXPORT_SYMBOL(amd_iommu_unbind_pasid); | |||
| 731 | int amd_iommu_init_device(struct pci_dev *pdev, int pasids) | 739 | int amd_iommu_init_device(struct pci_dev *pdev, int pasids) |
| 732 | { | 740 | { |
| 733 | struct device_state *dev_state; | 741 | struct device_state *dev_state; |
| 742 | struct iommu_group *group; | ||
| 734 | unsigned long flags; | 743 | unsigned long flags; |
| 735 | int ret, tmp; | 744 | int ret, tmp; |
| 736 | u16 devid; | 745 | u16 devid; |
| @@ -776,10 +785,16 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids) | |||
| 776 | if (ret) | 785 | if (ret) |
| 777 | goto out_free_domain; | 786 | goto out_free_domain; |
| 778 | 787 | ||
| 779 | ret = iommu_attach_device(dev_state->domain, &pdev->dev); | 788 | group = iommu_group_get(&pdev->dev); |
| 780 | if (ret != 0) | 789 | if (!group) |
| 781 | goto out_free_domain; | 790 | goto out_free_domain; |
| 782 | 791 | ||
| 792 | ret = iommu_attach_group(dev_state->domain, group); | ||
| 793 | if (ret != 0) | ||
| 794 | goto out_drop_group; | ||
| 795 | |||
| 796 | iommu_group_put(group); | ||
| 797 | |||
| 783 | spin_lock_irqsave(&state_lock, flags); | 798 | spin_lock_irqsave(&state_lock, flags); |
| 784 | 799 | ||
| 785 | if (__get_device_state(devid) != NULL) { | 800 | if (__get_device_state(devid) != NULL) { |
| @@ -794,6 +809,9 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids) | |||
| 794 | 809 | ||
| 795 | return 0; | 810 | return 0; |
| 796 | 811 | ||
| 812 | out_drop_group: | ||
| 813 | iommu_group_put(group); | ||
| 814 | |||
| 797 | out_free_domain: | 815 | out_free_domain: |
| 798 | iommu_domain_free(dev_state->domain); | 816 | iommu_domain_free(dev_state->domain); |
| 799 | 817 | ||
