diff options
44 files changed, 838 insertions, 611 deletions
diff --git a/Documentation/devicetree/bindings/iommu/nvidia,tegra20-gart.txt b/Documentation/devicetree/bindings/iommu/nvidia,tegra20-gart.txt deleted file mode 100644 index 099d9362ebc1..000000000000 --- a/Documentation/devicetree/bindings/iommu/nvidia,tegra20-gart.txt +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | NVIDIA Tegra 20 GART | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: "nvidia,tegra20-gart" | ||
5 | - reg: Two pairs of cells specifying the physical address and size of | ||
6 | the memory controller registers and the GART aperture respectively. | ||
7 | |||
8 | Example: | ||
9 | |||
10 | gart { | ||
11 | compatible = "nvidia,tegra20-gart"; | ||
12 | reg = <0x7000f024 0x00000018 /* controller registers */ | ||
13 | 0x58000000 0x02000000>; /* GART aperture */ | ||
14 | }; | ||
diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt index 7d60a50a4fa1..e55328237df4 100644 --- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt +++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt | |||
@@ -1,26 +1,37 @@ | |||
1 | NVIDIA Tegra20 MC(Memory Controller) | 1 | NVIDIA Tegra20 MC(Memory Controller) |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible : "nvidia,tegra20-mc" | 4 | - compatible : "nvidia,tegra20-mc-gart" |
5 | - reg : Should contain 2 register ranges(address and length); see the | 5 | - reg : Should contain 2 register ranges: physical base address and length of |
6 | example below. Note that the MC registers are interleaved with the | 6 | the controller's registers and the GART aperture respectively. |
7 | GART registers, and hence must be represented as multiple ranges. | 7 | - clocks: Must contain an entry for each entry in clock-names. |
8 | See ../clocks/clock-bindings.txt for details. | ||
9 | - clock-names: Must include the following entries: | ||
10 | - mc: the module's clock input | ||
8 | - interrupts : Should contain MC General interrupt. | 11 | - interrupts : Should contain MC General interrupt. |
9 | - #reset-cells : Should be 1. This cell represents memory client module ID. | 12 | - #reset-cells : Should be 1. This cell represents memory client module ID. |
10 | The assignments may be found in header file <dt-bindings/memory/tegra20-mc.h> | 13 | The assignments may be found in header file <dt-bindings/memory/tegra20-mc.h> |
11 | or in the TRM documentation. | 14 | or in the TRM documentation. |
15 | - #iommu-cells: Should be 0. This cell represents the number of cells in an | ||
16 | IOMMU specifier needed to encode an address. GART supports only a single | ||
17 | address space that is shared by all devices, therefore no additional | ||
18 | information needed for the address encoding. | ||
12 | 19 | ||
13 | Example: | 20 | Example: |
14 | mc: memory-controller@7000f000 { | 21 | mc: memory-controller@7000f000 { |
15 | compatible = "nvidia,tegra20-mc"; | 22 | compatible = "nvidia,tegra20-mc-gart"; |
16 | reg = <0x7000f000 0x024 | 23 | reg = <0x7000f000 0x400 /* controller registers */ |
17 | 0x7000f03c 0x3c4>; | 24 | 0x58000000 0x02000000>; /* GART aperture */ |
18 | interrupts = <0 77 0x04>; | 25 | clocks = <&tegra_car TEGRA20_CLK_MC>; |
26 | clock-names = "mc"; | ||
27 | interrupts = <GIC_SPI 77 0x04>; | ||
19 | #reset-cells = <1>; | 28 | #reset-cells = <1>; |
29 | #iommu-cells = <0>; | ||
20 | }; | 30 | }; |
21 | 31 | ||
22 | video-codec@6001a000 { | 32 | video-codec@6001a000 { |
23 | compatible = "nvidia,tegra20-vde"; | 33 | compatible = "nvidia,tegra20-vde"; |
24 | ... | 34 | ... |
25 | resets = <&mc TEGRA20_MC_RESET_VDE>; | 35 | resets = <&mc TEGRA20_MC_RESET_VDE>; |
36 | iommus = <&mc>; | ||
26 | }; | 37 | }; |
diff --git a/MAINTAINERS b/MAINTAINERS index dce5c099f43c..a7432224930b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7027,6 +7027,7 @@ F: drivers/net/hyperv/ | |||
7027 | F: drivers/scsi/storvsc_drv.c | 7027 | F: drivers/scsi/storvsc_drv.c |
7028 | F: drivers/uio/uio_hv_generic.c | 7028 | F: drivers/uio/uio_hv_generic.c |
7029 | F: drivers/video/fbdev/hyperv_fb.c | 7029 | F: drivers/video/fbdev/hyperv_fb.c |
7030 | F: drivers/iommu/hyperv_iommu.c | ||
7030 | F: net/vmw_vsock/hyperv_transport.c | 7031 | F: net/vmw_vsock/hyperv_transport.c |
7031 | F: include/linux/hyperv.h | 7032 | F: include/linux/hyperv.h |
7032 | F: include/uapi/linux/hyperv.h | 7033 | F: include/uapi/linux/hyperv.h |
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi index dcad6d6128cf..8c942e60703e 100644 --- a/arch/arm/boot/dts/tegra20.dtsi +++ b/arch/arm/boot/dts/tegra20.dtsi | |||
@@ -616,17 +616,14 @@ | |||
616 | }; | 616 | }; |
617 | 617 | ||
618 | mc: memory-controller@7000f000 { | 618 | mc: memory-controller@7000f000 { |
619 | compatible = "nvidia,tegra20-mc"; | 619 | compatible = "nvidia,tegra20-mc-gart"; |
620 | reg = <0x7000f000 0x024 | 620 | reg = <0x7000f000 0x400 /* controller registers */ |
621 | 0x7000f03c 0x3c4>; | 621 | 0x58000000 0x02000000>; /* GART aperture */ |
622 | clocks = <&tegra_car TEGRA20_CLK_MC>; | ||
623 | clock-names = "mc"; | ||
622 | interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; | 624 | interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>; |
623 | #reset-cells = <1>; | 625 | #reset-cells = <1>; |
624 | }; | 626 | #iommu-cells = <0>; |
625 | |||
626 | iommu@7000f024 { | ||
627 | compatible = "nvidia,tegra20-gart"; | ||
628 | reg = <0x7000f024 0x00000018 /* controller registers */ | ||
629 | 0x58000000 0x02000000>; /* GART aperture */ | ||
630 | }; | 627 | }; |
631 | 628 | ||
632 | memory-controller@7000f400 { | 629 | memory-controller@7000f400 { |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index e81a2db42df7..3fa238a137d2 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -328,6 +328,18 @@ static void __init ms_hyperv_init_platform(void) | |||
328 | # ifdef CONFIG_SMP | 328 | # ifdef CONFIG_SMP |
329 | smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu; | 329 | smp_ops.smp_prepare_boot_cpu = hv_smp_prepare_boot_cpu; |
330 | # endif | 330 | # endif |
331 | |||
332 | /* | ||
333 | * Hyper-V doesn't provide irq remapping for IO-APIC. To enable x2apic, | ||
334 | * set x2apic destination mode to physcial mode when x2apic is available | ||
335 | * and Hyper-V IOMMU driver makes sure cpus assigned with IO-APIC irqs | ||
336 | * have 8-bit APIC id. | ||
337 | */ | ||
338 | # ifdef CONFIG_X86_X2APIC | ||
339 | if (x2apic_supported()) | ||
340 | x2apic_phys = 1; | ||
341 | # endif | ||
342 | |||
331 | #endif | 343 | #endif |
332 | } | 344 | } |
333 | 345 | ||
diff --git a/drivers/Makefile b/drivers/Makefile index e1ce029d28fd..04da7876032c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -56,7 +56,7 @@ obj-y += tty/ | |||
56 | obj-y += char/ | 56 | obj-y += char/ |
57 | 57 | ||
58 | # iommu/ comes before gpu as gpu are using iommu controllers | 58 | # iommu/ comes before gpu as gpu are using iommu controllers |
59 | obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ | 59 | obj-y += iommu/ |
60 | 60 | ||
61 | # gpu/ comes after char for AGP vs DRM startup and after iommu | 61 | # gpu/ comes after char for AGP vs DRM startup and after iommu |
62 | obj-y += gpu/ | 62 | obj-y += gpu/ |
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index d9a25715650e..6f07f3b21816 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -1,3 +1,7 @@ | |||
1 | # The IOVA library may also be used by non-IOMMU_API users | ||
2 | config IOMMU_IOVA | ||
3 | tristate | ||
4 | |||
1 | # IOMMU_API always gets selected by whoever wants it. | 5 | # IOMMU_API always gets selected by whoever wants it. |
2 | config IOMMU_API | 6 | config IOMMU_API |
3 | bool | 7 | bool |
@@ -81,9 +85,6 @@ config IOMMU_DEFAULT_PASSTHROUGH | |||
81 | 85 | ||
82 | If unsure, say N here. | 86 | If unsure, say N here. |
83 | 87 | ||
84 | config IOMMU_IOVA | ||
85 | tristate | ||
86 | |||
87 | config OF_IOMMU | 88 | config OF_IOMMU |
88 | def_bool y | 89 | def_bool y |
89 | depends on OF && IOMMU_API | 90 | depends on OF && IOMMU_API |
@@ -282,6 +283,7 @@ config ROCKCHIP_IOMMU | |||
282 | config TEGRA_IOMMU_GART | 283 | config TEGRA_IOMMU_GART |
283 | bool "Tegra GART IOMMU Support" | 284 | bool "Tegra GART IOMMU Support" |
284 | depends on ARCH_TEGRA_2x_SOC | 285 | depends on ARCH_TEGRA_2x_SOC |
286 | depends on TEGRA_MC | ||
285 | select IOMMU_API | 287 | select IOMMU_API |
286 | help | 288 | help |
287 | Enables support for remapping discontiguous physical memory | 289 | Enables support for remapping discontiguous physical memory |
@@ -435,4 +437,13 @@ config QCOM_IOMMU | |||
435 | help | 437 | help |
436 | Support for IOMMU on certain Qualcomm SoCs. | 438 | Support for IOMMU on certain Qualcomm SoCs. |
437 | 439 | ||
440 | config HYPERV_IOMMU | ||
441 | bool "Hyper-V x2APIC IRQ Handling" | ||
442 | depends on HYPERV | ||
443 | select IOMMU_API | ||
444 | default HYPERV | ||
445 | help | ||
446 | Stub IOMMU driver to handle IRQs as to allow Hyper-V Linux | ||
447 | guests to run with x2APIC mode enabled. | ||
448 | |||
438 | endif # IOMMU_SUPPORT | 449 | endif # IOMMU_SUPPORT |
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index a158a68c8ea8..8c71a15e986b 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
@@ -32,3 +32,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o | |||
32 | obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o | 32 | obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o |
33 | obj-$(CONFIG_S390_IOMMU) += s390-iommu.o | 33 | obj-$(CONFIG_S390_IOMMU) += s390-iommu.o |
34 | obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o | 34 | obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o |
35 | obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o | ||
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2a7b78bb98b4..6b0760dafb3e 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define pr_fmt(fmt) "AMD-Vi: " fmt | 20 | #define pr_fmt(fmt) "AMD-Vi: " fmt |
21 | #define dev_fmt(fmt) pr_fmt(fmt) | ||
21 | 22 | ||
22 | #include <linux/ratelimit.h> | 23 | #include <linux/ratelimit.h> |
23 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
@@ -279,10 +280,10 @@ static u16 get_alias(struct device *dev) | |||
279 | return pci_alias; | 280 | return pci_alias; |
280 | } | 281 | } |
281 | 282 | ||
282 | pr_info("Using IVRS reported alias %02x:%02x.%d " | 283 | pci_info(pdev, "Using IVRS reported alias %02x:%02x.%d " |
283 | "for device %s[%04x:%04x], kernel reported alias " | 284 | "for device [%04x:%04x], kernel reported alias " |
284 | "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias), | 285 | "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias), |
285 | PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device, | 286 | PCI_FUNC(ivrs_alias), pdev->vendor, pdev->device, |
286 | PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias), | 287 | PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias), |
287 | PCI_FUNC(pci_alias)); | 288 | PCI_FUNC(pci_alias)); |
288 | 289 | ||
@@ -293,9 +294,8 @@ static u16 get_alias(struct device *dev) | |||
293 | if (pci_alias == devid && | 294 | if (pci_alias == devid && |
294 | PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) { | 295 | PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) { |
295 | pci_add_dma_alias(pdev, ivrs_alias & 0xff); | 296 | pci_add_dma_alias(pdev, ivrs_alias & 0xff); |
296 | pr_info("Added PCI DMA alias %02x.%d for %s\n", | 297 | pci_info(pdev, "Added PCI DMA alias %02x.%d\n", |
297 | PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias), | 298 | PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias)); |
298 | dev_name(dev)); | ||
299 | } | 299 | } |
300 | 300 | ||
301 | return ivrs_alias; | 301 | return ivrs_alias; |
@@ -545,7 +545,7 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id, | |||
545 | dev_data = get_dev_data(&pdev->dev); | 545 | dev_data = get_dev_data(&pdev->dev); |
546 | 546 | ||
547 | if (dev_data && __ratelimit(&dev_data->rs)) { | 547 | if (dev_data && __ratelimit(&dev_data->rs)) { |
548 | dev_err(&pdev->dev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n", | 548 | pci_err(pdev, "Event logged [IO_PAGE_FAULT domain=0x%04x address=0x%llx flags=0x%04x]\n", |
549 | domain_id, address, flags); | 549 | domain_id, address, flags); |
550 | } else if (printk_ratelimit()) { | 550 | } else if (printk_ratelimit()) { |
551 | pr_err("Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%llx flags=0x%04x]\n", | 551 | pr_err("Event logged [IO_PAGE_FAULT device=%02x:%02x.%x domain=0x%04x address=0x%llx flags=0x%04x]\n", |
@@ -2258,8 +2258,7 @@ static int amd_iommu_add_device(struct device *dev) | |||
2258 | ret = iommu_init_device(dev); | 2258 | ret = iommu_init_device(dev); |
2259 | if (ret) { | 2259 | if (ret) { |
2260 | if (ret != -ENOTSUPP) | 2260 | if (ret != -ENOTSUPP) |
2261 | pr_err("Failed to initialize device %s - trying to proceed anyway\n", | 2261 | dev_err(dev, "Failed to initialize - trying to proceed anyway\n"); |
2262 | dev_name(dev)); | ||
2263 | 2262 | ||
2264 | iommu_ignore_device(dev); | 2263 | iommu_ignore_device(dev); |
2265 | dev->dma_ops = NULL; | 2264 | dev->dma_ops = NULL; |
@@ -2569,6 +2568,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, | |||
2569 | struct scatterlist *s; | 2568 | struct scatterlist *s; |
2570 | unsigned long address; | 2569 | unsigned long address; |
2571 | u64 dma_mask; | 2570 | u64 dma_mask; |
2571 | int ret; | ||
2572 | 2572 | ||
2573 | domain = get_domain(dev); | 2573 | domain = get_domain(dev); |
2574 | if (IS_ERR(domain)) | 2574 | if (IS_ERR(domain)) |
@@ -2591,7 +2591,6 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, | |||
2591 | 2591 | ||
2592 | for (j = 0; j < pages; ++j) { | 2592 | for (j = 0; j < pages; ++j) { |
2593 | unsigned long bus_addr, phys_addr; | 2593 | unsigned long bus_addr, phys_addr; |
2594 | int ret; | ||
2595 | 2594 | ||
2596 | bus_addr = address + s->dma_address + (j << PAGE_SHIFT); | 2595 | bus_addr = address + s->dma_address + (j << PAGE_SHIFT); |
2597 | phys_addr = (sg_phys(s) & PAGE_MASK) + (j << PAGE_SHIFT); | 2596 | phys_addr = (sg_phys(s) & PAGE_MASK) + (j << PAGE_SHIFT); |
@@ -2612,8 +2611,8 @@ static int map_sg(struct device *dev, struct scatterlist *sglist, | |||
2612 | return nelems; | 2611 | return nelems; |
2613 | 2612 | ||
2614 | out_unmap: | 2613 | out_unmap: |
2615 | pr_err("%s: IOMMU mapping error in map_sg (io-pages: %d)\n", | 2614 | dev_err(dev, "IOMMU mapping error in map_sg (io-pages: %d reason: %d)\n", |
2616 | dev_name(dev), npages); | 2615 | npages, ret); |
2617 | 2616 | ||
2618 | for_each_sg(sglist, s, nelems, i) { | 2617 | for_each_sg(sglist, s, nelems, i) { |
2619 | int j, pages = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE); | 2618 | int j, pages = iommu_num_pages(sg_phys(s), s->length, PAGE_SIZE); |
@@ -2807,7 +2806,7 @@ static int init_reserved_iova_ranges(void) | |||
2807 | IOVA_PFN(r->start), | 2806 | IOVA_PFN(r->start), |
2808 | IOVA_PFN(r->end)); | 2807 | IOVA_PFN(r->end)); |
2809 | if (!val) { | 2808 | if (!val) { |
2810 | pr_err("Reserve pci-resource range failed\n"); | 2809 | pci_err(pdev, "Reserve pci-resource range %pR failed\n", r); |
2811 | return -ENOMEM; | 2810 | return -ENOMEM; |
2812 | } | 2811 | } |
2813 | } | 2812 | } |
@@ -3177,8 +3176,7 @@ static void amd_iommu_get_resv_regions(struct device *dev, | |||
3177 | length, prot, | 3176 | length, prot, |
3178 | IOMMU_RESV_DIRECT); | 3177 | IOMMU_RESV_DIRECT); |
3179 | if (!region) { | 3178 | if (!region) { |
3180 | pr_err("Out of memory allocating dm-regions for %s\n", | 3179 | dev_err(dev, "Out of memory allocating dm-regions\n"); |
3181 | dev_name(dev)); | ||
3182 | return; | 3180 | return; |
3183 | } | 3181 | } |
3184 | list_add_tail(®ion->list, head); | 3182 | list_add_tail(®ion->list, head); |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 66123b911ec8..f773792d77fd 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define pr_fmt(fmt) "AMD-Vi: " fmt | 20 | #define pr_fmt(fmt) "AMD-Vi: " fmt |
21 | #define dev_fmt(fmt) pr_fmt(fmt) | ||
21 | 22 | ||
22 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
23 | #include <linux/acpi.h> | 24 | #include <linux/acpi.h> |
@@ -1457,8 +1458,7 @@ static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) | |||
1457 | pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); | 1458 | pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); |
1458 | 1459 | ||
1459 | pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); | 1460 | pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); |
1460 | pr_info("Applying erratum 746 workaround for IOMMU at %s\n", | 1461 | pci_info(iommu->dev, "Applying erratum 746 workaround\n"); |
1461 | dev_name(&iommu->dev->dev)); | ||
1462 | 1462 | ||
1463 | /* Clear the enable writing bit */ | 1463 | /* Clear the enable writing bit */ |
1464 | pci_write_config_dword(iommu->dev, 0xf0, 0x90); | 1464 | pci_write_config_dword(iommu->dev, 0xf0, 0x90); |
@@ -1488,8 +1488,7 @@ static void amd_iommu_ats_write_check_workaround(struct amd_iommu *iommu) | |||
1488 | /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */ | 1488 | /* Set L2_DEBUG_3[AtsIgnoreIWDis] = 1 */ |
1489 | iommu_write_l2(iommu, 0x47, value | BIT(0)); | 1489 | iommu_write_l2(iommu, 0x47, value | BIT(0)); |
1490 | 1490 | ||
1491 | pr_info("Applying ATS write check workaround for IOMMU at %s\n", | 1491 | pci_info(iommu->dev, "Applying ATS write check workaround\n"); |
1492 | dev_name(&iommu->dev->dev)); | ||
1493 | } | 1492 | } |
1494 | 1493 | ||
1495 | /* | 1494 | /* |
@@ -1665,6 +1664,7 @@ static int iommu_pc_get_set_reg(struct amd_iommu *iommu, u8 bank, u8 cntr, | |||
1665 | 1664 | ||
1666 | static void init_iommu_perf_ctr(struct amd_iommu *iommu) | 1665 | static void init_iommu_perf_ctr(struct amd_iommu *iommu) |
1667 | { | 1666 | { |
1667 | struct pci_dev *pdev = iommu->dev; | ||
1668 | u64 val = 0xabcd, val2 = 0; | 1668 | u64 val = 0xabcd, val2 = 0; |
1669 | 1669 | ||
1670 | if (!iommu_feature(iommu, FEATURE_PC)) | 1670 | if (!iommu_feature(iommu, FEATURE_PC)) |
@@ -1676,12 +1676,12 @@ static void init_iommu_perf_ctr(struct amd_iommu *iommu) | |||
1676 | if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || | 1676 | if ((iommu_pc_get_set_reg(iommu, 0, 0, 0, &val, true)) || |
1677 | (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || | 1677 | (iommu_pc_get_set_reg(iommu, 0, 0, 0, &val2, false)) || |
1678 | (val != val2)) { | 1678 | (val != val2)) { |
1679 | pr_err("Unable to write to IOMMU perf counter.\n"); | 1679 | pci_err(pdev, "Unable to write to IOMMU perf counter.\n"); |
1680 | amd_iommu_pc_present = false; | 1680 | amd_iommu_pc_present = false; |
1681 | return; | 1681 | return; |
1682 | } | 1682 | } |
1683 | 1683 | ||
1684 | pr_info("IOMMU performance counters supported\n"); | 1684 | pci_info(pdev, "IOMMU performance counters supported\n"); |
1685 | 1685 | ||
1686 | val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET); | 1686 | val = readl(iommu->mmio_base + MMIO_CNTR_CONF_OFFSET); |
1687 | iommu->max_banks = (u8) ((val >> 12) & 0x3f); | 1687 | iommu->max_banks = (u8) ((val >> 12) & 0x3f); |
@@ -1840,14 +1840,14 @@ static void print_iommu_info(void) | |||
1840 | struct amd_iommu *iommu; | 1840 | struct amd_iommu *iommu; |
1841 | 1841 | ||
1842 | for_each_iommu(iommu) { | 1842 | for_each_iommu(iommu) { |
1843 | struct pci_dev *pdev = iommu->dev; | ||
1843 | int i; | 1844 | int i; |
1844 | 1845 | ||
1845 | pr_info("Found IOMMU at %s cap 0x%hx\n", | 1846 | pci_info(pdev, "Found IOMMU cap 0x%hx\n", iommu->cap_ptr); |
1846 | dev_name(&iommu->dev->dev), iommu->cap_ptr); | ||
1847 | 1847 | ||
1848 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { | 1848 | if (iommu->cap & (1 << IOMMU_CAP_EFR)) { |
1849 | pr_info("Extended features (%#llx):\n", | 1849 | pci_info(pdev, "Extended features (%#llx):\n", |
1850 | iommu->features); | 1850 | iommu->features); |
1851 | for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { | 1851 | for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { |
1852 | if (iommu_feature(iommu, (1ULL << i))) | 1852 | if (iommu_feature(iommu, (1ULL << i))) |
1853 | pr_cont(" %s", feat_str[i]); | 1853 | pr_cont(" %s", feat_str[i]); |
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 23dae9348ace..5d7ef750e4a0 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
@@ -370,29 +370,6 @@ static struct pasid_state *mn_to_state(struct mmu_notifier *mn) | |||
370 | return container_of(mn, struct pasid_state, mn); | 370 | return container_of(mn, struct pasid_state, mn); |
371 | } | 371 | } |
372 | 372 | ||
373 | static void __mn_flush_page(struct mmu_notifier *mn, | ||
374 | unsigned long address) | ||
375 | { | ||
376 | struct pasid_state *pasid_state; | ||
377 | struct device_state *dev_state; | ||
378 | |||
379 | pasid_state = mn_to_state(mn); | ||
380 | dev_state = pasid_state->device_state; | ||
381 | |||
382 | amd_iommu_flush_page(dev_state->domain, pasid_state->pasid, address); | ||
383 | } | ||
384 | |||
385 | static int mn_clear_flush_young(struct mmu_notifier *mn, | ||
386 | struct mm_struct *mm, | ||
387 | unsigned long start, | ||
388 | unsigned long end) | ||
389 | { | ||
390 | for (; start < end; start += PAGE_SIZE) | ||
391 | __mn_flush_page(mn, start); | ||
392 | |||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static void mn_invalidate_range(struct mmu_notifier *mn, | 373 | static void mn_invalidate_range(struct mmu_notifier *mn, |
397 | struct mm_struct *mm, | 374 | struct mm_struct *mm, |
398 | unsigned long start, unsigned long end) | 375 | unsigned long start, unsigned long end) |
@@ -430,7 +407,6 @@ static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm) | |||
430 | 407 | ||
431 | static const struct mmu_notifier_ops iommu_mn = { | 408 | static const struct mmu_notifier_ops iommu_mn = { |
432 | .release = mn_release, | 409 | .release = mn_release, |
433 | .clear_flush_young = mn_clear_flush_young, | ||
434 | .invalidate_range = mn_invalidate_range, | 410 | .invalidate_range = mn_invalidate_range, |
435 | }; | 411 | }; |
436 | 412 | ||
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 0d284029dc73..d3880010c6cf 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/dma-iommu.h> | 18 | #include <linux/dma-iommu.h> |
19 | #include <linux/err.h> | 19 | #include <linux/err.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/io-pgtable.h> | ||
21 | #include <linux/iommu.h> | 22 | #include <linux/iommu.h> |
22 | #include <linux/iopoll.h> | 23 | #include <linux/iopoll.h> |
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
@@ -32,8 +33,6 @@ | |||
32 | 33 | ||
33 | #include <linux/amba/bus.h> | 34 | #include <linux/amba/bus.h> |
34 | 35 | ||
35 | #include "io-pgtable.h" | ||
36 | |||
37 | /* MMIO registers */ | 36 | /* MMIO registers */ |
38 | #define ARM_SMMU_IDR0 0x0 | 37 | #define ARM_SMMU_IDR0 0x0 |
39 | #define IDR0_ST_LVL GENMASK(28, 27) | 38 | #define IDR0_ST_LVL GENMASK(28, 27) |
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index af18a7e7f917..045d93884164 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/interrupt.h> | 39 | #include <linux/interrupt.h> |
40 | #include <linux/io.h> | 40 | #include <linux/io.h> |
41 | #include <linux/io-64-nonatomic-hi-lo.h> | 41 | #include <linux/io-64-nonatomic-hi-lo.h> |
42 | #include <linux/io-pgtable.h> | ||
42 | #include <linux/iommu.h> | 43 | #include <linux/iommu.h> |
43 | #include <linux/iopoll.h> | 44 | #include <linux/iopoll.h> |
44 | #include <linux/init.h> | 45 | #include <linux/init.h> |
@@ -56,7 +57,6 @@ | |||
56 | #include <linux/amba/bus.h> | 57 | #include <linux/amba/bus.h> |
57 | #include <linux/fsl/mc.h> | 58 | #include <linux/fsl/mc.h> |
58 | 59 | ||
59 | #include "io-pgtable.h" | ||
60 | #include "arm-smmu-regs.h" | 60 | #include "arm-smmu-regs.h" |
61 | 61 | ||
62 | #define ARM_MMU500_ACTLR_CPRE (1 << 1) | 62 | #define ARM_MMU500_ACTLR_CPRE (1 << 1) |
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index d19f3d6b43c1..77aabe637a60 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c | |||
@@ -289,7 +289,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, | |||
289 | { | 289 | { |
290 | struct iommu_dma_cookie *cookie = domain->iova_cookie; | 290 | struct iommu_dma_cookie *cookie = domain->iova_cookie; |
291 | struct iova_domain *iovad = &cookie->iovad; | 291 | struct iova_domain *iovad = &cookie->iovad; |
292 | unsigned long order, base_pfn, end_pfn; | 292 | unsigned long order, base_pfn; |
293 | int attr; | 293 | int attr; |
294 | 294 | ||
295 | if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE) | 295 | if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE) |
@@ -298,7 +298,6 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, | |||
298 | /* Use the smallest supported page size for IOVA granularity */ | 298 | /* Use the smallest supported page size for IOVA granularity */ |
299 | order = __ffs(domain->pgsize_bitmap); | 299 | order = __ffs(domain->pgsize_bitmap); |
300 | base_pfn = max_t(unsigned long, 1, base >> order); | 300 | base_pfn = max_t(unsigned long, 1, base >> order); |
301 | end_pfn = (base + size - 1) >> order; | ||
302 | 301 | ||
303 | /* Check the domain allows at least some access to the device... */ | 302 | /* Check the domain allows at least some access to the device... */ |
304 | if (domain->geometry.force_aperture) { | 303 | if (domain->geometry.force_aperture) { |
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index dc9f14811e0f..58dc70bffd5b 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -144,7 +144,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) | |||
144 | for (tmp = dev; tmp; tmp = tmp->bus->self) | 144 | for (tmp = dev; tmp; tmp = tmp->bus->self) |
145 | level++; | 145 | level++; |
146 | 146 | ||
147 | size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path); | 147 | size = sizeof(*info) + level * sizeof(info->path[0]); |
148 | if (size <= sizeof(dmar_pci_notify_info_buf)) { | 148 | if (size <= sizeof(dmar_pci_notify_info_buf)) { |
149 | info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf; | 149 | info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf; |
150 | } else { | 150 | } else { |
diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c new file mode 100644 index 000000000000..a386b83e0e34 --- /dev/null +++ b/drivers/iommu/hyperv-iommu.c | |||
@@ -0,0 +1,196 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
3 | /* | ||
4 | * Hyper-V stub IOMMU driver. | ||
5 | * | ||
6 | * Copyright (C) 2019, Microsoft, Inc. | ||
7 | * | ||
8 | * Author : Lan Tianyu <Tianyu.Lan@microsoft.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/iommu.h> | ||
15 | #include <linux/module.h> | ||
16 | |||
17 | #include <asm/apic.h> | ||
18 | #include <asm/cpu.h> | ||
19 | #include <asm/hw_irq.h> | ||
20 | #include <asm/io_apic.h> | ||
21 | #include <asm/irq_remapping.h> | ||
22 | #include <asm/hypervisor.h> | ||
23 | |||
24 | #include "irq_remapping.h" | ||
25 | |||
26 | #ifdef CONFIG_IRQ_REMAP | ||
27 | |||
28 | /* | ||
29 | * According 82093AA IO-APIC spec , IO APIC has a 24-entry Interrupt | ||
30 | * Redirection Table. Hyper-V exposes one single IO-APIC and so define | ||
31 | * 24 IO APIC remmapping entries. | ||
32 | */ | ||
33 | #define IOAPIC_REMAPPING_ENTRY 24 | ||
34 | |||
35 | static cpumask_t ioapic_max_cpumask = { CPU_BITS_NONE }; | ||
36 | static struct irq_domain *ioapic_ir_domain; | ||
37 | |||
38 | static int hyperv_ir_set_affinity(struct irq_data *data, | ||
39 | const struct cpumask *mask, bool force) | ||
40 | { | ||
41 | struct irq_data *parent = data->parent_data; | ||
42 | struct irq_cfg *cfg = irqd_cfg(data); | ||
43 | struct IO_APIC_route_entry *entry; | ||
44 | int ret; | ||
45 | |||
46 | /* Return error If new irq affinity is out of ioapic_max_cpumask. */ | ||
47 | if (!cpumask_subset(mask, &ioapic_max_cpumask)) | ||
48 | return -EINVAL; | ||
49 | |||
50 | ret = parent->chip->irq_set_affinity(parent, mask, force); | ||
51 | if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) | ||
52 | return ret; | ||
53 | |||
54 | entry = data->chip_data; | ||
55 | entry->dest = cfg->dest_apicid; | ||
56 | entry->vector = cfg->vector; | ||
57 | send_cleanup_vector(cfg); | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | |||
62 | static struct irq_chip hyperv_ir_chip = { | ||
63 | .name = "HYPERV-IR", | ||
64 | .irq_ack = apic_ack_irq, | ||
65 | .irq_set_affinity = hyperv_ir_set_affinity, | ||
66 | }; | ||
67 | |||
68 | static int hyperv_irq_remapping_alloc(struct irq_domain *domain, | ||
69 | unsigned int virq, unsigned int nr_irqs, | ||
70 | void *arg) | ||
71 | { | ||
72 | struct irq_alloc_info *info = arg; | ||
73 | struct irq_data *irq_data; | ||
74 | struct irq_desc *desc; | ||
75 | int ret = 0; | ||
76 | |||
77 | if (!info || info->type != X86_IRQ_ALLOC_TYPE_IOAPIC || nr_irqs > 1) | ||
78 | return -EINVAL; | ||
79 | |||
80 | ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg); | ||
81 | if (ret < 0) | ||
82 | return ret; | ||
83 | |||
84 | irq_data = irq_domain_get_irq_data(domain, virq); | ||
85 | if (!irq_data) { | ||
86 | irq_domain_free_irqs_common(domain, virq, nr_irqs); | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | |||
90 | irq_data->chip = &hyperv_ir_chip; | ||
91 | |||
92 | /* | ||
93 | * If there is interrupt remapping function of IOMMU, setting irq | ||
94 | * affinity only needs to change IRTE of IOMMU. But Hyper-V doesn't | ||
95 | * support interrupt remapping function, setting irq affinity of IO-APIC | ||
96 | * interrupts still needs to change IO-APIC registers. But ioapic_ | ||
97 | * configure_entry() will ignore value of cfg->vector and cfg-> | ||
98 | * dest_apicid when IO-APIC's parent irq domain is not the vector | ||
99 | * domain.(See ioapic_configure_entry()) In order to setting vector | ||
100 | * and dest_apicid to IO-APIC register, IO-APIC entry pointer is saved | ||
101 | * in the chip_data and hyperv_irq_remapping_activate()/hyperv_ir_set_ | ||
102 | * affinity() set vector and dest_apicid directly into IO-APIC entry. | ||
103 | */ | ||
104 | irq_data->chip_data = info->ioapic_entry; | ||
105 | |||
106 | /* | ||
107 | * Hypver-V IO APIC irq affinity should be in the scope of | ||
108 | * ioapic_max_cpumask because no irq remapping support. | ||
109 | */ | ||
110 | desc = irq_data_to_desc(irq_data); | ||
111 | cpumask_copy(desc->irq_common_data.affinity, &ioapic_max_cpumask); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static void hyperv_irq_remapping_free(struct irq_domain *domain, | ||
117 | unsigned int virq, unsigned int nr_irqs) | ||
118 | { | ||
119 | irq_domain_free_irqs_common(domain, virq, nr_irqs); | ||
120 | } | ||
121 | |||
122 | static int hyperv_irq_remapping_activate(struct irq_domain *domain, | ||
123 | struct irq_data *irq_data, bool reserve) | ||
124 | { | ||
125 | struct irq_cfg *cfg = irqd_cfg(irq_data); | ||
126 | struct IO_APIC_route_entry *entry = irq_data->chip_data; | ||
127 | |||
128 | entry->dest = cfg->dest_apicid; | ||
129 | entry->vector = cfg->vector; | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static struct irq_domain_ops hyperv_ir_domain_ops = { | ||
135 | .alloc = hyperv_irq_remapping_alloc, | ||
136 | .free = hyperv_irq_remapping_free, | ||
137 | .activate = hyperv_irq_remapping_activate, | ||
138 | }; | ||
139 | |||
140 | static int __init hyperv_prepare_irq_remapping(void) | ||
141 | { | ||
142 | struct fwnode_handle *fn; | ||
143 | int i; | ||
144 | |||
145 | if (!hypervisor_is_type(X86_HYPER_MS_HYPERV) || | ||
146 | !x2apic_supported()) | ||
147 | return -ENODEV; | ||
148 | |||
149 | fn = irq_domain_alloc_named_id_fwnode("HYPERV-IR", 0); | ||
150 | if (!fn) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | ioapic_ir_domain = | ||
154 | irq_domain_create_hierarchy(arch_get_ir_parent_domain(), | ||
155 | 0, IOAPIC_REMAPPING_ENTRY, fn, | ||
156 | &hyperv_ir_domain_ops, NULL); | ||
157 | |||
158 | irq_domain_free_fwnode(fn); | ||
159 | |||
160 | /* | ||
161 | * Hyper-V doesn't provide irq remapping function for | ||
162 | * IO-APIC and so IO-APIC only accepts 8-bit APIC ID. | ||
163 | * Cpu's APIC ID is read from ACPI MADT table and APIC IDs | ||
164 | * in the MADT table on Hyper-v are sorted monotonic increasingly. | ||
165 | * APIC ID reflects cpu topology. There maybe some APIC ID | ||
166 | * gaps when cpu number in a socket is not power of two. Prepare | ||
167 | * max cpu affinity for IOAPIC irqs. Scan cpu 0-255 and set cpu | ||
168 | * into ioapic_max_cpumask if its APIC ID is less than 256. | ||
169 | */ | ||
170 | for (i = min_t(unsigned int, num_possible_cpus() - 1, 255); i >= 0; i--) | ||
171 | if (cpu_physical_id(i) < 256) | ||
172 | cpumask_set_cpu(i, &ioapic_max_cpumask); | ||
173 | |||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static int __init hyperv_enable_irq_remapping(void) | ||
178 | { | ||
179 | return IRQ_REMAP_X2APIC_MODE; | ||
180 | } | ||
181 | |||
182 | static struct irq_domain *hyperv_get_ir_irq_domain(struct irq_alloc_info *info) | ||
183 | { | ||
184 | if (info->type == X86_IRQ_ALLOC_TYPE_IOAPIC) | ||
185 | return ioapic_ir_domain; | ||
186 | else | ||
187 | return NULL; | ||
188 | } | ||
189 | |||
190 | struct irq_remap_ops hyperv_irq_remap_ops = { | ||
191 | .prepare = hyperv_prepare_irq_remapping, | ||
192 | .enable = hyperv_enable_irq_remapping, | ||
193 | .get_ir_irq_domain = hyperv_get_ir_irq_domain, | ||
194 | }; | ||
195 | |||
196 | #endif | ||
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 78188bf7e90d..c968b3c7bae0 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -19,6 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #define pr_fmt(fmt) "DMAR: " fmt | 21 | #define pr_fmt(fmt) "DMAR: " fmt |
22 | #define dev_fmt(fmt) pr_fmt(fmt) | ||
22 | 23 | ||
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/bitmap.h> | 25 | #include <linux/bitmap.h> |
@@ -342,8 +343,7 @@ static int g_num_of_iommus; | |||
342 | 343 | ||
343 | static void domain_exit(struct dmar_domain *domain); | 344 | static void domain_exit(struct dmar_domain *domain); |
344 | static void domain_remove_dev_info(struct dmar_domain *domain); | 345 | static void domain_remove_dev_info(struct dmar_domain *domain); |
345 | static void dmar_remove_one_dev_info(struct dmar_domain *domain, | 346 | static void dmar_remove_one_dev_info(struct device *dev); |
346 | struct device *dev); | ||
347 | static void __dmar_remove_one_dev_info(struct device_domain_info *info); | 347 | static void __dmar_remove_one_dev_info(struct device_domain_info *info); |
348 | static void domain_context_clear(struct intel_iommu *iommu, | 348 | static void domain_context_clear(struct intel_iommu *iommu, |
349 | struct device *dev); | 349 | struct device *dev); |
@@ -864,7 +864,7 @@ out: | |||
864 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, | 864 | static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, |
865 | unsigned long pfn, int *target_level) | 865 | unsigned long pfn, int *target_level) |
866 | { | 866 | { |
867 | struct dma_pte *parent, *pte = NULL; | 867 | struct dma_pte *parent, *pte; |
868 | int level = agaw_to_level(domain->agaw); | 868 | int level = agaw_to_level(domain->agaw); |
869 | int offset; | 869 | int offset; |
870 | 870 | ||
@@ -921,7 +921,7 @@ static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain, | |||
921 | unsigned long pfn, | 921 | unsigned long pfn, |
922 | int level, int *large_page) | 922 | int level, int *large_page) |
923 | { | 923 | { |
924 | struct dma_pte *parent, *pte = NULL; | 924 | struct dma_pte *parent, *pte; |
925 | int total = agaw_to_level(domain->agaw); | 925 | int total = agaw_to_level(domain->agaw); |
926 | int offset; | 926 | int offset; |
927 | 927 | ||
@@ -953,7 +953,7 @@ static void dma_pte_clear_range(struct dmar_domain *domain, | |||
953 | unsigned long start_pfn, | 953 | unsigned long start_pfn, |
954 | unsigned long last_pfn) | 954 | unsigned long last_pfn) |
955 | { | 955 | { |
956 | unsigned int large_page = 1; | 956 | unsigned int large_page; |
957 | struct dma_pte *first_pte, *pte; | 957 | struct dma_pte *first_pte, *pte; |
958 | 958 | ||
959 | BUG_ON(!domain_pfn_supported(domain, start_pfn)); | 959 | BUG_ON(!domain_pfn_supported(domain, start_pfn)); |
@@ -1131,7 +1131,7 @@ static struct page *domain_unmap(struct dmar_domain *domain, | |||
1131 | unsigned long start_pfn, | 1131 | unsigned long start_pfn, |
1132 | unsigned long last_pfn) | 1132 | unsigned long last_pfn) |
1133 | { | 1133 | { |
1134 | struct page *freelist = NULL; | 1134 | struct page *freelist; |
1135 | 1135 | ||
1136 | BUG_ON(!domain_pfn_supported(domain, start_pfn)); | 1136 | BUG_ON(!domain_pfn_supported(domain, start_pfn)); |
1137 | BUG_ON(!domain_pfn_supported(domain, last_pfn)); | 1137 | BUG_ON(!domain_pfn_supported(domain, last_pfn)); |
@@ -1402,10 +1402,13 @@ static void iommu_enable_dev_iotlb(struct device_domain_info *info) | |||
1402 | if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1)) | 1402 | if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1)) |
1403 | info->pasid_enabled = 1; | 1403 | info->pasid_enabled = 1; |
1404 | 1404 | ||
1405 | if (info->pri_supported && !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32)) | 1405 | if (info->pri_supported && |
1406 | (info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) && | ||
1407 | !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32)) | ||
1406 | info->pri_enabled = 1; | 1408 | info->pri_enabled = 1; |
1407 | #endif | 1409 | #endif |
1408 | if (!pdev->untrusted && info->ats_supported && | 1410 | if (!pdev->untrusted && info->ats_supported && |
1411 | pci_ats_page_aligned(pdev) && | ||
1409 | !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) { | 1412 | !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) { |
1410 | info->ats_enabled = 1; | 1413 | info->ats_enabled = 1; |
1411 | domain_update_iotlb(info->domain); | 1414 | domain_update_iotlb(info->domain); |
@@ -1762,7 +1765,7 @@ static int domain_attach_iommu(struct dmar_domain *domain, | |||
1762 | static int domain_detach_iommu(struct dmar_domain *domain, | 1765 | static int domain_detach_iommu(struct dmar_domain *domain, |
1763 | struct intel_iommu *iommu) | 1766 | struct intel_iommu *iommu) |
1764 | { | 1767 | { |
1765 | int num, count = INT_MAX; | 1768 | int num, count; |
1766 | 1769 | ||
1767 | assert_spin_locked(&device_domain_lock); | 1770 | assert_spin_locked(&device_domain_lock); |
1768 | assert_spin_locked(&iommu->lock); | 1771 | assert_spin_locked(&iommu->lock); |
@@ -1815,7 +1818,7 @@ static int dmar_init_reserved_ranges(void) | |||
1815 | IOVA_PFN(r->start), | 1818 | IOVA_PFN(r->start), |
1816 | IOVA_PFN(r->end)); | 1819 | IOVA_PFN(r->end)); |
1817 | if (!iova) { | 1820 | if (!iova) { |
1818 | pr_err("Reserve iova failed\n"); | 1821 | pci_err(pdev, "Reserve iova for %pR failed\n", r); |
1819 | return -ENODEV; | 1822 | return -ENODEV; |
1820 | } | 1823 | } |
1821 | } | 1824 | } |
@@ -1901,11 +1904,7 @@ static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu, | |||
1901 | 1904 | ||
1902 | static void domain_exit(struct dmar_domain *domain) | 1905 | static void domain_exit(struct dmar_domain *domain) |
1903 | { | 1906 | { |
1904 | struct page *freelist = NULL; | 1907 | struct page *freelist; |
1905 | |||
1906 | /* Domain 0 is reserved, so dont process it */ | ||
1907 | if (!domain) | ||
1908 | return; | ||
1909 | 1908 | ||
1910 | /* Remove associated devices and clear attached or cached domains */ | 1909 | /* Remove associated devices and clear attached or cached domains */ |
1911 | rcu_read_lock(); | 1910 | rcu_read_lock(); |
@@ -2057,7 +2056,6 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
2057 | int agaw; | 2056 | int agaw; |
2058 | 2057 | ||
2059 | context_set_domain_id(context, did); | 2058 | context_set_domain_id(context, did); |
2060 | context_set_translation_type(context, translation); | ||
2061 | 2059 | ||
2062 | if (translation != CONTEXT_TT_PASS_THROUGH) { | 2060 | if (translation != CONTEXT_TT_PASS_THROUGH) { |
2063 | /* | 2061 | /* |
@@ -2087,6 +2085,8 @@ static int domain_context_mapping_one(struct dmar_domain *domain, | |||
2087 | */ | 2085 | */ |
2088 | context_set_address_width(context, iommu->msagaw); | 2086 | context_set_address_width(context, iommu->msagaw); |
2089 | } | 2087 | } |
2088 | |||
2089 | context_set_translation_type(context, translation); | ||
2090 | } | 2090 | } |
2091 | 2091 | ||
2092 | context_set_fault_enable(context); | 2092 | context_set_fault_enable(context); |
@@ -2485,7 +2485,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, | |||
2485 | if (dev && dev_is_pci(dev)) { | 2485 | if (dev && dev_is_pci(dev)) { |
2486 | struct pci_dev *pdev = to_pci_dev(info->dev); | 2486 | struct pci_dev *pdev = to_pci_dev(info->dev); |
2487 | 2487 | ||
2488 | if (!pci_ats_disabled() && | 2488 | if (!pdev->untrusted && |
2489 | !pci_ats_disabled() && | ||
2489 | ecap_dev_iotlb_support(iommu->ecap) && | 2490 | ecap_dev_iotlb_support(iommu->ecap) && |
2490 | pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) && | 2491 | pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) && |
2491 | dmar_find_matched_atsr_unit(pdev)) | 2492 | dmar_find_matched_atsr_unit(pdev)) |
@@ -2544,9 +2545,8 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, | |||
2544 | if (dev && dev_is_pci(dev) && sm_supported(iommu)) { | 2545 | if (dev && dev_is_pci(dev) && sm_supported(iommu)) { |
2545 | ret = intel_pasid_alloc_table(dev); | 2546 | ret = intel_pasid_alloc_table(dev); |
2546 | if (ret) { | 2547 | if (ret) { |
2547 | pr_err("PASID table allocation for %s failed\n", | 2548 | dev_err(dev, "PASID table allocation failed\n"); |
2548 | dev_name(dev)); | 2549 | dmar_remove_one_dev_info(dev); |
2549 | dmar_remove_one_dev_info(domain, dev); | ||
2550 | return NULL; | 2550 | return NULL; |
2551 | } | 2551 | } |
2552 | 2552 | ||
@@ -2560,16 +2560,15 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu, | |||
2560 | dev, PASID_RID2PASID); | 2560 | dev, PASID_RID2PASID); |
2561 | spin_unlock(&iommu->lock); | 2561 | spin_unlock(&iommu->lock); |
2562 | if (ret) { | 2562 | if (ret) { |
2563 | pr_err("Setup RID2PASID for %s failed\n", | 2563 | dev_err(dev, "Setup RID2PASID failed\n"); |
2564 | dev_name(dev)); | 2564 | dmar_remove_one_dev_info(dev); |
2565 | dmar_remove_one_dev_info(domain, dev); | ||
2566 | return NULL; | 2565 | return NULL; |
2567 | } | 2566 | } |
2568 | } | 2567 | } |
2569 | 2568 | ||
2570 | if (dev && domain_context_mapping(domain, dev)) { | 2569 | if (dev && domain_context_mapping(domain, dev)) { |
2571 | pr_err("Domain context map for %s failed\n", dev_name(dev)); | 2570 | dev_err(dev, "Domain context map failed\n"); |
2572 | dmar_remove_one_dev_info(domain, dev); | 2571 | dmar_remove_one_dev_info(dev); |
2573 | return NULL; | 2572 | return NULL; |
2574 | } | 2573 | } |
2575 | 2574 | ||
@@ -2584,7 +2583,7 @@ static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque) | |||
2584 | 2583 | ||
2585 | static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw) | 2584 | static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw) |
2586 | { | 2585 | { |
2587 | struct device_domain_info *info = NULL; | 2586 | struct device_domain_info *info; |
2588 | struct dmar_domain *domain = NULL; | 2587 | struct dmar_domain *domain = NULL; |
2589 | struct intel_iommu *iommu; | 2588 | struct intel_iommu *iommu; |
2590 | u16 dma_alias; | 2589 | u16 dma_alias; |
@@ -2723,13 +2722,12 @@ static int domain_prepare_identity_map(struct device *dev, | |||
2723 | range which is reserved in E820, so which didn't get set | 2722 | range which is reserved in E820, so which didn't get set |
2724 | up to start with in si_domain */ | 2723 | up to start with in si_domain */ |
2725 | if (domain == si_domain && hw_pass_through) { | 2724 | if (domain == si_domain && hw_pass_through) { |
2726 | pr_warn("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n", | 2725 | dev_warn(dev, "Ignoring identity map for HW passthrough [0x%Lx - 0x%Lx]\n", |
2727 | dev_name(dev), start, end); | 2726 | start, end); |
2728 | return 0; | 2727 | return 0; |
2729 | } | 2728 | } |
2730 | 2729 | ||
2731 | pr_info("Setting identity map for device %s [0x%Lx - 0x%Lx]\n", | 2730 | dev_info(dev, "Setting identity map [0x%Lx - 0x%Lx]\n", start, end); |
2732 | dev_name(dev), start, end); | ||
2733 | 2731 | ||
2734 | if (end < start) { | 2732 | if (end < start) { |
2735 | WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n" | 2733 | WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n" |
@@ -2809,7 +2807,7 @@ static int md_domain_init(struct dmar_domain *domain, int guest_width); | |||
2809 | 2807 | ||
2810 | static int __init si_domain_init(int hw) | 2808 | static int __init si_domain_init(int hw) |
2811 | { | 2809 | { |
2812 | int nid, ret = 0; | 2810 | int nid, ret; |
2813 | 2811 | ||
2814 | si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY); | 2812 | si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY); |
2815 | if (!si_domain) | 2813 | if (!si_domain) |
@@ -2933,7 +2931,6 @@ static bool device_is_rmrr_locked(struct device *dev) | |||
2933 | 2931 | ||
2934 | static int iommu_should_identity_map(struct device *dev, int startup) | 2932 | static int iommu_should_identity_map(struct device *dev, int startup) |
2935 | { | 2933 | { |
2936 | |||
2937 | if (dev_is_pci(dev)) { | 2934 | if (dev_is_pci(dev)) { |
2938 | struct pci_dev *pdev = to_pci_dev(dev); | 2935 | struct pci_dev *pdev = to_pci_dev(dev); |
2939 | 2936 | ||
@@ -3016,8 +3013,8 @@ static int __init dev_prepare_static_identity_mapping(struct device *dev, int hw | |||
3016 | 3013 | ||
3017 | ret = domain_add_dev_info(si_domain, dev); | 3014 | ret = domain_add_dev_info(si_domain, dev); |
3018 | if (!ret) | 3015 | if (!ret) |
3019 | pr_info("%s identity mapping for device %s\n", | 3016 | dev_info(dev, "%s identity mapping\n", |
3020 | hw ? "Hardware" : "Software", dev_name(dev)); | 3017 | hw ? "Hardware" : "Software"); |
3021 | else if (ret == -ENODEV) | 3018 | else if (ret == -ENODEV) |
3022 | /* device not associated with an iommu */ | 3019 | /* device not associated with an iommu */ |
3023 | ret = 0; | 3020 | ret = 0; |
@@ -3529,7 +3526,7 @@ static unsigned long intel_alloc_iova(struct device *dev, | |||
3529 | struct dmar_domain *domain, | 3526 | struct dmar_domain *domain, |
3530 | unsigned long nrpages, uint64_t dma_mask) | 3527 | unsigned long nrpages, uint64_t dma_mask) |
3531 | { | 3528 | { |
3532 | unsigned long iova_pfn = 0; | 3529 | unsigned long iova_pfn; |
3533 | 3530 | ||
3534 | /* Restrict dma_mask to the width that the iommu can handle */ | 3531 | /* Restrict dma_mask to the width that the iommu can handle */ |
3535 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); | 3532 | dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw), dma_mask); |
@@ -3550,8 +3547,7 @@ static unsigned long intel_alloc_iova(struct device *dev, | |||
3550 | iova_pfn = alloc_iova_fast(&domain->iovad, nrpages, | 3547 | iova_pfn = alloc_iova_fast(&domain->iovad, nrpages, |
3551 | IOVA_PFN(dma_mask), true); | 3548 | IOVA_PFN(dma_mask), true); |
3552 | if (unlikely(!iova_pfn)) { | 3549 | if (unlikely(!iova_pfn)) { |
3553 | pr_err("Allocating %ld-page iova for %s failed", | 3550 | dev_err(dev, "Allocating %ld-page iova failed", nrpages); |
3554 | nrpages, dev_name(dev)); | ||
3555 | return 0; | 3551 | return 0; |
3556 | } | 3552 | } |
3557 | 3553 | ||
@@ -3599,7 +3595,7 @@ struct dmar_domain *get_valid_domain_for_dev(struct device *dev) | |||
3599 | out: | 3595 | out: |
3600 | 3596 | ||
3601 | if (!domain) | 3597 | if (!domain) |
3602 | pr_err("Allocating domain for %s failed\n", dev_name(dev)); | 3598 | dev_err(dev, "Allocating domain failed\n"); |
3603 | 3599 | ||
3604 | 3600 | ||
3605 | return domain; | 3601 | return domain; |
@@ -3625,9 +3621,8 @@ static int iommu_no_mapping(struct device *dev) | |||
3625 | * 32 bit DMA is removed from si_domain and fall back | 3621 | * 32 bit DMA is removed from si_domain and fall back |
3626 | * to non-identity mapping. | 3622 | * to non-identity mapping. |
3627 | */ | 3623 | */ |
3628 | dmar_remove_one_dev_info(si_domain, dev); | 3624 | dmar_remove_one_dev_info(dev); |
3629 | pr_info("32bit %s uses non-identity mapping\n", | 3625 | dev_info(dev, "32bit DMA uses non-identity mapping\n"); |
3630 | dev_name(dev)); | ||
3631 | return 0; | 3626 | return 0; |
3632 | } | 3627 | } |
3633 | } else { | 3628 | } else { |
@@ -3639,8 +3634,7 @@ static int iommu_no_mapping(struct device *dev) | |||
3639 | int ret; | 3634 | int ret; |
3640 | ret = domain_add_dev_info(si_domain, dev); | 3635 | ret = domain_add_dev_info(si_domain, dev); |
3641 | if (!ret) { | 3636 | if (!ret) { |
3642 | pr_info("64bit %s uses identity mapping\n", | 3637 | dev_info(dev, "64bit DMA uses identity mapping\n"); |
3643 | dev_name(dev)); | ||
3644 | return 1; | 3638 | return 1; |
3645 | } | 3639 | } |
3646 | } | 3640 | } |
@@ -3649,11 +3643,9 @@ static int iommu_no_mapping(struct device *dev) | |||
3649 | return 0; | 3643 | return 0; |
3650 | } | 3644 | } |
3651 | 3645 | ||
3652 | static dma_addr_t __intel_map_page(struct device *dev, struct page *page, | 3646 | static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr, |
3653 | unsigned long offset, size_t size, int dir, | 3647 | size_t size, int dir, u64 dma_mask) |
3654 | u64 dma_mask) | ||
3655 | { | 3648 | { |
3656 | phys_addr_t paddr = page_to_phys(page) + offset; | ||
3657 | struct dmar_domain *domain; | 3649 | struct dmar_domain *domain; |
3658 | phys_addr_t start_paddr; | 3650 | phys_addr_t start_paddr; |
3659 | unsigned long iova_pfn; | 3651 | unsigned long iova_pfn; |
@@ -3705,8 +3697,8 @@ static dma_addr_t __intel_map_page(struct device *dev, struct page *page, | |||
3705 | error: | 3697 | error: |
3706 | if (iova_pfn) | 3698 | if (iova_pfn) |
3707 | free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size)); | 3699 | free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size)); |
3708 | pr_err("Device %s request: %zx@%llx dir %d --- failed\n", | 3700 | dev_err(dev, "Device request: %zx@%llx dir %d --- failed\n", |
3709 | dev_name(dev), size, (unsigned long long)paddr, dir); | 3701 | size, (unsigned long long)paddr, dir); |
3710 | return DMA_MAPPING_ERROR; | 3702 | return DMA_MAPPING_ERROR; |
3711 | } | 3703 | } |
3712 | 3704 | ||
@@ -3715,7 +3707,15 @@ static dma_addr_t intel_map_page(struct device *dev, struct page *page, | |||
3715 | enum dma_data_direction dir, | 3707 | enum dma_data_direction dir, |
3716 | unsigned long attrs) | 3708 | unsigned long attrs) |
3717 | { | 3709 | { |
3718 | return __intel_map_page(dev, page, offset, size, dir, *dev->dma_mask); | 3710 | return __intel_map_single(dev, page_to_phys(page) + offset, size, |
3711 | dir, *dev->dma_mask); | ||
3712 | } | ||
3713 | |||
3714 | static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr, | ||
3715 | size_t size, enum dma_data_direction dir, | ||
3716 | unsigned long attrs) | ||
3717 | { | ||
3718 | return __intel_map_single(dev, phys_addr, size, dir, *dev->dma_mask); | ||
3719 | } | 3719 | } |
3720 | 3720 | ||
3721 | static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) | 3721 | static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) |
@@ -3741,8 +3741,7 @@ static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size) | |||
3741 | start_pfn = mm_to_dma_pfn(iova_pfn); | 3741 | start_pfn = mm_to_dma_pfn(iova_pfn); |
3742 | last_pfn = start_pfn + nrpages - 1; | 3742 | last_pfn = start_pfn + nrpages - 1; |
3743 | 3743 | ||
3744 | pr_debug("Device %s unmapping: pfn %lx-%lx\n", | 3744 | dev_dbg(dev, "Device unmapping: pfn %lx-%lx\n", start_pfn, last_pfn); |
3745 | dev_name(dev), start_pfn, last_pfn); | ||
3746 | 3745 | ||
3747 | freelist = domain_unmap(domain, start_pfn, last_pfn); | 3746 | freelist = domain_unmap(domain, start_pfn, last_pfn); |
3748 | 3747 | ||
@@ -3806,8 +3805,9 @@ static void *intel_alloc_coherent(struct device *dev, size_t size, | |||
3806 | return NULL; | 3805 | return NULL; |
3807 | memset(page_address(page), 0, size); | 3806 | memset(page_address(page), 0, size); |
3808 | 3807 | ||
3809 | *dma_handle = __intel_map_page(dev, page, 0, size, DMA_BIDIRECTIONAL, | 3808 | *dma_handle = __intel_map_single(dev, page_to_phys(page), size, |
3810 | dev->coherent_dma_mask); | 3809 | DMA_BIDIRECTIONAL, |
3810 | dev->coherent_dma_mask); | ||
3811 | if (*dma_handle != DMA_MAPPING_ERROR) | 3811 | if (*dma_handle != DMA_MAPPING_ERROR) |
3812 | return page_address(page); | 3812 | return page_address(page); |
3813 | if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) | 3813 | if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) |
@@ -3924,6 +3924,8 @@ static const struct dma_map_ops intel_dma_ops = { | |||
3924 | .unmap_sg = intel_unmap_sg, | 3924 | .unmap_sg = intel_unmap_sg, |
3925 | .map_page = intel_map_page, | 3925 | .map_page = intel_map_page, |
3926 | .unmap_page = intel_unmap_page, | 3926 | .unmap_page = intel_unmap_page, |
3927 | .map_resource = intel_map_resource, | ||
3928 | .unmap_resource = intel_unmap_page, | ||
3927 | .dma_supported = dma_direct_supported, | 3929 | .dma_supported = dma_direct_supported, |
3928 | }; | 3930 | }; |
3929 | 3931 | ||
@@ -4339,7 +4341,7 @@ int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg) | |||
4339 | 4341 | ||
4340 | static int intel_iommu_add(struct dmar_drhd_unit *dmaru) | 4342 | static int intel_iommu_add(struct dmar_drhd_unit *dmaru) |
4341 | { | 4343 | { |
4342 | int sp, ret = 0; | 4344 | int sp, ret; |
4343 | struct intel_iommu *iommu = dmaru->iommu; | 4345 | struct intel_iommu *iommu = dmaru->iommu; |
4344 | 4346 | ||
4345 | if (g_iommus[iommu->seq_id]) | 4347 | if (g_iommus[iommu->seq_id]) |
@@ -4503,7 +4505,7 @@ out: | |||
4503 | 4505 | ||
4504 | int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) | 4506 | int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) |
4505 | { | 4507 | { |
4506 | int ret = 0; | 4508 | int ret; |
4507 | struct dmar_rmrr_unit *rmrru; | 4509 | struct dmar_rmrr_unit *rmrru; |
4508 | struct dmar_atsr_unit *atsru; | 4510 | struct dmar_atsr_unit *atsru; |
4509 | struct acpi_dmar_atsr *atsr; | 4511 | struct acpi_dmar_atsr *atsr; |
@@ -4520,7 +4522,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) | |||
4520 | ((void *)rmrr) + rmrr->header.length, | 4522 | ((void *)rmrr) + rmrr->header.length, |
4521 | rmrr->segment, rmrru->devices, | 4523 | rmrr->segment, rmrru->devices, |
4522 | rmrru->devices_cnt); | 4524 | rmrru->devices_cnt); |
4523 | if(ret < 0) | 4525 | if (ret < 0) |
4524 | return ret; | 4526 | return ret; |
4525 | } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { | 4527 | } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { |
4526 | dmar_remove_dev_scope(info, rmrr->segment, | 4528 | dmar_remove_dev_scope(info, rmrr->segment, |
@@ -4540,7 +4542,7 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) | |||
4540 | atsru->devices_cnt); | 4542 | atsru->devices_cnt); |
4541 | if (ret > 0) | 4543 | if (ret > 0) |
4542 | break; | 4544 | break; |
4543 | else if(ret < 0) | 4545 | else if (ret < 0) |
4544 | return ret; | 4546 | return ret; |
4545 | } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { | 4547 | } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) { |
4546 | if (dmar_remove_dev_scope(info, atsr->segment, | 4548 | if (dmar_remove_dev_scope(info, atsr->segment, |
@@ -4567,16 +4569,19 @@ static int device_notifier(struct notifier_block *nb, | |||
4567 | if (iommu_dummy(dev)) | 4569 | if (iommu_dummy(dev)) |
4568 | return 0; | 4570 | return 0; |
4569 | 4571 | ||
4570 | if (action != BUS_NOTIFY_REMOVED_DEVICE) | 4572 | if (action == BUS_NOTIFY_REMOVED_DEVICE) { |
4571 | return 0; | 4573 | domain = find_domain(dev); |
4572 | 4574 | if (!domain) | |
4573 | domain = find_domain(dev); | 4575 | return 0; |
4574 | if (!domain) | ||
4575 | return 0; | ||
4576 | 4576 | ||
4577 | dmar_remove_one_dev_info(domain, dev); | 4577 | dmar_remove_one_dev_info(dev); |
4578 | if (!domain_type_is_vm_or_si(domain) && list_empty(&domain->devices)) | 4578 | if (!domain_type_is_vm_or_si(domain) && |
4579 | domain_exit(domain); | 4579 | list_empty(&domain->devices)) |
4580 | domain_exit(domain); | ||
4581 | } else if (action == BUS_NOTIFY_ADD_DEVICE) { | ||
4582 | if (iommu_should_identity_map(dev, 1)) | ||
4583 | domain_add_dev_info(si_domain, dev); | ||
4584 | } | ||
4580 | 4585 | ||
4581 | return 0; | 4586 | return 0; |
4582 | } | 4587 | } |
@@ -4987,8 +4992,7 @@ static void __dmar_remove_one_dev_info(struct device_domain_info *info) | |||
4987 | free_devinfo_mem(info); | 4992 | free_devinfo_mem(info); |
4988 | } | 4993 | } |
4989 | 4994 | ||
4990 | static void dmar_remove_one_dev_info(struct dmar_domain *domain, | 4995 | static void dmar_remove_one_dev_info(struct device *dev) |
4991 | struct device *dev) | ||
4992 | { | 4996 | { |
4993 | struct device_domain_info *info; | 4997 | struct device_domain_info *info; |
4994 | unsigned long flags; | 4998 | unsigned long flags; |
@@ -5077,7 +5081,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
5077 | old_domain = find_domain(dev); | 5081 | old_domain = find_domain(dev); |
5078 | if (old_domain) { | 5082 | if (old_domain) { |
5079 | rcu_read_lock(); | 5083 | rcu_read_lock(); |
5080 | dmar_remove_one_dev_info(old_domain, dev); | 5084 | dmar_remove_one_dev_info(dev); |
5081 | rcu_read_unlock(); | 5085 | rcu_read_unlock(); |
5082 | 5086 | ||
5083 | if (!domain_type_is_vm_or_si(old_domain) && | 5087 | if (!domain_type_is_vm_or_si(old_domain) && |
@@ -5096,9 +5100,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
5096 | addr_width = cap_mgaw(iommu->cap); | 5100 | addr_width = cap_mgaw(iommu->cap); |
5097 | 5101 | ||
5098 | if (dmar_domain->max_addr > (1LL << addr_width)) { | 5102 | if (dmar_domain->max_addr > (1LL << addr_width)) { |
5099 | pr_err("%s: iommu width (%d) is not " | 5103 | dev_err(dev, "%s: iommu width (%d) is not " |
5100 | "sufficient for the mapped address (%llx)\n", | 5104 | "sufficient for the mapped address (%llx)\n", |
5101 | __func__, addr_width, dmar_domain->max_addr); | 5105 | __func__, addr_width, dmar_domain->max_addr); |
5102 | return -EFAULT; | 5106 | return -EFAULT; |
5103 | } | 5107 | } |
5104 | dmar_domain->gaw = addr_width; | 5108 | dmar_domain->gaw = addr_width; |
@@ -5124,7 +5128,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, | |||
5124 | static void intel_iommu_detach_device(struct iommu_domain *domain, | 5128 | static void intel_iommu_detach_device(struct iommu_domain *domain, |
5125 | struct device *dev) | 5129 | struct device *dev) |
5126 | { | 5130 | { |
5127 | dmar_remove_one_dev_info(to_dmar_domain(domain), dev); | 5131 | dmar_remove_one_dev_info(dev); |
5128 | } | 5132 | } |
5129 | 5133 | ||
5130 | static int intel_iommu_map(struct iommu_domain *domain, | 5134 | static int intel_iommu_map(struct iommu_domain *domain, |
@@ -5399,7 +5403,7 @@ const struct iommu_ops intel_iommu_ops = { | |||
5399 | static void quirk_iommu_g4x_gfx(struct pci_dev *dev) | 5403 | static void quirk_iommu_g4x_gfx(struct pci_dev *dev) |
5400 | { | 5404 | { |
5401 | /* G4x/GM45 integrated gfx dmar support is totally busted. */ | 5405 | /* G4x/GM45 integrated gfx dmar support is totally busted. */ |
5402 | pr_info("Disabling IOMMU for graphics on this chipset\n"); | 5406 | pci_info(dev, "Disabling IOMMU for graphics on this chipset\n"); |
5403 | dmar_map_gfx = 0; | 5407 | dmar_map_gfx = 0; |
5404 | } | 5408 | } |
5405 | 5409 | ||
@@ -5417,7 +5421,7 @@ static void quirk_iommu_rwbf(struct pci_dev *dev) | |||
5417 | * Mobile 4 Series Chipset neglects to set RWBF capability, | 5421 | * Mobile 4 Series Chipset neglects to set RWBF capability, |
5418 | * but needs it. Same seems to hold for the desktop versions. | 5422 | * but needs it. Same seems to hold for the desktop versions. |
5419 | */ | 5423 | */ |
5420 | pr_info("Forcing write-buffer flush capability\n"); | 5424 | pci_info(dev, "Forcing write-buffer flush capability\n"); |
5421 | rwbf_quirk = 1; | 5425 | rwbf_quirk = 1; |
5422 | } | 5426 | } |
5423 | 5427 | ||
@@ -5447,11 +5451,11 @@ static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev) | |||
5447 | return; | 5451 | return; |
5448 | 5452 | ||
5449 | if (!(ggc & GGC_MEMORY_VT_ENABLED)) { | 5453 | if (!(ggc & GGC_MEMORY_VT_ENABLED)) { |
5450 | pr_info("BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); | 5454 | pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n"); |
5451 | dmar_map_gfx = 0; | 5455 | dmar_map_gfx = 0; |
5452 | } else if (dmar_map_gfx) { | 5456 | } else if (dmar_map_gfx) { |
5453 | /* we have to ensure the gfx device is idle before we flush */ | 5457 | /* we have to ensure the gfx device is idle before we flush */ |
5454 | pr_info("Disabling batched IOTLB flush on Ironlake\n"); | 5458 | pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n"); |
5455 | intel_iommu_strict = 1; | 5459 | intel_iommu_strict = 1; |
5456 | } | 5460 | } |
5457 | } | 5461 | } |
diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c index 53fe5248d8f1..03b12d2ee213 100644 --- a/drivers/iommu/intel-pasid.c +++ b/drivers/iommu/intel-pasid.c | |||
@@ -466,8 +466,8 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, | |||
466 | if (WARN_ON(!pte)) | 466 | if (WARN_ON(!pte)) |
467 | return; | 467 | return; |
468 | 468 | ||
469 | intel_pasid_clear_entry(dev, pasid); | ||
470 | did = pasid_get_domain_id(pte); | 469 | did = pasid_get_domain_id(pte); |
470 | intel_pasid_clear_entry(dev, pasid); | ||
471 | 471 | ||
472 | if (!ecap_coherent(iommu->ecap)) | 472 | if (!ecap_coherent(iommu->ecap)) |
473 | clflush_cache_range(pte, sizeof(*pte)); | 473 | clflush_cache_range(pte, sizeof(*pte)); |
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index a2a2aa4439aa..3a4b09ae8561 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c | |||
@@ -180,14 +180,6 @@ static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address, | |||
180 | rcu_read_unlock(); | 180 | rcu_read_unlock(); |
181 | } | 181 | } |
182 | 182 | ||
183 | static void intel_change_pte(struct mmu_notifier *mn, struct mm_struct *mm, | ||
184 | unsigned long address, pte_t pte) | ||
185 | { | ||
186 | struct intel_svm *svm = container_of(mn, struct intel_svm, notifier); | ||
187 | |||
188 | intel_flush_svm_range(svm, address, 1, 1, 0); | ||
189 | } | ||
190 | |||
191 | /* Pages have been freed at this point */ | 183 | /* Pages have been freed at this point */ |
192 | static void intel_invalidate_range(struct mmu_notifier *mn, | 184 | static void intel_invalidate_range(struct mmu_notifier *mn, |
193 | struct mm_struct *mm, | 185 | struct mm_struct *mm, |
@@ -227,7 +219,6 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm) | |||
227 | 219 | ||
228 | static const struct mmu_notifier_ops intel_mmuops = { | 220 | static const struct mmu_notifier_ops intel_mmuops = { |
229 | .release = intel_mm_release, | 221 | .release = intel_mm_release, |
230 | .change_pte = intel_change_pte, | ||
231 | .invalidate_range = intel_invalidate_range, | 222 | .invalidate_range = intel_invalidate_range, |
232 | }; | 223 | }; |
233 | 224 | ||
@@ -243,7 +234,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ | |||
243 | int pasid_max; | 234 | int pasid_max; |
244 | int ret; | 235 | int ret; |
245 | 236 | ||
246 | if (!iommu) | 237 | if (!iommu || dmar_disabled) |
247 | return -EINVAL; | 238 | return -EINVAL; |
248 | 239 | ||
249 | if (dev_is_pci(dev)) { | 240 | if (dev_is_pci(dev)) { |
@@ -470,20 +461,31 @@ EXPORT_SYMBOL_GPL(intel_svm_is_pasid_valid); | |||
470 | 461 | ||
471 | /* Page request queue descriptor */ | 462 | /* Page request queue descriptor */ |
472 | struct page_req_dsc { | 463 | struct page_req_dsc { |
473 | u64 srr:1; | 464 | union { |
474 | u64 bof:1; | 465 | struct { |
475 | u64 pasid_present:1; | 466 | u64 type:8; |
476 | u64 lpig:1; | 467 | u64 pasid_present:1; |
477 | u64 pasid:20; | 468 | u64 priv_data_present:1; |
478 | u64 bus:8; | 469 | u64 rsvd:6; |
479 | u64 private:23; | 470 | u64 rid:16; |
480 | u64 prg_index:9; | 471 | u64 pasid:20; |
481 | u64 rd_req:1; | 472 | u64 exe_req:1; |
482 | u64 wr_req:1; | 473 | u64 pm_req:1; |
483 | u64 exe_req:1; | 474 | u64 rsvd2:10; |
484 | u64 priv_req:1; | 475 | }; |
485 | u64 devfn:8; | 476 | u64 qw_0; |
486 | u64 addr:52; | 477 | }; |
478 | union { | ||
479 | struct { | ||
480 | u64 rd_req:1; | ||
481 | u64 wr_req:1; | ||
482 | u64 lpig:1; | ||
483 | u64 prg_index:9; | ||
484 | u64 addr:52; | ||
485 | }; | ||
486 | u64 qw_1; | ||
487 | }; | ||
488 | u64 priv_data[2]; | ||
487 | }; | 489 | }; |
488 | 490 | ||
489 | #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10) | 491 | #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10) |
@@ -596,7 +598,7 @@ static irqreturn_t prq_event_thread(int irq, void *d) | |||
596 | /* Accounting for major/minor faults? */ | 598 | /* Accounting for major/minor faults? */ |
597 | rcu_read_lock(); | 599 | rcu_read_lock(); |
598 | list_for_each_entry_rcu(sdev, &svm->devs, list) { | 600 | list_for_each_entry_rcu(sdev, &svm->devs, list) { |
599 | if (sdev->sid == PCI_DEVID(req->bus, req->devfn)) | 601 | if (sdev->sid == req->rid) |
600 | break; | 602 | break; |
601 | } | 603 | } |
602 | /* Other devices can go away, but the drivers are not permitted | 604 | /* Other devices can go away, but the drivers are not permitted |
@@ -609,33 +611,35 @@ static irqreturn_t prq_event_thread(int irq, void *d) | |||
609 | 611 | ||
610 | if (sdev && sdev->ops && sdev->ops->fault_cb) { | 612 | if (sdev && sdev->ops && sdev->ops->fault_cb) { |
611 | int rwxp = (req->rd_req << 3) | (req->wr_req << 2) | | 613 | int rwxp = (req->rd_req << 3) | (req->wr_req << 2) | |
612 | (req->exe_req << 1) | (req->priv_req); | 614 | (req->exe_req << 1) | (req->pm_req); |
613 | sdev->ops->fault_cb(sdev->dev, req->pasid, req->addr, req->private, rwxp, result); | 615 | sdev->ops->fault_cb(sdev->dev, req->pasid, req->addr, |
616 | req->priv_data, rwxp, result); | ||
614 | } | 617 | } |
615 | /* We get here in the error case where the PASID lookup failed, | 618 | /* We get here in the error case where the PASID lookup failed, |
616 | and these can be NULL. Do not use them below this point! */ | 619 | and these can be NULL. Do not use them below this point! */ |
617 | sdev = NULL; | 620 | sdev = NULL; |
618 | svm = NULL; | 621 | svm = NULL; |
619 | no_pasid: | 622 | no_pasid: |
620 | if (req->lpig) { | 623 | if (req->lpig || req->priv_data_present) { |
621 | /* Page Group Response */ | 624 | /* |
625 | * Per VT-d spec. v3.0 ch7.7, system software must | ||
626 | * respond with page group response if private data | ||
627 | * is present (PDP) or last page in group (LPIG) bit | ||
628 | * is set. This is an additional VT-d feature beyond | ||
629 | * PCI ATS spec. | ||
630 | */ | ||
622 | resp.qw0 = QI_PGRP_PASID(req->pasid) | | 631 | resp.qw0 = QI_PGRP_PASID(req->pasid) | |
623 | QI_PGRP_DID((req->bus << 8) | req->devfn) | | 632 | QI_PGRP_DID(req->rid) | |
624 | QI_PGRP_PASID_P(req->pasid_present) | | 633 | QI_PGRP_PASID_P(req->pasid_present) | |
634 | QI_PGRP_PDP(req->pasid_present) | | ||
635 | QI_PGRP_RESP_CODE(result) | | ||
625 | QI_PGRP_RESP_TYPE; | 636 | QI_PGRP_RESP_TYPE; |
626 | resp.qw1 = QI_PGRP_IDX(req->prg_index) | | 637 | resp.qw1 = QI_PGRP_IDX(req->prg_index) | |
627 | QI_PGRP_PRIV(req->private) | | 638 | QI_PGRP_LPIG(req->lpig); |
628 | QI_PGRP_RESP_CODE(result); | 639 | |
629 | } else if (req->srr) { | 640 | if (req->priv_data_present) |
630 | /* Page Stream Response */ | 641 | memcpy(&resp.qw2, req->priv_data, |
631 | resp.qw0 = QI_PSTRM_IDX(req->prg_index) | | 642 | sizeof(req->priv_data)); |
632 | QI_PSTRM_PRIV(req->private) | | ||
633 | QI_PSTRM_BUS(req->bus) | | ||
634 | QI_PSTRM_PASID(req->pasid) | | ||
635 | QI_PSTRM_RESP_TYPE; | ||
636 | resp.qw1 = QI_PSTRM_ADDR(address) | | ||
637 | QI_PSTRM_DEVFN(req->devfn) | | ||
638 | QI_PSTRM_RESP_CODE(result); | ||
639 | } | 643 | } |
640 | resp.qw2 = 0; | 644 | resp.qw2 = 0; |
641 | resp.qw3 = 0; | 645 | resp.qw3 = 0; |
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 24d45b07f425..2d74641b7f7b 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c | |||
@@ -294,6 +294,18 @@ static void set_irte_sid(struct irte *irte, unsigned int svt, | |||
294 | irte->sid = sid; | 294 | irte->sid = sid; |
295 | } | 295 | } |
296 | 296 | ||
297 | /* | ||
298 | * Set an IRTE to match only the bus number. Interrupt requests that reference | ||
299 | * this IRTE must have a requester-id whose bus number is between or equal | ||
300 | * to the start_bus and end_bus arguments. | ||
301 | */ | ||
302 | static void set_irte_verify_bus(struct irte *irte, unsigned int start_bus, | ||
303 | unsigned int end_bus) | ||
304 | { | ||
305 | set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, | ||
306 | (start_bus << 8) | end_bus); | ||
307 | } | ||
308 | |||
297 | static int set_ioapic_sid(struct irte *irte, int apic) | 309 | static int set_ioapic_sid(struct irte *irte, int apic) |
298 | { | 310 | { |
299 | int i; | 311 | int i; |
@@ -356,6 +368,8 @@ static int set_hpet_sid(struct irte *irte, u8 id) | |||
356 | struct set_msi_sid_data { | 368 | struct set_msi_sid_data { |
357 | struct pci_dev *pdev; | 369 | struct pci_dev *pdev; |
358 | u16 alias; | 370 | u16 alias; |
371 | int count; | ||
372 | int busmatch_count; | ||
359 | }; | 373 | }; |
360 | 374 | ||
361 | static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque) | 375 | static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque) |
@@ -364,6 +378,10 @@ static int set_msi_sid_cb(struct pci_dev *pdev, u16 alias, void *opaque) | |||
364 | 378 | ||
365 | data->pdev = pdev; | 379 | data->pdev = pdev; |
366 | data->alias = alias; | 380 | data->alias = alias; |
381 | data->count++; | ||
382 | |||
383 | if (PCI_BUS_NUM(alias) == pdev->bus->number) | ||
384 | data->busmatch_count++; | ||
367 | 385 | ||
368 | return 0; | 386 | return 0; |
369 | } | 387 | } |
@@ -375,6 +393,8 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev) | |||
375 | if (!irte || !dev) | 393 | if (!irte || !dev) |
376 | return -1; | 394 | return -1; |
377 | 395 | ||
396 | data.count = 0; | ||
397 | data.busmatch_count = 0; | ||
378 | pci_for_each_dma_alias(dev, set_msi_sid_cb, &data); | 398 | pci_for_each_dma_alias(dev, set_msi_sid_cb, &data); |
379 | 399 | ||
380 | /* | 400 | /* |
@@ -383,6 +403,11 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev) | |||
383 | * device is the case of a PCIe-to-PCI bridge, where the alias is for | 403 | * device is the case of a PCIe-to-PCI bridge, where the alias is for |
384 | * the subordinate bus. In this case we can only verify the bus. | 404 | * the subordinate bus. In this case we can only verify the bus. |
385 | * | 405 | * |
406 | * If there are multiple aliases, all with the same bus number, | ||
407 | * then all we can do is verify the bus. This is typical in NTB | ||
408 | * hardware which use proxy IDs where the device will generate traffic | ||
409 | * from multiple devfn numbers on the same bus. | ||
410 | * | ||
386 | * If the alias device is on a different bus than our source device | 411 | * If the alias device is on a different bus than our source device |
387 | * then we have a topology based alias, use it. | 412 | * then we have a topology based alias, use it. |
388 | * | 413 | * |
@@ -391,9 +416,10 @@ static int set_msi_sid(struct irte *irte, struct pci_dev *dev) | |||
391 | * original device. | 416 | * original device. |
392 | */ | 417 | */ |
393 | if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number) | 418 | if (PCI_BUS_NUM(data.alias) != data.pdev->bus->number) |
394 | set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, | 419 | set_irte_verify_bus(irte, PCI_BUS_NUM(data.alias), |
395 | PCI_DEVID(PCI_BUS_NUM(data.alias), | 420 | dev->bus->number); |
396 | dev->bus->number)); | 421 | else if (data.count >= 2 && data.busmatch_count == data.count) |
422 | set_irte_verify_bus(irte, dev->bus->number, dev->bus->number); | ||
397 | else if (data.pdev->bus->number != dev->bus->number) | 423 | else if (data.pdev->bus->number != dev->bus->number) |
398 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias); | 424 | set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, data.alias); |
399 | else | 425 | else |
diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index cec29bf45c9b..f101afc315ab 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/atomic.h> | 35 | #include <linux/atomic.h> |
36 | #include <linux/dma-mapping.h> | 36 | #include <linux/dma-mapping.h> |
37 | #include <linux/gfp.h> | 37 | #include <linux/gfp.h> |
38 | #include <linux/io-pgtable.h> | ||
38 | #include <linux/iommu.h> | 39 | #include <linux/iommu.h> |
39 | #include <linux/kernel.h> | 40 | #include <linux/kernel.h> |
40 | #include <linux/kmemleak.h> | 41 | #include <linux/kmemleak.h> |
@@ -45,8 +46,6 @@ | |||
45 | 46 | ||
46 | #include <asm/barrier.h> | 47 | #include <asm/barrier.h> |
47 | 48 | ||
48 | #include "io-pgtable.h" | ||
49 | |||
50 | /* Struct accessors */ | 49 | /* Struct accessors */ |
51 | #define io_pgtable_to_data(x) \ | 50 | #define io_pgtable_to_data(x) \ |
52 | container_of((x), struct arm_v7s_io_pgtable, iop) | 51 | container_of((x), struct arm_v7s_io_pgtable, iop) |
@@ -217,7 +216,8 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp, | |||
217 | if (dma != phys) | 216 | if (dma != phys) |
218 | goto out_unmap; | 217 | goto out_unmap; |
219 | } | 218 | } |
220 | kmemleak_ignore(table); | 219 | if (lvl == 2) |
220 | kmemleak_ignore(table); | ||
221 | return table; | 221 | return table; |
222 | 222 | ||
223 | out_unmap: | 223 | out_unmap: |
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index 237cacd4a62b..d3700ec15cbd 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/atomic.h> | 23 | #include <linux/atomic.h> |
24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | #include <linux/io-pgtable.h> | ||
25 | #include <linux/iommu.h> | 26 | #include <linux/iommu.h> |
26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
27 | #include <linux/sizes.h> | 28 | #include <linux/sizes.h> |
@@ -31,8 +32,6 @@ | |||
31 | 32 | ||
32 | #include <asm/barrier.h> | 33 | #include <asm/barrier.h> |
33 | 34 | ||
34 | #include "io-pgtable.h" | ||
35 | |||
36 | #define ARM_LPAE_MAX_ADDR_BITS 52 | 35 | #define ARM_LPAE_MAX_ADDR_BITS 52 |
37 | #define ARM_LPAE_S2_MAX_CONCAT_PAGES 16 | 36 | #define ARM_LPAE_S2_MAX_CONCAT_PAGES 16 |
38 | #define ARM_LPAE_MAX_LEVELS 4 | 37 | #define ARM_LPAE_MAX_LEVELS 4 |
diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c index 127558d83667..93f2880be6c6 100644 --- a/drivers/iommu/io-pgtable.c +++ b/drivers/iommu/io-pgtable.c | |||
@@ -19,11 +19,10 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/bug.h> | 21 | #include <linux/bug.h> |
22 | #include <linux/io-pgtable.h> | ||
22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
23 | #include <linux/types.h> | 24 | #include <linux/types.h> |
24 | 25 | ||
25 | #include "io-pgtable.h" | ||
26 | |||
27 | static const struct io_pgtable_init_fns * | 26 | static const struct io_pgtable_init_fns * |
28 | io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = { | 27 | io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = { |
29 | #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE | 28 | #ifdef CONFIG_IOMMU_IO_PGTABLE_LPAE |
@@ -61,6 +60,7 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt, | |||
61 | 60 | ||
62 | return &iop->ops; | 61 | return &iop->ops; |
63 | } | 62 | } |
63 | EXPORT_SYMBOL_GPL(alloc_io_pgtable_ops); | ||
64 | 64 | ||
65 | /* | 65 | /* |
66 | * It is the IOMMU driver's responsibility to ensure that the page table | 66 | * It is the IOMMU driver's responsibility to ensure that the page table |
@@ -77,3 +77,4 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops) | |||
77 | io_pgtable_tlb_flush_all(iop); | 77 | io_pgtable_tlb_flush_all(iop); |
78 | io_pgtable_init_table[iop->fmt]->free(iop); | 78 | io_pgtable_init_table[iop->fmt]->free(iop); |
79 | } | 79 | } |
80 | EXPORT_SYMBOL_GPL(free_io_pgtable_ops); | ||
diff --git a/drivers/iommu/iommu-debugfs.c b/drivers/iommu/iommu-debugfs.c index 3b1bf88fd1b0..f03548942096 100644 --- a/drivers/iommu/iommu-debugfs.c +++ b/drivers/iommu/iommu-debugfs.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/debugfs.h> | 12 | #include <linux/debugfs.h> |
13 | 13 | ||
14 | struct dentry *iommu_debugfs_dir; | 14 | struct dentry *iommu_debugfs_dir; |
15 | EXPORT_SYMBOL_GPL(iommu_debugfs_dir); | ||
15 | 16 | ||
16 | /** | 17 | /** |
17 | * iommu_debugfs_setup - create the top-level iommu directory in debugfs | 18 | * iommu_debugfs_setup - create the top-level iommu directory in debugfs |
@@ -23,9 +24,9 @@ struct dentry *iommu_debugfs_dir; | |||
23 | * Emit a strong warning at boot time to indicate that this feature is | 24 | * Emit a strong warning at boot time to indicate that this feature is |
24 | * enabled. | 25 | * enabled. |
25 | * | 26 | * |
26 | * This function is called from iommu_init; drivers may then call | 27 | * This function is called from iommu_init; drivers may then use |
27 | * iommu_debugfs_new_driver_dir() to instantiate a vendor-specific | 28 | * iommu_debugfs_dir to instantiate a vendor-specific directory to be used |
28 | * directory to be used to expose internal data. | 29 | * to expose internal data. |
29 | */ | 30 | */ |
30 | void iommu_debugfs_setup(void) | 31 | void iommu_debugfs_setup(void) |
31 | { | 32 | { |
@@ -48,19 +49,3 @@ void iommu_debugfs_setup(void) | |||
48 | pr_warn("*************************************************************\n"); | 49 | pr_warn("*************************************************************\n"); |
49 | } | 50 | } |
50 | } | 51 | } |
51 | |||
52 | /** | ||
53 | * iommu_debugfs_new_driver_dir - create a vendor directory under debugfs/iommu | ||
54 | * @vendor: name of the vendor-specific subdirectory to create | ||
55 | * | ||
56 | * This function is called by an IOMMU driver to create the top-level debugfs | ||
57 | * directory for that driver. | ||
58 | * | ||
59 | * Return: upon success, a pointer to the dentry for the new directory. | ||
60 | * NULL in case of failure. | ||
61 | */ | ||
62 | struct dentry *iommu_debugfs_new_driver_dir(const char *vendor) | ||
63 | { | ||
64 | return debugfs_create_dir(vendor, iommu_debugfs_dir); | ||
65 | } | ||
66 | EXPORT_SYMBOL_GPL(iommu_debugfs_new_driver_dir); | ||
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3ed4db334341..33a982e33716 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -668,7 +668,7 @@ rename: | |||
668 | 668 | ||
669 | trace_add_device_to_group(group->id, dev); | 669 | trace_add_device_to_group(group->id, dev); |
670 | 670 | ||
671 | pr_info("Adding device %s to group %d\n", dev_name(dev), group->id); | 671 | dev_info(dev, "Adding to iommu group %d\n", group->id); |
672 | 672 | ||
673 | return 0; | 673 | return 0; |
674 | 674 | ||
@@ -684,7 +684,7 @@ err_remove_link: | |||
684 | sysfs_remove_link(&dev->kobj, "iommu_group"); | 684 | sysfs_remove_link(&dev->kobj, "iommu_group"); |
685 | err_free_device: | 685 | err_free_device: |
686 | kfree(device); | 686 | kfree(device); |
687 | pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret); | 687 | dev_err(dev, "Failed to add to iommu group %d: %d\n", group->id, ret); |
688 | return ret; | 688 | return ret; |
689 | } | 689 | } |
690 | EXPORT_SYMBOL_GPL(iommu_group_add_device); | 690 | EXPORT_SYMBOL_GPL(iommu_group_add_device); |
@@ -701,7 +701,7 @@ void iommu_group_remove_device(struct device *dev) | |||
701 | struct iommu_group *group = dev->iommu_group; | 701 | struct iommu_group *group = dev->iommu_group; |
702 | struct group_device *tmp_device, *device = NULL; | 702 | struct group_device *tmp_device, *device = NULL; |
703 | 703 | ||
704 | pr_info("Removing device %s from group %d\n", dev_name(dev), group->id); | 704 | dev_info(dev, "Removing from iommu group %d\n", group->id); |
705 | 705 | ||
706 | /* Pre-notify listeners that a device is being removed. */ | 706 | /* Pre-notify listeners that a device is being removed. */ |
707 | blocking_notifier_call_chain(&group->notifier, | 707 | blocking_notifier_call_chain(&group->notifier, |
@@ -1585,13 +1585,14 @@ static size_t iommu_pgsize(struct iommu_domain *domain, | |||
1585 | int iommu_map(struct iommu_domain *domain, unsigned long iova, | 1585 | int iommu_map(struct iommu_domain *domain, unsigned long iova, |
1586 | phys_addr_t paddr, size_t size, int prot) | 1586 | phys_addr_t paddr, size_t size, int prot) |
1587 | { | 1587 | { |
1588 | const struct iommu_ops *ops = domain->ops; | ||
1588 | unsigned long orig_iova = iova; | 1589 | unsigned long orig_iova = iova; |
1589 | unsigned int min_pagesz; | 1590 | unsigned int min_pagesz; |
1590 | size_t orig_size = size; | 1591 | size_t orig_size = size; |
1591 | phys_addr_t orig_paddr = paddr; | 1592 | phys_addr_t orig_paddr = paddr; |
1592 | int ret = 0; | 1593 | int ret = 0; |
1593 | 1594 | ||
1594 | if (unlikely(domain->ops->map == NULL || | 1595 | if (unlikely(ops->map == NULL || |
1595 | domain->pgsize_bitmap == 0UL)) | 1596 | domain->pgsize_bitmap == 0UL)) |
1596 | return -ENODEV; | 1597 | return -ENODEV; |
1597 | 1598 | ||
@@ -1620,7 +1621,7 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
1620 | pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n", | 1621 | pr_debug("mapping: iova 0x%lx pa %pa pgsize 0x%zx\n", |
1621 | iova, &paddr, pgsize); | 1622 | iova, &paddr, pgsize); |
1622 | 1623 | ||
1623 | ret = domain->ops->map(domain, iova, paddr, pgsize, prot); | 1624 | ret = ops->map(domain, iova, paddr, pgsize, prot); |
1624 | if (ret) | 1625 | if (ret) |
1625 | break; | 1626 | break; |
1626 | 1627 | ||
@@ -1629,6 +1630,9 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
1629 | size -= pgsize; | 1630 | size -= pgsize; |
1630 | } | 1631 | } |
1631 | 1632 | ||
1633 | if (ops->iotlb_sync_map) | ||
1634 | ops->iotlb_sync_map(domain); | ||
1635 | |||
1632 | /* unroll mapping in case something went wrong */ | 1636 | /* unroll mapping in case something went wrong */ |
1633 | if (ret) | 1637 | if (ret) |
1634 | iommu_unmap(domain, orig_iova, orig_size - size); | 1638 | iommu_unmap(domain, orig_iova, orig_size - size); |
@@ -1951,7 +1955,7 @@ int iommu_request_dm_for_dev(struct device *dev) | |||
1951 | iommu_domain_free(group->default_domain); | 1955 | iommu_domain_free(group->default_domain); |
1952 | group->default_domain = dm_domain; | 1956 | group->default_domain = dm_domain; |
1953 | 1957 | ||
1954 | pr_info("Using direct mapping for device %s\n", dev_name(dev)); | 1958 | dev_info(dev, "Using iommu direct mapping\n"); |
1955 | 1959 | ||
1956 | ret = 0; | 1960 | ret = 0; |
1957 | out: | 1961 | out: |
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 7a4529c61c19..9a380c10655e 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/io-pgtable.h> | ||
18 | #include <linux/iommu.h> | 19 | #include <linux/iommu.h> |
19 | #include <linux/of.h> | 20 | #include <linux/of.h> |
20 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
@@ -35,8 +36,6 @@ | |||
35 | #define arm_iommu_detach_device(...) do {} while (0) | 36 | #define arm_iommu_detach_device(...) do {} while (0) |
36 | #endif | 37 | #endif |
37 | 38 | ||
38 | #include "io-pgtable.h" | ||
39 | |||
40 | #define IPMMU_CTX_MAX 8 | 39 | #define IPMMU_CTX_MAX 8 |
41 | 40 | ||
42 | struct ipmmu_features { | 41 | struct ipmmu_features { |
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index b94ebd42edd8..81cf2908c531 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
@@ -103,6 +103,9 @@ int __init irq_remapping_prepare(void) | |||
103 | else if (IS_ENABLED(CONFIG_AMD_IOMMU) && | 103 | else if (IS_ENABLED(CONFIG_AMD_IOMMU) && |
104 | amd_iommu_irq_ops.prepare() == 0) | 104 | amd_iommu_irq_ops.prepare() == 0) |
105 | remap_ops = &amd_iommu_irq_ops; | 105 | remap_ops = &amd_iommu_irq_ops; |
106 | else if (IS_ENABLED(CONFIG_HYPERV_IOMMU) && | ||
107 | hyperv_irq_remap_ops.prepare() == 0) | ||
108 | remap_ops = &hyperv_irq_remap_ops; | ||
106 | else | 109 | else |
107 | return -ENOSYS; | 110 | return -ENOSYS; |
108 | 111 | ||
diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index 0afef6e43be4..f8609e9f1f5d 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h | |||
@@ -64,6 +64,7 @@ struct irq_remap_ops { | |||
64 | 64 | ||
65 | extern struct irq_remap_ops intel_irq_remap_ops; | 65 | extern struct irq_remap_ops intel_irq_remap_ops; |
66 | extern struct irq_remap_ops amd_iommu_irq_ops; | 66 | extern struct irq_remap_ops amd_iommu_irq_ops; |
67 | extern struct irq_remap_ops hyperv_irq_remap_ops; | ||
67 | 68 | ||
68 | #else /* CONFIG_IRQ_REMAP */ | 69 | #else /* CONFIG_IRQ_REMAP */ |
69 | 70 | ||
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index fc4270733f11..9fb0eb7a4d02 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/io-pgtable.h> | ||
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | #include <linux/list.h> | 28 | #include <linux/list.h> |
28 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
@@ -37,7 +38,6 @@ | |||
37 | 38 | ||
38 | #include "msm_iommu_hw-8xxx.h" | 39 | #include "msm_iommu_hw-8xxx.h" |
39 | #include "msm_iommu.h" | 40 | #include "msm_iommu.h" |
40 | #include "io-pgtable.h" | ||
41 | 41 | ||
42 | #define MRC(reg, processor, op1, crn, crm, op2) \ | 42 | #define MRC(reg, processor, op1, crn, crm, op2) \ |
43 | __asm__ __volatile__ ( \ | 43 | __asm__ __volatile__ ( \ |
@@ -461,10 +461,10 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) | |||
461 | master->num = | 461 | master->num = |
462 | msm_iommu_alloc_ctx(iommu->context_map, | 462 | msm_iommu_alloc_ctx(iommu->context_map, |
463 | 0, iommu->ncb); | 463 | 0, iommu->ncb); |
464 | if (IS_ERR_VALUE(master->num)) { | 464 | if (IS_ERR_VALUE(master->num)) { |
465 | ret = -ENODEV; | 465 | ret = -ENODEV; |
466 | goto fail; | 466 | goto fail; |
467 | } | 467 | } |
468 | config_mids(iommu, master); | 468 | config_mids(iommu, master); |
469 | __program_context(iommu->base, master->num, | 469 | __program_context(iommu->base, master->num, |
470 | priv); | 470 | priv); |
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index 778498b8633f..62c2c3e8c5df 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h | |||
@@ -19,13 +19,12 @@ | |||
19 | #include <linux/component.h> | 19 | #include <linux/component.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <linux/io-pgtable.h> | ||
22 | #include <linux/iommu.h> | 23 | #include <linux/iommu.h> |
23 | #include <linux/list.h> | 24 | #include <linux/list.h> |
24 | #include <linux/spinlock.h> | 25 | #include <linux/spinlock.h> |
25 | #include <soc/mediatek/smi.h> | 26 | #include <soc/mediatek/smi.h> |
26 | 27 | ||
27 | #include "io-pgtable.h" | ||
28 | |||
29 | struct mtk_iommu_suspend_reg { | 28 | struct mtk_iommu_suspend_reg { |
30 | u32 standard_axi_mode; | 29 | u32 standard_axi_mode; |
31 | u32 dcm_dis; | 30 | u32 dcm_dis; |
diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index d8595f0a987d..8cdd3f059513 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/io.h> | 27 | #include <linux/io.h> |
28 | #include <linux/io-64-nonatomic-hi-lo.h> | 28 | #include <linux/io-64-nonatomic-hi-lo.h> |
29 | #include <linux/io-pgtable.h> | ||
29 | #include <linux/iommu.h> | 30 | #include <linux/iommu.h> |
30 | #include <linux/iopoll.h> | 31 | #include <linux/iopoll.h> |
31 | #include <linux/kconfig.h> | 32 | #include <linux/kconfig.h> |
@@ -42,7 +43,6 @@ | |||
42 | #include <linux/slab.h> | 43 | #include <linux/slab.h> |
43 | #include <linux/spinlock.h> | 44 | #include <linux/spinlock.h> |
44 | 45 | ||
45 | #include "io-pgtable.h" | ||
46 | #include "arm-smmu-regs.h" | 46 | #include "arm-smmu-regs.h" |
47 | 47 | ||
48 | #define SMMU_INTR_SEL_NS 0x2000 | 48 | #define SMMU_INTR_SEL_NS 0x2000 |
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c index da6a4e357b2b..4d8057916552 100644 --- a/drivers/iommu/tegra-gart.c +++ b/drivers/iommu/tegra-gart.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * IOMMU API for GART in Tegra20 | 2 | * IOMMU API for Graphics Address Relocation Table on Tegra20 |
3 | * | 3 | * |
4 | * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. | 4 | * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. |
5 | * | 5 | * |
@@ -19,101 +19,75 @@ | |||
19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) "%s(): " fmt, __func__ | 22 | #define dev_fmt(fmt) "gart: " fmt |
23 | 23 | ||
24 | #include <linux/init.h> | 24 | #include <linux/io.h> |
25 | #include <linux/iommu.h> | ||
25 | #include <linux/moduleparam.h> | 26 | #include <linux/moduleparam.h> |
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/spinlock.h> | ||
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/spinlock.h> | ||
29 | #include <linux/vmalloc.h> | 30 | #include <linux/vmalloc.h> |
30 | #include <linux/mm.h> | ||
31 | #include <linux/list.h> | ||
32 | #include <linux/device.h> | ||
33 | #include <linux/io.h> | ||
34 | #include <linux/iommu.h> | ||
35 | #include <linux/of.h> | ||
36 | |||
37 | #include <asm/cacheflush.h> | ||
38 | 31 | ||
39 | /* bitmap of the page sizes currently supported */ | 32 | #include <soc/tegra/mc.h> |
40 | #define GART_IOMMU_PGSIZES (SZ_4K) | ||
41 | 33 | ||
42 | #define GART_REG_BASE 0x24 | 34 | #define GART_REG_BASE 0x24 |
43 | #define GART_CONFIG (0x24 - GART_REG_BASE) | 35 | #define GART_CONFIG (0x24 - GART_REG_BASE) |
44 | #define GART_ENTRY_ADDR (0x28 - GART_REG_BASE) | 36 | #define GART_ENTRY_ADDR (0x28 - GART_REG_BASE) |
45 | #define GART_ENTRY_DATA (0x2c - GART_REG_BASE) | 37 | #define GART_ENTRY_DATA (0x2c - GART_REG_BASE) |
46 | #define GART_ENTRY_PHYS_ADDR_VALID (1 << 31) | 38 | |
39 | #define GART_ENTRY_PHYS_ADDR_VALID BIT(31) | ||
47 | 40 | ||
48 | #define GART_PAGE_SHIFT 12 | 41 | #define GART_PAGE_SHIFT 12 |
49 | #define GART_PAGE_SIZE (1 << GART_PAGE_SHIFT) | 42 | #define GART_PAGE_SIZE (1 << GART_PAGE_SHIFT) |
50 | #define GART_PAGE_MASK \ | 43 | #define GART_PAGE_MASK GENMASK(30, GART_PAGE_SHIFT) |
51 | (~(GART_PAGE_SIZE - 1) & ~GART_ENTRY_PHYS_ADDR_VALID) | ||
52 | 44 | ||
53 | struct gart_client { | 45 | /* bitmap of the page sizes currently supported */ |
54 | struct device *dev; | 46 | #define GART_IOMMU_PGSIZES (GART_PAGE_SIZE) |
55 | struct list_head list; | ||
56 | }; | ||
57 | 47 | ||
58 | struct gart_device { | 48 | struct gart_device { |
59 | void __iomem *regs; | 49 | void __iomem *regs; |
60 | u32 *savedata; | 50 | u32 *savedata; |
61 | u32 page_count; /* total remappable size */ | 51 | unsigned long iovmm_base; /* offset to vmm_area start */ |
62 | dma_addr_t iovmm_base; /* offset to vmm_area */ | 52 | unsigned long iovmm_end; /* offset to vmm_area end */ |
63 | spinlock_t pte_lock; /* for pagetable */ | 53 | spinlock_t pte_lock; /* for pagetable */ |
64 | struct list_head client; | 54 | spinlock_t dom_lock; /* for active domain */ |
65 | spinlock_t client_lock; /* for client list */ | 55 | unsigned int active_devices; /* number of active devices */ |
66 | struct device *dev; | 56 | struct iommu_domain *active_domain; /* current active domain */ |
67 | |||
68 | struct iommu_device iommu; /* IOMMU Core handle */ | 57 | struct iommu_device iommu; /* IOMMU Core handle */ |
69 | }; | 58 | struct device *dev; |
70 | |||
71 | struct gart_domain { | ||
72 | struct iommu_domain domain; /* generic domain handle */ | ||
73 | struct gart_device *gart; /* link to gart device */ | ||
74 | }; | 59 | }; |
75 | 60 | ||
76 | static struct gart_device *gart_handle; /* unique for a system */ | 61 | static struct gart_device *gart_handle; /* unique for a system */ |
77 | 62 | ||
78 | static bool gart_debug; | 63 | static bool gart_debug; |
79 | 64 | ||
80 | #define GART_PTE(_pfn) \ | ||
81 | (GART_ENTRY_PHYS_ADDR_VALID | ((_pfn) << PAGE_SHIFT)) | ||
82 | |||
83 | static struct gart_domain *to_gart_domain(struct iommu_domain *dom) | ||
84 | { | ||
85 | return container_of(dom, struct gart_domain, domain); | ||
86 | } | ||
87 | |||
88 | /* | 65 | /* |
89 | * Any interaction between any block on PPSB and a block on APB or AHB | 66 | * Any interaction between any block on PPSB and a block on APB or AHB |
90 | * must have these read-back to ensure the APB/AHB bus transaction is | 67 | * must have these read-back to ensure the APB/AHB bus transaction is |
91 | * complete before initiating activity on the PPSB block. | 68 | * complete before initiating activity on the PPSB block. |
92 | */ | 69 | */ |
93 | #define FLUSH_GART_REGS(gart) ((void)readl((gart)->regs + GART_CONFIG)) | 70 | #define FLUSH_GART_REGS(gart) readl_relaxed((gart)->regs + GART_CONFIG) |
94 | 71 | ||
95 | #define for_each_gart_pte(gart, iova) \ | 72 | #define for_each_gart_pte(gart, iova) \ |
96 | for (iova = gart->iovmm_base; \ | 73 | for (iova = gart->iovmm_base; \ |
97 | iova < gart->iovmm_base + GART_PAGE_SIZE * gart->page_count; \ | 74 | iova < gart->iovmm_end; \ |
98 | iova += GART_PAGE_SIZE) | 75 | iova += GART_PAGE_SIZE) |
99 | 76 | ||
100 | static inline void gart_set_pte(struct gart_device *gart, | 77 | static inline void gart_set_pte(struct gart_device *gart, |
101 | unsigned long offs, u32 pte) | 78 | unsigned long iova, unsigned long pte) |
102 | { | 79 | { |
103 | writel(offs, gart->regs + GART_ENTRY_ADDR); | 80 | writel_relaxed(iova, gart->regs + GART_ENTRY_ADDR); |
104 | writel(pte, gart->regs + GART_ENTRY_DATA); | 81 | writel_relaxed(pte, gart->regs + GART_ENTRY_DATA); |
105 | |||
106 | dev_dbg(gart->dev, "%s %08lx:%08x\n", | ||
107 | pte ? "map" : "unmap", offs, pte & GART_PAGE_MASK); | ||
108 | } | 82 | } |
109 | 83 | ||
110 | static inline unsigned long gart_read_pte(struct gart_device *gart, | 84 | static inline unsigned long gart_read_pte(struct gart_device *gart, |
111 | unsigned long offs) | 85 | unsigned long iova) |
112 | { | 86 | { |
113 | unsigned long pte; | 87 | unsigned long pte; |
114 | 88 | ||
115 | writel(offs, gart->regs + GART_ENTRY_ADDR); | 89 | writel_relaxed(iova, gart->regs + GART_ENTRY_ADDR); |
116 | pte = readl(gart->regs + GART_ENTRY_DATA); | 90 | pte = readl_relaxed(gart->regs + GART_ENTRY_DATA); |
117 | 91 | ||
118 | return pte; | 92 | return pte; |
119 | } | 93 | } |
@@ -125,224 +99,155 @@ static void do_gart_setup(struct gart_device *gart, const u32 *data) | |||
125 | for_each_gart_pte(gart, iova) | 99 | for_each_gart_pte(gart, iova) |
126 | gart_set_pte(gart, iova, data ? *(data++) : 0); | 100 | gart_set_pte(gart, iova, data ? *(data++) : 0); |
127 | 101 | ||
128 | writel(1, gart->regs + GART_CONFIG); | 102 | writel_relaxed(1, gart->regs + GART_CONFIG); |
129 | FLUSH_GART_REGS(gart); | 103 | FLUSH_GART_REGS(gart); |
130 | } | 104 | } |
131 | 105 | ||
132 | #ifdef DEBUG | 106 | static inline bool gart_iova_range_invalid(struct gart_device *gart, |
133 | static void gart_dump_table(struct gart_device *gart) | 107 | unsigned long iova, size_t bytes) |
134 | { | ||
135 | unsigned long iova; | ||
136 | unsigned long flags; | ||
137 | |||
138 | spin_lock_irqsave(&gart->pte_lock, flags); | ||
139 | for_each_gart_pte(gart, iova) { | ||
140 | unsigned long pte; | ||
141 | |||
142 | pte = gart_read_pte(gart, iova); | ||
143 | |||
144 | dev_dbg(gart->dev, "%s %08lx:%08lx\n", | ||
145 | (GART_ENTRY_PHYS_ADDR_VALID & pte) ? "v" : " ", | ||
146 | iova, pte & GART_PAGE_MASK); | ||
147 | } | ||
148 | spin_unlock_irqrestore(&gart->pte_lock, flags); | ||
149 | } | ||
150 | #else | ||
151 | static inline void gart_dump_table(struct gart_device *gart) | ||
152 | { | 108 | { |
109 | return unlikely(iova < gart->iovmm_base || bytes != GART_PAGE_SIZE || | ||
110 | iova + bytes > gart->iovmm_end); | ||
153 | } | 111 | } |
154 | #endif | ||
155 | 112 | ||
156 | static inline bool gart_iova_range_valid(struct gart_device *gart, | 113 | static inline bool gart_pte_valid(struct gart_device *gart, unsigned long iova) |
157 | unsigned long iova, size_t bytes) | ||
158 | { | 114 | { |
159 | unsigned long iova_start, iova_end, gart_start, gart_end; | 115 | return !!(gart_read_pte(gart, iova) & GART_ENTRY_PHYS_ADDR_VALID); |
160 | |||
161 | iova_start = iova; | ||
162 | iova_end = iova_start + bytes - 1; | ||
163 | gart_start = gart->iovmm_base; | ||
164 | gart_end = gart_start + gart->page_count * GART_PAGE_SIZE - 1; | ||
165 | |||
166 | if (iova_start < gart_start) | ||
167 | return false; | ||
168 | if (iova_end > gart_end) | ||
169 | return false; | ||
170 | return true; | ||
171 | } | 116 | } |
172 | 117 | ||
173 | static int gart_iommu_attach_dev(struct iommu_domain *domain, | 118 | static int gart_iommu_attach_dev(struct iommu_domain *domain, |
174 | struct device *dev) | 119 | struct device *dev) |
175 | { | 120 | { |
176 | struct gart_domain *gart_domain = to_gart_domain(domain); | 121 | struct gart_device *gart = gart_handle; |
177 | struct gart_device *gart = gart_domain->gart; | 122 | int ret = 0; |
178 | struct gart_client *client, *c; | 123 | |
179 | int err = 0; | 124 | spin_lock(&gart->dom_lock); |
180 | 125 | ||
181 | client = devm_kzalloc(gart->dev, sizeof(*c), GFP_KERNEL); | 126 | if (gart->active_domain && gart->active_domain != domain) { |
182 | if (!client) | 127 | ret = -EBUSY; |
183 | return -ENOMEM; | 128 | } else if (dev->archdata.iommu != domain) { |
184 | client->dev = dev; | 129 | dev->archdata.iommu = domain; |
185 | 130 | gart->active_domain = domain; | |
186 | spin_lock(&gart->client_lock); | 131 | gart->active_devices++; |
187 | list_for_each_entry(c, &gart->client, list) { | ||
188 | if (c->dev == dev) { | ||
189 | dev_err(gart->dev, | ||
190 | "%s is already attached\n", dev_name(dev)); | ||
191 | err = -EINVAL; | ||
192 | goto fail; | ||
193 | } | ||
194 | } | 132 | } |
195 | list_add(&client->list, &gart->client); | ||
196 | spin_unlock(&gart->client_lock); | ||
197 | dev_dbg(gart->dev, "Attached %s\n", dev_name(dev)); | ||
198 | return 0; | ||
199 | 133 | ||
200 | fail: | 134 | spin_unlock(&gart->dom_lock); |
201 | devm_kfree(gart->dev, client); | 135 | |
202 | spin_unlock(&gart->client_lock); | 136 | return ret; |
203 | return err; | ||
204 | } | 137 | } |
205 | 138 | ||
206 | static void gart_iommu_detach_dev(struct iommu_domain *domain, | 139 | static void gart_iommu_detach_dev(struct iommu_domain *domain, |
207 | struct device *dev) | 140 | struct device *dev) |
208 | { | 141 | { |
209 | struct gart_domain *gart_domain = to_gart_domain(domain); | 142 | struct gart_device *gart = gart_handle; |
210 | struct gart_device *gart = gart_domain->gart; | 143 | |
211 | struct gart_client *c; | 144 | spin_lock(&gart->dom_lock); |
212 | 145 | ||
213 | spin_lock(&gart->client_lock); | 146 | if (dev->archdata.iommu == domain) { |
214 | 147 | dev->archdata.iommu = NULL; | |
215 | list_for_each_entry(c, &gart->client, list) { | 148 | |
216 | if (c->dev == dev) { | 149 | if (--gart->active_devices == 0) |
217 | list_del(&c->list); | 150 | gart->active_domain = NULL; |
218 | devm_kfree(gart->dev, c); | ||
219 | dev_dbg(gart->dev, "Detached %s\n", dev_name(dev)); | ||
220 | goto out; | ||
221 | } | ||
222 | } | 151 | } |
223 | dev_err(gart->dev, "Couldn't find\n"); | 152 | |
224 | out: | 153 | spin_unlock(&gart->dom_lock); |
225 | spin_unlock(&gart->client_lock); | ||
226 | } | 154 | } |
227 | 155 | ||
228 | static struct iommu_domain *gart_iommu_domain_alloc(unsigned type) | 156 | static struct iommu_domain *gart_iommu_domain_alloc(unsigned type) |
229 | { | 157 | { |
230 | struct gart_domain *gart_domain; | 158 | struct iommu_domain *domain; |
231 | struct gart_device *gart; | ||
232 | 159 | ||
233 | if (type != IOMMU_DOMAIN_UNMANAGED) | 160 | if (type != IOMMU_DOMAIN_UNMANAGED) |
234 | return NULL; | 161 | return NULL; |
235 | 162 | ||
236 | gart = gart_handle; | 163 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); |
237 | if (!gart) | 164 | if (domain) { |
238 | return NULL; | 165 | domain->geometry.aperture_start = gart_handle->iovmm_base; |
239 | 166 | domain->geometry.aperture_end = gart_handle->iovmm_end - 1; | |
240 | gart_domain = kzalloc(sizeof(*gart_domain), GFP_KERNEL); | 167 | domain->geometry.force_aperture = true; |
241 | if (!gart_domain) | 168 | } |
242 | return NULL; | ||
243 | |||
244 | gart_domain->gart = gart; | ||
245 | gart_domain->domain.geometry.aperture_start = gart->iovmm_base; | ||
246 | gart_domain->domain.geometry.aperture_end = gart->iovmm_base + | ||
247 | gart->page_count * GART_PAGE_SIZE - 1; | ||
248 | gart_domain->domain.geometry.force_aperture = true; | ||
249 | 169 | ||
250 | return &gart_domain->domain; | 170 | return domain; |
251 | } | 171 | } |
252 | 172 | ||
253 | static void gart_iommu_domain_free(struct iommu_domain *domain) | 173 | static void gart_iommu_domain_free(struct iommu_domain *domain) |
254 | { | 174 | { |
255 | struct gart_domain *gart_domain = to_gart_domain(domain); | 175 | WARN_ON(gart_handle->active_domain == domain); |
256 | struct gart_device *gart = gart_domain->gart; | 176 | kfree(domain); |
257 | 177 | } | |
258 | if (gart) { | 178 | |
259 | spin_lock(&gart->client_lock); | 179 | static inline int __gart_iommu_map(struct gart_device *gart, unsigned long iova, |
260 | if (!list_empty(&gart->client)) { | 180 | unsigned long pa) |
261 | struct gart_client *c; | 181 | { |
262 | 182 | if (unlikely(gart_debug && gart_pte_valid(gart, iova))) { | |
263 | list_for_each_entry(c, &gart->client, list) | 183 | dev_err(gart->dev, "Page entry is in-use\n"); |
264 | gart_iommu_detach_dev(domain, c->dev); | 184 | return -EINVAL; |
265 | } | ||
266 | spin_unlock(&gart->client_lock); | ||
267 | } | 185 | } |
268 | 186 | ||
269 | kfree(gart_domain); | 187 | gart_set_pte(gart, iova, GART_ENTRY_PHYS_ADDR_VALID | pa); |
188 | |||
189 | return 0; | ||
270 | } | 190 | } |
271 | 191 | ||
272 | static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova, | 192 | static int gart_iommu_map(struct iommu_domain *domain, unsigned long iova, |
273 | phys_addr_t pa, size_t bytes, int prot) | 193 | phys_addr_t pa, size_t bytes, int prot) |
274 | { | 194 | { |
275 | struct gart_domain *gart_domain = to_gart_domain(domain); | 195 | struct gart_device *gart = gart_handle; |
276 | struct gart_device *gart = gart_domain->gart; | 196 | int ret; |
277 | unsigned long flags; | ||
278 | unsigned long pfn; | ||
279 | unsigned long pte; | ||
280 | 197 | ||
281 | if (!gart_iova_range_valid(gart, iova, bytes)) | 198 | if (gart_iova_range_invalid(gart, iova, bytes)) |
282 | return -EINVAL; | 199 | return -EINVAL; |
283 | 200 | ||
284 | spin_lock_irqsave(&gart->pte_lock, flags); | 201 | spin_lock(&gart->pte_lock); |
285 | pfn = __phys_to_pfn(pa); | 202 | ret = __gart_iommu_map(gart, iova, (unsigned long)pa); |
286 | if (!pfn_valid(pfn)) { | 203 | spin_unlock(&gart->pte_lock); |
287 | dev_err(gart->dev, "Invalid page: %pa\n", &pa); | 204 | |
288 | spin_unlock_irqrestore(&gart->pte_lock, flags); | 205 | return ret; |
206 | } | ||
207 | |||
208 | static inline int __gart_iommu_unmap(struct gart_device *gart, | ||
209 | unsigned long iova) | ||
210 | { | ||
211 | if (unlikely(gart_debug && !gart_pte_valid(gart, iova))) { | ||
212 | dev_err(gart->dev, "Page entry is invalid\n"); | ||
289 | return -EINVAL; | 213 | return -EINVAL; |
290 | } | 214 | } |
291 | if (gart_debug) { | 215 | |
292 | pte = gart_read_pte(gart, iova); | 216 | gart_set_pte(gart, iova, 0); |
293 | if (pte & GART_ENTRY_PHYS_ADDR_VALID) { | 217 | |
294 | spin_unlock_irqrestore(&gart->pte_lock, flags); | ||
295 | dev_err(gart->dev, "Page entry is in-use\n"); | ||
296 | return -EBUSY; | ||
297 | } | ||
298 | } | ||
299 | gart_set_pte(gart, iova, GART_PTE(pfn)); | ||
300 | FLUSH_GART_REGS(gart); | ||
301 | spin_unlock_irqrestore(&gart->pte_lock, flags); | ||
302 | return 0; | 218 | return 0; |
303 | } | 219 | } |
304 | 220 | ||
305 | static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova, | 221 | static size_t gart_iommu_unmap(struct iommu_domain *domain, unsigned long iova, |
306 | size_t bytes) | 222 | size_t bytes) |
307 | { | 223 | { |
308 | struct gart_domain *gart_domain = to_gart_domain(domain); | 224 | struct gart_device *gart = gart_handle; |
309 | struct gart_device *gart = gart_domain->gart; | 225 | int err; |
310 | unsigned long flags; | ||
311 | 226 | ||
312 | if (!gart_iova_range_valid(gart, iova, bytes)) | 227 | if (gart_iova_range_invalid(gart, iova, bytes)) |
313 | return 0; | 228 | return 0; |
314 | 229 | ||
315 | spin_lock_irqsave(&gart->pte_lock, flags); | 230 | spin_lock(&gart->pte_lock); |
316 | gart_set_pte(gart, iova, 0); | 231 | err = __gart_iommu_unmap(gart, iova); |
317 | FLUSH_GART_REGS(gart); | 232 | spin_unlock(&gart->pte_lock); |
318 | spin_unlock_irqrestore(&gart->pte_lock, flags); | 233 | |
319 | return bytes; | 234 | return err ? 0 : bytes; |
320 | } | 235 | } |
321 | 236 | ||
322 | static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain, | 237 | static phys_addr_t gart_iommu_iova_to_phys(struct iommu_domain *domain, |
323 | dma_addr_t iova) | 238 | dma_addr_t iova) |
324 | { | 239 | { |
325 | struct gart_domain *gart_domain = to_gart_domain(domain); | 240 | struct gart_device *gart = gart_handle; |
326 | struct gart_device *gart = gart_domain->gart; | ||
327 | unsigned long pte; | 241 | unsigned long pte; |
328 | phys_addr_t pa; | ||
329 | unsigned long flags; | ||
330 | 242 | ||
331 | if (!gart_iova_range_valid(gart, iova, 0)) | 243 | if (gart_iova_range_invalid(gart, iova, GART_PAGE_SIZE)) |
332 | return -EINVAL; | 244 | return -EINVAL; |
333 | 245 | ||
334 | spin_lock_irqsave(&gart->pte_lock, flags); | 246 | spin_lock(&gart->pte_lock); |
335 | pte = gart_read_pte(gart, iova); | 247 | pte = gart_read_pte(gart, iova); |
336 | spin_unlock_irqrestore(&gart->pte_lock, flags); | 248 | spin_unlock(&gart->pte_lock); |
337 | 249 | ||
338 | pa = (pte & GART_PAGE_MASK); | 250 | return pte & GART_PAGE_MASK; |
339 | if (!pfn_valid(__phys_to_pfn(pa))) { | ||
340 | dev_err(gart->dev, "No entry for %08llx:%pa\n", | ||
341 | (unsigned long long)iova, &pa); | ||
342 | gart_dump_table(gart); | ||
343 | return -EINVAL; | ||
344 | } | ||
345 | return pa; | ||
346 | } | 251 | } |
347 | 252 | ||
348 | static bool gart_iommu_capable(enum iommu_cap cap) | 253 | static bool gart_iommu_capable(enum iommu_cap cap) |
@@ -352,8 +257,12 @@ static bool gart_iommu_capable(enum iommu_cap cap) | |||
352 | 257 | ||
353 | static int gart_iommu_add_device(struct device *dev) | 258 | static int gart_iommu_add_device(struct device *dev) |
354 | { | 259 | { |
355 | struct iommu_group *group = iommu_group_get_for_dev(dev); | 260 | struct iommu_group *group; |
261 | |||
262 | if (!dev->iommu_fwspec) | ||
263 | return -ENODEV; | ||
356 | 264 | ||
265 | group = iommu_group_get_for_dev(dev); | ||
357 | if (IS_ERR(group)) | 266 | if (IS_ERR(group)) |
358 | return PTR_ERR(group); | 267 | return PTR_ERR(group); |
359 | 268 | ||
@@ -370,6 +279,17 @@ static void gart_iommu_remove_device(struct device *dev) | |||
370 | iommu_device_unlink(&gart_handle->iommu, dev); | 279 | iommu_device_unlink(&gart_handle->iommu, dev); |
371 | } | 280 | } |
372 | 281 | ||
282 | static int gart_iommu_of_xlate(struct device *dev, | ||
283 | struct of_phandle_args *args) | ||
284 | { | ||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static void gart_iommu_sync(struct iommu_domain *domain) | ||
289 | { | ||
290 | FLUSH_GART_REGS(gart_handle); | ||
291 | } | ||
292 | |||
373 | static const struct iommu_ops gart_iommu_ops = { | 293 | static const struct iommu_ops gart_iommu_ops = { |
374 | .capable = gart_iommu_capable, | 294 | .capable = gart_iommu_capable, |
375 | .domain_alloc = gart_iommu_domain_alloc, | 295 | .domain_alloc = gart_iommu_domain_alloc, |
@@ -383,129 +303,96 @@ static const struct iommu_ops gart_iommu_ops = { | |||
383 | .unmap = gart_iommu_unmap, | 303 | .unmap = gart_iommu_unmap, |
384 | .iova_to_phys = gart_iommu_iova_to_phys, | 304 | .iova_to_phys = gart_iommu_iova_to_phys, |
385 | .pgsize_bitmap = GART_IOMMU_PGSIZES, | 305 | .pgsize_bitmap = GART_IOMMU_PGSIZES, |
306 | .of_xlate = gart_iommu_of_xlate, | ||
307 | .iotlb_sync_map = gart_iommu_sync, | ||
308 | .iotlb_sync = gart_iommu_sync, | ||
386 | }; | 309 | }; |
387 | 310 | ||
388 | static int tegra_gart_suspend(struct device *dev) | 311 | int tegra_gart_suspend(struct gart_device *gart) |
389 | { | 312 | { |
390 | struct gart_device *gart = dev_get_drvdata(dev); | ||
391 | unsigned long iova; | ||
392 | u32 *data = gart->savedata; | 313 | u32 *data = gart->savedata; |
393 | unsigned long flags; | 314 | unsigned long iova; |
315 | |||
316 | /* | ||
317 | * All GART users shall be suspended at this point. Disable | ||
318 | * address translation to trap all GART accesses as invalid | ||
319 | * memory accesses. | ||
320 | */ | ||
321 | writel_relaxed(0, gart->regs + GART_CONFIG); | ||
322 | FLUSH_GART_REGS(gart); | ||
394 | 323 | ||
395 | spin_lock_irqsave(&gart->pte_lock, flags); | ||
396 | for_each_gart_pte(gart, iova) | 324 | for_each_gart_pte(gart, iova) |
397 | *(data++) = gart_read_pte(gart, iova); | 325 | *(data++) = gart_read_pte(gart, iova); |
398 | spin_unlock_irqrestore(&gart->pte_lock, flags); | 326 | |
399 | return 0; | 327 | return 0; |
400 | } | 328 | } |
401 | 329 | ||
402 | static int tegra_gart_resume(struct device *dev) | 330 | int tegra_gart_resume(struct gart_device *gart) |
403 | { | 331 | { |
404 | struct gart_device *gart = dev_get_drvdata(dev); | ||
405 | unsigned long flags; | ||
406 | |||
407 | spin_lock_irqsave(&gart->pte_lock, flags); | ||
408 | do_gart_setup(gart, gart->savedata); | 332 | do_gart_setup(gart, gart->savedata); |
409 | spin_unlock_irqrestore(&gart->pte_lock, flags); | 333 | |
410 | return 0; | 334 | return 0; |
411 | } | 335 | } |
412 | 336 | ||
413 | static int tegra_gart_probe(struct platform_device *pdev) | 337 | struct gart_device *tegra_gart_probe(struct device *dev, struct tegra_mc *mc) |
414 | { | 338 | { |
415 | struct gart_device *gart; | 339 | struct gart_device *gart; |
416 | struct resource *res, *res_remap; | 340 | struct resource *res; |
417 | void __iomem *gart_regs; | 341 | int err; |
418 | struct device *dev = &pdev->dev; | ||
419 | int ret; | ||
420 | |||
421 | if (gart_handle) | ||
422 | return -EIO; | ||
423 | 342 | ||
424 | BUILD_BUG_ON(PAGE_SHIFT != GART_PAGE_SHIFT); | 343 | BUILD_BUG_ON(PAGE_SHIFT != GART_PAGE_SHIFT); |
425 | 344 | ||
426 | /* the GART memory aperture is required */ | 345 | /* the GART memory aperture is required */ |
427 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 346 | res = platform_get_resource(to_platform_device(dev), IORESOURCE_MEM, 1); |
428 | res_remap = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 347 | if (!res) { |
429 | if (!res || !res_remap) { | 348 | dev_err(dev, "Memory aperture resource unavailable\n"); |
430 | dev_err(dev, "GART memory aperture expected\n"); | 349 | return ERR_PTR(-ENXIO); |
431 | return -ENXIO; | ||
432 | } | ||
433 | |||
434 | gart = devm_kzalloc(dev, sizeof(*gart), GFP_KERNEL); | ||
435 | if (!gart) { | ||
436 | dev_err(dev, "failed to allocate gart_device\n"); | ||
437 | return -ENOMEM; | ||
438 | } | 350 | } |
439 | 351 | ||
440 | gart_regs = devm_ioremap(dev, res->start, resource_size(res)); | 352 | gart = kzalloc(sizeof(*gart), GFP_KERNEL); |
441 | if (!gart_regs) { | 353 | if (!gart) |
442 | dev_err(dev, "failed to remap GART registers\n"); | 354 | return ERR_PTR(-ENOMEM); |
443 | return -ENXIO; | ||
444 | } | ||
445 | |||
446 | ret = iommu_device_sysfs_add(&gart->iommu, &pdev->dev, NULL, | ||
447 | dev_name(&pdev->dev)); | ||
448 | if (ret) { | ||
449 | dev_err(dev, "Failed to register IOMMU in sysfs\n"); | ||
450 | return ret; | ||
451 | } | ||
452 | |||
453 | iommu_device_set_ops(&gart->iommu, &gart_iommu_ops); | ||
454 | 355 | ||
455 | ret = iommu_device_register(&gart->iommu); | 356 | gart_handle = gart; |
456 | if (ret) { | ||
457 | dev_err(dev, "Failed to register IOMMU\n"); | ||
458 | iommu_device_sysfs_remove(&gart->iommu); | ||
459 | return ret; | ||
460 | } | ||
461 | 357 | ||
462 | gart->dev = &pdev->dev; | 358 | gart->dev = dev; |
359 | gart->regs = mc->regs + GART_REG_BASE; | ||
360 | gart->iovmm_base = res->start; | ||
361 | gart->iovmm_end = res->end + 1; | ||
463 | spin_lock_init(&gart->pte_lock); | 362 | spin_lock_init(&gart->pte_lock); |
464 | spin_lock_init(&gart->client_lock); | 363 | spin_lock_init(&gart->dom_lock); |
465 | INIT_LIST_HEAD(&gart->client); | ||
466 | gart->regs = gart_regs; | ||
467 | gart->iovmm_base = (dma_addr_t)res_remap->start; | ||
468 | gart->page_count = (resource_size(res_remap) >> GART_PAGE_SHIFT); | ||
469 | |||
470 | gart->savedata = vmalloc(array_size(sizeof(u32), gart->page_count)); | ||
471 | if (!gart->savedata) { | ||
472 | dev_err(dev, "failed to allocate context save area\n"); | ||
473 | return -ENOMEM; | ||
474 | } | ||
475 | 364 | ||
476 | platform_set_drvdata(pdev, gart); | ||
477 | do_gart_setup(gart, NULL); | 365 | do_gart_setup(gart, NULL); |
478 | 366 | ||
479 | gart_handle = gart; | 367 | err = iommu_device_sysfs_add(&gart->iommu, dev, NULL, "gart"); |
368 | if (err) | ||
369 | goto free_gart; | ||
480 | 370 | ||
481 | return 0; | 371 | iommu_device_set_ops(&gart->iommu, &gart_iommu_ops); |
482 | } | 372 | iommu_device_set_fwnode(&gart->iommu, dev->fwnode); |
483 | 373 | ||
484 | static const struct dev_pm_ops tegra_gart_pm_ops = { | 374 | err = iommu_device_register(&gart->iommu); |
485 | .suspend = tegra_gart_suspend, | 375 | if (err) |
486 | .resume = tegra_gart_resume, | 376 | goto remove_sysfs; |
487 | }; | ||
488 | 377 | ||
489 | static const struct of_device_id tegra_gart_of_match[] = { | 378 | gart->savedata = vmalloc(resource_size(res) / GART_PAGE_SIZE * |
490 | { .compatible = "nvidia,tegra20-gart", }, | 379 | sizeof(u32)); |
491 | { }, | 380 | if (!gart->savedata) { |
492 | }; | 381 | err = -ENOMEM; |
382 | goto unregister_iommu; | ||
383 | } | ||
493 | 384 | ||
494 | static struct platform_driver tegra_gart_driver = { | 385 | return gart; |
495 | .probe = tegra_gart_probe, | ||
496 | .driver = { | ||
497 | .name = "tegra-gart", | ||
498 | .pm = &tegra_gart_pm_ops, | ||
499 | .of_match_table = tegra_gart_of_match, | ||
500 | .suppress_bind_attrs = true, | ||
501 | }, | ||
502 | }; | ||
503 | 386 | ||
504 | static int __init tegra_gart_init(void) | 387 | unregister_iommu: |
505 | { | 388 | iommu_device_unregister(&gart->iommu); |
506 | return platform_driver_register(&tegra_gart_driver); | 389 | remove_sysfs: |
390 | iommu_device_sysfs_remove(&gart->iommu); | ||
391 | free_gart: | ||
392 | kfree(gart); | ||
393 | |||
394 | return ERR_PTR(err); | ||
507 | } | 395 | } |
508 | subsys_initcall(tegra_gart_init); | ||
509 | 396 | ||
510 | module_param(gart_debug, bool, 0644); | 397 | module_param(gart_debug, bool, 0644); |
511 | MODULE_PARM_DESC(gart_debug, "Enable GART debugging"); | 398 | MODULE_PARM_DESC(gart_debug, "Enable GART debugging"); |
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 3a5c7dc6dc57..5182c7d6171e 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c | |||
@@ -982,10 +982,6 @@ struct tegra_smmu *tegra_smmu_probe(struct device *dev, | |||
982 | u32 value; | 982 | u32 value; |
983 | int err; | 983 | int err; |
984 | 984 | ||
985 | /* This can happen on Tegra20 which doesn't have an SMMU */ | ||
986 | if (!soc) | ||
987 | return NULL; | ||
988 | |||
989 | smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); | 985 | smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL); |
990 | if (!smmu) | 986 | if (!smmu) |
991 | return ERR_PTR(-ENOMEM); | 987 | return ERR_PTR(-ENOMEM); |
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c index 24afc36833bf..0a53598d982f 100644 --- a/drivers/memory/tegra/mc.c +++ b/drivers/memory/tegra/mc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_device.h> | ||
15 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
16 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
17 | #include <linux/sort.h> | 18 | #include <linux/sort.h> |
@@ -38,6 +39,7 @@ | |||
38 | 39 | ||
39 | #define MC_ERR_ADR 0x0c | 40 | #define MC_ERR_ADR 0x0c |
40 | 41 | ||
42 | #define MC_GART_ERROR_REQ 0x30 | ||
41 | #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 | 43 | #define MC_DECERR_EMEM_OTHERS_STATUS 0x58 |
42 | #define MC_SECURITY_VIOLATION_STATUS 0x74 | 44 | #define MC_SECURITY_VIOLATION_STATUS 0x74 |
43 | 45 | ||
@@ -51,7 +53,7 @@ | |||
51 | 53 | ||
52 | static const struct of_device_id tegra_mc_of_match[] = { | 54 | static const struct of_device_id tegra_mc_of_match[] = { |
53 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | 55 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
54 | { .compatible = "nvidia,tegra20-mc", .data = &tegra20_mc_soc }, | 56 | { .compatible = "nvidia,tegra20-mc-gart", .data = &tegra20_mc_soc }, |
55 | #endif | 57 | #endif |
56 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC | 58 | #ifdef CONFIG_ARCH_TEGRA_3x_SOC |
57 | { .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc }, | 59 | { .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc }, |
@@ -161,7 +163,7 @@ static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev, | |||
161 | /* block clients DMA requests */ | 163 | /* block clients DMA requests */ |
162 | err = rst_ops->block_dma(mc, rst); | 164 | err = rst_ops->block_dma(mc, rst); |
163 | if (err) { | 165 | if (err) { |
164 | dev_err(mc->dev, "Failed to block %s DMA: %d\n", | 166 | dev_err(mc->dev, "failed to block %s DMA: %d\n", |
165 | rst->name, err); | 167 | rst->name, err); |
166 | return err; | 168 | return err; |
167 | } | 169 | } |
@@ -171,7 +173,7 @@ static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev, | |||
171 | /* wait for completion of the outstanding DMA requests */ | 173 | /* wait for completion of the outstanding DMA requests */ |
172 | while (!rst_ops->dma_idling(mc, rst)) { | 174 | while (!rst_ops->dma_idling(mc, rst)) { |
173 | if (!retries--) { | 175 | if (!retries--) { |
174 | dev_err(mc->dev, "Failed to flush %s DMA\n", | 176 | dev_err(mc->dev, "failed to flush %s DMA\n", |
175 | rst->name); | 177 | rst->name); |
176 | return -EBUSY; | 178 | return -EBUSY; |
177 | } | 179 | } |
@@ -184,7 +186,7 @@ static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev, | |||
184 | /* clear clients DMA requests sitting before arbitration */ | 186 | /* clear clients DMA requests sitting before arbitration */ |
185 | err = rst_ops->hotreset_assert(mc, rst); | 187 | err = rst_ops->hotreset_assert(mc, rst); |
186 | if (err) { | 188 | if (err) { |
187 | dev_err(mc->dev, "Failed to hot reset %s: %d\n", | 189 | dev_err(mc->dev, "failed to hot reset %s: %d\n", |
188 | rst->name, err); | 190 | rst->name, err); |
189 | return err; | 191 | return err; |
190 | } | 192 | } |
@@ -213,7 +215,7 @@ static int tegra_mc_hotreset_deassert(struct reset_controller_dev *rcdev, | |||
213 | /* take out client from hot reset */ | 215 | /* take out client from hot reset */ |
214 | err = rst_ops->hotreset_deassert(mc, rst); | 216 | err = rst_ops->hotreset_deassert(mc, rst); |
215 | if (err) { | 217 | if (err) { |
216 | dev_err(mc->dev, "Failed to deassert hot reset %s: %d\n", | 218 | dev_err(mc->dev, "failed to deassert hot reset %s: %d\n", |
217 | rst->name, err); | 219 | rst->name, err); |
218 | return err; | 220 | return err; |
219 | } | 221 | } |
@@ -223,7 +225,7 @@ static int tegra_mc_hotreset_deassert(struct reset_controller_dev *rcdev, | |||
223 | /* allow new DMA requests to proceed to arbitration */ | 225 | /* allow new DMA requests to proceed to arbitration */ |
224 | err = rst_ops->unblock_dma(mc, rst); | 226 | err = rst_ops->unblock_dma(mc, rst); |
225 | if (err) { | 227 | if (err) { |
226 | dev_err(mc->dev, "Failed to unblock %s DMA : %d\n", | 228 | dev_err(mc->dev, "failed to unblock %s DMA : %d\n", |
227 | rst->name, err); | 229 | rst->name, err); |
228 | return err; | 230 | return err; |
229 | } | 231 | } |
@@ -575,8 +577,15 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data) | |||
575 | break; | 577 | break; |
576 | 578 | ||
577 | case MC_INT_INVALID_GART_PAGE: | 579 | case MC_INT_INVALID_GART_PAGE: |
578 | dev_err_ratelimited(mc->dev, "%s\n", error); | 580 | reg = MC_GART_ERROR_REQ; |
579 | continue; | 581 | value = mc_readl(mc, reg); |
582 | |||
583 | id = (value >> 1) & mc->soc->client_id_mask; | ||
584 | desc = error_names[2]; | ||
585 | |||
586 | if (value & BIT(0)) | ||
587 | direction = "write"; | ||
588 | break; | ||
580 | 589 | ||
581 | case MC_INT_SECURITY_VIOLATION: | 590 | case MC_INT_SECURITY_VIOLATION: |
582 | reg = MC_SECURITY_VIOLATION_STATUS; | 591 | reg = MC_SECURITY_VIOLATION_STATUS; |
@@ -611,23 +620,18 @@ static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data) | |||
611 | 620 | ||
612 | static int tegra_mc_probe(struct platform_device *pdev) | 621 | static int tegra_mc_probe(struct platform_device *pdev) |
613 | { | 622 | { |
614 | const struct of_device_id *match; | ||
615 | struct resource *res; | 623 | struct resource *res; |
616 | struct tegra_mc *mc; | 624 | struct tegra_mc *mc; |
617 | void *isr; | 625 | void *isr; |
618 | int err; | 626 | int err; |
619 | 627 | ||
620 | match = of_match_node(tegra_mc_of_match, pdev->dev.of_node); | ||
621 | if (!match) | ||
622 | return -ENODEV; | ||
623 | |||
624 | mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); | 628 | mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); |
625 | if (!mc) | 629 | if (!mc) |
626 | return -ENOMEM; | 630 | return -ENOMEM; |
627 | 631 | ||
628 | platform_set_drvdata(pdev, mc); | 632 | platform_set_drvdata(pdev, mc); |
629 | spin_lock_init(&mc->lock); | 633 | spin_lock_init(&mc->lock); |
630 | mc->soc = match->data; | 634 | mc->soc = of_device_get_match_data(&pdev->dev); |
631 | mc->dev = &pdev->dev; | 635 | mc->dev = &pdev->dev; |
632 | 636 | ||
633 | /* length of MC tick in nanoseconds */ | 637 | /* length of MC tick in nanoseconds */ |
@@ -638,38 +642,35 @@ static int tegra_mc_probe(struct platform_device *pdev) | |||
638 | if (IS_ERR(mc->regs)) | 642 | if (IS_ERR(mc->regs)) |
639 | return PTR_ERR(mc->regs); | 643 | return PTR_ERR(mc->regs); |
640 | 644 | ||
645 | mc->clk = devm_clk_get(&pdev->dev, "mc"); | ||
646 | if (IS_ERR(mc->clk)) { | ||
647 | dev_err(&pdev->dev, "failed to get MC clock: %ld\n", | ||
648 | PTR_ERR(mc->clk)); | ||
649 | return PTR_ERR(mc->clk); | ||
650 | } | ||
651 | |||
641 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | 652 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC |
642 | if (mc->soc == &tegra20_mc_soc) { | 653 | if (mc->soc == &tegra20_mc_soc) { |
643 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
644 | mc->regs2 = devm_ioremap_resource(&pdev->dev, res); | ||
645 | if (IS_ERR(mc->regs2)) | ||
646 | return PTR_ERR(mc->regs2); | ||
647 | |||
648 | isr = tegra20_mc_irq; | 654 | isr = tegra20_mc_irq; |
649 | } else | 655 | } else |
650 | #endif | 656 | #endif |
651 | { | 657 | { |
652 | mc->clk = devm_clk_get(&pdev->dev, "mc"); | ||
653 | if (IS_ERR(mc->clk)) { | ||
654 | dev_err(&pdev->dev, "failed to get MC clock: %ld\n", | ||
655 | PTR_ERR(mc->clk)); | ||
656 | return PTR_ERR(mc->clk); | ||
657 | } | ||
658 | |||
659 | err = tegra_mc_setup_latency_allowance(mc); | 658 | err = tegra_mc_setup_latency_allowance(mc); |
660 | if (err < 0) { | 659 | if (err < 0) { |
661 | dev_err(&pdev->dev, "failed to setup latency allowance: %d\n", | 660 | dev_err(&pdev->dev, |
661 | "failed to setup latency allowance: %d\n", | ||
662 | err); | 662 | err); |
663 | return err; | 663 | return err; |
664 | } | 664 | } |
665 | 665 | ||
666 | isr = tegra_mc_irq; | 666 | isr = tegra_mc_irq; |
667 | } | ||
668 | 667 | ||
669 | err = tegra_mc_setup_timings(mc); | 668 | err = tegra_mc_setup_timings(mc); |
670 | if (err < 0) { | 669 | if (err < 0) { |
671 | dev_err(&pdev->dev, "failed to setup timings: %d\n", err); | 670 | dev_err(&pdev->dev, "failed to setup timings: %d\n", |
672 | return err; | 671 | err); |
672 | return err; | ||
673 | } | ||
673 | } | 674 | } |
674 | 675 | ||
675 | mc->irq = platform_get_irq(pdev, 0); | 676 | mc->irq = platform_get_irq(pdev, 0); |
@@ -678,11 +679,11 @@ static int tegra_mc_probe(struct platform_device *pdev) | |||
678 | return mc->irq; | 679 | return mc->irq; |
679 | } | 680 | } |
680 | 681 | ||
681 | WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n"); | 682 | WARN(!mc->soc->client_id_mask, "missing client ID mask for this SoC\n"); |
682 | 683 | ||
683 | mc_writel(mc, mc->soc->intmask, MC_INTMASK); | 684 | mc_writel(mc, mc->soc->intmask, MC_INTMASK); |
684 | 685 | ||
685 | err = devm_request_irq(&pdev->dev, mc->irq, isr, IRQF_SHARED, | 686 | err = devm_request_irq(&pdev->dev, mc->irq, isr, 0, |
686 | dev_name(&pdev->dev), mc); | 687 | dev_name(&pdev->dev), mc); |
687 | if (err < 0) { | 688 | if (err < 0) { |
688 | dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq, | 689 | dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq, |
@@ -695,20 +696,65 @@ static int tegra_mc_probe(struct platform_device *pdev) | |||
695 | dev_err(&pdev->dev, "failed to register reset controller: %d\n", | 696 | dev_err(&pdev->dev, "failed to register reset controller: %d\n", |
696 | err); | 697 | err); |
697 | 698 | ||
698 | if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) { | 699 | if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU) && mc->soc->smmu) { |
699 | mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc); | 700 | mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc); |
700 | if (IS_ERR(mc->smmu)) | 701 | if (IS_ERR(mc->smmu)) { |
701 | dev_err(&pdev->dev, "failed to probe SMMU: %ld\n", | 702 | dev_err(&pdev->dev, "failed to probe SMMU: %ld\n", |
702 | PTR_ERR(mc->smmu)); | 703 | PTR_ERR(mc->smmu)); |
704 | mc->smmu = NULL; | ||
705 | } | ||
706 | } | ||
707 | |||
708 | if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && !mc->soc->smmu) { | ||
709 | mc->gart = tegra_gart_probe(&pdev->dev, mc); | ||
710 | if (IS_ERR(mc->gart)) { | ||
711 | dev_err(&pdev->dev, "failed to probe GART: %ld\n", | ||
712 | PTR_ERR(mc->gart)); | ||
713 | mc->gart = NULL; | ||
714 | } | ||
715 | } | ||
716 | |||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | static int tegra_mc_suspend(struct device *dev) | ||
721 | { | ||
722 | struct tegra_mc *mc = dev_get_drvdata(dev); | ||
723 | int err; | ||
724 | |||
725 | if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && mc->gart) { | ||
726 | err = tegra_gart_suspend(mc->gart); | ||
727 | if (err) | ||
728 | return err; | ||
703 | } | 729 | } |
704 | 730 | ||
705 | return 0; | 731 | return 0; |
706 | } | 732 | } |
707 | 733 | ||
734 | static int tegra_mc_resume(struct device *dev) | ||
735 | { | ||
736 | struct tegra_mc *mc = dev_get_drvdata(dev); | ||
737 | int err; | ||
738 | |||
739 | if (IS_ENABLED(CONFIG_TEGRA_IOMMU_GART) && mc->gart) { | ||
740 | err = tegra_gart_resume(mc->gart); | ||
741 | if (err) | ||
742 | return err; | ||
743 | } | ||
744 | |||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | static const struct dev_pm_ops tegra_mc_pm_ops = { | ||
749 | .suspend = tegra_mc_suspend, | ||
750 | .resume = tegra_mc_resume, | ||
751 | }; | ||
752 | |||
708 | static struct platform_driver tegra_mc_driver = { | 753 | static struct platform_driver tegra_mc_driver = { |
709 | .driver = { | 754 | .driver = { |
710 | .name = "tegra-mc", | 755 | .name = "tegra-mc", |
711 | .of_match_table = tegra_mc_of_match, | 756 | .of_match_table = tegra_mc_of_match, |
757 | .pm = &tegra_mc_pm_ops, | ||
712 | .suppress_bind_attrs = true, | 758 | .suppress_bind_attrs = true, |
713 | }, | 759 | }, |
714 | .prevent_deferred_probe = true, | 760 | .prevent_deferred_probe = true, |
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h index 01065f12ebeb..887a3b07334f 100644 --- a/drivers/memory/tegra/mc.h +++ b/drivers/memory/tegra/mc.h | |||
@@ -26,19 +26,13 @@ | |||
26 | 26 | ||
27 | static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset) | 27 | static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset) |
28 | { | 28 | { |
29 | if (mc->regs2 && offset >= 0x24) | 29 | return readl_relaxed(mc->regs + offset); |
30 | return readl(mc->regs2 + offset - 0x3c); | ||
31 | |||
32 | return readl(mc->regs + offset); | ||
33 | } | 30 | } |
34 | 31 | ||
35 | static inline void mc_writel(struct tegra_mc *mc, u32 value, | 32 | static inline void mc_writel(struct tegra_mc *mc, u32 value, |
36 | unsigned long offset) | 33 | unsigned long offset) |
37 | { | 34 | { |
38 | if (mc->regs2 && offset >= 0x24) | 35 | writel_relaxed(value, mc->regs + offset); |
39 | return writel(value, mc->regs2 + offset - 0x3c); | ||
40 | |||
41 | writel(value, mc->regs + offset); | ||
42 | } | 36 | } |
43 | 37 | ||
44 | extern const struct tegra_mc_reset_ops terga_mc_reset_ops_common; | 38 | extern const struct tegra_mc_reset_ops terga_mc_reset_ops_common; |
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 5b78f3b1b918..97c08146534a 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c | |||
@@ -142,6 +142,33 @@ int pci_ats_queue_depth(struct pci_dev *dev) | |||
142 | } | 142 | } |
143 | EXPORT_SYMBOL_GPL(pci_ats_queue_depth); | 143 | EXPORT_SYMBOL_GPL(pci_ats_queue_depth); |
144 | 144 | ||
145 | /** | ||
146 | * pci_ats_page_aligned - Return Page Aligned Request bit status. | ||
147 | * @pdev: the PCI device | ||
148 | * | ||
149 | * Returns 1, if the Untranslated Addresses generated by the device | ||
150 | * are always aligned or 0 otherwise. | ||
151 | * | ||
152 | * Per PCIe spec r4.0, sec 10.5.1.2, if the Page Aligned Request bit | ||
153 | * is set, it indicates the Untranslated Addresses generated by the | ||
154 | * device are always aligned to a 4096 byte boundary. | ||
155 | */ | ||
156 | int pci_ats_page_aligned(struct pci_dev *pdev) | ||
157 | { | ||
158 | u16 cap; | ||
159 | |||
160 | if (!pdev->ats_cap) | ||
161 | return 0; | ||
162 | |||
163 | pci_read_config_word(pdev, pdev->ats_cap + PCI_ATS_CAP, &cap); | ||
164 | |||
165 | if (cap & PCI_ATS_CAP_PAGE_ALIGNED) | ||
166 | return 1; | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(pci_ats_page_aligned); | ||
171 | |||
145 | #ifdef CONFIG_PCI_PRI | 172 | #ifdef CONFIG_PCI_PRI |
146 | /** | 173 | /** |
147 | * pci_enable_pri - Enable PRI capability | 174 | * pci_enable_pri - Enable PRI capability |
@@ -368,6 +395,36 @@ int pci_pasid_features(struct pci_dev *pdev) | |||
368 | } | 395 | } |
369 | EXPORT_SYMBOL_GPL(pci_pasid_features); | 396 | EXPORT_SYMBOL_GPL(pci_pasid_features); |
370 | 397 | ||
398 | /** | ||
399 | * pci_prg_resp_pasid_required - Return PRG Response PASID Required bit | ||
400 | * status. | ||
401 | * @pdev: PCI device structure | ||
402 | * | ||
403 | * Returns 1 if PASID is required in PRG Response Message, 0 otherwise. | ||
404 | * | ||
405 | * Even though the PRG response PASID status is read from PRI Status | ||
406 | * Register, since this API will mainly be used by PASID users, this | ||
407 | * function is defined within #ifdef CONFIG_PCI_PASID instead of | ||
408 | * CONFIG_PCI_PRI. | ||
409 | */ | ||
410 | int pci_prg_resp_pasid_required(struct pci_dev *pdev) | ||
411 | { | ||
412 | u16 status; | ||
413 | int pos; | ||
414 | |||
415 | pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); | ||
416 | if (!pos) | ||
417 | return 0; | ||
418 | |||
419 | pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); | ||
420 | |||
421 | if (status & PCI_PRI_STATUS_PASID) | ||
422 | return 1; | ||
423 | |||
424 | return 0; | ||
425 | } | ||
426 | EXPORT_SYMBOL_GPL(pci_prg_resp_pasid_required); | ||
427 | |||
371 | #define PASID_NUMBER_SHIFT 8 | 428 | #define PASID_NUMBER_SHIFT 8 |
372 | #define PASID_NUMBER_MASK (0x1f << PASID_NUMBER_SHIFT) | 429 | #define PASID_NUMBER_MASK (0x1f << PASID_NUMBER_SHIFT) |
373 | /** | 430 | /** |
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 0605f3bf6e79..fa364de9db18 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
@@ -374,20 +374,17 @@ enum { | |||
374 | #define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52)) | 374 | #define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52)) |
375 | #define QI_DEV_EIOTLB_MAX_INVS 32 | 375 | #define QI_DEV_EIOTLB_MAX_INVS 32 |
376 | 376 | ||
377 | #define QI_PGRP_IDX(idx) (((u64)(idx)) << 55) | 377 | /* Page group response descriptor QW0 */ |
378 | #define QI_PGRP_PRIV(priv) (((u64)(priv)) << 32) | ||
379 | #define QI_PGRP_RESP_CODE(res) ((u64)(res)) | ||
380 | #define QI_PGRP_PASID(pasid) (((u64)(pasid)) << 32) | ||
381 | #define QI_PGRP_DID(did) (((u64)(did)) << 16) | ||
382 | #define QI_PGRP_PASID_P(p) (((u64)(p)) << 4) | 378 | #define QI_PGRP_PASID_P(p) (((u64)(p)) << 4) |
379 | #define QI_PGRP_PDP(p) (((u64)(p)) << 5) | ||
380 | #define QI_PGRP_RESP_CODE(res) (((u64)(res)) << 12) | ||
381 | #define QI_PGRP_DID(rid) (((u64)(rid)) << 16) | ||
382 | #define QI_PGRP_PASID(pasid) (((u64)(pasid)) << 32) | ||
383 | |||
384 | /* Page group response descriptor QW1 */ | ||
385 | #define QI_PGRP_LPIG(x) (((u64)(x)) << 2) | ||
386 | #define QI_PGRP_IDX(idx) (((u64)(idx)) << 3) | ||
383 | 387 | ||
384 | #define QI_PSTRM_ADDR(addr) (((u64)(addr)) & VTD_PAGE_MASK) | ||
385 | #define QI_PSTRM_DEVFN(devfn) (((u64)(devfn)) << 4) | ||
386 | #define QI_PSTRM_RESP_CODE(res) ((u64)(res)) | ||
387 | #define QI_PSTRM_IDX(idx) (((u64)(idx)) << 55) | ||
388 | #define QI_PSTRM_PRIV(priv) (((u64)(priv)) << 32) | ||
389 | #define QI_PSTRM_BUS(bus) (((u64)(bus)) << 24) | ||
390 | #define QI_PSTRM_PASID(pasid) (((u64)(pasid)) << 4) | ||
391 | 388 | ||
392 | #define QI_RESP_SUCCESS 0x0 | 389 | #define QI_RESP_SUCCESS 0x0 |
393 | #define QI_RESP_INVALID 0x1 | 390 | #define QI_RESP_INVALID 0x1 |
diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h index 99bc5b3ae26e..e3f76315ca4d 100644 --- a/include/linux/intel-svm.h +++ b/include/linux/intel-svm.h | |||
@@ -20,7 +20,7 @@ struct device; | |||
20 | 20 | ||
21 | struct svm_dev_ops { | 21 | struct svm_dev_ops { |
22 | void (*fault_cb)(struct device *dev, int pasid, u64 address, | 22 | void (*fault_cb)(struct device *dev, int pasid, u64 address, |
23 | u32 private, int rwxp, int response); | 23 | void *private, int rwxp, int response); |
24 | }; | 24 | }; |
25 | 25 | ||
26 | /* Values for rxwp in fault_cb callback */ | 26 | /* Values for rxwp in fault_cb callback */ |
diff --git a/drivers/iommu/io-pgtable.h b/include/linux/io-pgtable.h index 47d5ae559329..47d5ae559329 100644 --- a/drivers/iommu/io-pgtable.h +++ b/include/linux/io-pgtable.h | |||
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index e90da6b6f3d1..ffbbc7e39cee 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
@@ -167,8 +167,9 @@ struct iommu_resv_region { | |||
167 | * @detach_dev: detach device from an iommu domain | 167 | * @detach_dev: detach device from an iommu domain |
168 | * @map: map a physically contiguous memory region to an iommu domain | 168 | * @map: map a physically contiguous memory region to an iommu domain |
169 | * @unmap: unmap a physically contiguous memory region from an iommu domain | 169 | * @unmap: unmap a physically contiguous memory region from an iommu domain |
170 | * @flush_tlb_all: Synchronously flush all hardware TLBs for this domain | 170 | * @flush_iotlb_all: Synchronously flush all hardware TLBs for this domain |
171 | * @iotlb_range_add: Add a given iova range to the flush queue for this domain | 171 | * @iotlb_range_add: Add a given iova range to the flush queue for this domain |
172 | * @iotlb_sync_map: Sync mappings created recently using @map to the hardware | ||
172 | * @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush | 173 | * @iotlb_sync: Flush all queued ranges from the hardware TLBs and empty flush |
173 | * queue | 174 | * queue |
174 | * @iova_to_phys: translate iova to physical address | 175 | * @iova_to_phys: translate iova to physical address |
@@ -183,6 +184,8 @@ struct iommu_resv_region { | |||
183 | * @domain_window_enable: Configure and enable a particular window for a domain | 184 | * @domain_window_enable: Configure and enable a particular window for a domain |
184 | * @domain_window_disable: Disable a particular window for a domain | 185 | * @domain_window_disable: Disable a particular window for a domain |
185 | * @of_xlate: add OF master IDs to iommu grouping | 186 | * @of_xlate: add OF master IDs to iommu grouping |
187 | * @is_attach_deferred: Check if domain attach should be deferred from iommu | ||
188 | * driver init to device driver init (default no) | ||
186 | * @pgsize_bitmap: bitmap of all possible supported page sizes | 189 | * @pgsize_bitmap: bitmap of all possible supported page sizes |
187 | */ | 190 | */ |
188 | struct iommu_ops { | 191 | struct iommu_ops { |
@@ -201,6 +204,7 @@ struct iommu_ops { | |||
201 | void (*flush_iotlb_all)(struct iommu_domain *domain); | 204 | void (*flush_iotlb_all)(struct iommu_domain *domain); |
202 | void (*iotlb_range_add)(struct iommu_domain *domain, | 205 | void (*iotlb_range_add)(struct iommu_domain *domain, |
203 | unsigned long iova, size_t size); | 206 | unsigned long iova, size_t size); |
207 | void (*iotlb_sync_map)(struct iommu_domain *domain); | ||
204 | void (*iotlb_sync)(struct iommu_domain *domain); | 208 | void (*iotlb_sync)(struct iommu_domain *domain); |
205 | phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); | 209 | phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); |
206 | int (*add_device)(struct device *dev); | 210 | int (*add_device)(struct device *dev); |
diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index 7c4b8e27268c..1ebb88e7c184 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h | |||
@@ -40,6 +40,7 @@ void pci_disable_pasid(struct pci_dev *pdev); | |||
40 | void pci_restore_pasid_state(struct pci_dev *pdev); | 40 | void pci_restore_pasid_state(struct pci_dev *pdev); |
41 | int pci_pasid_features(struct pci_dev *pdev); | 41 | int pci_pasid_features(struct pci_dev *pdev); |
42 | int pci_max_pasids(struct pci_dev *pdev); | 42 | int pci_max_pasids(struct pci_dev *pdev); |
43 | int pci_prg_resp_pasid_required(struct pci_dev *pdev); | ||
43 | 44 | ||
44 | #else /* CONFIG_PCI_PASID */ | 45 | #else /* CONFIG_PCI_PASID */ |
45 | 46 | ||
@@ -66,6 +67,10 @@ static inline int pci_max_pasids(struct pci_dev *pdev) | |||
66 | return -EINVAL; | 67 | return -EINVAL; |
67 | } | 68 | } |
68 | 69 | ||
70 | static inline int pci_prg_resp_pasid_required(struct pci_dev *pdev) | ||
71 | { | ||
72 | return 0; | ||
73 | } | ||
69 | #endif /* CONFIG_PCI_PASID */ | 74 | #endif /* CONFIG_PCI_PASID */ |
70 | 75 | ||
71 | 76 | ||
diff --git a/include/linux/pci.h b/include/linux/pci.h index 65f1d8c2f082..9724a8c0496b 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -1524,11 +1524,13 @@ void pci_ats_init(struct pci_dev *dev); | |||
1524 | int pci_enable_ats(struct pci_dev *dev, int ps); | 1524 | int pci_enable_ats(struct pci_dev *dev, int ps); |
1525 | void pci_disable_ats(struct pci_dev *dev); | 1525 | void pci_disable_ats(struct pci_dev *dev); |
1526 | int pci_ats_queue_depth(struct pci_dev *dev); | 1526 | int pci_ats_queue_depth(struct pci_dev *dev); |
1527 | int pci_ats_page_aligned(struct pci_dev *dev); | ||
1527 | #else | 1528 | #else |
1528 | static inline void pci_ats_init(struct pci_dev *d) { } | 1529 | static inline void pci_ats_init(struct pci_dev *d) { } |
1529 | static inline int pci_enable_ats(struct pci_dev *d, int ps) { return -ENODEV; } | 1530 | static inline int pci_enable_ats(struct pci_dev *d, int ps) { return -ENODEV; } |
1530 | static inline void pci_disable_ats(struct pci_dev *d) { } | 1531 | static inline void pci_disable_ats(struct pci_dev *d) { } |
1531 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } | 1532 | static inline int pci_ats_queue_depth(struct pci_dev *d) { return -ENODEV; } |
1533 | static inline int pci_ats_page_aligned(struct pci_dev *dev) { return 0; } | ||
1532 | #endif | 1534 | #endif |
1533 | 1535 | ||
1534 | #ifdef CONFIG_PCIE_PTM | 1536 | #ifdef CONFIG_PCIE_PTM |
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h index b43f37fea096..e489a028ec9f 100644 --- a/include/soc/tegra/mc.h +++ b/include/soc/tegra/mc.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #ifndef __SOC_TEGRA_MC_H__ | 9 | #ifndef __SOC_TEGRA_MC_H__ |
10 | #define __SOC_TEGRA_MC_H__ | 10 | #define __SOC_TEGRA_MC_H__ |
11 | 11 | ||
12 | #include <linux/err.h> | ||
12 | #include <linux/reset-controller.h> | 13 | #include <linux/reset-controller.h> |
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | 15 | ||
@@ -77,6 +78,7 @@ struct tegra_smmu_soc { | |||
77 | 78 | ||
78 | struct tegra_mc; | 79 | struct tegra_mc; |
79 | struct tegra_smmu; | 80 | struct tegra_smmu; |
81 | struct gart_device; | ||
80 | 82 | ||
81 | #ifdef CONFIG_TEGRA_IOMMU_SMMU | 83 | #ifdef CONFIG_TEGRA_IOMMU_SMMU |
82 | struct tegra_smmu *tegra_smmu_probe(struct device *dev, | 84 | struct tegra_smmu *tegra_smmu_probe(struct device *dev, |
@@ -96,6 +98,28 @@ static inline void tegra_smmu_remove(struct tegra_smmu *smmu) | |||
96 | } | 98 | } |
97 | #endif | 99 | #endif |
98 | 100 | ||
101 | #ifdef CONFIG_TEGRA_IOMMU_GART | ||
102 | struct gart_device *tegra_gart_probe(struct device *dev, struct tegra_mc *mc); | ||
103 | int tegra_gart_suspend(struct gart_device *gart); | ||
104 | int tegra_gart_resume(struct gart_device *gart); | ||
105 | #else | ||
106 | static inline struct gart_device * | ||
107 | tegra_gart_probe(struct device *dev, struct tegra_mc *mc) | ||
108 | { | ||
109 | return ERR_PTR(-ENODEV); | ||
110 | } | ||
111 | |||
112 | static inline int tegra_gart_suspend(struct gart_device *gart) | ||
113 | { | ||
114 | return -ENODEV; | ||
115 | } | ||
116 | |||
117 | static inline int tegra_gart_resume(struct gart_device *gart) | ||
118 | { | ||
119 | return -ENODEV; | ||
120 | } | ||
121 | #endif | ||
122 | |||
99 | struct tegra_mc_reset { | 123 | struct tegra_mc_reset { |
100 | const char *name; | 124 | const char *name; |
101 | unsigned long id; | 125 | unsigned long id; |
@@ -144,7 +168,8 @@ struct tegra_mc_soc { | |||
144 | struct tegra_mc { | 168 | struct tegra_mc { |
145 | struct device *dev; | 169 | struct device *dev; |
146 | struct tegra_smmu *smmu; | 170 | struct tegra_smmu *smmu; |
147 | void __iomem *regs, *regs2; | 171 | struct gart_device *gart; |
172 | void __iomem *regs; | ||
148 | struct clk *clk; | 173 | struct clk *clk; |
149 | int irq; | 174 | int irq; |
150 | 175 | ||
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index e1e9888c85e6..5c98133f2c94 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h | |||
@@ -866,6 +866,7 @@ | |||
866 | #define PCI_ATS_CAP 0x04 /* ATS Capability Register */ | 866 | #define PCI_ATS_CAP 0x04 /* ATS Capability Register */ |
867 | #define PCI_ATS_CAP_QDEP(x) ((x) & 0x1f) /* Invalidate Queue Depth */ | 867 | #define PCI_ATS_CAP_QDEP(x) ((x) & 0x1f) /* Invalidate Queue Depth */ |
868 | #define PCI_ATS_MAX_QDEP 32 /* Max Invalidate Queue Depth */ | 868 | #define PCI_ATS_MAX_QDEP 32 /* Max Invalidate Queue Depth */ |
869 | #define PCI_ATS_CAP_PAGE_ALIGNED 0x0020 /* Page Aligned Request */ | ||
869 | #define PCI_ATS_CTRL 0x06 /* ATS Control Register */ | 870 | #define PCI_ATS_CTRL 0x06 /* ATS Control Register */ |
870 | #define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */ | 871 | #define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */ |
871 | #define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */ | 872 | #define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */ |
@@ -880,6 +881,7 @@ | |||
880 | #define PCI_PRI_STATUS_RF 0x001 /* Response Failure */ | 881 | #define PCI_PRI_STATUS_RF 0x001 /* Response Failure */ |
881 | #define PCI_PRI_STATUS_UPRGI 0x002 /* Unexpected PRG index */ | 882 | #define PCI_PRI_STATUS_UPRGI 0x002 /* Unexpected PRG index */ |
882 | #define PCI_PRI_STATUS_STOPPED 0x100 /* PRI Stopped */ | 883 | #define PCI_PRI_STATUS_STOPPED 0x100 /* PRI Stopped */ |
884 | #define PCI_PRI_STATUS_PASID 0x8000 /* PRG Response PASID Required */ | ||
883 | #define PCI_PRI_MAX_REQ 0x08 /* PRI max reqs supported */ | 885 | #define PCI_PRI_MAX_REQ 0x08 /* PRI max reqs supported */ |
884 | #define PCI_PRI_ALLOC_REQ 0x0c /* PRI max reqs allowed */ | 886 | #define PCI_PRI_ALLOC_REQ 0x0c /* PRI max reqs allowed */ |
885 | #define PCI_EXT_CAP_PRI_SIZEOF 16 | 887 | #define PCI_EXT_CAP_PRI_SIZEOF 16 |