diff options
25 files changed, 1527 insertions, 481 deletions
diff --git a/Documentation/ABI/testing/sysfs-kernel-iommu_groups b/Documentation/ABI/testing/sysfs-kernel-iommu_groups new file mode 100644 index 000000000000..9b31556cfdda --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-iommu_groups | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | What: /sys/kernel/iommu_groups/ | ||
| 2 | Date: May 2012 | ||
| 3 | KernelVersion: v3.5 | ||
| 4 | Contact: Alex Williamson <alex.williamson@redhat.com> | ||
| 5 | Description: /sys/kernel/iommu_groups/ contains a number of sub- | ||
| 6 | directories, each representing an IOMMU group. The | ||
| 7 | name of the sub-directory matches the iommu_group_id() | ||
| 8 | for the group, which is an integer value. Within each | ||
| 9 | subdirectory is another directory named "devices" with | ||
| 10 | links to the sysfs devices contained in this group. | ||
| 11 | The group directory also optionally contains a "name" | ||
| 12 | file if the IOMMU driver has chosen to register a more | ||
| 13 | common name for the group. | ||
| 14 | Users: | ||
diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt new file mode 100644 index 000000000000..89fb5434b730 --- /dev/null +++ b/Documentation/devicetree/bindings/iommu/nvidia,tegra30-smmu.txt | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | NVIDIA Tegra 30 IOMMU H/W, SMMU (System Memory Management Unit) | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : "nvidia,tegra30-smmu" | ||
| 5 | - reg : Should contain 3 register banks(address and length) for each | ||
| 6 | of the SMMU register blocks. | ||
| 7 | - interrupts : Should contain MC General interrupt. | ||
| 8 | - nvidia,#asids : # of ASIDs | ||
| 9 | - dma-window : IOVA start address and length. | ||
| 10 | - nvidia,ahb : phandle to the ahb bus connected to SMMU. | ||
| 11 | |||
| 12 | Example: | ||
| 13 | smmu { | ||
| 14 | compatible = "nvidia,tegra30-smmu"; | ||
| 15 | reg = <0x7000f010 0x02c | ||
| 16 | 0x7000f1f0 0x010 | ||
| 17 | 0x7000f228 0x05c>; | ||
| 18 | nvidia,#asids = <4>; /* # of ASIDs */ | ||
| 19 | dma-window = <0 0x40000000>; /* IOVA start & length */ | ||
| 20 | nvidia,ahb = <&ahb>; | ||
| 21 | }; | ||
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 12783fa833c3..e714a025c99d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1134,7 +1134,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. | |||
| 1134 | forcesac | 1134 | forcesac |
| 1135 | soft | 1135 | soft |
| 1136 | pt [x86, IA-64] | 1136 | pt [x86, IA-64] |
| 1137 | group_mf [x86, IA-64] | ||
| 1138 | 1137 | ||
| 1139 | 1138 | ||
| 1140 | io7= [HW] IO7 for Marvel based alpha systems | 1139 | io7= [HW] IO7 for Marvel based alpha systems |
diff --git a/arch/ia64/include/asm/iommu.h b/arch/ia64/include/asm/iommu.h index b6a809fa2995..105c93b00b1b 100644 --- a/arch/ia64/include/asm/iommu.h +++ b/arch/ia64/include/asm/iommu.h | |||
| @@ -11,12 +11,10 @@ extern void no_iommu_init(void); | |||
| 11 | extern int force_iommu, no_iommu; | 11 | extern int force_iommu, no_iommu; |
| 12 | extern int iommu_pass_through; | 12 | extern int iommu_pass_through; |
| 13 | extern int iommu_detected; | 13 | extern int iommu_detected; |
| 14 | extern int iommu_group_mf; | ||
| 15 | #else | 14 | #else |
| 16 | #define iommu_pass_through (0) | 15 | #define iommu_pass_through (0) |
| 17 | #define no_iommu (1) | 16 | #define no_iommu (1) |
| 18 | #define iommu_detected (0) | 17 | #define iommu_detected (0) |
| 19 | #define iommu_group_mf (0) | ||
| 20 | #endif | 18 | #endif |
| 21 | extern void iommu_dma_init(void); | 19 | extern void iommu_dma_init(void); |
| 22 | extern void machvec_init(const char *name); | 20 | extern void machvec_init(const char *name); |
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c index 7cdc89b2483c..1ddcfe5ef353 100644 --- a/arch/ia64/kernel/pci-dma.c +++ b/arch/ia64/kernel/pci-dma.c | |||
| @@ -32,7 +32,6 @@ int force_iommu __read_mostly; | |||
| 32 | #endif | 32 | #endif |
| 33 | 33 | ||
| 34 | int iommu_pass_through; | 34 | int iommu_pass_through; |
| 35 | int iommu_group_mf; | ||
| 36 | 35 | ||
| 37 | /* Dummy device used for NULL arguments (normally ISA). Better would | 36 | /* Dummy device used for NULL arguments (normally ISA). Better would |
| 38 | be probably a smaller DMA mask, but this is bug-to-bug compatible | 37 | be probably a smaller DMA mask, but this is bug-to-bug compatible |
diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index dffc38ee6255..345c99cef152 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h | |||
| @@ -5,7 +5,6 @@ extern struct dma_map_ops nommu_dma_ops; | |||
| 5 | extern int force_iommu, no_iommu; | 5 | extern int force_iommu, no_iommu; |
| 6 | extern int iommu_detected; | 6 | extern int iommu_detected; |
| 7 | extern int iommu_pass_through; | 7 | extern int iommu_pass_through; |
| 8 | extern int iommu_group_mf; | ||
| 9 | 8 | ||
| 10 | /* 10 seconds */ | 9 | /* 10 seconds */ |
| 11 | #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) | 10 | #define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) |
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index c0f420f76cd3..de2b7ad70273 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c | |||
| @@ -45,15 +45,6 @@ int iommu_detected __read_mostly = 0; | |||
| 45 | */ | 45 | */ |
| 46 | int iommu_pass_through __read_mostly; | 46 | int iommu_pass_through __read_mostly; |
| 47 | 47 | ||
| 48 | /* | ||
| 49 | * Group multi-function PCI devices into a single device-group for the | ||
| 50 | * iommu_device_group interface. This tells the iommu driver to pretend | ||
| 51 | * it cannot distinguish between functions of a device, exposing only one | ||
| 52 | * group for the device. Useful for disallowing use of individual PCI | ||
| 53 | * functions from userspace drivers. | ||
| 54 | */ | ||
| 55 | int iommu_group_mf __read_mostly; | ||
| 56 | |||
| 57 | extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; | 48 | extern struct iommu_table_entry __iommu_table[], __iommu_table_end[]; |
| 58 | 49 | ||
| 59 | /* Dummy device used for NULL arguments (normally ISA). */ | 50 | /* Dummy device used for NULL arguments (normally ISA). */ |
| @@ -194,8 +185,6 @@ static __init int iommu_setup(char *p) | |||
| 194 | #endif | 185 | #endif |
| 195 | if (!strncmp(p, "pt", 2)) | 186 | if (!strncmp(p, "pt", 2)) |
| 196 | iommu_pass_through = 1; | 187 | iommu_pass_through = 1; |
| 197 | if (!strncmp(p, "group_mf", 8)) | ||
| 198 | iommu_group_mf = 1; | ||
| 199 | 188 | ||
| 200 | gart_parse_options(p); | 189 | gart_parse_options(p); |
| 201 | 190 | ||
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 340893727538..9f69b561f5db 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
| @@ -13,6 +13,10 @@ menuconfig IOMMU_SUPPORT | |||
| 13 | 13 | ||
| 14 | if IOMMU_SUPPORT | 14 | if IOMMU_SUPPORT |
| 15 | 15 | ||
| 16 | config OF_IOMMU | ||
| 17 | def_bool y | ||
| 18 | depends on OF | ||
| 19 | |||
| 16 | # MSM IOMMU support | 20 | # MSM IOMMU support |
| 17 | config MSM_IOMMU | 21 | config MSM_IOMMU |
| 18 | bool "MSM IOMMU Support" | 22 | bool "MSM IOMMU Support" |
| @@ -154,7 +158,7 @@ config TEGRA_IOMMU_GART | |||
| 154 | 158 | ||
| 155 | config TEGRA_IOMMU_SMMU | 159 | config TEGRA_IOMMU_SMMU |
| 156 | bool "Tegra SMMU IOMMU Support" | 160 | bool "Tegra SMMU IOMMU Support" |
| 157 | depends on ARCH_TEGRA_3x_SOC | 161 | depends on ARCH_TEGRA_3x_SOC && TEGRA_AHB |
| 158 | select IOMMU_API | 162 | select IOMMU_API |
| 159 | help | 163 | help |
| 160 | Enables support for remapping discontiguous physical memory | 164 | Enables support for remapping discontiguous physical memory |
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 76e54ef796de..14a4d5fc94fa 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | obj-$(CONFIG_IOMMU_API) += iommu.o | 1 | obj-$(CONFIG_IOMMU_API) += iommu.o |
| 2 | obj-$(CONFIG_OF_IOMMU) += of_iommu.o | ||
| 2 | obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o | 3 | obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o |
| 3 | obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o | 4 | obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o |
| 4 | obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o | 5 | obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 625626391f2d..6d1cbdfc9b2a 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
| @@ -256,11 +256,21 @@ static bool check_device(struct device *dev) | |||
| 256 | return true; | 256 | return true; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) | ||
| 260 | { | ||
| 261 | pci_dev_put(*from); | ||
| 262 | *from = to; | ||
| 263 | } | ||
| 264 | |||
| 265 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) | ||
| 266 | |||
| 259 | static int iommu_init_device(struct device *dev) | 267 | static int iommu_init_device(struct device *dev) |
| 260 | { | 268 | { |
| 261 | struct pci_dev *pdev = to_pci_dev(dev); | 269 | struct pci_dev *dma_pdev, *pdev = to_pci_dev(dev); |
| 262 | struct iommu_dev_data *dev_data; | 270 | struct iommu_dev_data *dev_data; |
| 271 | struct iommu_group *group; | ||
| 263 | u16 alias; | 272 | u16 alias; |
| 273 | int ret; | ||
| 264 | 274 | ||
| 265 | if (dev->archdata.iommu) | 275 | if (dev->archdata.iommu) |
| 266 | return 0; | 276 | return 0; |
| @@ -281,8 +291,43 @@ static int iommu_init_device(struct device *dev) | |||
| 281 | return -ENOTSUPP; | 291 | return -ENOTSUPP; |
| 282 | } | 292 | } |
| 283 | dev_data->alias_data = alias_data; | 293 | dev_data->alias_data = alias_data; |
| 294 | |||
| 295 | dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff); | ||
| 296 | } else | ||
| 297 | dma_pdev = pci_dev_get(pdev); | ||
| 298 | |||
| 299 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | ||
| 300 | |||
| 301 | if (dma_pdev->multifunction && | ||
| 302 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) | ||
| 303 | swap_pci_ref(&dma_pdev, | ||
| 304 | pci_get_slot(dma_pdev->bus, | ||
| 305 | PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), | ||
| 306 | 0))); | ||
| 307 | |||
| 308 | while (!pci_is_root_bus(dma_pdev->bus)) { | ||
| 309 | if (pci_acs_path_enabled(dma_pdev->bus->self, | ||
| 310 | NULL, REQ_ACS_FLAGS)) | ||
| 311 | break; | ||
| 312 | |||
| 313 | swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); | ||
| 314 | } | ||
| 315 | |||
| 316 | group = iommu_group_get(&dma_pdev->dev); | ||
| 317 | pci_dev_put(dma_pdev); | ||
| 318 | if (!group) { | ||
| 319 | group = iommu_group_alloc(); | ||
| 320 | if (IS_ERR(group)) | ||
| 321 | return PTR_ERR(group); | ||
| 284 | } | 322 | } |
| 285 | 323 | ||
| 324 | ret = iommu_group_add_device(group, dev); | ||
| 325 | |||
| 326 | iommu_group_put(group); | ||
| 327 | |||
| 328 | if (ret) | ||
| 329 | return ret; | ||
| 330 | |||
| 286 | if (pci_iommuv2_capable(pdev)) { | 331 | if (pci_iommuv2_capable(pdev)) { |
| 287 | struct amd_iommu *iommu; | 332 | struct amd_iommu *iommu; |
| 288 | 333 | ||
| @@ -311,6 +356,8 @@ static void iommu_ignore_device(struct device *dev) | |||
| 311 | 356 | ||
| 312 | static void iommu_uninit_device(struct device *dev) | 357 | static void iommu_uninit_device(struct device *dev) |
| 313 | { | 358 | { |
| 359 | iommu_group_remove_device(dev); | ||
| 360 | |||
| 314 | /* | 361 | /* |
| 315 | * Nothing to do here - we keep dev_data around for unplugged devices | 362 | * Nothing to do here - we keep dev_data around for unplugged devices |
| 316 | * and reuse it when the device is re-plugged - not doing so would | 363 | * and reuse it when the device is re-plugged - not doing so would |
| @@ -384,7 +431,6 @@ DECLARE_STATS_COUNTER(invalidate_iotlb); | |||
| 384 | DECLARE_STATS_COUNTER(invalidate_iotlb_all); | 431 | DECLARE_STATS_COUNTER(invalidate_iotlb_all); |
| 385 | DECLARE_STATS_COUNTER(pri_requests); | 432 | DECLARE_STATS_COUNTER(pri_requests); |
| 386 | 433 | ||
| 387 | |||
| 388 | static struct dentry *stats_dir; | 434 | static struct dentry *stats_dir; |
| 389 | static struct dentry *de_fflush; | 435 | static struct dentry *de_fflush; |
| 390 | 436 | ||
| @@ -2073,7 +2119,7 @@ out_err: | |||
| 2073 | /* FIXME: Move this to PCI code */ | 2119 | /* FIXME: Move this to PCI code */ |
| 2074 | #define PCI_PRI_TLP_OFF (1 << 15) | 2120 | #define PCI_PRI_TLP_OFF (1 << 15) |
| 2075 | 2121 | ||
| 2076 | bool pci_pri_tlp_required(struct pci_dev *pdev) | 2122 | static bool pci_pri_tlp_required(struct pci_dev *pdev) |
| 2077 | { | 2123 | { |
| 2078 | u16 status; | 2124 | u16 status; |
| 2079 | int pos; | 2125 | int pos; |
| @@ -2254,6 +2300,18 @@ static int device_change_notifier(struct notifier_block *nb, | |||
| 2254 | 2300 | ||
| 2255 | iommu_init_device(dev); | 2301 | iommu_init_device(dev); |
| 2256 | 2302 | ||
| 2303 | /* | ||
| 2304 | * dev_data is still NULL and | ||
| 2305 | * got initialized in iommu_init_device | ||
| 2306 | */ | ||
| 2307 | dev_data = get_dev_data(dev); | ||
| 2308 | |||
| 2309 | if (iommu_pass_through || dev_data->iommu_v2) { | ||
| 2310 | dev_data->passthrough = true; | ||
| 2311 | attach_device(dev, pt_domain); | ||
| 2312 | break; | ||
| 2313 | } | ||
| 2314 | |||
| 2257 | domain = domain_for_device(dev); | 2315 | domain = domain_for_device(dev); |
| 2258 | 2316 | ||
| 2259 | /* allocate a protection domain if a device is added */ | 2317 | /* allocate a protection domain if a device is added */ |
| @@ -2271,10 +2329,7 @@ static int device_change_notifier(struct notifier_block *nb, | |||
| 2271 | 2329 | ||
| 2272 | dev_data = get_dev_data(dev); | 2330 | dev_data = get_dev_data(dev); |
| 2273 | 2331 | ||
| 2274 | if (!dev_data->passthrough) | 2332 | dev->archdata.dma_ops = &amd_iommu_dma_ops; |
| 2275 | dev->archdata.dma_ops = &amd_iommu_dma_ops; | ||
| 2276 | else | ||
| 2277 | dev->archdata.dma_ops = &nommu_dma_ops; | ||
| 2278 | 2333 | ||
| 2279 | break; | 2334 | break; |
| 2280 | case BUS_NOTIFY_DEL_DEVICE: | 2335 | case BUS_NOTIFY_DEL_DEVICE: |
| @@ -2972,6 +3027,11 @@ int __init amd_iommu_init_dma_ops(void) | |||
| 2972 | 3027 | ||
| 2973 | amd_iommu_stats_init(); | 3028 | amd_iommu_stats_init(); |
| 2974 | 3029 | ||
| 3030 | if (amd_iommu_unmap_flush) | ||
| 3031 | pr_info("AMD-Vi: IO/TLB flush on unmap enabled\n"); | ||
| 3032 | else | ||
| 3033 | pr_info("AMD-Vi: Lazy IO/TLB flushing enabled\n"); | ||
| 3034 | |||
| 2975 | return 0; | 3035 | return 0; |
| 2976 | 3036 | ||
| 2977 | free_domains: | 3037 | free_domains: |
| @@ -3078,6 +3138,10 @@ static int amd_iommu_domain_init(struct iommu_domain *dom) | |||
| 3078 | 3138 | ||
| 3079 | dom->priv = domain; | 3139 | dom->priv = domain; |
| 3080 | 3140 | ||
| 3141 | dom->geometry.aperture_start = 0; | ||
| 3142 | dom->geometry.aperture_end = ~0ULL; | ||
| 3143 | dom->geometry.force_aperture = true; | ||
| 3144 | |||
| 3081 | return 0; | 3145 | return 0; |
| 3082 | 3146 | ||
| 3083 | out_free: | 3147 | out_free: |
| @@ -3236,26 +3300,6 @@ static int amd_iommu_domain_has_cap(struct iommu_domain *domain, | |||
| 3236 | return 0; | 3300 | return 0; |
| 3237 | } | 3301 | } |
| 3238 | 3302 | ||
| 3239 | static int amd_iommu_device_group(struct device *dev, unsigned int *groupid) | ||
| 3240 | { | ||
| 3241 | struct iommu_dev_data *dev_data = dev->archdata.iommu; | ||
| 3242 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 3243 | u16 devid; | ||
| 3244 | |||
| 3245 | if (!dev_data) | ||
| 3246 | return -ENODEV; | ||
| 3247 | |||
| 3248 | if (pdev->is_virtfn || !iommu_group_mf) | ||
| 3249 | devid = dev_data->devid; | ||
| 3250 | else | ||
| 3251 | devid = calc_devid(pdev->bus->number, | ||
| 3252 | PCI_DEVFN(PCI_SLOT(pdev->devfn), 0)); | ||
| 3253 | |||
| 3254 | *groupid = amd_iommu_alias_table[devid]; | ||
| 3255 | |||
| 3256 | return 0; | ||
| 3257 | } | ||
| 3258 | |||
| 3259 | static struct iommu_ops amd_iommu_ops = { | 3303 | static struct iommu_ops amd_iommu_ops = { |
| 3260 | .domain_init = amd_iommu_domain_init, | 3304 | .domain_init = amd_iommu_domain_init, |
| 3261 | .domain_destroy = amd_iommu_domain_destroy, | 3305 | .domain_destroy = amd_iommu_domain_destroy, |
| @@ -3265,7 +3309,6 @@ static struct iommu_ops amd_iommu_ops = { | |||
| 3265 | .unmap = amd_iommu_unmap, | 3309 | .unmap = amd_iommu_unmap, |
| 3266 | .iova_to_phys = amd_iommu_iova_to_phys, | 3310 | .iova_to_phys = amd_iommu_iova_to_phys, |
| 3267 | .domain_has_cap = amd_iommu_domain_has_cap, | 3311 | .domain_has_cap = amd_iommu_domain_has_cap, |
| 3268 | .device_group = amd_iommu_device_group, | ||
| 3269 | .pgsize_bitmap = AMD_IOMMU_PGSIZES, | 3312 | .pgsize_bitmap = AMD_IOMMU_PGSIZES, |
| 3270 | }; | 3313 | }; |
| 3271 | 3314 | ||
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index a33612f3206f..500e7f15f5c2 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #include <linux/msi.h> | 26 | #include <linux/msi.h> |
| 27 | #include <linux/amd-iommu.h> | 27 | #include <linux/amd-iommu.h> |
| 28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
| 29 | #include <linux/acpi.h> | ||
| 30 | #include <acpi/acpi.h> | ||
| 29 | #include <asm/pci-direct.h> | 31 | #include <asm/pci-direct.h> |
| 30 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
| 31 | #include <asm/gart.h> | 33 | #include <asm/gart.h> |
| @@ -122,7 +124,7 @@ struct ivmd_header { | |||
| 122 | 124 | ||
| 123 | bool amd_iommu_dump; | 125 | bool amd_iommu_dump; |
| 124 | 126 | ||
| 125 | static int __initdata amd_iommu_detected; | 127 | static bool amd_iommu_detected; |
| 126 | static bool __initdata amd_iommu_disabled; | 128 | static bool __initdata amd_iommu_disabled; |
| 127 | 129 | ||
| 128 | u16 amd_iommu_last_bdf; /* largest PCI device id we have | 130 | u16 amd_iommu_last_bdf; /* largest PCI device id we have |
| @@ -149,11 +151,6 @@ bool amd_iommu_v2_present __read_mostly; | |||
| 149 | bool amd_iommu_force_isolation __read_mostly; | 151 | bool amd_iommu_force_isolation __read_mostly; |
| 150 | 152 | ||
| 151 | /* | 153 | /* |
| 152 | * The ACPI table parsing functions set this variable on an error | ||
| 153 | */ | ||
| 154 | static int __initdata amd_iommu_init_err; | ||
| 155 | |||
| 156 | /* | ||
| 157 | * List of protection domains - used during resume | 154 | * List of protection domains - used during resume |
| 158 | */ | 155 | */ |
| 159 | LIST_HEAD(amd_iommu_pd_list); | 156 | LIST_HEAD(amd_iommu_pd_list); |
| @@ -190,13 +187,23 @@ static u32 dev_table_size; /* size of the device table */ | |||
| 190 | static u32 alias_table_size; /* size of the alias table */ | 187 | static u32 alias_table_size; /* size of the alias table */ |
| 191 | static u32 rlookup_table_size; /* size if the rlookup table */ | 188 | static u32 rlookup_table_size; /* size if the rlookup table */ |
| 192 | 189 | ||
| 193 | /* | 190 | enum iommu_init_state { |
| 194 | * This function flushes all internal caches of | 191 | IOMMU_START_STATE, |
| 195 | * the IOMMU used by this driver. | 192 | IOMMU_IVRS_DETECTED, |
| 196 | */ | 193 | IOMMU_ACPI_FINISHED, |
| 197 | extern void iommu_flush_all_caches(struct amd_iommu *iommu); | 194 | IOMMU_ENABLED, |
| 195 | IOMMU_PCI_INIT, | ||
| 196 | IOMMU_INTERRUPTS_EN, | ||
| 197 | IOMMU_DMA_OPS, | ||
| 198 | IOMMU_INITIALIZED, | ||
| 199 | IOMMU_NOT_FOUND, | ||
| 200 | IOMMU_INIT_ERROR, | ||
| 201 | }; | ||
| 202 | |||
| 203 | static enum iommu_init_state init_state = IOMMU_START_STATE; | ||
| 198 | 204 | ||
| 199 | static int amd_iommu_enable_interrupts(void); | 205 | static int amd_iommu_enable_interrupts(void); |
| 206 | static int __init iommu_go_to_state(enum iommu_init_state state); | ||
| 200 | 207 | ||
| 201 | static inline void update_last_devid(u16 devid) | 208 | static inline void update_last_devid(u16 devid) |
| 202 | { | 209 | { |
| @@ -321,23 +328,6 @@ static void iommu_set_inv_tlb_timeout(struct amd_iommu *iommu, int timeout) | |||
| 321 | /* Function to enable the hardware */ | 328 | /* Function to enable the hardware */ |
| 322 | static void iommu_enable(struct amd_iommu *iommu) | 329 | static void iommu_enable(struct amd_iommu *iommu) |
| 323 | { | 330 | { |
| 324 | static const char * const feat_str[] = { | ||
| 325 | "PreF", "PPR", "X2APIC", "NX", "GT", "[5]", | ||
| 326 | "IA", "GA", "HE", "PC", NULL | ||
| 327 | }; | ||
| 328 | int i; | ||
| 329 | |||
| 330 | printk(KERN_INFO "AMD-Vi: Enabling IOMMU at %s cap 0x%hx", | ||
| 331 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | ||
| 332 | |||
| 333 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | ||
| 334 | printk(KERN_CONT " extended features: "); | ||
| 335 | for (i = 0; feat_str[i]; ++i) | ||
| 336 | if (iommu_feature(iommu, (1ULL << i))) | ||
| 337 | printk(KERN_CONT " %s", feat_str[i]); | ||
| 338 | } | ||
| 339 | printk(KERN_CONT "\n"); | ||
| 340 | |||
| 341 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); | 331 | iommu_feature_enable(iommu, CONTROL_IOMMU_EN); |
| 342 | } | 332 | } |
| 343 | 333 | ||
| @@ -358,7 +348,7 @@ static void iommu_disable(struct amd_iommu *iommu) | |||
| 358 | * mapping and unmapping functions for the IOMMU MMIO space. Each AMD IOMMU in | 348 | * mapping and unmapping functions for the IOMMU MMIO space. Each AMD IOMMU in |
| 359 | * the system has one. | 349 | * the system has one. |
| 360 | */ | 350 | */ |
| 361 | static u8 * __init iommu_map_mmio_space(u64 address) | 351 | static u8 __iomem * __init iommu_map_mmio_space(u64 address) |
| 362 | { | 352 | { |
| 363 | if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) { | 353 | if (!request_mem_region(address, MMIO_REGION_LENGTH, "amd_iommu")) { |
| 364 | pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n", | 354 | pr_err("AMD-Vi: Can not reserve memory region %llx for mmio\n", |
| @@ -367,7 +357,7 @@ static u8 * __init iommu_map_mmio_space(u64 address) | |||
| 367 | return NULL; | 357 | return NULL; |
| 368 | } | 358 | } |
| 369 | 359 | ||
| 370 | return ioremap_nocache(address, MMIO_REGION_LENGTH); | 360 | return (u8 __iomem *)ioremap_nocache(address, MMIO_REGION_LENGTH); |
| 371 | } | 361 | } |
| 372 | 362 | ||
| 373 | static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) | 363 | static void __init iommu_unmap_mmio_space(struct amd_iommu *iommu) |
| @@ -463,11 +453,9 @@ static int __init find_last_devid_acpi(struct acpi_table_header *table) | |||
| 463 | */ | 453 | */ |
| 464 | for (i = 0; i < table->length; ++i) | 454 | for (i = 0; i < table->length; ++i) |
| 465 | checksum += p[i]; | 455 | checksum += p[i]; |
| 466 | if (checksum != 0) { | 456 | if (checksum != 0) |
| 467 | /* ACPI table corrupt */ | 457 | /* ACPI table corrupt */ |
| 468 | amd_iommu_init_err = -ENODEV; | 458 | return -ENODEV; |
| 469 | return 0; | ||
| 470 | } | ||
| 471 | 459 | ||
| 472 | p += IVRS_HEADER_LENGTH; | 460 | p += IVRS_HEADER_LENGTH; |
| 473 | 461 | ||
| @@ -726,90 +714,6 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) | |||
| 726 | } | 714 | } |
| 727 | 715 | ||
| 728 | /* | 716 | /* |
| 729 | * This function reads some important data from the IOMMU PCI space and | ||
| 730 | * initializes the driver data structure with it. It reads the hardware | ||
| 731 | * capabilities and the first/last device entries | ||
| 732 | */ | ||
| 733 | static void __init init_iommu_from_pci(struct amd_iommu *iommu) | ||
| 734 | { | ||
| 735 | int cap_ptr = iommu->cap_ptr; | ||
| 736 | u32 range, misc, low, high; | ||
| 737 | int i, j; | ||
| 738 | |||
| 739 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, | ||
| 740 | &iommu->cap); | ||
| 741 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, | ||
| 742 | &range); | ||
| 743 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET, | ||
| 744 | &misc); | ||
| 745 | |||
| 746 | iommu->first_device = calc_devid(MMIO_GET_BUS(range), | ||
| 747 | MMIO_GET_FD(range)); | ||
| 748 | iommu->last_device = calc_devid(MMIO_GET_BUS(range), | ||
| 749 | MMIO_GET_LD(range)); | ||
| 750 | iommu->evt_msi_num = MMIO_MSI_NUM(misc); | ||
| 751 | |||
| 752 | if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB))) | ||
| 753 | amd_iommu_iotlb_sup = false; | ||
| 754 | |||
| 755 | /* read extended feature bits */ | ||
| 756 | low = readl(iommu->mmio_base + MMIO_EXT_FEATURES); | ||
| 757 | high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4); | ||
| 758 | |||
| 759 | iommu->features = ((u64)high << 32) | low; | ||
| 760 | |||
| 761 | if (iommu_feature(iommu, FEATURE_GT)) { | ||
| 762 | int glxval; | ||
| 763 | u32 pasids; | ||
| 764 | u64 shift; | ||
| 765 | |||
| 766 | shift = iommu->features & FEATURE_PASID_MASK; | ||
| 767 | shift >>= FEATURE_PASID_SHIFT; | ||
| 768 | pasids = (1 << shift); | ||
| 769 | |||
| 770 | amd_iommu_max_pasids = min(amd_iommu_max_pasids, pasids); | ||
| 771 | |||
| 772 | glxval = iommu->features & FEATURE_GLXVAL_MASK; | ||
| 773 | glxval >>= FEATURE_GLXVAL_SHIFT; | ||
| 774 | |||
| 775 | if (amd_iommu_max_glx_val == -1) | ||
| 776 | amd_iommu_max_glx_val = glxval; | ||
| 777 | else | ||
| 778 | amd_iommu_max_glx_val = min(amd_iommu_max_glx_val, glxval); | ||
| 779 | } | ||
| 780 | |||
| 781 | if (iommu_feature(iommu, FEATURE_GT) && | ||
| 782 | iommu_feature(iommu, FEATURE_PPR)) { | ||
| 783 | iommu->is_iommu_v2 = true; | ||
| 784 | amd_iommu_v2_present = true; | ||
| 785 | } | ||
| 786 | |||
| 787 | if (!is_rd890_iommu(iommu->dev)) | ||
| 788 | return; | ||
| 789 | |||
| 790 | /* | ||
| 791 | * Some rd890 systems may not be fully reconfigured by the BIOS, so | ||
| 792 | * it's necessary for us to store this information so it can be | ||
| 793 | * reprogrammed on resume | ||
| 794 | */ | ||
| 795 | |||
| 796 | pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4, | ||
| 797 | &iommu->stored_addr_lo); | ||
| 798 | pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8, | ||
| 799 | &iommu->stored_addr_hi); | ||
| 800 | |||
| 801 | /* Low bit locks writes to configuration space */ | ||
| 802 | iommu->stored_addr_lo &= ~1; | ||
| 803 | |||
| 804 | for (i = 0; i < 6; i++) | ||
| 805 | for (j = 0; j < 0x12; j++) | ||
| 806 | iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j); | ||
| 807 | |||
| 808 | for (i = 0; i < 0x83; i++) | ||
| 809 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); | ||
| 810 | } | ||
| 811 | |||
| 812 | /* | ||
| 813 | * Takes a pointer to an AMD IOMMU entry in the ACPI table and | 717 | * Takes a pointer to an AMD IOMMU entry in the ACPI table and |
| 814 | * initializes the hardware and our data structures with it. | 718 | * initializes the hardware and our data structures with it. |
| 815 | */ | 719 | */ |
| @@ -1025,13 +929,7 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
| 1025 | /* | 929 | /* |
| 1026 | * Copy data from ACPI table entry to the iommu struct | 930 | * Copy data from ACPI table entry to the iommu struct |
| 1027 | */ | 931 | */ |
| 1028 | iommu->dev = pci_get_bus_and_slot(PCI_BUS(h->devid), h->devid & 0xff); | 932 | iommu->devid = h->devid; |
| 1029 | if (!iommu->dev) | ||
| 1030 | return 1; | ||
| 1031 | |||
| 1032 | iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number, | ||
| 1033 | PCI_DEVFN(0, 0)); | ||
| 1034 | |||
| 1035 | iommu->cap_ptr = h->cap_ptr; | 933 | iommu->cap_ptr = h->cap_ptr; |
| 1036 | iommu->pci_seg = h->pci_seg; | 934 | iommu->pci_seg = h->pci_seg; |
| 1037 | iommu->mmio_phys = h->mmio_phys; | 935 | iommu->mmio_phys = h->mmio_phys; |
| @@ -1049,20 +947,10 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) | |||
| 1049 | 947 | ||
| 1050 | iommu->int_enabled = false; | 948 | iommu->int_enabled = false; |
| 1051 | 949 | ||
| 1052 | init_iommu_from_pci(iommu); | ||
| 1053 | init_iommu_from_acpi(iommu, h); | 950 | init_iommu_from_acpi(iommu, h); |
| 1054 | init_iommu_devices(iommu); | 951 | init_iommu_devices(iommu); |
| 1055 | 952 | ||
| 1056 | if (iommu_feature(iommu, FEATURE_PPR)) { | 953 | return 0; |
| 1057 | iommu->ppr_log = alloc_ppr_log(iommu); | ||
| 1058 | if (!iommu->ppr_log) | ||
| 1059 | return -ENOMEM; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) | ||
| 1063 | amd_iommu_np_cache = true; | ||
| 1064 | |||
| 1065 | return pci_enable_device(iommu->dev); | ||
| 1066 | } | 954 | } |
| 1067 | 955 | ||
| 1068 | /* | 956 | /* |
| @@ -1093,16 +981,12 @@ static int __init init_iommu_all(struct acpi_table_header *table) | |||
| 1093 | h->mmio_phys); | 981 | h->mmio_phys); |
| 1094 | 982 | ||
| 1095 | iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL); | 983 | iommu = kzalloc(sizeof(struct amd_iommu), GFP_KERNEL); |
| 1096 | if (iommu == NULL) { | 984 | if (iommu == NULL) |
| 1097 | amd_iommu_init_err = -ENOMEM; | 985 | return -ENOMEM; |
| 1098 | return 0; | ||
| 1099 | } | ||
| 1100 | 986 | ||
| 1101 | ret = init_iommu_one(iommu, h); | 987 | ret = init_iommu_one(iommu, h); |
| 1102 | if (ret) { | 988 | if (ret) |
| 1103 | amd_iommu_init_err = ret; | 989 | return ret; |
| 1104 | return 0; | ||
| 1105 | } | ||
| 1106 | break; | 990 | break; |
| 1107 | default: | 991 | default: |
| 1108 | break; | 992 | break; |
| @@ -1115,6 +999,148 @@ static int __init init_iommu_all(struct acpi_table_header *table) | |||
| 1115 | return 0; | 999 | return 0; |
| 1116 | } | 1000 | } |
| 1117 | 1001 | ||
| 1002 | static int iommu_init_pci(struct amd_iommu *iommu) | ||
| 1003 | { | ||
| 1004 | int cap_ptr = iommu->cap_ptr; | ||
| 1005 | u32 range, misc, low, high; | ||
| 1006 | |||
| 1007 | iommu->dev = pci_get_bus_and_slot(PCI_BUS(iommu->devid), | ||
| 1008 | iommu->devid & 0xff); | ||
| 1009 | if (!iommu->dev) | ||
| 1010 | return -ENODEV; | ||
| 1011 | |||
| 1012 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_CAP_HDR_OFFSET, | ||
| 1013 | &iommu->cap); | ||
| 1014 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_RANGE_OFFSET, | ||
| 1015 | &range); | ||
| 1016 | pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET, | ||
| 1017 | &misc); | ||
| 1018 | |||
| 1019 | iommu->first_device = calc_devid(MMIO_GET_BUS(range), | ||
| 1020 | MMIO_GET_FD(range)); | ||
| 1021 | iommu->last_device = calc_devid(MMIO_GET_BUS(range), | ||
| 1022 | MMIO_GET_LD(range)); | ||
| 1023 | |||
| 1024 | if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB))) | ||
| 1025 | amd_iommu_iotlb_sup = false; | ||
| 1026 | |||
| 1027 | /* read extended feature bits */ | ||
| 1028 | low = readl(iommu->mmio_base + MMIO_EXT_FEATURES); | ||
| 1029 | high = readl(iommu->mmio_base + MMIO_EXT_FEATURES + 4); | ||
| 1030 | |||
| 1031 | iommu->features = ((u64)high << 32) | low; | ||
| 1032 | |||
| 1033 | if (iommu_feature(iommu, FEATURE_GT)) { | ||
| 1034 | int glxval; | ||
| 1035 | u32 pasids; | ||
| 1036 | u64 shift; | ||
| 1037 | |||
| 1038 | shift = iommu->features & FEATURE_PASID_MASK; | ||
| 1039 | shift >>= FEATURE_PASID_SHIFT; | ||
| 1040 | pasids = (1 << shift); | ||
| 1041 | |||
| 1042 | amd_iommu_max_pasids = min(amd_iommu_max_pasids, pasids); | ||
| 1043 | |||
| 1044 | glxval = iommu->features & FEATURE_GLXVAL_MASK; | ||
| 1045 | glxval >>= FEATURE_GLXVAL_SHIFT; | ||
| 1046 | |||
| 1047 | if (amd_iommu_max_glx_val == -1) | ||
| 1048 | amd_iommu_max_glx_val = glxval; | ||
| 1049 | else | ||
| 1050 | amd_iommu_max_glx_val = min(amd_iommu_max_glx_val, glxval); | ||
| 1051 | } | ||
| 1052 | |||
| 1053 | if (iommu_feature(iommu, FEATURE_GT) && | ||
| 1054 | iommu_feature(iommu, FEATURE_PPR)) { | ||
| 1055 | iommu->is_iommu_v2 = true; | ||
| 1056 | amd_iommu_v2_present = true; | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | if (iommu_feature(iommu, FEATURE_PPR)) { | ||
| 1060 | iommu->ppr_log = alloc_ppr_log(iommu); | ||
| 1061 | if (!iommu->ppr_log) | ||
| 1062 | return -ENOMEM; | ||
| 1063 | } | ||
| 1064 | |||
| 1065 | if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) | ||
| 1066 | amd_iommu_np_cache = true; | ||
| 1067 | |||
| 1068 | if (is_rd890_iommu(iommu->dev)) { | ||
| 1069 | int i, j; | ||
| 1070 | |||
| 1071 | iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number, | ||
| 1072 | PCI_DEVFN(0, 0)); | ||
| 1073 | |||
| 1074 | /* | ||
| 1075 | * Some rd890 systems may not be fully reconfigured by the | ||
| 1076 | * BIOS, so it's necessary for us to store this information so | ||
| 1077 | * it can be reprogrammed on resume | ||
| 1078 | */ | ||
| 1079 | pci_read_config_dword(iommu->dev, iommu->cap_ptr + 4, | ||
| 1080 | &iommu->stored_addr_lo); | ||
| 1081 | pci_read_config_dword(iommu->dev, iommu->cap_ptr + 8, | ||
| 1082 | &iommu->stored_addr_hi); | ||
| 1083 | |||
| 1084 | /* Low bit locks writes to configuration space */ | ||
| 1085 | iommu->stored_addr_lo &= ~1; | ||
| 1086 | |||
| 1087 | for (i = 0; i < 6; i++) | ||
| 1088 | for (j = 0; j < 0x12; j++) | ||
| 1089 | iommu->stored_l1[i][j] = iommu_read_l1(iommu, i, j); | ||
| 1090 | |||
| 1091 | for (i = 0; i < 0x83; i++) | ||
| 1092 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | return pci_enable_device(iommu->dev); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | static void print_iommu_info(void) | ||
| 1099 | { | ||
| 1100 | static const char * const feat_str[] = { | ||
| 1101 | "PreF", "PPR", "X2APIC", "NX", "GT", "[5]", | ||
| 1102 | "IA", "GA", "HE", "PC" | ||
| 1103 | }; | ||
| 1104 | struct amd_iommu *iommu; | ||
| 1105 | |||
| 1106 | for_each_iommu(iommu) { | ||
| 1107 | int i; | ||
| 1108 | |||
| 1109 | pr_info("AMD-Vi: Found IOMMU at %s cap 0x%hx\n", | ||
| 1110 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | ||
| 1111 | |||
| 1112 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | ||
| 1113 | pr_info("AMD-Vi: Extended features: "); | ||
| 1114 | for (i = 0; ARRAY_SIZE(feat_str); ++i) { | ||
| 1115 | if (iommu_feature(iommu, (1ULL << i))) | ||
| 1116 | pr_cont(" %s", feat_str[i]); | ||
| 1117 | } | ||
| 1118 | } | ||
| 1119 | pr_cont("\n"); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | static int __init amd_iommu_init_pci(void) | ||
| 1124 | { | ||
| 1125 | struct amd_iommu *iommu; | ||
| 1126 | int ret = 0; | ||
| 1127 | |||
| 1128 | for_each_iommu(iommu) { | ||
| 1129 | ret = iommu_init_pci(iommu); | ||
| 1130 | if (ret) | ||
| 1131 | break; | ||
| 1132 | } | ||
| 1133 | |||
| 1134 | /* Make sure ACS will be enabled */ | ||
| 1135 | pci_request_acs(); | ||
| 1136 | |||
| 1137 | ret = amd_iommu_init_devices(); | ||
| 1138 | |||
| 1139 | print_iommu_info(); | ||
| 1140 | |||
| 1141 | return ret; | ||
| 1142 | } | ||
| 1143 | |||
| 1118 | /**************************************************************************** | 1144 | /**************************************************************************** |
| 1119 | * | 1145 | * |
| 1120 | * The following functions initialize the MSI interrupts for all IOMMUs | 1146 | * The following functions initialize the MSI interrupts for all IOMMUs |
| @@ -1217,7 +1243,7 @@ static int __init init_exclusion_range(struct ivmd_header *m) | |||
| 1217 | /* called for unity map ACPI definition */ | 1243 | /* called for unity map ACPI definition */ |
| 1218 | static int __init init_unity_map_range(struct ivmd_header *m) | 1244 | static int __init init_unity_map_range(struct ivmd_header *m) |
| 1219 | { | 1245 | { |
| 1220 | struct unity_map_entry *e = 0; | 1246 | struct unity_map_entry *e = NULL; |
| 1221 | char *s; | 1247 | char *s; |
| 1222 | 1248 | ||
| 1223 | e = kzalloc(sizeof(*e), GFP_KERNEL); | 1249 | e = kzalloc(sizeof(*e), GFP_KERNEL); |
| @@ -1369,7 +1395,7 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) | |||
| 1369 | * This function finally enables all IOMMUs found in the system after | 1395 | * This function finally enables all IOMMUs found in the system after |
| 1370 | * they have been initialized | 1396 | * they have been initialized |
| 1371 | */ | 1397 | */ |
| 1372 | static void enable_iommus(void) | 1398 | static void early_enable_iommus(void) |
| 1373 | { | 1399 | { |
| 1374 | struct amd_iommu *iommu; | 1400 | struct amd_iommu *iommu; |
| 1375 | 1401 | ||
| @@ -1379,14 +1405,29 @@ static void enable_iommus(void) | |||
| 1379 | iommu_set_device_table(iommu); | 1405 | iommu_set_device_table(iommu); |
| 1380 | iommu_enable_command_buffer(iommu); | 1406 | iommu_enable_command_buffer(iommu); |
| 1381 | iommu_enable_event_buffer(iommu); | 1407 | iommu_enable_event_buffer(iommu); |
| 1382 | iommu_enable_ppr_log(iommu); | ||
| 1383 | iommu_enable_gt(iommu); | ||
| 1384 | iommu_set_exclusion_range(iommu); | 1408 | iommu_set_exclusion_range(iommu); |
| 1385 | iommu_enable(iommu); | 1409 | iommu_enable(iommu); |
| 1386 | iommu_flush_all_caches(iommu); | 1410 | iommu_flush_all_caches(iommu); |
| 1387 | } | 1411 | } |
| 1388 | } | 1412 | } |
| 1389 | 1413 | ||
| 1414 | static void enable_iommus_v2(void) | ||
| 1415 | { | ||
| 1416 | struct amd_iommu *iommu; | ||
| 1417 | |||
| 1418 | for_each_iommu(iommu) { | ||
| 1419 | iommu_enable_ppr_log(iommu); | ||
| 1420 | iommu_enable_gt(iommu); | ||
| 1421 | } | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | static void enable_iommus(void) | ||
| 1425 | { | ||
| 1426 | early_enable_iommus(); | ||
| 1427 | |||
| 1428 | enable_iommus_v2(); | ||
| 1429 | } | ||
| 1430 | |||
| 1390 | static void disable_iommus(void) | 1431 | static void disable_iommus(void) |
| 1391 | { | 1432 | { |
| 1392 | struct amd_iommu *iommu; | 1433 | struct amd_iommu *iommu; |
| @@ -1481,16 +1522,23 @@ static void __init free_on_init_error(void) | |||
| 1481 | * After everything is set up the IOMMUs are enabled and the necessary | 1522 | * After everything is set up the IOMMUs are enabled and the necessary |
| 1482 | * hotplug and suspend notifiers are registered. | 1523 | * hotplug and suspend notifiers are registered. |
| 1483 | */ | 1524 | */ |
| 1484 | int __init amd_iommu_init_hardware(void) | 1525 | static int __init early_amd_iommu_init(void) |
| 1485 | { | 1526 | { |
| 1527 | struct acpi_table_header *ivrs_base; | ||
| 1528 | acpi_size ivrs_size; | ||
| 1529 | acpi_status status; | ||
| 1486 | int i, ret = 0; | 1530 | int i, ret = 0; |
| 1487 | 1531 | ||
| 1488 | if (!amd_iommu_detected) | 1532 | if (!amd_iommu_detected) |
| 1489 | return -ENODEV; | 1533 | return -ENODEV; |
| 1490 | 1534 | ||
| 1491 | if (amd_iommu_dev_table != NULL) { | 1535 | status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size); |
| 1492 | /* Hardware already initialized */ | 1536 | if (status == AE_NOT_FOUND) |
| 1493 | return 0; | 1537 | return -ENODEV; |
| 1538 | else if (ACPI_FAILURE(status)) { | ||
| 1539 | const char *err = acpi_format_exception(status); | ||
| 1540 | pr_err("AMD-Vi: IVRS table error: %s\n", err); | ||
| 1541 | return -EINVAL; | ||
| 1494 | } | 1542 | } |
| 1495 | 1543 | ||
| 1496 | /* | 1544 | /* |
| @@ -1498,10 +1546,7 @@ int __init amd_iommu_init_hardware(void) | |||
| 1498 | * we need to handle. Upon this information the shared data | 1546 | * we need to handle. Upon this information the shared data |
| 1499 | * structures for the IOMMUs in the system will be allocated | 1547 | * structures for the IOMMUs in the system will be allocated |
| 1500 | */ | 1548 | */ |
| 1501 | if (acpi_table_parse("IVRS", find_last_devid_acpi) != 0) | 1549 | ret = find_last_devid_acpi(ivrs_base); |
| 1502 | return -ENODEV; | ||
| 1503 | |||
| 1504 | ret = amd_iommu_init_err; | ||
| 1505 | if (ret) | 1550 | if (ret) |
| 1506 | goto out; | 1551 | goto out; |
| 1507 | 1552 | ||
| @@ -1523,20 +1568,20 @@ int __init amd_iommu_init_hardware(void) | |||
| 1523 | amd_iommu_alias_table = (void *)__get_free_pages(GFP_KERNEL, | 1568 | amd_iommu_alias_table = (void *)__get_free_pages(GFP_KERNEL, |
| 1524 | get_order(alias_table_size)); | 1569 | get_order(alias_table_size)); |
| 1525 | if (amd_iommu_alias_table == NULL) | 1570 | if (amd_iommu_alias_table == NULL) |
| 1526 | goto free; | 1571 | goto out; |
| 1527 | 1572 | ||
| 1528 | /* IOMMU rlookup table - find the IOMMU for a specific device */ | 1573 | /* IOMMU rlookup table - find the IOMMU for a specific device */ |
| 1529 | amd_iommu_rlookup_table = (void *)__get_free_pages( | 1574 | amd_iommu_rlookup_table = (void *)__get_free_pages( |
| 1530 | GFP_KERNEL | __GFP_ZERO, | 1575 | GFP_KERNEL | __GFP_ZERO, |
| 1531 | get_order(rlookup_table_size)); | 1576 | get_order(rlookup_table_size)); |
| 1532 | if (amd_iommu_rlookup_table == NULL) | 1577 | if (amd_iommu_rlookup_table == NULL) |
| 1533 | goto free; | 1578 | goto out; |
| 1534 | 1579 | ||
| 1535 | amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages( | 1580 | amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages( |
| 1536 | GFP_KERNEL | __GFP_ZERO, | 1581 | GFP_KERNEL | __GFP_ZERO, |
| 1537 | get_order(MAX_DOMAIN_ID/8)); | 1582 | get_order(MAX_DOMAIN_ID/8)); |
| 1538 | if (amd_iommu_pd_alloc_bitmap == NULL) | 1583 | if (amd_iommu_pd_alloc_bitmap == NULL) |
| 1539 | goto free; | 1584 | goto out; |
| 1540 | 1585 | ||
| 1541 | /* init the device table */ | 1586 | /* init the device table */ |
| 1542 | init_device_table(); | 1587 | init_device_table(); |
| @@ -1559,38 +1604,18 @@ int __init amd_iommu_init_hardware(void) | |||
| 1559 | * now the data structures are allocated and basically initialized | 1604 | * now the data structures are allocated and basically initialized |
| 1560 | * start the real acpi table scan | 1605 | * start the real acpi table scan |
| 1561 | */ | 1606 | */ |
| 1562 | ret = -ENODEV; | 1607 | ret = init_iommu_all(ivrs_base); |
| 1563 | if (acpi_table_parse("IVRS", init_iommu_all) != 0) | ||
| 1564 | goto free; | ||
| 1565 | |||
| 1566 | if (amd_iommu_init_err) { | ||
| 1567 | ret = amd_iommu_init_err; | ||
| 1568 | goto free; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | if (acpi_table_parse("IVRS", init_memory_definitions) != 0) | ||
| 1572 | goto free; | ||
| 1573 | |||
| 1574 | if (amd_iommu_init_err) { | ||
| 1575 | ret = amd_iommu_init_err; | ||
| 1576 | goto free; | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | ret = amd_iommu_init_devices(); | ||
| 1580 | if (ret) | 1608 | if (ret) |
| 1581 | goto free; | 1609 | goto out; |
| 1582 | |||
| 1583 | enable_iommus(); | ||
| 1584 | |||
| 1585 | amd_iommu_init_notifier(); | ||
| 1586 | 1610 | ||
| 1587 | register_syscore_ops(&amd_iommu_syscore_ops); | 1611 | ret = init_memory_definitions(ivrs_base); |
| 1612 | if (ret) | ||
| 1613 | goto out; | ||
| 1588 | 1614 | ||
| 1589 | out: | 1615 | out: |
| 1590 | return ret; | 1616 | /* Don't leak any ACPI memory */ |
| 1591 | 1617 | early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); | |
| 1592 | free: | 1618 | ivrs_base = NULL; |
| 1593 | free_on_init_error(); | ||
| 1594 | 1619 | ||
| 1595 | return ret; | 1620 | return ret; |
| 1596 | } | 1621 | } |
| @@ -1610,26 +1635,29 @@ out: | |||
| 1610 | return ret; | 1635 | return ret; |
| 1611 | } | 1636 | } |
| 1612 | 1637 | ||
| 1613 | /* | 1638 | static bool detect_ivrs(void) |
| 1614 | * This is the core init function for AMD IOMMU hardware in the system. | ||
| 1615 | * This function is called from the generic x86 DMA layer initialization | ||
| 1616 | * code. | ||
| 1617 | * | ||
| 1618 | * The function calls amd_iommu_init_hardware() to setup and enable the | ||
| 1619 | * IOMMU hardware if this has not happened yet. After that the driver | ||
| 1620 | * registers for the DMA-API and for the IOMMU-API as necessary. | ||
| 1621 | */ | ||
| 1622 | static int __init amd_iommu_init(void) | ||
| 1623 | { | 1639 | { |
| 1624 | int ret = 0; | 1640 | struct acpi_table_header *ivrs_base; |
| 1641 | acpi_size ivrs_size; | ||
| 1642 | acpi_status status; | ||
| 1625 | 1643 | ||
| 1626 | ret = amd_iommu_init_hardware(); | 1644 | status = acpi_get_table_with_size("IVRS", 0, &ivrs_base, &ivrs_size); |
| 1627 | if (ret) | 1645 | if (status == AE_NOT_FOUND) |
| 1628 | goto out; | 1646 | return false; |
| 1647 | else if (ACPI_FAILURE(status)) { | ||
| 1648 | const char *err = acpi_format_exception(status); | ||
| 1649 | pr_err("AMD-Vi: IVRS table error: %s\n", err); | ||
| 1650 | return false; | ||
| 1651 | } | ||
| 1629 | 1652 | ||
| 1630 | ret = amd_iommu_enable_interrupts(); | 1653 | early_acpi_os_unmap_memory((char __iomem *)ivrs_base, ivrs_size); |
| 1631 | if (ret) | 1654 | |
| 1632 | goto free; | 1655 | return true; |
| 1656 | } | ||
| 1657 | |||
| 1658 | static int amd_iommu_init_dma(void) | ||
| 1659 | { | ||
| 1660 | int ret; | ||
| 1633 | 1661 | ||
| 1634 | if (iommu_pass_through) | 1662 | if (iommu_pass_through) |
| 1635 | ret = amd_iommu_init_passthrough(); | 1663 | ret = amd_iommu_init_passthrough(); |
| @@ -1637,29 +1665,108 @@ static int __init amd_iommu_init(void) | |||
| 1637 | ret = amd_iommu_init_dma_ops(); | 1665 | ret = amd_iommu_init_dma_ops(); |
| 1638 | 1666 | ||
| 1639 | if (ret) | 1667 | if (ret) |
| 1640 | goto free; | 1668 | return ret; |
| 1641 | 1669 | ||
| 1642 | amd_iommu_init_api(); | 1670 | amd_iommu_init_api(); |
| 1643 | 1671 | ||
| 1644 | x86_platform.iommu_shutdown = disable_iommus; | 1672 | amd_iommu_init_notifier(); |
| 1645 | 1673 | ||
| 1646 | if (iommu_pass_through) | 1674 | return 0; |
| 1647 | goto out; | 1675 | } |
| 1648 | 1676 | ||
| 1649 | if (amd_iommu_unmap_flush) | 1677 | /**************************************************************************** |
| 1650 | printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n"); | 1678 | * |
| 1651 | else | 1679 | * AMD IOMMU Initialization State Machine |
| 1652 | printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); | 1680 | * |
| 1681 | ****************************************************************************/ | ||
| 1682 | |||
| 1683 | static int __init state_next(void) | ||
| 1684 | { | ||
| 1685 | int ret = 0; | ||
| 1686 | |||
| 1687 | switch (init_state) { | ||
| 1688 | case IOMMU_START_STATE: | ||
| 1689 | if (!detect_ivrs()) { | ||
| 1690 | init_state = IOMMU_NOT_FOUND; | ||
| 1691 | ret = -ENODEV; | ||
| 1692 | } else { | ||
| 1693 | init_state = IOMMU_IVRS_DETECTED; | ||
| 1694 | } | ||
| 1695 | break; | ||
| 1696 | case IOMMU_IVRS_DETECTED: | ||
| 1697 | ret = early_amd_iommu_init(); | ||
| 1698 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_ACPI_FINISHED; | ||
| 1699 | break; | ||
| 1700 | case IOMMU_ACPI_FINISHED: | ||
| 1701 | early_enable_iommus(); | ||
| 1702 | register_syscore_ops(&amd_iommu_syscore_ops); | ||
| 1703 | x86_platform.iommu_shutdown = disable_iommus; | ||
| 1704 | init_state = IOMMU_ENABLED; | ||
| 1705 | break; | ||
| 1706 | case IOMMU_ENABLED: | ||
| 1707 | ret = amd_iommu_init_pci(); | ||
| 1708 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_PCI_INIT; | ||
| 1709 | enable_iommus_v2(); | ||
| 1710 | break; | ||
| 1711 | case IOMMU_PCI_INIT: | ||
| 1712 | ret = amd_iommu_enable_interrupts(); | ||
| 1713 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_INTERRUPTS_EN; | ||
| 1714 | break; | ||
| 1715 | case IOMMU_INTERRUPTS_EN: | ||
| 1716 | ret = amd_iommu_init_dma(); | ||
| 1717 | init_state = ret ? IOMMU_INIT_ERROR : IOMMU_DMA_OPS; | ||
| 1718 | break; | ||
| 1719 | case IOMMU_DMA_OPS: | ||
| 1720 | init_state = IOMMU_INITIALIZED; | ||
| 1721 | break; | ||
| 1722 | case IOMMU_INITIALIZED: | ||
| 1723 | /* Nothing to do */ | ||
| 1724 | break; | ||
| 1725 | case IOMMU_NOT_FOUND: | ||
| 1726 | case IOMMU_INIT_ERROR: | ||
| 1727 | /* Error states => do nothing */ | ||
| 1728 | ret = -EINVAL; | ||
| 1729 | break; | ||
| 1730 | default: | ||
| 1731 | /* Unknown state */ | ||
| 1732 | BUG(); | ||
| 1733 | } | ||
| 1653 | 1734 | ||
| 1654 | out: | ||
| 1655 | return ret; | 1735 | return ret; |
| 1736 | } | ||
| 1656 | 1737 | ||
| 1657 | free: | 1738 | static int __init iommu_go_to_state(enum iommu_init_state state) |
| 1658 | disable_iommus(); | 1739 | { |
| 1740 | int ret = 0; | ||
| 1741 | |||
| 1742 | while (init_state != state) { | ||
| 1743 | ret = state_next(); | ||
| 1744 | if (init_state == IOMMU_NOT_FOUND || | ||
| 1745 | init_state == IOMMU_INIT_ERROR) | ||
| 1746 | break; | ||
| 1747 | } | ||
| 1748 | |||
| 1749 | return ret; | ||
| 1750 | } | ||
| 1751 | |||
| 1752 | |||
| 1753 | |||
| 1754 | /* | ||
| 1755 | * This is the core init function for AMD IOMMU hardware in the system. | ||
| 1756 | * This function is called from the generic x86 DMA layer initialization | ||
| 1757 | * code. | ||
| 1758 | */ | ||
| 1759 | static int __init amd_iommu_init(void) | ||
| 1760 | { | ||
| 1761 | int ret; | ||
| 1659 | 1762 | ||
| 1660 | free_on_init_error(); | 1763 | ret = iommu_go_to_state(IOMMU_INITIALIZED); |
| 1764 | if (ret) { | ||
| 1765 | disable_iommus(); | ||
| 1766 | free_on_init_error(); | ||
| 1767 | } | ||
| 1661 | 1768 | ||
| 1662 | goto out; | 1769 | return ret; |
| 1663 | } | 1770 | } |
| 1664 | 1771 | ||
| 1665 | /**************************************************************************** | 1772 | /**************************************************************************** |
| @@ -1669,29 +1776,25 @@ free: | |||
| 1669 | * IOMMUs | 1776 | * IOMMUs |
| 1670 | * | 1777 | * |
| 1671 | ****************************************************************************/ | 1778 | ****************************************************************************/ |
| 1672 | static int __init early_amd_iommu_detect(struct acpi_table_header *table) | ||
| 1673 | { | ||
| 1674 | return 0; | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | int __init amd_iommu_detect(void) | 1779 | int __init amd_iommu_detect(void) |
| 1678 | { | 1780 | { |
| 1781 | int ret; | ||
| 1782 | |||
| 1679 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) | 1783 | if (no_iommu || (iommu_detected && !gart_iommu_aperture)) |
| 1680 | return -ENODEV; | 1784 | return -ENODEV; |
| 1681 | 1785 | ||
| 1682 | if (amd_iommu_disabled) | 1786 | if (amd_iommu_disabled) |
| 1683 | return -ENODEV; | 1787 | return -ENODEV; |
| 1684 | 1788 | ||
| 1685 | if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) { | 1789 | ret = iommu_go_to_state(IOMMU_IVRS_DETECTED); |
| 1686 | iommu_detected = 1; | 1790 | if (ret) |
| 1687 | amd_iommu_detected = 1; | 1791 | return ret; |
| 1688 | x86_init.iommu.iommu_init = amd_iommu_init; | ||
| 1689 | 1792 | ||
| 1690 | /* Make sure ACS will be enabled */ | 1793 | amd_iommu_detected = true; |
| 1691 | pci_request_acs(); | 1794 | iommu_detected = 1; |
| 1692 | return 1; | 1795 | x86_init.iommu.iommu_init = amd_iommu_init; |
| 1693 | } | 1796 | |
| 1694 | return -ENODEV; | 1797 | return 0; |
| 1695 | } | 1798 | } |
| 1696 | 1799 | ||
| 1697 | /**************************************************************************** | 1800 | /**************************************************************************** |
| @@ -1727,8 +1830,8 @@ __setup("amd_iommu=", parse_amd_iommu_options); | |||
| 1727 | 1830 | ||
| 1728 | IOMMU_INIT_FINISH(amd_iommu_detect, | 1831 | IOMMU_INIT_FINISH(amd_iommu_detect, |
| 1729 | gart_iommu_hole_init, | 1832 | gart_iommu_hole_init, |
| 1730 | 0, | 1833 | NULL, |
| 1731 | 0); | 1834 | NULL); |
| 1732 | 1835 | ||
| 1733 | bool amd_iommu_v2_supported(void) | 1836 | bool amd_iommu_v2_supported(void) |
| 1734 | { | 1837 | { |
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index c1b1d489817e..d0dab865a8b8 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h | |||
| @@ -487,7 +487,7 @@ struct amd_iommu { | |||
| 487 | /* physical address of MMIO space */ | 487 | /* physical address of MMIO space */ |
| 488 | u64 mmio_phys; | 488 | u64 mmio_phys; |
| 489 | /* virtual address of MMIO space */ | 489 | /* virtual address of MMIO space */ |
| 490 | u8 *mmio_base; | 490 | u8 __iomem *mmio_base; |
| 491 | 491 | ||
| 492 | /* capabilities of that IOMMU read from ACPI */ | 492 | /* capabilities of that IOMMU read from ACPI */ |
| 493 | u32 cap; | 493 | u32 cap; |
| @@ -501,6 +501,9 @@ struct amd_iommu { | |||
| 501 | /* IOMMUv2 */ | 501 | /* IOMMUv2 */ |
| 502 | bool is_iommu_v2; | 502 | bool is_iommu_v2; |
| 503 | 503 | ||
| 504 | /* PCI device id of the IOMMU device */ | ||
| 505 | u16 devid; | ||
| 506 | |||
| 504 | /* | 507 | /* |
| 505 | * Capability pointer. There could be more than one IOMMU per PCI | 508 | * Capability pointer. There could be more than one IOMMU per PCI |
| 506 | * device function if there are more than one AMD IOMMU capability | 509 | * device function if there are more than one AMD IOMMU capability |
| @@ -530,8 +533,6 @@ struct amd_iommu { | |||
| 530 | u32 evt_buf_size; | 533 | u32 evt_buf_size; |
| 531 | /* event buffer virtual address */ | 534 | /* event buffer virtual address */ |
| 532 | u8 *evt_buf; | 535 | u8 *evt_buf; |
| 533 | /* MSI number for event interrupt */ | ||
| 534 | u16 evt_msi_num; | ||
| 535 | 536 | ||
| 536 | /* Base of the PPR log, if present */ | 537 | /* Base of the PPR log, if present */ |
| 537 | u8 *ppr_log; | 538 | u8 *ppr_log; |
| @@ -664,6 +665,12 @@ extern bool amd_iommu_force_isolation; | |||
| 664 | /* Max levels of glxval supported */ | 665 | /* Max levels of glxval supported */ |
| 665 | extern int amd_iommu_max_glx_val; | 666 | extern int amd_iommu_max_glx_val; |
| 666 | 667 | ||
| 668 | /* | ||
| 669 | * This function flushes all internal caches of | ||
| 670 | * the IOMMU used by this driver. | ||
| 671 | */ | ||
| 672 | extern void iommu_flush_all_caches(struct amd_iommu *iommu); | ||
| 673 | |||
| 667 | /* takes bus and device/function and returns the device id | 674 | /* takes bus and device/function and returns the device id |
| 668 | * FIXME: should that be in generic PCI code? */ | 675 | * FIXME: should that be in generic PCI code? */ |
| 669 | static inline u16 calc_devid(u8 bus, u8 devfn) | 676 | static inline u16 calc_devid(u8 bus, u8 devfn) |
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index be03238ad815..5208828792e6 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
| @@ -81,7 +81,7 @@ struct fault { | |||
| 81 | u16 flags; | 81 | u16 flags; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | struct device_state **state_table; | 84 | static struct device_state **state_table; |
| 85 | static spinlock_t state_lock; | 85 | static spinlock_t state_lock; |
| 86 | 86 | ||
| 87 | /* List and lock for all pasid_states */ | 87 | /* List and lock for all pasid_states */ |
| @@ -681,6 +681,8 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid, | |||
| 681 | 681 | ||
| 682 | atomic_set(&pasid_state->count, 1); | 682 | atomic_set(&pasid_state->count, 1); |
| 683 | init_waitqueue_head(&pasid_state->wq); | 683 | init_waitqueue_head(&pasid_state->wq); |
| 684 | spin_lock_init(&pasid_state->lock); | ||
| 685 | |||
| 684 | pasid_state->task = task; | 686 | pasid_state->task = task; |
| 685 | pasid_state->mm = get_task_mm(task); | 687 | pasid_state->mm = get_task_mm(task); |
| 686 | pasid_state->device_state = dev_state; | 688 | pasid_state->device_state = dev_state; |
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 4407d5eff05e..45350ff5e93c 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
| @@ -732,6 +732,10 @@ static int exynos_iommu_domain_init(struct iommu_domain *domain) | |||
| 732 | spin_lock_init(&priv->pgtablelock); | 732 | spin_lock_init(&priv->pgtablelock); |
| 733 | INIT_LIST_HEAD(&priv->clients); | 733 | INIT_LIST_HEAD(&priv->clients); |
| 734 | 734 | ||
| 735 | dom->geometry.aperture_start = 0; | ||
| 736 | dom->geometry.aperture_end = ~0UL; | ||
| 737 | dom->geometry.force_aperture = true; | ||
| 738 | |||
| 735 | domain->priv = priv; | 739 | domain->priv = priv; |
| 736 | return 0; | 740 | return 0; |
| 737 | 741 | ||
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2fb7d1598a68..7469b5346643 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
| @@ -3932,6 +3932,10 @@ static int intel_iommu_domain_init(struct iommu_domain *domain) | |||
| 3932 | domain_update_iommu_cap(dmar_domain); | 3932 | domain_update_iommu_cap(dmar_domain); |
| 3933 | domain->priv = dmar_domain; | 3933 | domain->priv = dmar_domain; |
| 3934 | 3934 | ||
| 3935 | domain->geometry.aperture_start = 0; | ||
| 3936 | domain->geometry.aperture_end = __DOMAIN_MAX_ADDR(dmar_domain->gaw); | ||
| 3937 | domain->geometry.force_aperture = true; | ||
| 3938 | |||
| 3935 | return 0; | 3939 | return 0; |
| 3936 | } | 3940 | } |
| 3937 | 3941 | ||
| @@ -4090,52 +4094,70 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain, | |||
| 4090 | return 0; | 4094 | return 0; |
| 4091 | } | 4095 | } |
| 4092 | 4096 | ||
| 4093 | /* | 4097 | static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) |
| 4094 | * Group numbers are arbitrary. Device with the same group number | ||
| 4095 | * indicate the iommu cannot differentiate between them. To avoid | ||
| 4096 | * tracking used groups we just use the seg|bus|devfn of the lowest | ||
| 4097 | * level we're able to differentiate devices | ||
| 4098 | */ | ||
| 4099 | static int intel_iommu_device_group(struct device *dev, unsigned int *groupid) | ||
| 4100 | { | 4098 | { |
| 4101 | struct pci_dev *pdev = to_pci_dev(dev); | 4099 | pci_dev_put(*from); |
| 4102 | struct pci_dev *bridge; | 4100 | *from = to; |
| 4103 | union { | 4101 | } |
| 4104 | struct { | ||
| 4105 | u8 devfn; | ||
| 4106 | u8 bus; | ||
| 4107 | u16 segment; | ||
| 4108 | } pci; | ||
| 4109 | u32 group; | ||
| 4110 | } id; | ||
| 4111 | 4102 | ||
| 4112 | if (iommu_no_mapping(dev)) | 4103 | #define REQ_ACS_FLAGS (PCI_ACS_SV | PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF) |
| 4113 | return -ENODEV; | ||
| 4114 | 4104 | ||
| 4115 | id.pci.segment = pci_domain_nr(pdev->bus); | 4105 | static int intel_iommu_add_device(struct device *dev) |
| 4116 | id.pci.bus = pdev->bus->number; | 4106 | { |
| 4117 | id.pci.devfn = pdev->devfn; | 4107 | struct pci_dev *pdev = to_pci_dev(dev); |
| 4108 | struct pci_dev *bridge, *dma_pdev; | ||
| 4109 | struct iommu_group *group; | ||
| 4110 | int ret; | ||
| 4118 | 4111 | ||
| 4119 | if (!device_to_iommu(id.pci.segment, id.pci.bus, id.pci.devfn)) | 4112 | if (!device_to_iommu(pci_domain_nr(pdev->bus), |
| 4113 | pdev->bus->number, pdev->devfn)) | ||
| 4120 | return -ENODEV; | 4114 | return -ENODEV; |
| 4121 | 4115 | ||
| 4122 | bridge = pci_find_upstream_pcie_bridge(pdev); | 4116 | bridge = pci_find_upstream_pcie_bridge(pdev); |
| 4123 | if (bridge) { | 4117 | if (bridge) { |
| 4124 | if (pci_is_pcie(bridge)) { | 4118 | if (pci_is_pcie(bridge)) |
| 4125 | id.pci.bus = bridge->subordinate->number; | 4119 | dma_pdev = pci_get_domain_bus_and_slot( |
| 4126 | id.pci.devfn = 0; | 4120 | pci_domain_nr(pdev->bus), |
| 4127 | } else { | 4121 | bridge->subordinate->number, 0); |
| 4128 | id.pci.bus = bridge->bus->number; | 4122 | else |
| 4129 | id.pci.devfn = bridge->devfn; | 4123 | dma_pdev = pci_dev_get(bridge); |
| 4130 | } | 4124 | } else |
| 4125 | dma_pdev = pci_dev_get(pdev); | ||
| 4126 | |||
| 4127 | swap_pci_ref(&dma_pdev, pci_get_dma_source(dma_pdev)); | ||
| 4128 | |||
| 4129 | if (dma_pdev->multifunction && | ||
| 4130 | !pci_acs_enabled(dma_pdev, REQ_ACS_FLAGS)) | ||
| 4131 | swap_pci_ref(&dma_pdev, | ||
| 4132 | pci_get_slot(dma_pdev->bus, | ||
| 4133 | PCI_DEVFN(PCI_SLOT(dma_pdev->devfn), | ||
| 4134 | 0))); | ||
| 4135 | |||
| 4136 | while (!pci_is_root_bus(dma_pdev->bus)) { | ||
| 4137 | if (pci_acs_path_enabled(dma_pdev->bus->self, | ||
| 4138 | NULL, REQ_ACS_FLAGS)) | ||
| 4139 | break; | ||
| 4140 | |||
| 4141 | swap_pci_ref(&dma_pdev, pci_dev_get(dma_pdev->bus->self)); | ||
| 4142 | } | ||
| 4143 | |||
| 4144 | group = iommu_group_get(&dma_pdev->dev); | ||
| 4145 | pci_dev_put(dma_pdev); | ||
| 4146 | if (!group) { | ||
| 4147 | group = iommu_group_alloc(); | ||
| 4148 | if (IS_ERR(group)) | ||
| 4149 | return PTR_ERR(group); | ||
| 4131 | } | 4150 | } |
| 4132 | 4151 | ||
| 4133 | if (!pdev->is_virtfn && iommu_group_mf) | 4152 | ret = iommu_group_add_device(group, dev); |
| 4134 | id.pci.devfn = PCI_DEVFN(PCI_SLOT(id.pci.devfn), 0); | ||
| 4135 | 4153 | ||
| 4136 | *groupid = id.group; | 4154 | iommu_group_put(group); |
| 4155 | return ret; | ||
| 4156 | } | ||
| 4137 | 4157 | ||
| 4138 | return 0; | 4158 | static void intel_iommu_remove_device(struct device *dev) |
| 4159 | { | ||
| 4160 | iommu_group_remove_device(dev); | ||
| 4139 | } | 4161 | } |
| 4140 | 4162 | ||
| 4141 | static struct iommu_ops intel_iommu_ops = { | 4163 | static struct iommu_ops intel_iommu_ops = { |
| @@ -4147,7 +4169,8 @@ static struct iommu_ops intel_iommu_ops = { | |||
| 4147 | .unmap = intel_iommu_unmap, | 4169 | .unmap = intel_iommu_unmap, |
| 4148 | .iova_to_phys = intel_iommu_iova_to_phys, | 4170 | .iova_to_phys = intel_iommu_iova_to_phys, |
| 4149 | .domain_has_cap = intel_iommu_domain_has_cap, | 4171 | .domain_has_cap = intel_iommu_domain_has_cap, |
| 4150 | .device_group = intel_iommu_device_group, | 4172 | .add_device = intel_iommu_add_device, |
| 4173 | .remove_device = intel_iommu_remove_device, | ||
| 4151 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, | 4174 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, |
| 4152 | }; | 4175 | }; |
| 4153 | 4176 | ||
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 8b9ded88e6f5..ddbdacad7768 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
| @@ -26,60 +26,535 @@ | |||
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
| 28 | #include <linux/iommu.h> | 28 | #include <linux/iommu.h> |
| 29 | #include <linux/idr.h> | ||
| 30 | #include <linux/notifier.h> | ||
| 31 | #include <linux/err.h> | ||
| 32 | |||
| 33 | static struct kset *iommu_group_kset; | ||
| 34 | static struct ida iommu_group_ida; | ||
| 35 | static struct mutex iommu_group_mutex; | ||
| 36 | |||
| 37 | struct iommu_group { | ||
| 38 | struct kobject kobj; | ||
| 39 | struct kobject *devices_kobj; | ||
| 40 | struct list_head devices; | ||
| 41 | struct mutex mutex; | ||
| 42 | struct blocking_notifier_head notifier; | ||
| 43 | void *iommu_data; | ||
| 44 | void (*iommu_data_release)(void *iommu_data); | ||
| 45 | char *name; | ||
| 46 | int id; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct iommu_device { | ||
| 50 | struct list_head list; | ||
| 51 | struct device *dev; | ||
| 52 | char *name; | ||
| 53 | }; | ||
| 54 | |||
| 55 | struct iommu_group_attribute { | ||
| 56 | struct attribute attr; | ||
| 57 | ssize_t (*show)(struct iommu_group *group, char *buf); | ||
| 58 | ssize_t (*store)(struct iommu_group *group, | ||
| 59 | const char *buf, size_t count); | ||
| 60 | }; | ||
| 61 | |||
| 62 | #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ | ||
| 63 | struct iommu_group_attribute iommu_group_attr_##_name = \ | ||
| 64 | __ATTR(_name, _mode, _show, _store) | ||
| 65 | |||
| 66 | #define to_iommu_group_attr(_attr) \ | ||
| 67 | container_of(_attr, struct iommu_group_attribute, attr) | ||
| 68 | #define to_iommu_group(_kobj) \ | ||
| 69 | container_of(_kobj, struct iommu_group, kobj) | ||
| 29 | 70 | ||
| 30 | static ssize_t show_iommu_group(struct device *dev, | 71 | static ssize_t iommu_group_attr_show(struct kobject *kobj, |
| 31 | struct device_attribute *attr, char *buf) | 72 | struct attribute *__attr, char *buf) |
| 32 | { | 73 | { |
| 33 | unsigned int groupid; | 74 | struct iommu_group_attribute *attr = to_iommu_group_attr(__attr); |
| 75 | struct iommu_group *group = to_iommu_group(kobj); | ||
| 76 | ssize_t ret = -EIO; | ||
| 34 | 77 | ||
| 35 | if (iommu_device_group(dev, &groupid)) | 78 | if (attr->show) |
| 36 | return 0; | 79 | ret = attr->show(group, buf); |
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | static ssize_t iommu_group_attr_store(struct kobject *kobj, | ||
| 84 | struct attribute *__attr, | ||
| 85 | const char *buf, size_t count) | ||
| 86 | { | ||
| 87 | struct iommu_group_attribute *attr = to_iommu_group_attr(__attr); | ||
| 88 | struct iommu_group *group = to_iommu_group(kobj); | ||
| 89 | ssize_t ret = -EIO; | ||
| 90 | |||
| 91 | if (attr->store) | ||
| 92 | ret = attr->store(group, buf, count); | ||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | |||
| 96 | static const struct sysfs_ops iommu_group_sysfs_ops = { | ||
| 97 | .show = iommu_group_attr_show, | ||
| 98 | .store = iommu_group_attr_store, | ||
| 99 | }; | ||
| 37 | 100 | ||
| 38 | return sprintf(buf, "%u", groupid); | 101 | static int iommu_group_create_file(struct iommu_group *group, |
| 102 | struct iommu_group_attribute *attr) | ||
| 103 | { | ||
| 104 | return sysfs_create_file(&group->kobj, &attr->attr); | ||
| 39 | } | 105 | } |
| 40 | static DEVICE_ATTR(iommu_group, S_IRUGO, show_iommu_group, NULL); | ||
| 41 | 106 | ||
| 42 | static int add_iommu_group(struct device *dev, void *data) | 107 | static void iommu_group_remove_file(struct iommu_group *group, |
| 108 | struct iommu_group_attribute *attr) | ||
| 109 | { | ||
| 110 | sysfs_remove_file(&group->kobj, &attr->attr); | ||
| 111 | } | ||
| 112 | |||
| 113 | static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf) | ||
| 114 | { | ||
| 115 | return sprintf(buf, "%s\n", group->name); | ||
| 116 | } | ||
| 117 | |||
| 118 | static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); | ||
| 119 | |||
| 120 | static void iommu_group_release(struct kobject *kobj) | ||
| 121 | { | ||
| 122 | struct iommu_group *group = to_iommu_group(kobj); | ||
| 123 | |||
| 124 | if (group->iommu_data_release) | ||
| 125 | group->iommu_data_release(group->iommu_data); | ||
| 126 | |||
| 127 | mutex_lock(&iommu_group_mutex); | ||
| 128 | ida_remove(&iommu_group_ida, group->id); | ||
| 129 | mutex_unlock(&iommu_group_mutex); | ||
| 130 | |||
| 131 | kfree(group->name); | ||
| 132 | kfree(group); | ||
| 133 | } | ||
| 134 | |||
| 135 | static struct kobj_type iommu_group_ktype = { | ||
| 136 | .sysfs_ops = &iommu_group_sysfs_ops, | ||
| 137 | .release = iommu_group_release, | ||
| 138 | }; | ||
| 139 | |||
| 140 | /** | ||
| 141 | * iommu_group_alloc - Allocate a new group | ||
| 142 | * @name: Optional name to associate with group, visible in sysfs | ||
| 143 | * | ||
| 144 | * This function is called by an iommu driver to allocate a new iommu | ||
| 145 | * group. The iommu group represents the minimum granularity of the iommu. | ||
| 146 | * Upon successful return, the caller holds a reference to the supplied | ||
| 147 | * group in order to hold the group until devices are added. Use | ||
| 148 | * iommu_group_put() to release this extra reference count, allowing the | ||
| 149 | * group to be automatically reclaimed once it has no devices or external | ||
| 150 | * references. | ||
| 151 | */ | ||
| 152 | struct iommu_group *iommu_group_alloc(void) | ||
| 153 | { | ||
| 154 | struct iommu_group *group; | ||
| 155 | int ret; | ||
| 156 | |||
| 157 | group = kzalloc(sizeof(*group), GFP_KERNEL); | ||
| 158 | if (!group) | ||
| 159 | return ERR_PTR(-ENOMEM); | ||
| 160 | |||
| 161 | group->kobj.kset = iommu_group_kset; | ||
| 162 | mutex_init(&group->mutex); | ||
| 163 | INIT_LIST_HEAD(&group->devices); | ||
| 164 | BLOCKING_INIT_NOTIFIER_HEAD(&group->notifier); | ||
| 165 | |||
| 166 | mutex_lock(&iommu_group_mutex); | ||
| 167 | |||
| 168 | again: | ||
| 169 | if (unlikely(0 == ida_pre_get(&iommu_group_ida, GFP_KERNEL))) { | ||
| 170 | kfree(group); | ||
| 171 | mutex_unlock(&iommu_group_mutex); | ||
| 172 | return ERR_PTR(-ENOMEM); | ||
| 173 | } | ||
| 174 | |||
| 175 | if (-EAGAIN == ida_get_new(&iommu_group_ida, &group->id)) | ||
| 176 | goto again; | ||
| 177 | |||
| 178 | mutex_unlock(&iommu_group_mutex); | ||
| 179 | |||
| 180 | ret = kobject_init_and_add(&group->kobj, &iommu_group_ktype, | ||
| 181 | NULL, "%d", group->id); | ||
| 182 | if (ret) { | ||
| 183 | mutex_lock(&iommu_group_mutex); | ||
| 184 | ida_remove(&iommu_group_ida, group->id); | ||
| 185 | mutex_unlock(&iommu_group_mutex); | ||
| 186 | kfree(group); | ||
| 187 | return ERR_PTR(ret); | ||
| 188 | } | ||
| 189 | |||
| 190 | group->devices_kobj = kobject_create_and_add("devices", &group->kobj); | ||
| 191 | if (!group->devices_kobj) { | ||
| 192 | kobject_put(&group->kobj); /* triggers .release & free */ | ||
| 193 | return ERR_PTR(-ENOMEM); | ||
| 194 | } | ||
| 195 | |||
| 196 | /* | ||
| 197 | * The devices_kobj holds a reference on the group kobject, so | ||
| 198 | * as long as that exists so will the group. We can therefore | ||
| 199 | * use the devices_kobj for reference counting. | ||
| 200 | */ | ||
| 201 | kobject_put(&group->kobj); | ||
| 202 | |||
| 203 | return group; | ||
| 204 | } | ||
| 205 | EXPORT_SYMBOL_GPL(iommu_group_alloc); | ||
| 206 | |||
| 207 | /** | ||
| 208 | * iommu_group_get_iommudata - retrieve iommu_data registered for a group | ||
| 209 | * @group: the group | ||
| 210 | * | ||
| 211 | * iommu drivers can store data in the group for use when doing iommu | ||
| 212 | * operations. This function provides a way to retrieve it. Caller | ||
| 213 | * should hold a group reference. | ||
| 214 | */ | ||
| 215 | void *iommu_group_get_iommudata(struct iommu_group *group) | ||
| 216 | { | ||
| 217 | return group->iommu_data; | ||
| 218 | } | ||
| 219 | EXPORT_SYMBOL_GPL(iommu_group_get_iommudata); | ||
| 220 | |||
| 221 | /** | ||
| 222 | * iommu_group_set_iommudata - set iommu_data for a group | ||
| 223 | * @group: the group | ||
| 224 | * @iommu_data: new data | ||
| 225 | * @release: release function for iommu_data | ||
| 226 | * | ||
| 227 | * iommu drivers can store data in the group for use when doing iommu | ||
| 228 | * operations. This function provides a way to set the data after | ||
| 229 | * the group has been allocated. Caller should hold a group reference. | ||
| 230 | */ | ||
| 231 | void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data, | ||
| 232 | void (*release)(void *iommu_data)) | ||
| 43 | { | 233 | { |
| 44 | unsigned int groupid; | 234 | group->iommu_data = iommu_data; |
| 235 | group->iommu_data_release = release; | ||
| 236 | } | ||
| 237 | EXPORT_SYMBOL_GPL(iommu_group_set_iommudata); | ||
| 45 | 238 | ||
| 46 | if (iommu_device_group(dev, &groupid) == 0) | 239 | /** |
| 47 | return device_create_file(dev, &dev_attr_iommu_group); | 240 | * iommu_group_set_name - set name for a group |
| 241 | * @group: the group | ||
| 242 | * @name: name | ||
| 243 | * | ||
| 244 | * Allow iommu driver to set a name for a group. When set it will | ||
| 245 | * appear in a name attribute file under the group in sysfs. | ||
| 246 | */ | ||
| 247 | int iommu_group_set_name(struct iommu_group *group, const char *name) | ||
| 248 | { | ||
| 249 | int ret; | ||
| 250 | |||
| 251 | if (group->name) { | ||
| 252 | iommu_group_remove_file(group, &iommu_group_attr_name); | ||
| 253 | kfree(group->name); | ||
| 254 | group->name = NULL; | ||
| 255 | if (!name) | ||
| 256 | return 0; | ||
| 257 | } | ||
| 258 | |||
| 259 | group->name = kstrdup(name, GFP_KERNEL); | ||
| 260 | if (!group->name) | ||
| 261 | return -ENOMEM; | ||
| 262 | |||
| 263 | ret = iommu_group_create_file(group, &iommu_group_attr_name); | ||
| 264 | if (ret) { | ||
| 265 | kfree(group->name); | ||
| 266 | group->name = NULL; | ||
| 267 | return ret; | ||
| 268 | } | ||
| 48 | 269 | ||
| 49 | return 0; | 270 | return 0; |
| 50 | } | 271 | } |
| 272 | EXPORT_SYMBOL_GPL(iommu_group_set_name); | ||
| 273 | |||
| 274 | /** | ||
| 275 | * iommu_group_add_device - add a device to an iommu group | ||
| 276 | * @group: the group into which to add the device (reference should be held) | ||
| 277 | * @dev: the device | ||
| 278 | * | ||
| 279 | * This function is called by an iommu driver to add a device into a | ||
| 280 | * group. Adding a device increments the group reference count. | ||
| 281 | */ | ||
| 282 | int iommu_group_add_device(struct iommu_group *group, struct device *dev) | ||
| 283 | { | ||
| 284 | int ret, i = 0; | ||
| 285 | struct iommu_device *device; | ||
| 286 | |||
| 287 | device = kzalloc(sizeof(*device), GFP_KERNEL); | ||
| 288 | if (!device) | ||
| 289 | return -ENOMEM; | ||
| 290 | |||
| 291 | device->dev = dev; | ||
| 292 | |||
| 293 | ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group"); | ||
| 294 | if (ret) { | ||
| 295 | kfree(device); | ||
| 296 | return ret; | ||
| 297 | } | ||
| 298 | |||
| 299 | device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj)); | ||
| 300 | rename: | ||
| 301 | if (!device->name) { | ||
| 302 | sysfs_remove_link(&dev->kobj, "iommu_group"); | ||
| 303 | kfree(device); | ||
| 304 | return -ENOMEM; | ||
| 305 | } | ||
| 306 | |||
| 307 | ret = sysfs_create_link_nowarn(group->devices_kobj, | ||
| 308 | &dev->kobj, device->name); | ||
| 309 | if (ret) { | ||
| 310 | kfree(device->name); | ||
| 311 | if (ret == -EEXIST && i >= 0) { | ||
| 312 | /* | ||
| 313 | * Account for the slim chance of collision | ||
| 314 | * and append an instance to the name. | ||
| 315 | */ | ||
| 316 | device->name = kasprintf(GFP_KERNEL, "%s.%d", | ||
| 317 | kobject_name(&dev->kobj), i++); | ||
| 318 | goto rename; | ||
| 319 | } | ||
| 320 | |||
| 321 | sysfs_remove_link(&dev->kobj, "iommu_group"); | ||
| 322 | kfree(device); | ||
| 323 | return ret; | ||
| 324 | } | ||
| 325 | |||
| 326 | kobject_get(group->devices_kobj); | ||
| 327 | |||
| 328 | dev->iommu_group = group; | ||
| 329 | |||
| 330 | mutex_lock(&group->mutex); | ||
| 331 | list_add_tail(&device->list, &group->devices); | ||
| 332 | mutex_unlock(&group->mutex); | ||
| 333 | |||
| 334 | /* Notify any listeners about change to group. */ | ||
| 335 | blocking_notifier_call_chain(&group->notifier, | ||
| 336 | IOMMU_GROUP_NOTIFY_ADD_DEVICE, dev); | ||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | EXPORT_SYMBOL_GPL(iommu_group_add_device); | ||
| 340 | |||
| 341 | /** | ||
| 342 | * iommu_group_remove_device - remove a device from it's current group | ||
| 343 | * @dev: device to be removed | ||
| 344 | * | ||
| 345 | * This function is called by an iommu driver to remove the device from | ||
| 346 | * it's current group. This decrements the iommu group reference count. | ||
| 347 | */ | ||
| 348 | void iommu_group_remove_device(struct device *dev) | ||
| 349 | { | ||
| 350 | struct iommu_group *group = dev->iommu_group; | ||
| 351 | struct iommu_device *tmp_device, *device = NULL; | ||
| 352 | |||
| 353 | /* Pre-notify listeners that a device is being removed. */ | ||
| 354 | blocking_notifier_call_chain(&group->notifier, | ||
| 355 | IOMMU_GROUP_NOTIFY_DEL_DEVICE, dev); | ||
| 356 | |||
| 357 | mutex_lock(&group->mutex); | ||
| 358 | list_for_each_entry(tmp_device, &group->devices, list) { | ||
| 359 | if (tmp_device->dev == dev) { | ||
| 360 | device = tmp_device; | ||
| 361 | list_del(&device->list); | ||
| 362 | break; | ||
| 363 | } | ||
| 364 | } | ||
| 365 | mutex_unlock(&group->mutex); | ||
| 366 | |||
| 367 | if (!device) | ||
| 368 | return; | ||
| 369 | |||
| 370 | sysfs_remove_link(group->devices_kobj, device->name); | ||
| 371 | sysfs_remove_link(&dev->kobj, "iommu_group"); | ||
| 372 | |||
| 373 | kfree(device->name); | ||
| 374 | kfree(device); | ||
| 375 | dev->iommu_group = NULL; | ||
| 376 | kobject_put(group->devices_kobj); | ||
| 377 | } | ||
| 378 | EXPORT_SYMBOL_GPL(iommu_group_remove_device); | ||
| 379 | |||
| 380 | /** | ||
| 381 | * iommu_group_for_each_dev - iterate over each device in the group | ||
| 382 | * @group: the group | ||
| 383 | * @data: caller opaque data to be passed to callback function | ||
| 384 | * @fn: caller supplied callback function | ||
| 385 | * | ||
| 386 | * This function is called by group users to iterate over group devices. | ||
| 387 | * Callers should hold a reference count to the group during callback. | ||
| 388 | * The group->mutex is held across callbacks, which will block calls to | ||
| 389 | * iommu_group_add/remove_device. | ||
| 390 | */ | ||
| 391 | int iommu_group_for_each_dev(struct iommu_group *group, void *data, | ||
| 392 | int (*fn)(struct device *, void *)) | ||
| 393 | { | ||
| 394 | struct iommu_device *device; | ||
| 395 | int ret = 0; | ||
| 396 | |||
| 397 | mutex_lock(&group->mutex); | ||
| 398 | list_for_each_entry(device, &group->devices, list) { | ||
| 399 | ret = fn(device->dev, data); | ||
| 400 | if (ret) | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | mutex_unlock(&group->mutex); | ||
| 404 | return ret; | ||
| 405 | } | ||
| 406 | EXPORT_SYMBOL_GPL(iommu_group_for_each_dev); | ||
| 407 | |||
| 408 | /** | ||
| 409 | * iommu_group_get - Return the group for a device and increment reference | ||
| 410 | * @dev: get the group that this device belongs to | ||
| 411 | * | ||
| 412 | * This function is called by iommu drivers and users to get the group | ||
| 413 | * for the specified device. If found, the group is returned and the group | ||
| 414 | * reference in incremented, else NULL. | ||
| 415 | */ | ||
| 416 | struct iommu_group *iommu_group_get(struct device *dev) | ||
| 417 | { | ||
| 418 | struct iommu_group *group = dev->iommu_group; | ||
| 419 | |||
| 420 | if (group) | ||
| 421 | kobject_get(group->devices_kobj); | ||
| 422 | |||
| 423 | return group; | ||
| 424 | } | ||
| 425 | EXPORT_SYMBOL_GPL(iommu_group_get); | ||
| 426 | |||
| 427 | /** | ||
| 428 | * iommu_group_put - Decrement group reference | ||
| 429 | * @group: the group to use | ||
| 430 | * | ||
| 431 | * This function is called by iommu drivers and users to release the | ||
| 432 | * iommu group. Once the reference count is zero, the group is released. | ||
| 433 | */ | ||
| 434 | void iommu_group_put(struct iommu_group *group) | ||
| 435 | { | ||
| 436 | if (group) | ||
| 437 | kobject_put(group->devices_kobj); | ||
| 438 | } | ||
| 439 | EXPORT_SYMBOL_GPL(iommu_group_put); | ||
| 440 | |||
| 441 | /** | ||
| 442 | * iommu_group_register_notifier - Register a notifier for group changes | ||
| 443 | * @group: the group to watch | ||
| 444 | * @nb: notifier block to signal | ||
| 445 | * | ||
| 446 | * This function allows iommu group users to track changes in a group. | ||
| 447 | * See include/linux/iommu.h for actions sent via this notifier. Caller | ||
| 448 | * should hold a reference to the group throughout notifier registration. | ||
| 449 | */ | ||
| 450 | int iommu_group_register_notifier(struct iommu_group *group, | ||
| 451 | struct notifier_block *nb) | ||
| 452 | { | ||
| 453 | return blocking_notifier_chain_register(&group->notifier, nb); | ||
| 454 | } | ||
| 455 | EXPORT_SYMBOL_GPL(iommu_group_register_notifier); | ||
| 456 | |||
| 457 | /** | ||
| 458 | * iommu_group_unregister_notifier - Unregister a notifier | ||
| 459 | * @group: the group to watch | ||
| 460 | * @nb: notifier block to signal | ||
| 461 | * | ||
| 462 | * Unregister a previously registered group notifier block. | ||
| 463 | */ | ||
| 464 | int iommu_group_unregister_notifier(struct iommu_group *group, | ||
| 465 | struct notifier_block *nb) | ||
| 466 | { | ||
| 467 | return blocking_notifier_chain_unregister(&group->notifier, nb); | ||
| 468 | } | ||
| 469 | EXPORT_SYMBOL_GPL(iommu_group_unregister_notifier); | ||
| 470 | |||
| 471 | /** | ||
| 472 | * iommu_group_id - Return ID for a group | ||
| 473 | * @group: the group to ID | ||
| 474 | * | ||
| 475 | * Return the unique ID for the group matching the sysfs group number. | ||
| 476 | */ | ||
| 477 | int iommu_group_id(struct iommu_group *group) | ||
| 478 | { | ||
| 479 | return group->id; | ||
| 480 | } | ||
| 481 | EXPORT_SYMBOL_GPL(iommu_group_id); | ||
| 51 | 482 | ||
| 52 | static int remove_iommu_group(struct device *dev) | 483 | static int add_iommu_group(struct device *dev, void *data) |
| 53 | { | 484 | { |
| 54 | unsigned int groupid; | 485 | struct iommu_ops *ops = data; |
| 486 | |||
| 487 | if (!ops->add_device) | ||
| 488 | return -ENODEV; | ||
| 55 | 489 | ||
| 56 | if (iommu_device_group(dev, &groupid) == 0) | 490 | WARN_ON(dev->iommu_group); |
| 57 | device_remove_file(dev, &dev_attr_iommu_group); | 491 | |
| 492 | ops->add_device(dev); | ||
| 58 | 493 | ||
| 59 | return 0; | 494 | return 0; |
| 60 | } | 495 | } |
| 61 | 496 | ||
| 62 | static int iommu_device_notifier(struct notifier_block *nb, | 497 | static int iommu_bus_notifier(struct notifier_block *nb, |
| 63 | unsigned long action, void *data) | 498 | unsigned long action, void *data) |
| 64 | { | 499 | { |
| 65 | struct device *dev = data; | 500 | struct device *dev = data; |
| 501 | struct iommu_ops *ops = dev->bus->iommu_ops; | ||
| 502 | struct iommu_group *group; | ||
| 503 | unsigned long group_action = 0; | ||
| 504 | |||
| 505 | /* | ||
| 506 | * ADD/DEL call into iommu driver ops if provided, which may | ||
| 507 | * result in ADD/DEL notifiers to group->notifier | ||
| 508 | */ | ||
| 509 | if (action == BUS_NOTIFY_ADD_DEVICE) { | ||
| 510 | if (ops->add_device) | ||
| 511 | return ops->add_device(dev); | ||
| 512 | } else if (action == BUS_NOTIFY_DEL_DEVICE) { | ||
| 513 | if (ops->remove_device && dev->iommu_group) { | ||
| 514 | ops->remove_device(dev); | ||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | } | ||
| 518 | |||
| 519 | /* | ||
| 520 | * Remaining BUS_NOTIFYs get filtered and republished to the | ||
| 521 | * group, if anyone is listening | ||
| 522 | */ | ||
| 523 | group = iommu_group_get(dev); | ||
| 524 | if (!group) | ||
| 525 | return 0; | ||
| 526 | |||
| 527 | switch (action) { | ||
| 528 | case BUS_NOTIFY_BIND_DRIVER: | ||
| 529 | group_action = IOMMU_GROUP_NOTIFY_BIND_DRIVER; | ||
| 530 | break; | ||
| 531 | case BUS_NOTIFY_BOUND_DRIVER: | ||
| 532 | group_action = IOMMU_GROUP_NOTIFY_BOUND_DRIVER; | ||
| 533 | break; | ||
| 534 | case BUS_NOTIFY_UNBIND_DRIVER: | ||
| 535 | group_action = IOMMU_GROUP_NOTIFY_UNBIND_DRIVER; | ||
| 536 | break; | ||
| 537 | case BUS_NOTIFY_UNBOUND_DRIVER: | ||
| 538 | group_action = IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER; | ||
| 539 | break; | ||
| 540 | } | ||
| 66 | 541 | ||
| 67 | if (action == BUS_NOTIFY_ADD_DEVICE) | 542 | if (group_action) |
| 68 | return add_iommu_group(dev, NULL); | 543 | blocking_notifier_call_chain(&group->notifier, |
| 69 | else if (action == BUS_NOTIFY_DEL_DEVICE) | 544 | group_action, dev); |
| 70 | return remove_iommu_group(dev); | ||
| 71 | 545 | ||
| 546 | iommu_group_put(group); | ||
| 72 | return 0; | 547 | return 0; |
| 73 | } | 548 | } |
| 74 | 549 | ||
| 75 | static struct notifier_block iommu_device_nb = { | 550 | static struct notifier_block iommu_bus_nb = { |
| 76 | .notifier_call = iommu_device_notifier, | 551 | .notifier_call = iommu_bus_notifier, |
| 77 | }; | 552 | }; |
| 78 | 553 | ||
| 79 | static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) | 554 | static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) |
| 80 | { | 555 | { |
| 81 | bus_register_notifier(bus, &iommu_device_nb); | 556 | bus_register_notifier(bus, &iommu_bus_nb); |
| 82 | bus_for_each_dev(bus, NULL, NULL, add_iommu_group); | 557 | bus_for_each_dev(bus, NULL, ops, add_iommu_group); |
| 83 | } | 558 | } |
| 84 | 559 | ||
| 85 | /** | 560 | /** |
| @@ -192,6 +667,45 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) | |||
| 192 | } | 667 | } |
| 193 | EXPORT_SYMBOL_GPL(iommu_detach_device); | 668 | EXPORT_SYMBOL_GPL(iommu_detach_device); |
| 194 | 669 | ||
| 670 | /* | ||
| 671 | * IOMMU groups are really the natrual working unit of the IOMMU, but | ||
| 672 | * the IOMMU API works on domains and devices. Bridge that gap by | ||
| 673 | * iterating over the devices in a group. Ideally we'd have a single | ||
| 674 | * device which represents the requestor ID of the group, but we also | ||
| 675 | * allow IOMMU drivers to create policy defined minimum sets, where | ||
| 676 | * the physical hardware may be able to distiguish members, but we | ||
| 677 | * wish to group them at a higher level (ex. untrusted multi-function | ||
| 678 | * PCI devices). Thus we attach each device. | ||
| 679 | */ | ||
| 680 | static int iommu_group_do_attach_device(struct device *dev, void *data) | ||
| 681 | { | ||
| 682 | struct iommu_domain *domain = data; | ||
| 683 | |||
| 684 | return iommu_attach_device(domain, dev); | ||
| 685 | } | ||
| 686 | |||
| 687 | int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) | ||
| 688 | { | ||
| 689 | return iommu_group_for_each_dev(group, domain, | ||
| 690 | iommu_group_do_attach_device); | ||
| 691 | } | ||
| 692 | EXPORT_SYMBOL_GPL(iommu_attach_group); | ||
| 693 | |||
| 694 | static int iommu_group_do_detach_device(struct device *dev, void *data) | ||
| 695 | { | ||
| 696 | struct iommu_domain *domain = data; | ||
| 697 | |||
| 698 | iommu_detach_device(domain, dev); | ||
| 699 | |||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group) | ||
| 704 | { | ||
| 705 | iommu_group_for_each_dev(group, domain, iommu_group_do_detach_device); | ||
| 706 | } | ||
| 707 | EXPORT_SYMBOL_GPL(iommu_detach_group); | ||
| 708 | |||
| 195 | phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, | 709 | phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, |
| 196 | unsigned long iova) | 710 | unsigned long iova) |
| 197 | { | 711 | { |
| @@ -336,11 +850,48 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) | |||
| 336 | } | 850 | } |
| 337 | EXPORT_SYMBOL_GPL(iommu_unmap); | 851 | EXPORT_SYMBOL_GPL(iommu_unmap); |
| 338 | 852 | ||
| 339 | int iommu_device_group(struct device *dev, unsigned int *groupid) | 853 | static int __init iommu_init(void) |
| 340 | { | 854 | { |
| 341 | if (iommu_present(dev->bus) && dev->bus->iommu_ops->device_group) | 855 | iommu_group_kset = kset_create_and_add("iommu_groups", |
| 342 | return dev->bus->iommu_ops->device_group(dev, groupid); | 856 | NULL, kernel_kobj); |
| 857 | ida_init(&iommu_group_ida); | ||
| 858 | mutex_init(&iommu_group_mutex); | ||
| 859 | |||
| 860 | BUG_ON(!iommu_group_kset); | ||
| 861 | |||
| 862 | return 0; | ||
| 863 | } | ||
| 864 | subsys_initcall(iommu_init); | ||
| 865 | |||
| 866 | int iommu_domain_get_attr(struct iommu_domain *domain, | ||
| 867 | enum iommu_attr attr, void *data) | ||
| 868 | { | ||
| 869 | struct iommu_domain_geometry *geometry; | ||
| 870 | int ret = 0; | ||
| 871 | |||
| 872 | switch (attr) { | ||
| 873 | case DOMAIN_ATTR_GEOMETRY: | ||
| 874 | geometry = data; | ||
| 875 | *geometry = domain->geometry; | ||
| 876 | |||
| 877 | break; | ||
| 878 | default: | ||
| 879 | if (!domain->ops->domain_get_attr) | ||
| 880 | return -EINVAL; | ||
| 881 | |||
| 882 | ret = domain->ops->domain_get_attr(domain, attr, data); | ||
| 883 | } | ||
| 884 | |||
| 885 | return ret; | ||
| 886 | } | ||
| 887 | EXPORT_SYMBOL_GPL(iommu_domain_get_attr); | ||
| 888 | |||
| 889 | int iommu_domain_set_attr(struct iommu_domain *domain, | ||
| 890 | enum iommu_attr attr, void *data) | ||
| 891 | { | ||
| 892 | if (!domain->ops->domain_set_attr) | ||
| 893 | return -EINVAL; | ||
| 343 | 894 | ||
| 344 | return -ENODEV; | 895 | return domain->ops->domain_set_attr(domain, attr, data); |
| 345 | } | 896 | } |
| 346 | EXPORT_SYMBOL_GPL(iommu_device_group); | 897 | EXPORT_SYMBOL_GPL(iommu_domain_set_attr); |
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 1d29b1c66e72..151690db692c 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
| @@ -1,6 +1,11 @@ | |||
| 1 | #include <linux/kernel.h> | 1 | #include <linux/kernel.h> |
| 2 | #include <linux/string.h> | 2 | #include <linux/string.h> |
| 3 | #include <linux/cpumask.h> | ||
| 3 | #include <linux/errno.h> | 4 | #include <linux/errno.h> |
| 5 | #include <linux/msi.h> | ||
| 6 | |||
| 7 | #include <asm/hw_irq.h> | ||
| 8 | #include <asm/irq_remapping.h> | ||
| 4 | 9 | ||
| 5 | #include "irq_remapping.h" | 10 | #include "irq_remapping.h" |
| 6 | 11 | ||
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index cee307e86606..6a8870a31668 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c | |||
| @@ -226,6 +226,11 @@ static int msm_iommu_domain_init(struct iommu_domain *domain) | |||
| 226 | 226 | ||
| 227 | memset(priv->pgtable, 0, SZ_16K); | 227 | memset(priv->pgtable, 0, SZ_16K); |
| 228 | domain->priv = priv; | 228 | domain->priv = priv; |
| 229 | |||
| 230 | domain->geometry.aperture_start = 0; | ||
| 231 | domain->geometry.aperture_end = (1ULL << 32) - 1; | ||
| 232 | domain->geometry.force_aperture = true; | ||
| 233 | |||
| 229 | return 0; | 234 | return 0; |
| 230 | 235 | ||
| 231 | fail_nomem: | 236 | fail_nomem: |
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c new file mode 100644 index 000000000000..ee249bc959f8 --- /dev/null +++ b/drivers/iommu/of_iommu.c | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* | ||
| 2 | * OF helpers for IOMMU | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms and conditions of the GNU General Public License, | ||
| 8 | * version 2, as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
| 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
| 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
| 13 | * more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License along with | ||
| 16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
| 17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/export.h> | ||
| 21 | #include <linux/limits.h> | ||
| 22 | #include <linux/of.h> | ||
| 23 | |||
| 24 | /** | ||
| 25 | * of_get_dma_window - Parse *dma-window property and returns 0 if found. | ||
| 26 | * | ||
| 27 | * @dn: device node | ||
| 28 | * @prefix: prefix for property name if any | ||
| 29 | * @index: index to start to parse | ||
| 30 | * @busno: Returns busno if supported. Otherwise pass NULL | ||
| 31 | * @addr: Returns address that DMA starts | ||
| 32 | * @size: Returns the range that DMA can handle | ||
| 33 | * | ||
| 34 | * This supports different formats flexibly. "prefix" can be | ||
| 35 | * configured if any. "busno" and "index" are optionally | ||
| 36 | * specified. Set 0(or NULL) if not used. | ||
| 37 | */ | ||
| 38 | int of_get_dma_window(struct device_node *dn, const char *prefix, int index, | ||
| 39 | unsigned long *busno, dma_addr_t *addr, size_t *size) | ||
| 40 | { | ||
| 41 | const __be32 *dma_window, *end; | ||
| 42 | int bytes, cur_index = 0; | ||
| 43 | char propname[NAME_MAX], addrname[NAME_MAX], sizename[NAME_MAX]; | ||
| 44 | |||
| 45 | if (!dn || !addr || !size) | ||
| 46 | return -EINVAL; | ||
| 47 | |||
| 48 | if (!prefix) | ||
| 49 | prefix = ""; | ||
| 50 | |||
| 51 | snprintf(propname, sizeof(propname), "%sdma-window", prefix); | ||
| 52 | snprintf(addrname, sizeof(addrname), "%s#dma-address-cells", prefix); | ||
| 53 | snprintf(sizename, sizeof(sizename), "%s#dma-size-cells", prefix); | ||
| 54 | |||
| 55 | dma_window = of_get_property(dn, propname, &bytes); | ||
| 56 | if (!dma_window) | ||
| 57 | return -ENODEV; | ||
| 58 | end = dma_window + bytes / sizeof(*dma_window); | ||
| 59 | |||
| 60 | while (dma_window < end) { | ||
| 61 | u32 cells; | ||
| 62 | const void *prop; | ||
| 63 | |||
| 64 | /* busno is one cell if supported */ | ||
| 65 | if (busno) | ||
| 66 | *busno = be32_to_cpup(dma_window++); | ||
| 67 | |||
| 68 | prop = of_get_property(dn, addrname, NULL); | ||
| 69 | if (!prop) | ||
| 70 | prop = of_get_property(dn, "#address-cells", NULL); | ||
| 71 | |||
| 72 | cells = prop ? be32_to_cpup(prop) : of_n_addr_cells(dn); | ||
| 73 | if (!cells) | ||
| 74 | return -EINVAL; | ||
| 75 | *addr = of_read_number(dma_window, cells); | ||
| 76 | dma_window += cells; | ||
| 77 | |||
| 78 | prop = of_get_property(dn, sizename, NULL); | ||
| 79 | cells = prop ? be32_to_cpup(prop) : of_n_size_cells(dn); | ||
| 80 | if (!cells) | ||
| 81 | return -EINVAL; | ||
| 82 | *size = of_read_number(dma_window, cells); | ||
| 83 | dma_window += cells; | ||
| 84 | |||
| 85 | if (cur_index++ == index) | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | EXPORT_SYMBOL_GPL(of_get_dma_window); | ||
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index e70ee2b59df9..d0b1234581be 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
| @@ -1148,6 +1148,10 @@ static int omap_iommu_domain_init(struct iommu_domain *domain) | |||
| 1148 | 1148 | ||
| 1149 | domain->priv = omap_domain; | 1149 | domain->priv = omap_domain; |
| 1150 | 1150 | ||
| 1151 | domain->geometry.aperture_start = 0; | ||
| 1152 | domain->geometry.aperture_end = (1ULL << 32) - 1; | ||
| 1153 | domain->geometry.force_aperture = true; | ||
| 1154 | |||
| 1151 | return 0; | 1155 | return 0; |
| 1152 | 1156 | ||
| 1153 | fail_nomem: | 1157 | fail_nomem: |
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index 0c0a37792218..c16e8fc8a4bd 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c | |||
| @@ -165,6 +165,11 @@ static int gart_iommu_attach_dev(struct iommu_domain *domain, | |||
| 165 | return -EINVAL; | 165 | return -EINVAL; |
| 166 | domain->priv = gart; | 166 | domain->priv = gart; |
| 167 | 167 | ||
| 168 | domain->geometry.aperture_start = gart->iovmm_base; | ||
| 169 | domain->geometry.aperture_end = gart->iovmm_base + | ||
| 170 | gart->page_count * GART_PAGE_SIZE - 1; | ||
| 171 | domain->geometry.force_aperture = true; | ||
| 172 | |||
| 168 | client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL); | 173 | client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL); |
| 169 | if (!client) | 174 | if (!client) |
| 170 | return -ENOMEM; | 175 | return -ENOMEM; |
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 3f3d09d560ea..4ba325ab6262 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c | |||
| @@ -30,12 +30,15 @@ | |||
| 30 | #include <linux/sched.h> | 30 | #include <linux/sched.h> |
| 31 | #include <linux/iommu.h> | 31 | #include <linux/iommu.h> |
| 32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
| 33 | #include <linux/of.h> | ||
| 34 | #include <linux/of_iommu.h> | ||
| 33 | 35 | ||
| 34 | #include <asm/page.h> | 36 | #include <asm/page.h> |
| 35 | #include <asm/cacheflush.h> | 37 | #include <asm/cacheflush.h> |
| 36 | 38 | ||
| 37 | #include <mach/iomap.h> | 39 | #include <mach/iomap.h> |
| 38 | #include <mach/smmu.h> | 40 | #include <mach/smmu.h> |
| 41 | #include <mach/tegra-ahb.h> | ||
| 39 | 42 | ||
| 40 | /* bitmap of the page sizes currently supported */ | 43 | /* bitmap of the page sizes currently supported */ |
| 41 | #define SMMU_IOMMU_PGSIZES (SZ_4K) | 44 | #define SMMU_IOMMU_PGSIZES (SZ_4K) |
| @@ -111,12 +114,6 @@ | |||
| 111 | 114 | ||
| 112 | #define SMMU_PDE_NEXT_SHIFT 28 | 115 | #define SMMU_PDE_NEXT_SHIFT 28 |
| 113 | 116 | ||
| 114 | /* AHB Arbiter Registers */ | ||
| 115 | #define AHB_XBAR_CTRL 0xe0 | ||
| 116 | #define AHB_XBAR_CTRL_SMMU_INIT_DONE_DONE 1 | ||
| 117 | #define AHB_XBAR_CTRL_SMMU_INIT_DONE_SHIFT 17 | ||
| 118 | |||
| 119 | #define SMMU_NUM_ASIDS 4 | ||
| 120 | #define SMMU_TLB_FLUSH_VA_SECTION__MASK 0xffc00000 | 117 | #define SMMU_TLB_FLUSH_VA_SECTION__MASK 0xffc00000 |
| 121 | #define SMMU_TLB_FLUSH_VA_SECTION__SHIFT 12 /* right shift */ | 118 | #define SMMU_TLB_FLUSH_VA_SECTION__SHIFT 12 /* right shift */ |
| 122 | #define SMMU_TLB_FLUSH_VA_GROUP__MASK 0xffffc000 | 119 | #define SMMU_TLB_FLUSH_VA_GROUP__MASK 0xffffc000 |
| @@ -136,6 +133,7 @@ | |||
| 136 | 133 | ||
| 137 | #define SMMU_PAGE_SHIFT 12 | 134 | #define SMMU_PAGE_SHIFT 12 |
| 138 | #define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT) | 135 | #define SMMU_PAGE_SIZE (1 << SMMU_PAGE_SHIFT) |
| 136 | #define SMMU_PAGE_MASK ((1 << SMMU_PAGE_SHIFT) - 1) | ||
| 139 | 137 | ||
| 140 | #define SMMU_PDIR_COUNT 1024 | 138 | #define SMMU_PDIR_COUNT 1024 |
| 141 | #define SMMU_PDIR_SIZE (sizeof(unsigned long) * SMMU_PDIR_COUNT) | 139 | #define SMMU_PDIR_SIZE (sizeof(unsigned long) * SMMU_PDIR_COUNT) |
| @@ -177,6 +175,8 @@ | |||
| 177 | #define SMMU_ASID_DISABLE 0 | 175 | #define SMMU_ASID_DISABLE 0 |
| 178 | #define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0)) | 176 | #define SMMU_ASID_ASID(n) ((n) & ~SMMU_ASID_ENABLE(0)) |
| 179 | 177 | ||
| 178 | #define NUM_SMMU_REG_BANKS 3 | ||
| 179 | |||
| 180 | #define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) | 180 | #define smmu_client_enable_hwgrp(c, m) smmu_client_set_hwgrp(c, m, 1) |
| 181 | #define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) | 181 | #define smmu_client_disable_hwgrp(c) smmu_client_set_hwgrp(c, 0, 0) |
| 182 | #define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) | 182 | #define __smmu_client_enable_hwgrp(c, m) __smmu_client_set_hwgrp(c, m, 1) |
| @@ -235,14 +235,12 @@ struct smmu_as { | |||
| 235 | * Per SMMU device - IOMMU device | 235 | * Per SMMU device - IOMMU device |
| 236 | */ | 236 | */ |
| 237 | struct smmu_device { | 237 | struct smmu_device { |
| 238 | void __iomem *regs, *regs_ahbarb; | 238 | void __iomem *regs[NUM_SMMU_REG_BANKS]; |
| 239 | unsigned long iovmm_base; /* remappable base address */ | 239 | unsigned long iovmm_base; /* remappable base address */ |
| 240 | unsigned long page_count; /* total remappable size */ | 240 | unsigned long page_count; /* total remappable size */ |
| 241 | spinlock_t lock; | 241 | spinlock_t lock; |
| 242 | char *name; | 242 | char *name; |
| 243 | struct device *dev; | 243 | struct device *dev; |
| 244 | int num_as; | ||
| 245 | struct smmu_as *as; /* Run-time allocated array */ | ||
| 246 | struct page *avp_vector_page; /* dummy page shared by all AS's */ | 244 | struct page *avp_vector_page; /* dummy page shared by all AS's */ |
| 247 | 245 | ||
| 248 | /* | 246 | /* |
| @@ -252,29 +250,50 @@ struct smmu_device { | |||
| 252 | unsigned long translation_enable_1; | 250 | unsigned long translation_enable_1; |
| 253 | unsigned long translation_enable_2; | 251 | unsigned long translation_enable_2; |
| 254 | unsigned long asid_security; | 252 | unsigned long asid_security; |
| 253 | |||
| 254 | struct device_node *ahb; | ||
| 255 | |||
| 256 | int num_as; | ||
| 257 | struct smmu_as as[0]; /* Run-time allocated array */ | ||
| 255 | }; | 258 | }; |
| 256 | 259 | ||
| 257 | static struct smmu_device *smmu_handle; /* unique for a system */ | 260 | static struct smmu_device *smmu_handle; /* unique for a system */ |
| 258 | 261 | ||
| 259 | /* | 262 | /* |
| 260 | * SMMU/AHB register accessors | 263 | * SMMU register accessors |
| 261 | */ | 264 | */ |
| 262 | static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) | 265 | static inline u32 smmu_read(struct smmu_device *smmu, size_t offs) |
| 263 | { | 266 | { |
| 264 | return readl(smmu->regs + offs); | 267 | BUG_ON(offs < 0x10); |
| 265 | } | 268 | if (offs < 0x3c) |
| 266 | static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) | 269 | return readl(smmu->regs[0] + offs - 0x10); |
| 267 | { | 270 | BUG_ON(offs < 0x1f0); |
| 268 | writel(val, smmu->regs + offs); | 271 | if (offs < 0x200) |
| 272 | return readl(smmu->regs[1] + offs - 0x1f0); | ||
| 273 | BUG_ON(offs < 0x228); | ||
| 274 | if (offs < 0x284) | ||
| 275 | return readl(smmu->regs[2] + offs - 0x228); | ||
| 276 | BUG(); | ||
| 269 | } | 277 | } |
| 270 | 278 | ||
| 271 | static inline u32 ahb_read(struct smmu_device *smmu, size_t offs) | 279 | static inline void smmu_write(struct smmu_device *smmu, u32 val, size_t offs) |
| 272 | { | ||
| 273 | return readl(smmu->regs_ahbarb + offs); | ||
| 274 | } | ||
| 275 | static inline void ahb_write(struct smmu_device *smmu, u32 val, size_t offs) | ||
| 276 | { | 280 | { |
| 277 | writel(val, smmu->regs_ahbarb + offs); | 281 | BUG_ON(offs < 0x10); |
| 282 | if (offs < 0x3c) { | ||
| 283 | writel(val, smmu->regs[0] + offs - 0x10); | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | BUG_ON(offs < 0x1f0); | ||
| 287 | if (offs < 0x200) { | ||
| 288 | writel(val, smmu->regs[1] + offs - 0x1f0); | ||
| 289 | return; | ||
| 290 | } | ||
| 291 | BUG_ON(offs < 0x228); | ||
| 292 | if (offs < 0x284) { | ||
| 293 | writel(val, smmu->regs[2] + offs - 0x228); | ||
| 294 | return; | ||
| 295 | } | ||
| 296 | BUG(); | ||
| 278 | } | 297 | } |
| 279 | 298 | ||
| 280 | #define VA_PAGE_TO_PA(va, page) \ | 299 | #define VA_PAGE_TO_PA(va, page) \ |
| @@ -370,7 +389,7 @@ static void smmu_flush_regs(struct smmu_device *smmu, int enable) | |||
| 370 | FLUSH_SMMU_REGS(smmu); | 389 | FLUSH_SMMU_REGS(smmu); |
| 371 | } | 390 | } |
| 372 | 391 | ||
| 373 | static void smmu_setup_regs(struct smmu_device *smmu) | 392 | static int smmu_setup_regs(struct smmu_device *smmu) |
| 374 | { | 393 | { |
| 375 | int i; | 394 | int i; |
| 376 | u32 val; | 395 | u32 val; |
| @@ -398,10 +417,7 @@ static void smmu_setup_regs(struct smmu_device *smmu) | |||
| 398 | 417 | ||
| 399 | smmu_flush_regs(smmu, 1); | 418 | smmu_flush_regs(smmu, 1); |
| 400 | 419 | ||
| 401 | val = ahb_read(smmu, AHB_XBAR_CTRL); | 420 | return tegra_ahb_enable_smmu(smmu->ahb); |
| 402 | val |= AHB_XBAR_CTRL_SMMU_INIT_DONE_DONE << | ||
| 403 | AHB_XBAR_CTRL_SMMU_INIT_DONE_SHIFT; | ||
| 404 | ahb_write(smmu, val, AHB_XBAR_CTRL); | ||
| 405 | } | 421 | } |
| 406 | 422 | ||
| 407 | static void flush_ptc_and_tlb(struct smmu_device *smmu, | 423 | static void flush_ptc_and_tlb(struct smmu_device *smmu, |
| @@ -537,33 +553,42 @@ static inline void put_signature(struct smmu_as *as, | |||
| 537 | #endif | 553 | #endif |
| 538 | 554 | ||
| 539 | /* | 555 | /* |
| 540 | * Caller must lock/unlock as | 556 | * Caller must not hold as->lock |
| 541 | */ | 557 | */ |
| 542 | static int alloc_pdir(struct smmu_as *as) | 558 | static int alloc_pdir(struct smmu_as *as) |
| 543 | { | 559 | { |
| 544 | unsigned long *pdir; | 560 | unsigned long *pdir, flags; |
| 545 | int pdn; | 561 | int pdn, err = 0; |
| 546 | u32 val; | 562 | u32 val; |
| 547 | struct smmu_device *smmu = as->smmu; | 563 | struct smmu_device *smmu = as->smmu; |
| 564 | struct page *page; | ||
| 565 | unsigned int *cnt; | ||
| 566 | |||
| 567 | /* | ||
| 568 | * do the allocation, then grab as->lock | ||
| 569 | */ | ||
| 570 | cnt = devm_kzalloc(smmu->dev, | ||
| 571 | sizeof(cnt[0]) * SMMU_PDIR_COUNT, | ||
| 572 | GFP_KERNEL); | ||
| 573 | page = alloc_page(GFP_KERNEL | __GFP_DMA); | ||
| 548 | 574 | ||
| 549 | if (as->pdir_page) | 575 | spin_lock_irqsave(&as->lock, flags); |
| 550 | return 0; | ||
| 551 | 576 | ||
| 552 | as->pte_count = devm_kzalloc(smmu->dev, | 577 | if (as->pdir_page) { |
| 553 | sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_ATOMIC); | 578 | /* We raced, free the redundant */ |
| 554 | if (!as->pte_count) { | 579 | err = -EAGAIN; |
| 555 | dev_err(smmu->dev, | 580 | goto err_out; |
| 556 | "failed to allocate smmu_device PTE cunters\n"); | ||
| 557 | return -ENOMEM; | ||
| 558 | } | 581 | } |
| 559 | as->pdir_page = alloc_page(GFP_ATOMIC | __GFP_DMA); | 582 | |
| 560 | if (!as->pdir_page) { | 583 | if (!page || !cnt) { |
| 561 | dev_err(smmu->dev, | 584 | dev_err(smmu->dev, "failed to allocate at %s\n", __func__); |
| 562 | "failed to allocate smmu_device page directory\n"); | 585 | err = -ENOMEM; |
| 563 | devm_kfree(smmu->dev, as->pte_count); | 586 | goto err_out; |
| 564 | as->pte_count = NULL; | ||
| 565 | return -ENOMEM; | ||
| 566 | } | 587 | } |
| 588 | |||
| 589 | as->pdir_page = page; | ||
| 590 | as->pte_count = cnt; | ||
| 591 | |||
| 567 | SetPageReserved(as->pdir_page); | 592 | SetPageReserved(as->pdir_page); |
| 568 | pdir = page_address(as->pdir_page); | 593 | pdir = page_address(as->pdir_page); |
| 569 | 594 | ||
| @@ -579,7 +604,17 @@ static int alloc_pdir(struct smmu_as *as) | |||
| 579 | smmu_write(smmu, val, SMMU_TLB_FLUSH); | 604 | smmu_write(smmu, val, SMMU_TLB_FLUSH); |
| 580 | FLUSH_SMMU_REGS(as->smmu); | 605 | FLUSH_SMMU_REGS(as->smmu); |
| 581 | 606 | ||
| 607 | spin_unlock_irqrestore(&as->lock, flags); | ||
| 608 | |||
| 582 | return 0; | 609 | return 0; |
| 610 | |||
| 611 | err_out: | ||
| 612 | spin_unlock_irqrestore(&as->lock, flags); | ||
| 613 | |||
| 614 | devm_kfree(smmu->dev, cnt); | ||
| 615 | if (page) | ||
| 616 | __free_page(page); | ||
| 617 | return err; | ||
| 583 | } | 618 | } |
| 584 | 619 | ||
| 585 | static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova) | 620 | static void __smmu_iommu_unmap(struct smmu_as *as, dma_addr_t iova) |
| @@ -771,30 +806,28 @@ out: | |||
| 771 | 806 | ||
| 772 | static int smmu_iommu_domain_init(struct iommu_domain *domain) | 807 | static int smmu_iommu_domain_init(struct iommu_domain *domain) |
| 773 | { | 808 | { |
| 774 | int i; | 809 | int i, err = -ENODEV; |
| 775 | unsigned long flags; | 810 | unsigned long flags; |
| 776 | struct smmu_as *as; | 811 | struct smmu_as *as; |
| 777 | struct smmu_device *smmu = smmu_handle; | 812 | struct smmu_device *smmu = smmu_handle; |
| 778 | 813 | ||
| 779 | /* Look for a free AS with lock held */ | 814 | /* Look for a free AS with lock held */ |
| 780 | for (i = 0; i < smmu->num_as; i++) { | 815 | for (i = 0; i < smmu->num_as; i++) { |
| 781 | struct smmu_as *tmp = &smmu->as[i]; | 816 | as = &smmu->as[i]; |
| 782 | 817 | if (!as->pdir_page) { | |
| 783 | spin_lock_irqsave(&tmp->lock, flags); | 818 | err = alloc_pdir(as); |
| 784 | if (!tmp->pdir_page) { | 819 | if (!err) |
| 785 | as = tmp; | 820 | goto found; |
| 786 | goto found; | ||
| 787 | } | 821 | } |
| 788 | spin_unlock_irqrestore(&tmp->lock, flags); | 822 | if (err != -EAGAIN) |
| 823 | break; | ||
| 789 | } | 824 | } |
| 790 | dev_err(smmu->dev, "no free AS\n"); | 825 | if (i == smmu->num_as) |
| 791 | return -ENODEV; | 826 | dev_err(smmu->dev, "no free AS\n"); |
| 827 | return err; | ||
| 792 | 828 | ||
| 793 | found: | 829 | found: |
| 794 | if (alloc_pdir(as) < 0) | 830 | spin_lock_irqsave(&smmu->lock, flags); |
| 795 | goto err_alloc_pdir; | ||
| 796 | |||
| 797 | spin_lock(&smmu->lock); | ||
| 798 | 831 | ||
| 799 | /* Update PDIR register */ | 832 | /* Update PDIR register */ |
| 800 | smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID); | 833 | smmu_write(smmu, SMMU_PTB_ASID_CUR(as->asid), SMMU_PTB_ASID); |
| @@ -802,17 +835,18 @@ found: | |||
| 802 | SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA); | 835 | SMMU_MK_PDIR(as->pdir_page, as->pdir_attr), SMMU_PTB_DATA); |
| 803 | FLUSH_SMMU_REGS(smmu); | 836 | FLUSH_SMMU_REGS(smmu); |
| 804 | 837 | ||
| 805 | spin_unlock(&smmu->lock); | 838 | spin_unlock_irqrestore(&smmu->lock, flags); |
| 806 | 839 | ||
| 807 | spin_unlock_irqrestore(&as->lock, flags); | ||
| 808 | domain->priv = as; | 840 | domain->priv = as; |
| 809 | 841 | ||
| 842 | domain->geometry.aperture_start = smmu->iovmm_base; | ||
| 843 | domain->geometry.aperture_end = smmu->iovmm_base + | ||
| 844 | smmu->page_count * SMMU_PAGE_SIZE - 1; | ||
| 845 | domain->geometry.force_aperture = true; | ||
| 846 | |||
| 810 | dev_dbg(smmu->dev, "smmu_as@%p\n", as); | 847 | dev_dbg(smmu->dev, "smmu_as@%p\n", as); |
| 811 | return 0; | ||
| 812 | 848 | ||
| 813 | err_alloc_pdir: | 849 | return 0; |
| 814 | spin_unlock_irqrestore(&as->lock, flags); | ||
| 815 | return -ENODEV; | ||
| 816 | } | 850 | } |
| 817 | 851 | ||
| 818 | static void smmu_iommu_domain_destroy(struct iommu_domain *domain) | 852 | static void smmu_iommu_domain_destroy(struct iommu_domain *domain) |
| @@ -873,65 +907,73 @@ static int tegra_smmu_resume(struct device *dev) | |||
| 873 | { | 907 | { |
| 874 | struct smmu_device *smmu = dev_get_drvdata(dev); | 908 | struct smmu_device *smmu = dev_get_drvdata(dev); |
| 875 | unsigned long flags; | 909 | unsigned long flags; |
| 910 | int err; | ||
| 876 | 911 | ||
| 877 | spin_lock_irqsave(&smmu->lock, flags); | 912 | spin_lock_irqsave(&smmu->lock, flags); |
| 878 | smmu_setup_regs(smmu); | 913 | err = smmu_setup_regs(smmu); |
| 879 | spin_unlock_irqrestore(&smmu->lock, flags); | 914 | spin_unlock_irqrestore(&smmu->lock, flags); |
| 880 | return 0; | 915 | return err; |
| 881 | } | 916 | } |
| 882 | 917 | ||
| 883 | static int tegra_smmu_probe(struct platform_device *pdev) | 918 | static int tegra_smmu_probe(struct platform_device *pdev) |
| 884 | { | 919 | { |
| 885 | struct smmu_device *smmu; | 920 | struct smmu_device *smmu; |
| 886 | struct resource *regs, *regs2, *window; | ||
| 887 | struct device *dev = &pdev->dev; | 921 | struct device *dev = &pdev->dev; |
| 888 | int i, err = 0; | 922 | int i, asids, err = 0; |
| 923 | dma_addr_t uninitialized_var(base); | ||
| 924 | size_t bytes, uninitialized_var(size); | ||
| 889 | 925 | ||
| 890 | if (smmu_handle) | 926 | if (smmu_handle) |
| 891 | return -EIO; | 927 | return -EIO; |
| 892 | 928 | ||
| 893 | BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT); | 929 | BUILD_BUG_ON(PAGE_SHIFT != SMMU_PAGE_SHIFT); |
| 894 | 930 | ||
| 895 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 931 | if (of_property_read_u32(dev->of_node, "nvidia,#asids", &asids)) |
| 896 | regs2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 897 | window = platform_get_resource(pdev, IORESOURCE_MEM, 2); | ||
| 898 | if (!regs || !regs2 || !window) { | ||
| 899 | dev_err(dev, "No SMMU resources\n"); | ||
| 900 | return -ENODEV; | 932 | return -ENODEV; |
| 901 | } | ||
| 902 | 933 | ||
| 903 | smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); | 934 | bytes = sizeof(*smmu) + asids * sizeof(*smmu->as); |
| 935 | smmu = devm_kzalloc(dev, bytes, GFP_KERNEL); | ||
| 904 | if (!smmu) { | 936 | if (!smmu) { |
| 905 | dev_err(dev, "failed to allocate smmu_device\n"); | 937 | dev_err(dev, "failed to allocate smmu_device\n"); |
| 906 | return -ENOMEM; | 938 | return -ENOMEM; |
| 907 | } | 939 | } |
| 908 | 940 | ||
| 909 | smmu->dev = dev; | 941 | for (i = 0; i < ARRAY_SIZE(smmu->regs); i++) { |
| 910 | smmu->num_as = SMMU_NUM_ASIDS; | 942 | struct resource *res; |
| 911 | smmu->iovmm_base = (unsigned long)window->start; | 943 | |
| 912 | smmu->page_count = resource_size(window) >> SMMU_PAGE_SHIFT; | 944 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); |
| 913 | smmu->regs = devm_ioremap(dev, regs->start, resource_size(regs)); | 945 | if (!res) |
| 914 | smmu->regs_ahbarb = devm_ioremap(dev, regs2->start, | 946 | return -ENODEV; |
| 915 | resource_size(regs2)); | 947 | smmu->regs[i] = devm_request_and_ioremap(&pdev->dev, res); |
| 916 | if (!smmu->regs || !smmu->regs_ahbarb) { | 948 | if (!smmu->regs[i]) |
| 917 | dev_err(dev, "failed to remap SMMU registers\n"); | 949 | return -EBUSY; |
| 918 | err = -ENXIO; | ||
| 919 | goto fail; | ||
| 920 | } | 950 | } |
| 921 | 951 | ||
| 952 | err = of_get_dma_window(dev->of_node, NULL, 0, NULL, &base, &size); | ||
| 953 | if (err) | ||
| 954 | return -ENODEV; | ||
| 955 | |||
| 956 | if (size & SMMU_PAGE_MASK) | ||
| 957 | return -EINVAL; | ||
| 958 | |||
| 959 | size >>= SMMU_PAGE_SHIFT; | ||
| 960 | if (!size) | ||
| 961 | return -EINVAL; | ||
| 962 | |||
| 963 | smmu->ahb = of_parse_phandle(dev->of_node, "nvidia,ahb", 0); | ||
| 964 | if (!smmu->ahb) | ||
| 965 | return -ENODEV; | ||
| 966 | |||
| 967 | smmu->dev = dev; | ||
| 968 | smmu->num_as = asids; | ||
| 969 | smmu->iovmm_base = base; | ||
| 970 | smmu->page_count = size; | ||
| 971 | |||
| 922 | smmu->translation_enable_0 = ~0; | 972 | smmu->translation_enable_0 = ~0; |
| 923 | smmu->translation_enable_1 = ~0; | 973 | smmu->translation_enable_1 = ~0; |
| 924 | smmu->translation_enable_2 = ~0; | 974 | smmu->translation_enable_2 = ~0; |
| 925 | smmu->asid_security = 0; | 975 | smmu->asid_security = 0; |
| 926 | 976 | ||
| 927 | smmu->as = devm_kzalloc(dev, | ||
| 928 | sizeof(smmu->as[0]) * smmu->num_as, GFP_KERNEL); | ||
| 929 | if (!smmu->as) { | ||
| 930 | dev_err(dev, "failed to allocate smmu_as\n"); | ||
| 931 | err = -ENOMEM; | ||
| 932 | goto fail; | ||
| 933 | } | ||
| 934 | |||
| 935 | for (i = 0; i < smmu->num_as; i++) { | 977 | for (i = 0; i < smmu->num_as; i++) { |
| 936 | struct smmu_as *as = &smmu->as[i]; | 978 | struct smmu_as *as = &smmu->as[i]; |
| 937 | 979 | ||
| @@ -945,57 +987,28 @@ static int tegra_smmu_probe(struct platform_device *pdev) | |||
| 945 | INIT_LIST_HEAD(&as->client); | 987 | INIT_LIST_HEAD(&as->client); |
| 946 | } | 988 | } |
| 947 | spin_lock_init(&smmu->lock); | 989 | spin_lock_init(&smmu->lock); |
| 948 | smmu_setup_regs(smmu); | 990 | err = smmu_setup_regs(smmu); |
| 991 | if (err) | ||
| 992 | return err; | ||
| 949 | platform_set_drvdata(pdev, smmu); | 993 | platform_set_drvdata(pdev, smmu); |
| 950 | 994 | ||
| 951 | smmu->avp_vector_page = alloc_page(GFP_KERNEL); | 995 | smmu->avp_vector_page = alloc_page(GFP_KERNEL); |
| 952 | if (!smmu->avp_vector_page) | 996 | if (!smmu->avp_vector_page) |
| 953 | goto fail; | 997 | return -ENOMEM; |
| 954 | 998 | ||
| 955 | smmu_handle = smmu; | 999 | smmu_handle = smmu; |
| 956 | return 0; | 1000 | return 0; |
| 957 | |||
| 958 | fail: | ||
| 959 | if (smmu->avp_vector_page) | ||
| 960 | __free_page(smmu->avp_vector_page); | ||
| 961 | if (smmu->regs) | ||
| 962 | devm_iounmap(dev, smmu->regs); | ||
| 963 | if (smmu->regs_ahbarb) | ||
| 964 | devm_iounmap(dev, smmu->regs_ahbarb); | ||
| 965 | if (smmu && smmu->as) { | ||
| 966 | for (i = 0; i < smmu->num_as; i++) { | ||
| 967 | if (smmu->as[i].pdir_page) { | ||
| 968 | ClearPageReserved(smmu->as[i].pdir_page); | ||
| 969 | __free_page(smmu->as[i].pdir_page); | ||
| 970 | } | ||
| 971 | } | ||
| 972 | devm_kfree(dev, smmu->as); | ||
| 973 | } | ||
| 974 | devm_kfree(dev, smmu); | ||
| 975 | return err; | ||
| 976 | } | 1001 | } |
| 977 | 1002 | ||
| 978 | static int tegra_smmu_remove(struct platform_device *pdev) | 1003 | static int tegra_smmu_remove(struct platform_device *pdev) |
| 979 | { | 1004 | { |
| 980 | struct smmu_device *smmu = platform_get_drvdata(pdev); | 1005 | struct smmu_device *smmu = platform_get_drvdata(pdev); |
| 981 | struct device *dev = smmu->dev; | 1006 | int i; |
| 982 | 1007 | ||
| 983 | smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG); | 1008 | smmu_write(smmu, SMMU_CONFIG_DISABLE, SMMU_CONFIG); |
| 984 | platform_set_drvdata(pdev, NULL); | 1009 | for (i = 0; i < smmu->num_as; i++) |
| 985 | if (smmu->as) { | 1010 | free_pdir(&smmu->as[i]); |
| 986 | int i; | 1011 | __free_page(smmu->avp_vector_page); |
| 987 | |||
| 988 | for (i = 0; i < smmu->num_as; i++) | ||
| 989 | free_pdir(&smmu->as[i]); | ||
| 990 | devm_kfree(dev, smmu->as); | ||
| 991 | } | ||
| 992 | if (smmu->avp_vector_page) | ||
| 993 | __free_page(smmu->avp_vector_page); | ||
| 994 | if (smmu->regs) | ||
| 995 | devm_iounmap(dev, smmu->regs); | ||
| 996 | if (smmu->regs_ahbarb) | ||
| 997 | devm_iounmap(dev, smmu->regs_ahbarb); | ||
| 998 | devm_kfree(dev, smmu); | ||
| 999 | smmu_handle = NULL; | 1012 | smmu_handle = NULL; |
| 1000 | return 0; | 1013 | return 0; |
| 1001 | } | 1014 | } |
| @@ -1005,6 +1018,14 @@ const struct dev_pm_ops tegra_smmu_pm_ops = { | |||
| 1005 | .resume = tegra_smmu_resume, | 1018 | .resume = tegra_smmu_resume, |
| 1006 | }; | 1019 | }; |
| 1007 | 1020 | ||
| 1021 | #ifdef CONFIG_OF | ||
| 1022 | static struct of_device_id tegra_smmu_of_match[] __devinitdata = { | ||
| 1023 | { .compatible = "nvidia,tegra30-smmu", }, | ||
| 1024 | { }, | ||
| 1025 | }; | ||
| 1026 | MODULE_DEVICE_TABLE(of, tegra_smmu_of_match); | ||
| 1027 | #endif | ||
| 1028 | |||
| 1008 | static struct platform_driver tegra_smmu_driver = { | 1029 | static struct platform_driver tegra_smmu_driver = { |
| 1009 | .probe = tegra_smmu_probe, | 1030 | .probe = tegra_smmu_probe, |
| 1010 | .remove = tegra_smmu_remove, | 1031 | .remove = tegra_smmu_remove, |
| @@ -1012,6 +1033,7 @@ static struct platform_driver tegra_smmu_driver = { | |||
| 1012 | .owner = THIS_MODULE, | 1033 | .owner = THIS_MODULE, |
| 1013 | .name = "tegra-smmu", | 1034 | .name = "tegra-smmu", |
| 1014 | .pm = &tegra_smmu_pm_ops, | 1035 | .pm = &tegra_smmu_pm_ops, |
| 1036 | .of_match_table = of_match_ptr(tegra_smmu_of_match), | ||
| 1015 | }, | 1037 | }, |
| 1016 | }; | 1038 | }; |
| 1017 | 1039 | ||
| @@ -1031,4 +1053,5 @@ module_exit(tegra_smmu_exit); | |||
| 1031 | 1053 | ||
| 1032 | MODULE_DESCRIPTION("IOMMU API for SMMU in Tegra30"); | 1054 | MODULE_DESCRIPTION("IOMMU API for SMMU in Tegra30"); |
| 1033 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); | 1055 | MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>"); |
| 1056 | MODULE_ALIAS("platform:tegra-smmu"); | ||
| 1034 | MODULE_LICENSE("GPL v2"); | 1057 | MODULE_LICENSE("GPL v2"); |
diff --git a/include/linux/device.h b/include/linux/device.h index 6de94151ff6f..5083bccae967 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -36,6 +36,7 @@ struct subsys_private; | |||
| 36 | struct bus_type; | 36 | struct bus_type; |
| 37 | struct device_node; | 37 | struct device_node; |
| 38 | struct iommu_ops; | 38 | struct iommu_ops; |
| 39 | struct iommu_group; | ||
| 39 | 40 | ||
| 40 | struct bus_attribute { | 41 | struct bus_attribute { |
| 41 | struct attribute attr; | 42 | struct attribute attr; |
| @@ -687,6 +688,7 @@ struct device { | |||
| 687 | const struct attribute_group **groups; /* optional groups */ | 688 | const struct attribute_group **groups; /* optional groups */ |
| 688 | 689 | ||
| 689 | void (*release)(struct device *dev); | 690 | void (*release)(struct device *dev); |
| 691 | struct iommu_group *iommu_group; | ||
| 690 | }; | 692 | }; |
| 691 | 693 | ||
| 692 | /* Get the wakeup routines, which depend on struct device */ | 694 | /* Get the wakeup routines, which depend on struct device */ |
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 450293f6d68b..54d6d690073c 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #define IOMMU_CACHE (4) /* DMA cache coherency */ | 26 | #define IOMMU_CACHE (4) /* DMA cache coherency */ |
| 27 | 27 | ||
| 28 | struct iommu_ops; | 28 | struct iommu_ops; |
| 29 | struct iommu_group; | ||
| 29 | struct bus_type; | 30 | struct bus_type; |
| 30 | struct device; | 31 | struct device; |
| 31 | struct iommu_domain; | 32 | struct iommu_domain; |
| @@ -37,16 +38,28 @@ struct iommu_domain; | |||
| 37 | typedef int (*iommu_fault_handler_t)(struct iommu_domain *, | 38 | typedef int (*iommu_fault_handler_t)(struct iommu_domain *, |
| 38 | struct device *, unsigned long, int, void *); | 39 | struct device *, unsigned long, int, void *); |
| 39 | 40 | ||
| 41 | struct iommu_domain_geometry { | ||
| 42 | dma_addr_t aperture_start; /* First address that can be mapped */ | ||
| 43 | dma_addr_t aperture_end; /* Last address that can be mapped */ | ||
| 44 | bool force_aperture; /* DMA only allowed in mappable range? */ | ||
| 45 | }; | ||
| 46 | |||
| 40 | struct iommu_domain { | 47 | struct iommu_domain { |
| 41 | struct iommu_ops *ops; | 48 | struct iommu_ops *ops; |
| 42 | void *priv; | 49 | void *priv; |
| 43 | iommu_fault_handler_t handler; | 50 | iommu_fault_handler_t handler; |
| 44 | void *handler_token; | 51 | void *handler_token; |
| 52 | struct iommu_domain_geometry geometry; | ||
| 45 | }; | 53 | }; |
| 46 | 54 | ||
| 47 | #define IOMMU_CAP_CACHE_COHERENCY 0x1 | 55 | #define IOMMU_CAP_CACHE_COHERENCY 0x1 |
| 48 | #define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ | 56 | #define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ |
| 49 | 57 | ||
| 58 | enum iommu_attr { | ||
| 59 | DOMAIN_ATTR_MAX, | ||
| 60 | DOMAIN_ATTR_GEOMETRY, | ||
| 61 | }; | ||
| 62 | |||
| 50 | #ifdef CONFIG_IOMMU_API | 63 | #ifdef CONFIG_IOMMU_API |
| 51 | 64 | ||
| 52 | /** | 65 | /** |
| @@ -59,7 +72,10 @@ struct iommu_domain { | |||
| 59 | * @unmap: unmap a physically contiguous memory region from an iommu domain | 72 | * @unmap: unmap a physically contiguous memory region from an iommu domain |
| 60 | * @iova_to_phys: translate iova to physical address | 73 | * @iova_to_phys: translate iova to physical address |
| 61 | * @domain_has_cap: domain capabilities query | 74 | * @domain_has_cap: domain capabilities query |
| 62 | * @commit: commit iommu domain | 75 | * @add_device: add device to iommu grouping |
| 76 | * @remove_device: remove device from iommu grouping | ||
| 77 | * @domain_get_attr: Query domain attributes | ||
| 78 | * @domain_set_attr: Change domain attributes | ||
| 63 | * @pgsize_bitmap: bitmap of supported page sizes | 79 | * @pgsize_bitmap: bitmap of supported page sizes |
| 64 | */ | 80 | */ |
| 65 | struct iommu_ops { | 81 | struct iommu_ops { |
| @@ -75,10 +91,23 @@ struct iommu_ops { | |||
| 75 | unsigned long iova); | 91 | unsigned long iova); |
| 76 | int (*domain_has_cap)(struct iommu_domain *domain, | 92 | int (*domain_has_cap)(struct iommu_domain *domain, |
| 77 | unsigned long cap); | 93 | unsigned long cap); |
| 94 | int (*add_device)(struct device *dev); | ||
| 95 | void (*remove_device)(struct device *dev); | ||
| 78 | int (*device_group)(struct device *dev, unsigned int *groupid); | 96 | int (*device_group)(struct device *dev, unsigned int *groupid); |
| 97 | int (*domain_get_attr)(struct iommu_domain *domain, | ||
| 98 | enum iommu_attr attr, void *data); | ||
| 99 | int (*domain_set_attr)(struct iommu_domain *domain, | ||
| 100 | enum iommu_attr attr, void *data); | ||
| 79 | unsigned long pgsize_bitmap; | 101 | unsigned long pgsize_bitmap; |
| 80 | }; | 102 | }; |
| 81 | 103 | ||
| 104 | #define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */ | ||
| 105 | #define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ | ||
| 106 | #define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ | ||
| 107 | #define IOMMU_GROUP_NOTIFY_BOUND_DRIVER 4 /* Post Driver bind */ | ||
| 108 | #define IOMMU_GROUP_NOTIFY_UNBIND_DRIVER 5 /* Pre Driver unbind */ | ||
| 109 | #define IOMMU_GROUP_NOTIFY_UNBOUND_DRIVER 6 /* Post Driver unbind */ | ||
| 110 | |||
| 82 | extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); | 111 | extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); |
| 83 | extern bool iommu_present(struct bus_type *bus); | 112 | extern bool iommu_present(struct bus_type *bus); |
| 84 | extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); | 113 | extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); |
| @@ -97,7 +126,34 @@ extern int iommu_domain_has_cap(struct iommu_domain *domain, | |||
| 97 | unsigned long cap); | 126 | unsigned long cap); |
| 98 | extern void iommu_set_fault_handler(struct iommu_domain *domain, | 127 | extern void iommu_set_fault_handler(struct iommu_domain *domain, |
| 99 | iommu_fault_handler_t handler, void *token); | 128 | iommu_fault_handler_t handler, void *token); |
| 100 | extern int iommu_device_group(struct device *dev, unsigned int *groupid); | 129 | |
| 130 | extern int iommu_attach_group(struct iommu_domain *domain, | ||
| 131 | struct iommu_group *group); | ||
| 132 | extern void iommu_detach_group(struct iommu_domain *domain, | ||
| 133 | struct iommu_group *group); | ||
| 134 | extern struct iommu_group *iommu_group_alloc(void); | ||
| 135 | extern void *iommu_group_get_iommudata(struct iommu_group *group); | ||
| 136 | extern void iommu_group_set_iommudata(struct iommu_group *group, | ||
| 137 | void *iommu_data, | ||
| 138 | void (*release)(void *iommu_data)); | ||
| 139 | extern int iommu_group_set_name(struct iommu_group *group, const char *name); | ||
| 140 | extern int iommu_group_add_device(struct iommu_group *group, | ||
| 141 | struct device *dev); | ||
| 142 | extern void iommu_group_remove_device(struct device *dev); | ||
| 143 | extern int iommu_group_for_each_dev(struct iommu_group *group, void *data, | ||
| 144 | int (*fn)(struct device *, void *)); | ||
| 145 | extern struct iommu_group *iommu_group_get(struct device *dev); | ||
| 146 | extern void iommu_group_put(struct iommu_group *group); | ||
| 147 | extern int iommu_group_register_notifier(struct iommu_group *group, | ||
| 148 | struct notifier_block *nb); | ||
| 149 | extern int iommu_group_unregister_notifier(struct iommu_group *group, | ||
| 150 | struct notifier_block *nb); | ||
| 151 | extern int iommu_group_id(struct iommu_group *group); | ||
| 152 | |||
| 153 | extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr, | ||
| 154 | void *data); | ||
| 155 | extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, | ||
| 156 | void *data); | ||
| 101 | 157 | ||
| 102 | /** | 158 | /** |
| 103 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework | 159 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework |
| @@ -142,6 +198,7 @@ static inline int report_iommu_fault(struct iommu_domain *domain, | |||
| 142 | #else /* CONFIG_IOMMU_API */ | 198 | #else /* CONFIG_IOMMU_API */ |
| 143 | 199 | ||
| 144 | struct iommu_ops {}; | 200 | struct iommu_ops {}; |
| 201 | struct iommu_group {}; | ||
| 145 | 202 | ||
| 146 | static inline bool iommu_present(struct bus_type *bus) | 203 | static inline bool iommu_present(struct bus_type *bus) |
| 147 | { | 204 | { |
| @@ -197,11 +254,88 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain, | |||
| 197 | { | 254 | { |
| 198 | } | 255 | } |
| 199 | 256 | ||
| 200 | static inline int iommu_device_group(struct device *dev, unsigned int *groupid) | 257 | int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group) |
| 258 | { | ||
| 259 | return -ENODEV; | ||
| 260 | } | ||
| 261 | |||
| 262 | void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group) | ||
| 263 | { | ||
| 264 | } | ||
| 265 | |||
| 266 | struct iommu_group *iommu_group_alloc(void) | ||
| 267 | { | ||
| 268 | return ERR_PTR(-ENODEV); | ||
| 269 | } | ||
| 270 | |||
| 271 | void *iommu_group_get_iommudata(struct iommu_group *group) | ||
| 272 | { | ||
| 273 | return NULL; | ||
| 274 | } | ||
| 275 | |||
| 276 | void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data, | ||
| 277 | void (*release)(void *iommu_data)) | ||
| 278 | { | ||
| 279 | } | ||
| 280 | |||
| 281 | int iommu_group_set_name(struct iommu_group *group, const char *name) | ||
| 282 | { | ||
| 283 | return -ENODEV; | ||
| 284 | } | ||
| 285 | |||
| 286 | int iommu_group_add_device(struct iommu_group *group, struct device *dev) | ||
| 287 | { | ||
| 288 | return -ENODEV; | ||
| 289 | } | ||
| 290 | |||
| 291 | void iommu_group_remove_device(struct device *dev) | ||
| 292 | { | ||
| 293 | } | ||
| 294 | |||
| 295 | int iommu_group_for_each_dev(struct iommu_group *group, void *data, | ||
| 296 | int (*fn)(struct device *, void *)) | ||
| 297 | { | ||
| 298 | return -ENODEV; | ||
| 299 | } | ||
| 300 | |||
| 301 | struct iommu_group *iommu_group_get(struct device *dev) | ||
| 302 | { | ||
| 303 | return NULL; | ||
| 304 | } | ||
| 305 | |||
| 306 | void iommu_group_put(struct iommu_group *group) | ||
| 307 | { | ||
| 308 | } | ||
| 309 | |||
| 310 | int iommu_group_register_notifier(struct iommu_group *group, | ||
| 311 | struct notifier_block *nb) | ||
| 201 | { | 312 | { |
| 202 | return -ENODEV; | 313 | return -ENODEV; |
| 203 | } | 314 | } |
| 204 | 315 | ||
| 316 | int iommu_group_unregister_notifier(struct iommu_group *group, | ||
| 317 | struct notifier_block *nb) | ||
| 318 | { | ||
| 319 | return 0; | ||
| 320 | } | ||
| 321 | |||
| 322 | int iommu_group_id(struct iommu_group *group) | ||
| 323 | { | ||
| 324 | return -ENODEV; | ||
| 325 | } | ||
| 326 | |||
| 327 | static inline int iommu_domain_get_attr(struct iommu_domain *domain, | ||
| 328 | enum iommu_attr attr, void *data) | ||
| 329 | { | ||
| 330 | return -EINVAL; | ||
| 331 | } | ||
| 332 | |||
| 333 | static inline int iommu_domain_set_attr(struct iommu_domain *domain, | ||
| 334 | enum iommu_attr attr, void *data) | ||
| 335 | { | ||
| 336 | return -EINVAL; | ||
| 337 | } | ||
| 338 | |||
| 205 | #endif /* CONFIG_IOMMU_API */ | 339 | #endif /* CONFIG_IOMMU_API */ |
| 206 | 340 | ||
| 207 | #endif /* __LINUX_IOMMU_H */ | 341 | #endif /* __LINUX_IOMMU_H */ |
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h new file mode 100644 index 000000000000..51a560f34bca --- /dev/null +++ b/include/linux/of_iommu.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | #ifndef __OF_IOMMU_H | ||
| 2 | #define __OF_IOMMU_H | ||
| 3 | |||
| 4 | #ifdef CONFIG_OF_IOMMU | ||
| 5 | |||
| 6 | extern int of_get_dma_window(struct device_node *dn, const char *prefix, | ||
| 7 | int index, unsigned long *busno, dma_addr_t *addr, | ||
| 8 | size_t *size); | ||
| 9 | |||
| 10 | #else | ||
| 11 | |||
| 12 | static inline int of_get_dma_window(struct device_node *dn, const char *prefix, | ||
| 13 | int index, unsigned long *busno, dma_addr_t *addr, | ||
| 14 | size_t *size) | ||
| 15 | { | ||
| 16 | return -EINVAL; | ||
| 17 | } | ||
| 18 | |||
| 19 | #endif /* CONFIG_OF_IOMMU */ | ||
| 20 | |||
| 21 | #endif /* __OF_IOMMU_H */ | ||
