diff options
229 files changed, 4418 insertions, 1898 deletions
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt index f732a8321e8a..8cc17ca71813 100644 --- a/Documentation/power/swsusp.txt +++ b/Documentation/power/swsusp.txt | |||
| @@ -410,8 +410,17 @@ Documentation/usb/persist.txt. | |||
| 410 | 410 | ||
| 411 | Q: Can I suspend-to-disk using a swap partition under LVM? | 411 | Q: Can I suspend-to-disk using a swap partition under LVM? |
| 412 | 412 | ||
| 413 | A: No. You can suspend successfully, but you'll not be able to | 413 | A: Yes and No. You can suspend successfully, but the kernel will not be able |
| 414 | resume. uswsusp should be able to work with LVM. See suspend.sf.net. | 414 | to resume on its own. You need an initramfs that can recognize the resume |
| 415 | situation, activate the logical volume containing the swap volume (but not | ||
| 416 | touch any filesystems!), and eventually call | ||
| 417 | |||
| 418 | echo -n "$major:$minor" > /sys/power/resume | ||
| 419 | |||
| 420 | where $major and $minor are the respective major and minor device numbers of | ||
| 421 | the swap volume. | ||
| 422 | |||
| 423 | uswsusp works with LVM, too. See http://suspend.sourceforge.net/ | ||
| 415 | 424 | ||
| 416 | Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were | 425 | Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were |
| 417 | compiled with the similar configuration files. Anyway I found that | 426 | compiled with the similar configuration files. Anyway I found that |
diff --git a/MAINTAINERS b/MAINTAINERS index 6b8e19a0fdef..c1a1d6daac35 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -2564,19 +2564,31 @@ F: arch/powerpc/include/uapi/asm/spu*.h | |||
| 2564 | F: arch/powerpc/oprofile/*cell* | 2564 | F: arch/powerpc/oprofile/*cell* |
| 2565 | F: arch/powerpc/platforms/cell/ | 2565 | F: arch/powerpc/platforms/cell/ |
| 2566 | 2566 | ||
| 2567 | CEPH DISTRIBUTED FILE SYSTEM CLIENT | 2567 | CEPH COMMON CODE (LIBCEPH) |
| 2568 | M: Ilya Dryomov <idryomov@gmail.com> | ||
| 2568 | M: "Yan, Zheng" <zyan@redhat.com> | 2569 | M: "Yan, Zheng" <zyan@redhat.com> |
| 2569 | M: Sage Weil <sage@redhat.com> | 2570 | M: Sage Weil <sage@redhat.com> |
| 2570 | L: ceph-devel@vger.kernel.org | 2571 | L: ceph-devel@vger.kernel.org |
| 2571 | W: http://ceph.com/ | 2572 | W: http://ceph.com/ |
| 2572 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git | 2573 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git |
| 2574 | T: git git://github.com/ceph/ceph-client.git | ||
| 2573 | S: Supported | 2575 | S: Supported |
| 2574 | F: Documentation/filesystems/ceph.txt | ||
| 2575 | F: fs/ceph/ | ||
| 2576 | F: net/ceph/ | 2576 | F: net/ceph/ |
| 2577 | F: include/linux/ceph/ | 2577 | F: include/linux/ceph/ |
| 2578 | F: include/linux/crush/ | 2578 | F: include/linux/crush/ |
| 2579 | 2579 | ||
| 2580 | CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH) | ||
| 2581 | M: "Yan, Zheng" <zyan@redhat.com> | ||
| 2582 | M: Sage Weil <sage@redhat.com> | ||
| 2583 | M: Ilya Dryomov <idryomov@gmail.com> | ||
| 2584 | L: ceph-devel@vger.kernel.org | ||
| 2585 | W: http://ceph.com/ | ||
| 2586 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git | ||
| 2587 | T: git git://github.com/ceph/ceph-client.git | ||
| 2588 | S: Supported | ||
| 2589 | F: Documentation/filesystems/ceph.txt | ||
| 2590 | F: fs/ceph/ | ||
| 2591 | |||
| 2580 | CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: | 2592 | CERTIFIED WIRELESS USB (WUSB) SUBSYSTEM: |
| 2581 | L: linux-usb@vger.kernel.org | 2593 | L: linux-usb@vger.kernel.org |
| 2582 | S: Orphan | 2594 | S: Orphan |
| @@ -6149,6 +6161,7 @@ L: linux-nvdimm@lists.01.org | |||
| 6149 | Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ | 6161 | Q: https://patchwork.kernel.org/project/linux-nvdimm/list/ |
| 6150 | S: Supported | 6162 | S: Supported |
| 6151 | F: drivers/nvdimm/pmem.c | 6163 | F: drivers/nvdimm/pmem.c |
| 6164 | F: include/linux/pmem.h | ||
| 6152 | 6165 | ||
| 6153 | LINUX FOR IBM pSERIES (RS/6000) | 6166 | LINUX FOR IBM pSERIES (RS/6000) |
| 6154 | M: Paul Mackerras <paulus@au.ibm.com> | 6167 | M: Paul Mackerras <paulus@au.ibm.com> |
| @@ -6163,7 +6176,7 @@ M: Michael Ellerman <mpe@ellerman.id.au> | |||
| 6163 | W: http://www.penguinppc.org/ | 6176 | W: http://www.penguinppc.org/ |
| 6164 | L: linuxppc-dev@lists.ozlabs.org | 6177 | L: linuxppc-dev@lists.ozlabs.org |
| 6165 | Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/ | 6178 | Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/ |
| 6166 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git | 6179 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git |
| 6167 | S: Supported | 6180 | S: Supported |
| 6168 | F: Documentation/powerpc/ | 6181 | F: Documentation/powerpc/ |
| 6169 | F: arch/powerpc/ | 6182 | F: arch/powerpc/ |
| @@ -8368,10 +8381,12 @@ RADOS BLOCK DEVICE (RBD) | |||
| 8368 | M: Ilya Dryomov <idryomov@gmail.com> | 8381 | M: Ilya Dryomov <idryomov@gmail.com> |
| 8369 | M: Sage Weil <sage@redhat.com> | 8382 | M: Sage Weil <sage@redhat.com> |
| 8370 | M: Alex Elder <elder@kernel.org> | 8383 | M: Alex Elder <elder@kernel.org> |
| 8371 | M: ceph-devel@vger.kernel.org | 8384 | L: ceph-devel@vger.kernel.org |
| 8372 | W: http://ceph.com/ | 8385 | W: http://ceph.com/ |
| 8373 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git | 8386 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph-client.git |
| 8387 | T: git git://github.com/ceph/ceph-client.git | ||
| 8374 | S: Supported | 8388 | S: Supported |
| 8389 | F: Documentation/ABI/testing/sysfs-bus-rbd | ||
| 8375 | F: drivers/block/rbd.c | 8390 | F: drivers/block/rbd.c |
| 8376 | F: drivers/block/rbd_types.h | 8391 | F: drivers/block/rbd_types.h |
| 8377 | 8392 | ||
| @@ -1,7 +1,7 @@ | |||
| 1 | VERSION = 4 | 1 | VERSION = 4 |
| 2 | PATCHLEVEL = 2 | 2 | PATCHLEVEL = 2 |
| 3 | SUBLEVEL = 0 | 3 | SUBLEVEL = 0 |
| 4 | EXTRAVERSION = -rc1 | 4 | EXTRAVERSION = -rc2 |
| 5 | NAME = Hurr durr I'ma sheep | 5 | NAME = Hurr durr I'ma sheep |
| 6 | 6 | ||
| 7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a750c1425c3a..1c5021002fe4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -1693,6 +1693,12 @@ config HIGHMEM | |||
| 1693 | config HIGHPTE | 1693 | config HIGHPTE |
| 1694 | bool "Allocate 2nd-level pagetables from highmem" | 1694 | bool "Allocate 2nd-level pagetables from highmem" |
| 1695 | depends on HIGHMEM | 1695 | depends on HIGHMEM |
| 1696 | help | ||
| 1697 | The VM uses one page of physical memory for each page table. | ||
| 1698 | For systems with a lot of processes, this can use a lot of | ||
| 1699 | precious low memory, eventually leading to low memory being | ||
| 1700 | consumed by page tables. Setting this option will allow | ||
| 1701 | user-space 2nd level page tables to reside in high memory. | ||
| 1696 | 1702 | ||
| 1697 | config HW_PERF_EVENTS | 1703 | config HW_PERF_EVENTS |
| 1698 | bool "Enable hardware performance counter support for perf events" | 1704 | bool "Enable hardware performance counter support for perf events" |
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index f1b157971366..a2e16f940394 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug | |||
| @@ -1635,7 +1635,7 @@ config PID_IN_CONTEXTIDR | |||
| 1635 | 1635 | ||
| 1636 | config DEBUG_SET_MODULE_RONX | 1636 | config DEBUG_SET_MODULE_RONX |
| 1637 | bool "Set loadable kernel module data as NX and text as RO" | 1637 | bool "Set loadable kernel module data as NX and text as RO" |
| 1638 | depends on MODULES | 1638 | depends on MODULES && MMU |
| 1639 | ---help--- | 1639 | ---help--- |
| 1640 | This option helps catch unintended modifications to loadable | 1640 | This option helps catch unintended modifications to loadable |
| 1641 | kernel module's text and read-only data. It also prevents execution | 1641 | kernel module's text and read-only data. It also prevents execution |
diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts index 0d35ab64641c..7106114c7464 100644 --- a/arch/arm/boot/dts/am335x-pepper.dts +++ b/arch/arm/boot/dts/am335x-pepper.dts | |||
| @@ -74,6 +74,7 @@ | |||
| 74 | audio_codec: tlv320aic3106@1b { | 74 | audio_codec: tlv320aic3106@1b { |
| 75 | compatible = "ti,tlv320aic3106"; | 75 | compatible = "ti,tlv320aic3106"; |
| 76 | reg = <0x1b>; | 76 | reg = <0x1b>; |
| 77 | ai3x-micbias-vg = <0x2>; | ||
| 77 | }; | 78 | }; |
| 78 | 79 | ||
| 79 | accel: lis331dlh@1d { | 80 | accel: lis331dlh@1d { |
| @@ -153,7 +154,7 @@ | |||
| 153 | ti,audio-routing = | 154 | ti,audio-routing = |
| 154 | "Headphone Jack", "HPLOUT", | 155 | "Headphone Jack", "HPLOUT", |
| 155 | "Headphone Jack", "HPROUT", | 156 | "Headphone Jack", "HPROUT", |
| 156 | "LINE1L", "Line In"; | 157 | "MIC3L", "Mic3L Switch"; |
| 157 | }; | 158 | }; |
| 158 | 159 | ||
| 159 | &mcasp0 { | 160 | &mcasp0 { |
| @@ -438,41 +439,50 @@ | |||
| 438 | regulators { | 439 | regulators { |
| 439 | dcdc1_reg: regulator@0 { | 440 | dcdc1_reg: regulator@0 { |
| 440 | /* VDD_1V8 system supply */ | 441 | /* VDD_1V8 system supply */ |
| 442 | regulator-always-on; | ||
| 441 | }; | 443 | }; |
| 442 | 444 | ||
| 443 | dcdc2_reg: regulator@1 { | 445 | dcdc2_reg: regulator@1 { |
| 444 | /* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */ | 446 | /* VDD_CORE voltage limits 0.95V - 1.26V with +/-4% tolerance */ |
| 445 | regulator-name = "vdd_core"; | 447 | regulator-name = "vdd_core"; |
| 446 | regulator-min-microvolt = <925000>; | 448 | regulator-min-microvolt = <925000>; |
| 447 | regulator-max-microvolt = <1325000>; | 449 | regulator-max-microvolt = <1150000>; |
| 448 | regulator-boot-on; | 450 | regulator-boot-on; |
| 451 | regulator-always-on; | ||
| 449 | }; | 452 | }; |
| 450 | 453 | ||
| 451 | dcdc3_reg: regulator@2 { | 454 | dcdc3_reg: regulator@2 { |
| 452 | /* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */ | 455 | /* VDD_MPU voltage limits 0.95V - 1.1V with +/-4% tolerance */ |
| 453 | regulator-name = "vdd_mpu"; | 456 | regulator-name = "vdd_mpu"; |
| 454 | regulator-min-microvolt = <925000>; | 457 | regulator-min-microvolt = <925000>; |
| 455 | regulator-max-microvolt = <1150000>; | 458 | regulator-max-microvolt = <1325000>; |
| 456 | regulator-boot-on; | 459 | regulator-boot-on; |
| 460 | regulator-always-on; | ||
| 457 | }; | 461 | }; |
| 458 | 462 | ||
| 459 | ldo1_reg: regulator@3 { | 463 | ldo1_reg: regulator@3 { |
| 460 | /* VRTC 1.8V always-on supply */ | 464 | /* VRTC 1.8V always-on supply */ |
| 465 | regulator-name = "vrtc,vdds"; | ||
| 461 | regulator-always-on; | 466 | regulator-always-on; |
| 462 | }; | 467 | }; |
| 463 | 468 | ||
| 464 | ldo2_reg: regulator@4 { | 469 | ldo2_reg: regulator@4 { |
| 465 | /* 3.3V rail */ | 470 | /* 3.3V rail */ |
| 471 | regulator-name = "vdd_3v3aux"; | ||
| 472 | regulator-always-on; | ||
| 466 | }; | 473 | }; |
| 467 | 474 | ||
| 468 | ldo3_reg: regulator@5 { | 475 | ldo3_reg: regulator@5 { |
| 469 | /* VDD_3V3A 3.3V rail */ | 476 | /* VDD_3V3A 3.3V rail */ |
| 477 | regulator-name = "vdd_3v3a"; | ||
| 470 | regulator-min-microvolt = <3300000>; | 478 | regulator-min-microvolt = <3300000>; |
| 471 | regulator-max-microvolt = <3300000>; | 479 | regulator-max-microvolt = <3300000>; |
| 472 | }; | 480 | }; |
| 473 | 481 | ||
| 474 | ldo4_reg: regulator@6 { | 482 | ldo4_reg: regulator@6 { |
| 475 | /* VDD_3V3B 3.3V rail */ | 483 | /* VDD_3V3B 3.3V rail */ |
| 484 | regulator-name = "vdd_3v3b"; | ||
| 485 | regulator-always-on; | ||
| 476 | }; | 486 | }; |
| 477 | }; | 487 | }; |
| 478 | }; | 488 | }; |
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi index 233c69e50ae3..df8908adb0cb 100644 --- a/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi +++ b/arch/arm/boot/dts/omap3-overo-common-lcd35.dtsi | |||
| @@ -120,7 +120,7 @@ | |||
| 120 | 120 | ||
| 121 | lcd0: display@0 { | 121 | lcd0: display@0 { |
| 122 | compatible = "lgphilips,lb035q02"; | 122 | compatible = "lgphilips,lb035q02"; |
| 123 | label = "lcd"; | 123 | label = "lcd35"; |
| 124 | 124 | ||
| 125 | reg = <1>; /* CS1 */ | 125 | reg = <1>; /* CS1 */ |
| 126 | spi-max-frequency = <10000000>; | 126 | spi-max-frequency = <10000000>; |
diff --git a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi index f5395b7da912..048fd216970a 100644 --- a/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi +++ b/arch/arm/boot/dts/omap3-overo-common-lcd43.dtsi | |||
| @@ -98,7 +98,7 @@ | |||
| 98 | 98 | ||
| 99 | lcd0: display@0 { | 99 | lcd0: display@0 { |
| 100 | compatible = "samsung,lte430wq-f0c", "panel-dpi"; | 100 | compatible = "samsung,lte430wq-f0c", "panel-dpi"; |
| 101 | label = "lcd"; | 101 | label = "lcd43"; |
| 102 | 102 | ||
| 103 | pinctrl-names = "default"; | 103 | pinctrl-names = "default"; |
| 104 | pinctrl-0 = <<e430_pins>; | 104 | pinctrl-0 = <<e430_pins>; |
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index f884d6adb71e..7d31c6ff246f 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi | |||
| @@ -551,6 +551,7 @@ | |||
| 551 | reg = <0x4a066000 0x100>; | 551 | reg = <0x4a066000 0x100>; |
| 552 | interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; | 552 | interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; |
| 553 | ti,hwmods = "mmu_dsp"; | 553 | ti,hwmods = "mmu_dsp"; |
| 554 | #iommu-cells = <0>; | ||
| 554 | }; | 555 | }; |
| 555 | 556 | ||
| 556 | mmu_ipu: mmu@55082000 { | 557 | mmu_ipu: mmu@55082000 { |
| @@ -558,6 +559,7 @@ | |||
| 558 | reg = <0x55082000 0x100>; | 559 | reg = <0x55082000 0x100>; |
| 559 | interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; | 560 | interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; |
| 560 | ti,hwmods = "mmu_ipu"; | 561 | ti,hwmods = "mmu_ipu"; |
| 562 | #iommu-cells = <0>; | ||
| 561 | ti,iommu-bus-err-back; | 563 | ti,iommu-bus-err-back; |
| 562 | }; | 564 | }; |
| 563 | 565 | ||
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 7d24ae0306b5..c8fd648a7108 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi | |||
| @@ -612,6 +612,7 @@ | |||
| 612 | reg = <0x4a066000 0x100>; | 612 | reg = <0x4a066000 0x100>; |
| 613 | interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; | 613 | interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>; |
| 614 | ti,hwmods = "mmu_dsp"; | 614 | ti,hwmods = "mmu_dsp"; |
| 615 | #iommu-cells = <0>; | ||
| 615 | }; | 616 | }; |
| 616 | 617 | ||
| 617 | mmu_ipu: mmu@55082000 { | 618 | mmu_ipu: mmu@55082000 { |
| @@ -619,6 +620,7 @@ | |||
| 619 | reg = <0x55082000 0x100>; | 620 | reg = <0x55082000 0x100>; |
| 620 | interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; | 621 | interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>; |
| 621 | ti,hwmods = "mmu_ipu"; | 622 | ti,hwmods = "mmu_ipu"; |
| 623 | #iommu-cells = <0>; | ||
| 622 | ti,iommu-bus-err-back; | 624 | ti,iommu-bus-err-back; |
| 623 | }; | 625 | }; |
| 624 | 626 | ||
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 1c3938f26beb..485982084fe9 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h | |||
| @@ -140,16 +140,11 @@ static inline u32 __raw_readl(const volatile void __iomem *addr) | |||
| 140 | * The _caller variety takes a __builtin_return_address(0) value for | 140 | * The _caller variety takes a __builtin_return_address(0) value for |
| 141 | * /proc/vmalloc to use - and should only be used in non-inline functions. | 141 | * /proc/vmalloc to use - and should only be used in non-inline functions. |
| 142 | */ | 142 | */ |
| 143 | extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long, | ||
| 144 | size_t, unsigned int, void *); | ||
| 145 | extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, | 143 | extern void __iomem *__arm_ioremap_caller(phys_addr_t, size_t, unsigned int, |
| 146 | void *); | 144 | void *); |
| 147 | |||
| 148 | extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); | 145 | extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); |
| 149 | extern void __iomem *__arm_ioremap(phys_addr_t, size_t, unsigned int); | ||
| 150 | extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); | 146 | extern void __iomem *__arm_ioremap_exec(phys_addr_t, size_t, bool cached); |
| 151 | extern void __iounmap(volatile void __iomem *addr); | 147 | extern void __iounmap(volatile void __iomem *addr); |
| 152 | extern void __arm_iounmap(volatile void __iomem *addr); | ||
| 153 | 148 | ||
| 154 | extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, | 149 | extern void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, |
| 155 | unsigned int, void *); | 150 | unsigned int, void *); |
| @@ -321,21 +316,24 @@ extern void _memset_io(volatile void __iomem *, int, size_t); | |||
| 321 | static inline void memset_io(volatile void __iomem *dst, unsigned c, | 316 | static inline void memset_io(volatile void __iomem *dst, unsigned c, |
| 322 | size_t count) | 317 | size_t count) |
| 323 | { | 318 | { |
| 324 | memset((void __force *)dst, c, count); | 319 | extern void mmioset(void *, unsigned int, size_t); |
| 320 | mmioset((void __force *)dst, c, count); | ||
| 325 | } | 321 | } |
| 326 | #define memset_io(dst,c,count) memset_io(dst,c,count) | 322 | #define memset_io(dst,c,count) memset_io(dst,c,count) |
| 327 | 323 | ||
| 328 | static inline void memcpy_fromio(void *to, const volatile void __iomem *from, | 324 | static inline void memcpy_fromio(void *to, const volatile void __iomem *from, |
| 329 | size_t count) | 325 | size_t count) |
| 330 | { | 326 | { |
| 331 | memcpy(to, (const void __force *)from, count); | 327 | extern void mmiocpy(void *, const void *, size_t); |
| 328 | mmiocpy(to, (const void __force *)from, count); | ||
| 332 | } | 329 | } |
| 333 | #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) | 330 | #define memcpy_fromio(to,from,count) memcpy_fromio(to,from,count) |
| 334 | 331 | ||
| 335 | static inline void memcpy_toio(volatile void __iomem *to, const void *from, | 332 | static inline void memcpy_toio(volatile void __iomem *to, const void *from, |
| 336 | size_t count) | 333 | size_t count) |
| 337 | { | 334 | { |
| 338 | memcpy((void __force *)to, from, count); | 335 | extern void mmiocpy(void *, const void *, size_t); |
| 336 | mmiocpy((void __force *)to, from, count); | ||
| 339 | } | 337 | } |
| 340 | #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) | 338 | #define memcpy_toio(to,from,count) memcpy_toio(to,from,count) |
| 341 | 339 | ||
| @@ -348,18 +346,61 @@ static inline void memcpy_toio(volatile void __iomem *to, const void *from, | |||
| 348 | #endif /* readl */ | 346 | #endif /* readl */ |
| 349 | 347 | ||
| 350 | /* | 348 | /* |
| 351 | * ioremap and friends. | 349 | * ioremap() and friends. |
| 350 | * | ||
| 351 | * ioremap() takes a resource address, and size. Due to the ARM memory | ||
| 352 | * types, it is important to use the correct ioremap() function as each | ||
| 353 | * mapping has specific properties. | ||
| 354 | * | ||
| 355 | * Function Memory type Cacheability Cache hint | ||
| 356 | * ioremap() Device n/a n/a | ||
| 357 | * ioremap_nocache() Device n/a n/a | ||
| 358 | * ioremap_cache() Normal Writeback Read allocate | ||
| 359 | * ioremap_wc() Normal Non-cacheable n/a | ||
| 360 | * ioremap_wt() Normal Non-cacheable n/a | ||
| 361 | * | ||
| 362 | * All device mappings have the following properties: | ||
| 363 | * - no access speculation | ||
| 364 | * - no repetition (eg, on return from an exception) | ||
| 365 | * - number, order and size of accesses are maintained | ||
| 366 | * - unaligned accesses are "unpredictable" | ||
| 367 | * - writes may be delayed before they hit the endpoint device | ||
| 352 | * | 368 | * |
| 353 | * ioremap takes a PCI memory address, as specified in | 369 | * ioremap_nocache() is the same as ioremap() as there are too many device |
| 354 | * Documentation/io-mapping.txt. | 370 | * drivers using this for device registers, and documentation which tells |
| 371 | * people to use it for such for this to be any different. This is not a | ||
| 372 | * safe fallback for memory-like mappings, or memory regions where the | ||
| 373 | * compiler may generate unaligned accesses - eg, via inlining its own | ||
| 374 | * memcpy. | ||
| 355 | * | 375 | * |
| 376 | * All normal memory mappings have the following properties: | ||
| 377 | * - reads can be repeated with no side effects | ||
| 378 | * - repeated reads return the last value written | ||
| 379 | * - reads can fetch additional locations without side effects | ||
| 380 | * - writes can be repeated (in certain cases) with no side effects | ||
| 381 | * - writes can be merged before accessing the target | ||
| 382 | * - unaligned accesses can be supported | ||
| 383 | * - ordering is not guaranteed without explicit dependencies or barrier | ||
| 384 | * instructions | ||
| 385 | * - writes may be delayed before they hit the endpoint memory | ||
| 386 | * | ||
| 387 | * The cache hint is only a performance hint: CPUs may alias these hints. | ||
| 388 | * Eg, a CPU not implementing read allocate but implementing write allocate | ||
| 389 | * will provide a write allocate mapping instead. | ||
| 356 | */ | 390 | */ |
| 357 | #define ioremap(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) | 391 | void __iomem *ioremap(resource_size_t res_cookie, size_t size); |
| 358 | #define ioremap_nocache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) | 392 | #define ioremap ioremap |
| 359 | #define ioremap_cache(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_CACHED) | 393 | #define ioremap_nocache ioremap |
| 360 | #define ioremap_wc(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE_WC) | 394 | |
| 361 | #define ioremap_wt(cookie,size) __arm_ioremap((cookie), (size), MT_DEVICE) | 395 | void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size); |
| 362 | #define iounmap __arm_iounmap | 396 | #define ioremap_cache ioremap_cache |
| 397 | |||
| 398 | void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size); | ||
| 399 | #define ioremap_wc ioremap_wc | ||
| 400 | #define ioremap_wt ioremap_wc | ||
| 401 | |||
| 402 | void iounmap(volatile void __iomem *iomem_cookie); | ||
| 403 | #define iounmap iounmap | ||
| 363 | 404 | ||
| 364 | /* | 405 | /* |
| 365 | * io{read,write}{16,32}be() macros | 406 | * io{read,write}{16,32}be() macros |
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 3a72d69b3255..6f225acc07c5 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
| @@ -275,7 +275,7 @@ static inline void *phys_to_virt(phys_addr_t x) | |||
| 275 | */ | 275 | */ |
| 276 | #define __pa(x) __virt_to_phys((unsigned long)(x)) | 276 | #define __pa(x) __virt_to_phys((unsigned long)(x)) |
| 277 | #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) | 277 | #define __va(x) ((void *)__phys_to_virt((phys_addr_t)(x))) |
| 278 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | 278 | #define pfn_to_kaddr(pfn) __va((phys_addr_t)(pfn) << PAGE_SHIFT) |
| 279 | 279 | ||
| 280 | extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x); | 280 | extern phys_addr_t (*arch_virt_to_idmap)(unsigned long x); |
| 281 | 281 | ||
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h index bfd662e49a25..aeddd28b3595 100644 --- a/arch/arm/include/asm/pgtable-2level.h +++ b/arch/arm/include/asm/pgtable-2level.h | |||
| @@ -129,7 +129,36 @@ | |||
| 129 | 129 | ||
| 130 | /* | 130 | /* |
| 131 | * These are the memory types, defined to be compatible with | 131 | * These are the memory types, defined to be compatible with |
| 132 | * pre-ARMv6 CPUs cacheable and bufferable bits: XXCB | 132 | * pre-ARMv6 CPUs cacheable and bufferable bits: n/a,n/a,C,B |
| 133 | * ARMv6+ without TEX remapping, they are a table index. | ||
| 134 | * ARMv6+ with TEX remapping, they correspond to n/a,TEX(0),C,B | ||
| 135 | * | ||
| 136 | * MT type Pre-ARMv6 ARMv6+ type / cacheable status | ||
| 137 | * UNCACHED Uncached Strongly ordered | ||
| 138 | * BUFFERABLE Bufferable Normal memory / non-cacheable | ||
| 139 | * WRITETHROUGH Writethrough Normal memory / write through | ||
| 140 | * WRITEBACK Writeback Normal memory / write back, read alloc | ||
| 141 | * MINICACHE Minicache N/A | ||
| 142 | * WRITEALLOC Writeback Normal memory / write back, write alloc | ||
| 143 | * DEV_SHARED Uncached Device memory (shared) | ||
| 144 | * DEV_NONSHARED Uncached Device memory (non-shared) | ||
| 145 | * DEV_WC Bufferable Normal memory / non-cacheable | ||
| 146 | * DEV_CACHED Writeback Normal memory / write back, read alloc | ||
| 147 | * VECTORS Variable Normal memory / variable | ||
| 148 | * | ||
| 149 | * All normal memory mappings have the following properties: | ||
| 150 | * - reads can be repeated with no side effects | ||
| 151 | * - repeated reads return the last value written | ||
| 152 | * - reads can fetch additional locations without side effects | ||
| 153 | * - writes can be repeated (in certain cases) with no side effects | ||
| 154 | * - writes can be merged before accessing the target | ||
| 155 | * - unaligned accesses can be supported | ||
| 156 | * | ||
| 157 | * All device mappings have the following properties: | ||
| 158 | * - no access speculation | ||
| 159 | * - no repetition (eg, on return from an exception) | ||
| 160 | * - number, order and size of accesses are maintained | ||
| 161 | * - unaligned accesses are "unpredictable" | ||
| 133 | */ | 162 | */ |
| 134 | #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ | 163 | #define L_PTE_MT_UNCACHED (_AT(pteval_t, 0x00) << 2) /* 0000 */ |
| 135 | #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ | 164 | #define L_PTE_MT_BUFFERABLE (_AT(pteval_t, 0x01) << 2) /* 0001 */ |
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index a88671cfe1ff..5e5a51a99e68 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c | |||
| @@ -50,6 +50,9 @@ extern void __aeabi_ulcmp(void); | |||
| 50 | 50 | ||
| 51 | extern void fpundefinstr(void); | 51 | extern void fpundefinstr(void); |
| 52 | 52 | ||
| 53 | void mmioset(void *, unsigned int, size_t); | ||
| 54 | void mmiocpy(void *, const void *, size_t); | ||
| 55 | |||
| 53 | /* platform dependent support */ | 56 | /* platform dependent support */ |
| 54 | EXPORT_SYMBOL(arm_delay_ops); | 57 | EXPORT_SYMBOL(arm_delay_ops); |
| 55 | 58 | ||
| @@ -88,6 +91,9 @@ EXPORT_SYMBOL(memmove); | |||
| 88 | EXPORT_SYMBOL(memchr); | 91 | EXPORT_SYMBOL(memchr); |
| 89 | EXPORT_SYMBOL(__memzero); | 92 | EXPORT_SYMBOL(__memzero); |
| 90 | 93 | ||
| 94 | EXPORT_SYMBOL(mmioset); | ||
| 95 | EXPORT_SYMBOL(mmiocpy); | ||
| 96 | |||
| 91 | #ifdef CONFIG_MMU | 97 | #ifdef CONFIG_MMU |
| 92 | EXPORT_SYMBOL(copy_page); | 98 | EXPORT_SYMBOL(copy_page); |
| 93 | 99 | ||
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7dac3086e361..cb4fb1e69778 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S | |||
| @@ -410,7 +410,7 @@ ENDPROC(__fiq_abt) | |||
| 410 | zero_fp | 410 | zero_fp |
| 411 | 411 | ||
| 412 | .if \trace | 412 | .if \trace |
| 413 | #ifdef CONFIG_IRQSOFF_TRACER | 413 | #ifdef CONFIG_TRACE_IRQFLAGS |
| 414 | bl trace_hardirqs_off | 414 | bl trace_hardirqs_off |
| 415 | #endif | 415 | #endif |
| 416 | ct_user_exit save = 0 | 416 | ct_user_exit save = 0 |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 90dfbedfbfb8..3d6b7821cff8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
| @@ -578,7 +578,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
| 578 | struct pt_regs *old_regs = set_irq_regs(regs); | 578 | struct pt_regs *old_regs = set_irq_regs(regs); |
| 579 | 579 | ||
| 580 | if ((unsigned)ipinr < NR_IPI) { | 580 | if ((unsigned)ipinr < NR_IPI) { |
| 581 | trace_ipi_entry(ipi_types[ipinr]); | 581 | trace_ipi_entry_rcuidle(ipi_types[ipinr]); |
| 582 | __inc_irq_stat(cpu, ipi_irqs[ipinr]); | 582 | __inc_irq_stat(cpu, ipi_irqs[ipinr]); |
| 583 | } | 583 | } |
| 584 | 584 | ||
| @@ -637,7 +637,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs) | |||
| 637 | } | 637 | } |
| 638 | 638 | ||
| 639 | if ((unsigned)ipinr < NR_IPI) | 639 | if ((unsigned)ipinr < NR_IPI) |
| 640 | trace_ipi_exit(ipi_types[ipinr]); | 640 | trace_ipi_exit_rcuidle(ipi_types[ipinr]); |
| 641 | set_irq_regs(old_regs); | 641 | set_irq_regs(old_regs); |
| 642 | } | 642 | } |
| 643 | 643 | ||
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S index 7797e81e40e0..64111bd4440b 100644 --- a/arch/arm/lib/memcpy.S +++ b/arch/arm/lib/memcpy.S | |||
| @@ -61,8 +61,10 @@ | |||
| 61 | 61 | ||
| 62 | /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ | 62 | /* Prototype: void *memcpy(void *dest, const void *src, size_t n); */ |
| 63 | 63 | ||
| 64 | ENTRY(mmiocpy) | ||
| 64 | ENTRY(memcpy) | 65 | ENTRY(memcpy) |
| 65 | 66 | ||
| 66 | #include "copy_template.S" | 67 | #include "copy_template.S" |
| 67 | 68 | ||
| 68 | ENDPROC(memcpy) | 69 | ENDPROC(memcpy) |
| 70 | ENDPROC(mmiocpy) | ||
diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index a4ee97b5a2bf..3c65e3bd790f 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | .text | 16 | .text |
| 17 | .align 5 | 17 | .align 5 |
| 18 | 18 | ||
| 19 | ENTRY(mmioset) | ||
| 19 | ENTRY(memset) | 20 | ENTRY(memset) |
| 20 | UNWIND( .fnstart ) | 21 | UNWIND( .fnstart ) |
| 21 | ands r3, r0, #3 @ 1 unaligned? | 22 | ands r3, r0, #3 @ 1 unaligned? |
| @@ -133,3 +134,4 @@ UNWIND( .fnstart ) | |||
| 133 | b 1b | 134 | b 1b |
| 134 | UNWIND( .fnend ) | 135 | UNWIND( .fnend ) |
| 135 | ENDPROC(memset) | 136 | ENDPROC(memset) |
| 137 | ENDPROC(mmioset) | ||
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index ecc04ff13e95..4a023e8d1bdb 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig | |||
| @@ -60,6 +60,7 @@ config SOC_AM43XX | |||
| 60 | select ARM_GIC | 60 | select ARM_GIC |
| 61 | select MACH_OMAP_GENERIC | 61 | select MACH_OMAP_GENERIC |
| 62 | select MIGHT_HAVE_CACHE_L2X0 | 62 | select MIGHT_HAVE_CACHE_L2X0 |
| 63 | select HAVE_ARM_SCU | ||
| 63 | 64 | ||
| 64 | config SOC_DRA7XX | 65 | config SOC_DRA7XX |
| 65 | bool "TI DRA7XX" | 66 | bool "TI DRA7XX" |
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index d1e5ad7ab3bc..0c81056c1dd7 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c | |||
| @@ -255,7 +255,7 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, | |||
| 255 | } | 255 | } |
| 256 | #endif | 256 | #endif |
| 257 | 257 | ||
| 258 | void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, | 258 | static void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, |
| 259 | unsigned long offset, size_t size, unsigned int mtype, void *caller) | 259 | unsigned long offset, size_t size, unsigned int mtype, void *caller) |
| 260 | { | 260 | { |
| 261 | const struct mem_type *type; | 261 | const struct mem_type *type; |
| @@ -363,7 +363,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, | |||
| 363 | unsigned int mtype) | 363 | unsigned int mtype) |
| 364 | { | 364 | { |
| 365 | return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, | 365 | return __arm_ioremap_pfn_caller(pfn, offset, size, mtype, |
| 366 | __builtin_return_address(0)); | 366 | __builtin_return_address(0)); |
| 367 | } | 367 | } |
| 368 | EXPORT_SYMBOL(__arm_ioremap_pfn); | 368 | EXPORT_SYMBOL(__arm_ioremap_pfn); |
| 369 | 369 | ||
| @@ -371,13 +371,26 @@ void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, | |||
| 371 | unsigned int, void *) = | 371 | unsigned int, void *) = |
| 372 | __arm_ioremap_caller; | 372 | __arm_ioremap_caller; |
| 373 | 373 | ||
| 374 | void __iomem * | 374 | void __iomem *ioremap(resource_size_t res_cookie, size_t size) |
| 375 | __arm_ioremap(phys_addr_t phys_addr, size_t size, unsigned int mtype) | 375 | { |
| 376 | return arch_ioremap_caller(res_cookie, size, MT_DEVICE, | ||
| 377 | __builtin_return_address(0)); | ||
| 378 | } | ||
| 379 | EXPORT_SYMBOL(ioremap); | ||
| 380 | |||
| 381 | void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) | ||
| 382 | { | ||
| 383 | return arch_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, | ||
| 384 | __builtin_return_address(0)); | ||
| 385 | } | ||
| 386 | EXPORT_SYMBOL(ioremap_cache); | ||
| 387 | |||
| 388 | void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) | ||
| 376 | { | 389 | { |
| 377 | return arch_ioremap_caller(phys_addr, size, mtype, | 390 | return arch_ioremap_caller(res_cookie, size, MT_DEVICE_WC, |
| 378 | __builtin_return_address(0)); | 391 | __builtin_return_address(0)); |
| 379 | } | 392 | } |
| 380 | EXPORT_SYMBOL(__arm_ioremap); | 393 | EXPORT_SYMBOL(ioremap_wc); |
| 381 | 394 | ||
| 382 | /* | 395 | /* |
| 383 | * Remap an arbitrary physical address space into the kernel virtual | 396 | * Remap an arbitrary physical address space into the kernel virtual |
| @@ -431,11 +444,11 @@ void __iounmap(volatile void __iomem *io_addr) | |||
| 431 | 444 | ||
| 432 | void (*arch_iounmap)(volatile void __iomem *) = __iounmap; | 445 | void (*arch_iounmap)(volatile void __iomem *) = __iounmap; |
| 433 | 446 | ||
| 434 | void __arm_iounmap(volatile void __iomem *io_addr) | 447 | void iounmap(volatile void __iomem *cookie) |
| 435 | { | 448 | { |
| 436 | arch_iounmap(io_addr); | 449 | arch_iounmap(cookie); |
| 437 | } | 450 | } |
| 438 | EXPORT_SYMBOL(__arm_iounmap); | 451 | EXPORT_SYMBOL(iounmap); |
| 439 | 452 | ||
| 440 | #ifdef CONFIG_PCI | 453 | #ifdef CONFIG_PCI |
| 441 | static int pci_ioremap_mem_type = MT_DEVICE; | 454 | static int pci_ioremap_mem_type = MT_DEVICE; |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 6ca7d9aa896f..870838a46d52 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
| @@ -1072,6 +1072,7 @@ void __init sanity_check_meminfo(void) | |||
| 1072 | int highmem = 0; | 1072 | int highmem = 0; |
| 1073 | phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; | 1073 | phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1; |
| 1074 | struct memblock_region *reg; | 1074 | struct memblock_region *reg; |
| 1075 | bool should_use_highmem = false; | ||
| 1075 | 1076 | ||
| 1076 | for_each_memblock(memory, reg) { | 1077 | for_each_memblock(memory, reg) { |
| 1077 | phys_addr_t block_start = reg->base; | 1078 | phys_addr_t block_start = reg->base; |
| @@ -1090,6 +1091,7 @@ void __init sanity_check_meminfo(void) | |||
| 1090 | pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", | 1091 | pr_notice("Ignoring RAM at %pa-%pa (!CONFIG_HIGHMEM)\n", |
| 1091 | &block_start, &block_end); | 1092 | &block_start, &block_end); |
| 1092 | memblock_remove(reg->base, reg->size); | 1093 | memblock_remove(reg->base, reg->size); |
| 1094 | should_use_highmem = true; | ||
| 1093 | continue; | 1095 | continue; |
| 1094 | } | 1096 | } |
| 1095 | 1097 | ||
| @@ -1100,6 +1102,7 @@ void __init sanity_check_meminfo(void) | |||
| 1100 | &block_start, &block_end, &vmalloc_limit); | 1102 | &block_start, &block_end, &vmalloc_limit); |
| 1101 | memblock_remove(vmalloc_limit, overlap_size); | 1103 | memblock_remove(vmalloc_limit, overlap_size); |
| 1102 | block_end = vmalloc_limit; | 1104 | block_end = vmalloc_limit; |
| 1105 | should_use_highmem = true; | ||
| 1103 | } | 1106 | } |
| 1104 | } | 1107 | } |
| 1105 | 1108 | ||
| @@ -1134,6 +1137,9 @@ void __init sanity_check_meminfo(void) | |||
| 1134 | } | 1137 | } |
| 1135 | } | 1138 | } |
| 1136 | 1139 | ||
| 1140 | if (should_use_highmem) | ||
| 1141 | pr_notice("Consider using a HIGHMEM enabled kernel.\n"); | ||
| 1142 | |||
| 1137 | high_memory = __va(arm_lowmem_limit - 1) + 1; | 1143 | high_memory = __va(arm_lowmem_limit - 1) + 1; |
| 1138 | 1144 | ||
| 1139 | /* | 1145 | /* |
| @@ -1494,6 +1500,7 @@ void __init paging_init(const struct machine_desc *mdesc) | |||
| 1494 | build_mem_type_table(); | 1500 | build_mem_type_table(); |
| 1495 | prepare_page_table(); | 1501 | prepare_page_table(); |
| 1496 | map_lowmem(); | 1502 | map_lowmem(); |
| 1503 | memblock_set_current_limit(arm_lowmem_limit); | ||
| 1497 | dma_contiguous_remap(); | 1504 | dma_contiguous_remap(); |
| 1498 | devicemaps_init(mdesc); | 1505 | devicemaps_init(mdesc); |
| 1499 | kmap_init(); | 1506 | kmap_init(); |
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index afd7e05d95f1..1dd10936d68d 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c | |||
| @@ -351,30 +351,43 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, | |||
| 351 | } | 351 | } |
| 352 | EXPORT_SYMBOL(__arm_ioremap_pfn); | 352 | EXPORT_SYMBOL(__arm_ioremap_pfn); |
| 353 | 353 | ||
| 354 | void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset, | 354 | void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, |
| 355 | size_t size, unsigned int mtype, void *caller) | 355 | unsigned int mtype, void *caller) |
| 356 | { | 356 | { |
| 357 | return __arm_ioremap_pfn(pfn, offset, size, mtype); | 357 | return (void __iomem *)phys_addr; |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | void __iomem *__arm_ioremap(phys_addr_t phys_addr, size_t size, | 360 | void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); |
| 361 | unsigned int mtype) | 361 | |
| 362 | void __iomem *ioremap(resource_size_t res_cookie, size_t size) | ||
| 362 | { | 363 | { |
| 363 | return (void __iomem *)phys_addr; | 364 | return __arm_ioremap_caller(res_cookie, size, MT_DEVICE, |
| 365 | __builtin_return_address(0)); | ||
| 364 | } | 366 | } |
| 365 | EXPORT_SYMBOL(__arm_ioremap); | 367 | EXPORT_SYMBOL(ioremap); |
| 366 | 368 | ||
| 367 | void __iomem * (*arch_ioremap_caller)(phys_addr_t, size_t, unsigned int, void *); | 369 | void __iomem *ioremap_cache(resource_size_t res_cookie, size_t size) |
| 370 | { | ||
| 371 | return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_CACHED, | ||
| 372 | __builtin_return_address(0)); | ||
| 373 | } | ||
| 374 | EXPORT_SYMBOL(ioremap_cache); | ||
| 368 | 375 | ||
| 369 | void __iomem *__arm_ioremap_caller(phys_addr_t phys_addr, size_t size, | 376 | void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size) |
| 370 | unsigned int mtype, void *caller) | 377 | { |
| 378 | return __arm_ioremap_caller(res_cookie, size, MT_DEVICE_WC, | ||
| 379 | __builtin_return_address(0)); | ||
| 380 | } | ||
| 381 | EXPORT_SYMBOL(ioremap_wc); | ||
| 382 | |||
| 383 | void __iounmap(volatile void __iomem *addr) | ||
| 371 | { | 384 | { |
| 372 | return __arm_ioremap(phys_addr, size, mtype); | ||
| 373 | } | 385 | } |
| 386 | EXPORT_SYMBOL(__iounmap); | ||
| 374 | 387 | ||
| 375 | void (*arch_iounmap)(volatile void __iomem *); | 388 | void (*arch_iounmap)(volatile void __iomem *); |
| 376 | 389 | ||
| 377 | void __arm_iounmap(volatile void __iomem *addr) | 390 | void iounmap(volatile void __iomem *addr) |
| 378 | { | 391 | { |
| 379 | } | 392 | } |
| 380 | EXPORT_SYMBOL(__arm_iounmap); | 393 | EXPORT_SYMBOL(iounmap); |
diff --git a/arch/arm/vdso/vdsomunge.c b/arch/arm/vdso/vdsomunge.c index 9005b07296c8..aedec81d1198 100644 --- a/arch/arm/vdso/vdsomunge.c +++ b/arch/arm/vdso/vdsomunge.c | |||
| @@ -45,13 +45,11 @@ | |||
| 45 | * it does. | 45 | * it does. |
| 46 | */ | 46 | */ |
| 47 | 47 | ||
| 48 | #define _GNU_SOURCE | ||
| 49 | |||
| 50 | #include <byteswap.h> | 48 | #include <byteswap.h> |
| 51 | #include <elf.h> | 49 | #include <elf.h> |
| 52 | #include <errno.h> | 50 | #include <errno.h> |
| 53 | #include <error.h> | ||
| 54 | #include <fcntl.h> | 51 | #include <fcntl.h> |
| 52 | #include <stdarg.h> | ||
| 55 | #include <stdbool.h> | 53 | #include <stdbool.h> |
| 56 | #include <stdio.h> | 54 | #include <stdio.h> |
| 57 | #include <stdlib.h> | 55 | #include <stdlib.h> |
| @@ -82,11 +80,25 @@ | |||
| 82 | #define EF_ARM_ABI_FLOAT_HARD 0x400 | 80 | #define EF_ARM_ABI_FLOAT_HARD 0x400 |
| 83 | #endif | 81 | #endif |
| 84 | 82 | ||
| 83 | static int failed; | ||
| 84 | static const char *argv0; | ||
| 85 | static const char *outfile; | 85 | static const char *outfile; |
| 86 | 86 | ||
| 87 | static void fail(const char *fmt, ...) | ||
| 88 | { | ||
| 89 | va_list ap; | ||
| 90 | |||
| 91 | failed = 1; | ||
| 92 | fprintf(stderr, "%s: ", argv0); | ||
| 93 | va_start(ap, fmt); | ||
| 94 | vfprintf(stderr, fmt, ap); | ||
| 95 | va_end(ap); | ||
| 96 | exit(EXIT_FAILURE); | ||
| 97 | } | ||
| 98 | |||
| 87 | static void cleanup(void) | 99 | static void cleanup(void) |
| 88 | { | 100 | { |
| 89 | if (error_message_count > 0 && outfile != NULL) | 101 | if (failed && outfile != NULL) |
| 90 | unlink(outfile); | 102 | unlink(outfile); |
| 91 | } | 103 | } |
| 92 | 104 | ||
| @@ -119,68 +131,66 @@ int main(int argc, char **argv) | |||
| 119 | int infd; | 131 | int infd; |
| 120 | 132 | ||
| 121 | atexit(cleanup); | 133 | atexit(cleanup); |
| 134 | argv0 = argv[0]; | ||
| 122 | 135 | ||
| 123 | if (argc != 3) | 136 | if (argc != 3) |
| 124 | error(EXIT_FAILURE, 0, "Usage: %s [infile] [outfile]", argv[0]); | 137 | fail("Usage: %s [infile] [outfile]\n", argv[0]); |
| 125 | 138 | ||
| 126 | infile = argv[1]; | 139 | infile = argv[1]; |
| 127 | outfile = argv[2]; | 140 | outfile = argv[2]; |
| 128 | 141 | ||
| 129 | infd = open(infile, O_RDONLY); | 142 | infd = open(infile, O_RDONLY); |
| 130 | if (infd < 0) | 143 | if (infd < 0) |
| 131 | error(EXIT_FAILURE, errno, "Cannot open %s", infile); | 144 | fail("Cannot open %s: %s\n", infile, strerror(errno)); |
| 132 | 145 | ||
| 133 | if (fstat(infd, &stat) != 0) | 146 | if (fstat(infd, &stat) != 0) |
| 134 | error(EXIT_FAILURE, errno, "Failed stat for %s", infile); | 147 | fail("Failed stat for %s: %s\n", infile, strerror(errno)); |
| 135 | 148 | ||
| 136 | inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0); | 149 | inbuf = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, infd, 0); |
| 137 | if (inbuf == MAP_FAILED) | 150 | if (inbuf == MAP_FAILED) |
| 138 | error(EXIT_FAILURE, errno, "Failed to map %s", infile); | 151 | fail("Failed to map %s: %s\n", infile, strerror(errno)); |
| 139 | 152 | ||
| 140 | close(infd); | 153 | close(infd); |
| 141 | 154 | ||
| 142 | inhdr = inbuf; | 155 | inhdr = inbuf; |
| 143 | 156 | ||
| 144 | if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0) | 157 | if (memcmp(&inhdr->e_ident, ELFMAG, SELFMAG) != 0) |
| 145 | error(EXIT_FAILURE, 0, "Not an ELF file"); | 158 | fail("Not an ELF file\n"); |
| 146 | 159 | ||
| 147 | if (inhdr->e_ident[EI_CLASS] != ELFCLASS32) | 160 | if (inhdr->e_ident[EI_CLASS] != ELFCLASS32) |
| 148 | error(EXIT_FAILURE, 0, "Unsupported ELF class"); | 161 | fail("Unsupported ELF class\n"); |
| 149 | 162 | ||
| 150 | swap = inhdr->e_ident[EI_DATA] != HOST_ORDER; | 163 | swap = inhdr->e_ident[EI_DATA] != HOST_ORDER; |
| 151 | 164 | ||
| 152 | if (read_elf_half(inhdr->e_type, swap) != ET_DYN) | 165 | if (read_elf_half(inhdr->e_type, swap) != ET_DYN) |
| 153 | error(EXIT_FAILURE, 0, "Not a shared object"); | 166 | fail("Not a shared object\n"); |
| 154 | 167 | ||
| 155 | if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) { | 168 | if (read_elf_half(inhdr->e_machine, swap) != EM_ARM) |
| 156 | error(EXIT_FAILURE, 0, "Unsupported architecture %#x", | 169 | fail("Unsupported architecture %#x\n", inhdr->e_machine); |
| 157 | inhdr->e_machine); | ||
| 158 | } | ||
| 159 | 170 | ||
| 160 | e_flags = read_elf_word(inhdr->e_flags, swap); | 171 | e_flags = read_elf_word(inhdr->e_flags, swap); |
| 161 | 172 | ||
| 162 | if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) { | 173 | if (EF_ARM_EABI_VERSION(e_flags) != EF_ARM_EABI_VER5) { |
| 163 | error(EXIT_FAILURE, 0, "Unsupported EABI version %#x", | 174 | fail("Unsupported EABI version %#x\n", |
| 164 | EF_ARM_EABI_VERSION(e_flags)); | 175 | EF_ARM_EABI_VERSION(e_flags)); |
| 165 | } | 176 | } |
| 166 | 177 | ||
| 167 | if (e_flags & EF_ARM_ABI_FLOAT_HARD) | 178 | if (e_flags & EF_ARM_ABI_FLOAT_HARD) |
| 168 | error(EXIT_FAILURE, 0, | 179 | fail("Unexpected hard-float flag set in e_flags\n"); |
| 169 | "Unexpected hard-float flag set in e_flags"); | ||
| 170 | 180 | ||
| 171 | clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT); | 181 | clear_soft_float = !!(e_flags & EF_ARM_ABI_FLOAT_SOFT); |
| 172 | 182 | ||
| 173 | outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); | 183 | outfd = open(outfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); |
| 174 | if (outfd < 0) | 184 | if (outfd < 0) |
| 175 | error(EXIT_FAILURE, errno, "Cannot open %s", outfile); | 185 | fail("Cannot open %s: %s\n", outfile, strerror(errno)); |
| 176 | 186 | ||
| 177 | if (ftruncate(outfd, stat.st_size) != 0) | 187 | if (ftruncate(outfd, stat.st_size) != 0) |
| 178 | error(EXIT_FAILURE, errno, "Cannot truncate %s", outfile); | 188 | fail("Cannot truncate %s: %s\n", outfile, strerror(errno)); |
| 179 | 189 | ||
| 180 | outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, | 190 | outbuf = mmap(NULL, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, |
| 181 | outfd, 0); | 191 | outfd, 0); |
| 182 | if (outbuf == MAP_FAILED) | 192 | if (outbuf == MAP_FAILED) |
| 183 | error(EXIT_FAILURE, errno, "Failed to map %s", outfile); | 193 | fail("Failed to map %s: %s\n", outfile, strerror(errno)); |
| 184 | 194 | ||
| 185 | close(outfd); | 195 | close(outfd); |
| 186 | 196 | ||
| @@ -195,7 +205,7 @@ int main(int argc, char **argv) | |||
| 195 | } | 205 | } |
| 196 | 206 | ||
| 197 | if (msync(outbuf, stat.st_size, MS_SYNC) != 0) | 207 | if (msync(outbuf, stat.st_size, MS_SYNC) != 0) |
| 198 | error(EXIT_FAILURE, errno, "Failed to sync %s", outfile); | 208 | fail("Failed to sync %s: %s\n", outfile, strerror(errno)); |
| 199 | 209 | ||
| 200 | return EXIT_SUCCESS; | 210 | return EXIT_SUCCESS; |
| 201 | } | 211 | } |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0f6edb14b7e4..318175f62c24 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
| @@ -23,9 +23,9 @@ config ARM64 | |||
| 23 | select BUILDTIME_EXTABLE_SORT | 23 | select BUILDTIME_EXTABLE_SORT |
| 24 | select CLONE_BACKWARDS | 24 | select CLONE_BACKWARDS |
| 25 | select COMMON_CLK | 25 | select COMMON_CLK |
| 26 | select EDAC_SUPPORT | ||
| 27 | select CPU_PM if (SUSPEND || CPU_IDLE) | 26 | select CPU_PM if (SUSPEND || CPU_IDLE) |
| 28 | select DCACHE_WORD_ACCESS | 27 | select DCACHE_WORD_ACCESS |
| 28 | select EDAC_SUPPORT | ||
| 29 | select GENERIC_ALLOCATOR | 29 | select GENERIC_ALLOCATOR |
| 30 | select GENERIC_CLOCKEVENTS | 30 | select GENERIC_CLOCKEVENTS |
| 31 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP | 31 | select GENERIC_CLOCKEVENTS_BROADCAST if SMP |
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f38c94f1d898..4e17e7ede33d 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig | |||
| @@ -83,6 +83,7 @@ CONFIG_BLK_DEV_SD=y | |||
| 83 | CONFIG_ATA=y | 83 | CONFIG_ATA=y |
| 84 | CONFIG_SATA_AHCI=y | 84 | CONFIG_SATA_AHCI=y |
| 85 | CONFIG_SATA_AHCI_PLATFORM=y | 85 | CONFIG_SATA_AHCI_PLATFORM=y |
| 86 | CONFIG_AHCI_CEVA=y | ||
| 86 | CONFIG_AHCI_XGENE=y | 87 | CONFIG_AHCI_XGENE=y |
| 87 | CONFIG_PATA_PLATFORM=y | 88 | CONFIG_PATA_PLATFORM=y |
| 88 | CONFIG_PATA_OF_PLATFORM=y | 89 | CONFIG_PATA_OF_PLATFORM=y |
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 39248d3adf5d..406485ed110a 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h | |||
| @@ -19,6 +19,14 @@ | |||
| 19 | #include <asm/psci.h> | 19 | #include <asm/psci.h> |
| 20 | #include <asm/smp_plat.h> | 20 | #include <asm/smp_plat.h> |
| 21 | 21 | ||
| 22 | /* Macros for consistency checks of the GICC subtable of MADT */ | ||
| 23 | #define ACPI_MADT_GICC_LENGTH \ | ||
| 24 | (acpi_gbl_FADT.header.revision < 6 ? 76 : 80) | ||
| 25 | |||
| 26 | #define BAD_MADT_GICC_ENTRY(entry, end) \ | ||
| 27 | (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \ | ||
| 28 | (entry)->header.length != ACPI_MADT_GICC_LENGTH) | ||
| 29 | |||
| 22 | /* Basic configuration for ACPI */ | 30 | /* Basic configuration for ACPI */ |
| 23 | #ifdef CONFIG_ACPI | 31 | #ifdef CONFIG_ACPI |
| 24 | /* ACPI table mapping after acpi_gbl_permanent_mmap is set */ | 32 | /* ACPI table mapping after acpi_gbl_permanent_mmap is set */ |
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a7691a378668..f860bfda454a 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
| @@ -352,8 +352,8 @@ el1_inv: | |||
| 352 | // TODO: add support for undefined instructions in kernel mode | 352 | // TODO: add support for undefined instructions in kernel mode |
| 353 | enable_dbg | 353 | enable_dbg |
| 354 | mov x0, sp | 354 | mov x0, sp |
| 355 | mov x2, x1 | ||
| 355 | mov x1, #BAD_SYNC | 356 | mov x1, #BAD_SYNC |
| 356 | mrs x2, esr_el1 | ||
| 357 | b bad_mode | 357 | b bad_mode |
| 358 | ENDPROC(el1_sync) | 358 | ENDPROC(el1_sync) |
| 359 | 359 | ||
| @@ -553,7 +553,7 @@ el0_inv: | |||
| 553 | ct_user_exit | 553 | ct_user_exit |
| 554 | mov x0, sp | 554 | mov x0, sp |
| 555 | mov x1, #BAD_SYNC | 555 | mov x1, #BAD_SYNC |
| 556 | mrs x2, esr_el1 | 556 | mov x2, x25 |
| 557 | bl bad_mode | 557 | bl bad_mode |
| 558 | b ret_to_user | 558 | b ret_to_user |
| 559 | ENDPROC(el0_sync) | 559 | ENDPROC(el0_sync) |
diff --git a/arch/arm64/kernel/entry32.S b/arch/arm64/kernel/entry32.S index bd9bfaa9269b..f332d5d1f6b4 100644 --- a/arch/arm64/kernel/entry32.S +++ b/arch/arm64/kernel/entry32.S | |||
| @@ -32,13 +32,11 @@ | |||
| 32 | 32 | ||
| 33 | ENTRY(compat_sys_sigreturn_wrapper) | 33 | ENTRY(compat_sys_sigreturn_wrapper) |
| 34 | mov x0, sp | 34 | mov x0, sp |
| 35 | mov x27, #0 // prevent syscall restart handling (why) | ||
| 36 | b compat_sys_sigreturn | 35 | b compat_sys_sigreturn |
| 37 | ENDPROC(compat_sys_sigreturn_wrapper) | 36 | ENDPROC(compat_sys_sigreturn_wrapper) |
| 38 | 37 | ||
| 39 | ENTRY(compat_sys_rt_sigreturn_wrapper) | 38 | ENTRY(compat_sys_rt_sigreturn_wrapper) |
| 40 | mov x0, sp | 39 | mov x0, sp |
| 41 | mov x27, #0 // prevent syscall restart handling (why) | ||
| 42 | b compat_sys_rt_sigreturn | 40 | b compat_sys_rt_sigreturn |
| 43 | ENDPROC(compat_sys_rt_sigreturn_wrapper) | 41 | ENDPROC(compat_sys_rt_sigreturn_wrapper) |
| 44 | 42 | ||
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 695801a54ca5..50fb4696654e 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c | |||
| @@ -438,7 +438,7 @@ acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header, | |||
| 438 | struct acpi_madt_generic_interrupt *processor; | 438 | struct acpi_madt_generic_interrupt *processor; |
| 439 | 439 | ||
| 440 | processor = (struct acpi_madt_generic_interrupt *)header; | 440 | processor = (struct acpi_madt_generic_interrupt *)header; |
| 441 | if (BAD_MADT_ENTRY(processor, end)) | 441 | if (BAD_MADT_GICC_ENTRY(processor, end)) |
| 442 | return -EINVAL; | 442 | return -EINVAL; |
| 443 | 443 | ||
| 444 | acpi_table_print_madt_entry(header); | 444 | acpi_table_print_madt_entry(header); |
diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile index 9d84feb41a16..773d37a14039 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile | |||
| @@ -4,5 +4,3 @@ obj-y := dma-mapping.o extable.o fault.o init.o \ | |||
| 4 | context.o proc.o pageattr.o | 4 | context.o proc.o pageattr.o |
| 5 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 5 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
| 6 | obj-$(CONFIG_ARM64_PTDUMP) += dump.o | 6 | obj-$(CONFIG_ARM64_PTDUMP) += dump.o |
| 7 | |||
| 8 | CFLAGS_mmu.o := -I$(srctree)/scripts/dtc/libfdt/ | ||
diff --git a/arch/cris/arch-v32/drivers/sync_serial.c b/arch/cris/arch-v32/drivers/sync_serial.c index 4dda9bd6b8fb..e989cee77414 100644 --- a/arch/cris/arch-v32/drivers/sync_serial.c +++ b/arch/cris/arch-v32/drivers/sync_serial.c | |||
| @@ -1464,7 +1464,7 @@ static inline void handle_rx_packet(struct sync_port *port) | |||
| 1464 | if (port->write_ts_idx == NBR_IN_DESCR) | 1464 | if (port->write_ts_idx == NBR_IN_DESCR) |
| 1465 | port->write_ts_idx = 0; | 1465 | port->write_ts_idx = 0; |
| 1466 | idx = port->write_ts_idx++; | 1466 | idx = port->write_ts_idx++; |
| 1467 | do_posix_clock_monotonic_gettime(&port->timestamp[idx]); | 1467 | ktime_get_ts(&port->timestamp[idx]); |
| 1468 | port->in_buffer_len += port->inbufchunk; | 1468 | port->in_buffer_len += port->inbufchunk; |
| 1469 | } | 1469 | } |
| 1470 | spin_unlock_irqrestore(&port->lock, flags); | 1470 | spin_unlock_irqrestore(&port->lock, flags); |
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 2a14585c90d2..aab7e46cadd5 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
| @@ -2231,7 +2231,7 @@ config MIPS_CMP | |||
| 2231 | 2231 | ||
| 2232 | config MIPS_CPS | 2232 | config MIPS_CPS |
| 2233 | bool "MIPS Coherent Processing System support" | 2233 | bool "MIPS Coherent Processing System support" |
| 2234 | depends on SYS_SUPPORTS_MIPS_CPS && !64BIT | 2234 | depends on SYS_SUPPORTS_MIPS_CPS |
| 2235 | select MIPS_CM | 2235 | select MIPS_CM |
| 2236 | select MIPS_CPC | 2236 | select MIPS_CPC |
| 2237 | select MIPS_CPS_PM if HOTPLUG_CPU | 2237 | select MIPS_CPS_PM if HOTPLUG_CPU |
diff --git a/arch/mips/include/asm/mach-loongson64/mmzone.h b/arch/mips/include/asm/mach-loongson64/mmzone.h index 37c08a27b4f0..c9f7e231e66b 100644 --- a/arch/mips/include/asm/mach-loongson64/mmzone.h +++ b/arch/mips/include/asm/mach-loongson64/mmzone.h | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & | 2 | * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & |
| 3 | * Insititute of Computing Technology | 3 | * Institute of Computing Technology |
| 4 | * Author: Xiang Gao, gaoxiang@ict.ac.cn | 4 | * Author: Xiang Gao, gaoxiang@ict.ac.cn |
| 5 | * Huacai Chen, chenhc@lemote.com | 5 | * Huacai Chen, chenhc@lemote.com |
| 6 | * Xiaofu Meng, Shuangshuang Zhang | 6 | * Xiaofu Meng, Shuangshuang Zhang |
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h index 2b25d1ba1ea0..16f1ea9ab191 100644 --- a/arch/mips/include/asm/smp.h +++ b/arch/mips/include/asm/smp.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | extern int smp_num_siblings; | 23 | extern int smp_num_siblings; |
| 24 | extern cpumask_t cpu_sibling_map[]; | 24 | extern cpumask_t cpu_sibling_map[]; |
| 25 | extern cpumask_t cpu_core_map[]; | 25 | extern cpumask_t cpu_core_map[]; |
| 26 | extern cpumask_t cpu_foreign_map; | ||
| 26 | 27 | ||
| 27 | #define raw_smp_processor_id() (current_thread_info()->cpu) | 28 | #define raw_smp_processor_id() (current_thread_info()->cpu) |
| 28 | 29 | ||
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c index c0c5e5972256..d8f9b357b222 100644 --- a/arch/mips/kernel/branch.c +++ b/arch/mips/kernel/branch.c | |||
| @@ -600,7 +600,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, | |||
| 600 | break; | 600 | break; |
| 601 | 601 | ||
| 602 | case blezl_op: /* not really i_format */ | 602 | case blezl_op: /* not really i_format */ |
| 603 | if (NO_R6EMU) | 603 | if (!insn.i_format.rt && NO_R6EMU) |
| 604 | goto sigill_r6; | 604 | goto sigill_r6; |
| 605 | case blez_op: | 605 | case blez_op: |
| 606 | /* | 606 | /* |
| @@ -635,7 +635,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs, | |||
| 635 | break; | 635 | break; |
| 636 | 636 | ||
| 637 | case bgtzl_op: | 637 | case bgtzl_op: |
| 638 | if (NO_R6EMU) | 638 | if (!insn.i_format.rt && NO_R6EMU) |
| 639 | goto sigill_r6; | 639 | goto sigill_r6; |
| 640 | case bgtz_op: | 640 | case bgtz_op: |
| 641 | /* | 641 | /* |
diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index 55b759a0019e..1b6ca634e646 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S | |||
| @@ -60,7 +60,7 @@ LEAF(mips_cps_core_entry) | |||
| 60 | nop | 60 | nop |
| 61 | 61 | ||
| 62 | /* This is an NMI */ | 62 | /* This is an NMI */ |
| 63 | la k0, nmi_handler | 63 | PTR_LA k0, nmi_handler |
| 64 | jr k0 | 64 | jr k0 |
| 65 | nop | 65 | nop |
| 66 | 66 | ||
| @@ -107,10 +107,10 @@ not_nmi: | |||
| 107 | mul t1, t1, t0 | 107 | mul t1, t1, t0 |
| 108 | mul t1, t1, t2 | 108 | mul t1, t1, t2 |
| 109 | 109 | ||
| 110 | li a0, KSEG0 | 110 | li a0, CKSEG0 |
| 111 | add a1, a0, t1 | 111 | PTR_ADD a1, a0, t1 |
| 112 | 1: cache Index_Store_Tag_I, 0(a0) | 112 | 1: cache Index_Store_Tag_I, 0(a0) |
| 113 | add a0, a0, t0 | 113 | PTR_ADD a0, a0, t0 |
| 114 | bne a0, a1, 1b | 114 | bne a0, a1, 1b |
| 115 | nop | 115 | nop |
| 116 | icache_done: | 116 | icache_done: |
| @@ -134,12 +134,12 @@ icache_done: | |||
| 134 | mul t1, t1, t0 | 134 | mul t1, t1, t0 |
| 135 | mul t1, t1, t2 | 135 | mul t1, t1, t2 |
| 136 | 136 | ||
| 137 | li a0, KSEG0 | 137 | li a0, CKSEG0 |
| 138 | addu a1, a0, t1 | 138 | PTR_ADDU a1, a0, t1 |
| 139 | subu a1, a1, t0 | 139 | PTR_SUBU a1, a1, t0 |
| 140 | 1: cache Index_Store_Tag_D, 0(a0) | 140 | 1: cache Index_Store_Tag_D, 0(a0) |
| 141 | bne a0, a1, 1b | 141 | bne a0, a1, 1b |
| 142 | add a0, a0, t0 | 142 | PTR_ADD a0, a0, t0 |
| 143 | dcache_done: | 143 | dcache_done: |
| 144 | 144 | ||
| 145 | /* Set Kseg0 CCA to that in s0 */ | 145 | /* Set Kseg0 CCA to that in s0 */ |
| @@ -152,11 +152,11 @@ dcache_done: | |||
| 152 | 152 | ||
| 153 | /* Enter the coherent domain */ | 153 | /* Enter the coherent domain */ |
| 154 | li t0, 0xff | 154 | li t0, 0xff |
| 155 | sw t0, GCR_CL_COHERENCE_OFS(v1) | 155 | PTR_S t0, GCR_CL_COHERENCE_OFS(v1) |
| 156 | ehb | 156 | ehb |
| 157 | 157 | ||
| 158 | /* Jump to kseg0 */ | 158 | /* Jump to kseg0 */ |
| 159 | la t0, 1f | 159 | PTR_LA t0, 1f |
| 160 | jr t0 | 160 | jr t0 |
| 161 | nop | 161 | nop |
| 162 | 162 | ||
| @@ -178,9 +178,9 @@ dcache_done: | |||
| 178 | nop | 178 | nop |
| 179 | 179 | ||
| 180 | /* Off we go! */ | 180 | /* Off we go! */ |
| 181 | lw t1, VPEBOOTCFG_PC(v0) | 181 | PTR_L t1, VPEBOOTCFG_PC(v0) |
| 182 | lw gp, VPEBOOTCFG_GP(v0) | 182 | PTR_L gp, VPEBOOTCFG_GP(v0) |
| 183 | lw sp, VPEBOOTCFG_SP(v0) | 183 | PTR_L sp, VPEBOOTCFG_SP(v0) |
| 184 | jr t1 | 184 | jr t1 |
| 185 | nop | 185 | nop |
| 186 | END(mips_cps_core_entry) | 186 | END(mips_cps_core_entry) |
| @@ -217,7 +217,7 @@ LEAF(excep_intex) | |||
| 217 | 217 | ||
| 218 | .org 0x480 | 218 | .org 0x480 |
| 219 | LEAF(excep_ejtag) | 219 | LEAF(excep_ejtag) |
| 220 | la k0, ejtag_debug_handler | 220 | PTR_LA k0, ejtag_debug_handler |
| 221 | jr k0 | 221 | jr k0 |
| 222 | nop | 222 | nop |
| 223 | END(excep_ejtag) | 223 | END(excep_ejtag) |
| @@ -229,7 +229,7 @@ LEAF(mips_cps_core_init) | |||
| 229 | nop | 229 | nop |
| 230 | 230 | ||
| 231 | .set push | 231 | .set push |
| 232 | .set mips32r2 | 232 | .set mips64r2 |
| 233 | .set mt | 233 | .set mt |
| 234 | 234 | ||
| 235 | /* Only allow 1 TC per VPE to execute... */ | 235 | /* Only allow 1 TC per VPE to execute... */ |
| @@ -237,7 +237,7 @@ LEAF(mips_cps_core_init) | |||
| 237 | 237 | ||
| 238 | /* ...and for the moment only 1 VPE */ | 238 | /* ...and for the moment only 1 VPE */ |
| 239 | dvpe | 239 | dvpe |
| 240 | la t1, 1f | 240 | PTR_LA t1, 1f |
| 241 | jr.hb t1 | 241 | jr.hb t1 |
| 242 | nop | 242 | nop |
| 243 | 243 | ||
| @@ -250,25 +250,25 @@ LEAF(mips_cps_core_init) | |||
| 250 | mfc0 t0, CP0_MVPCONF0 | 250 | mfc0 t0, CP0_MVPCONF0 |
| 251 | srl t0, t0, MVPCONF0_PVPE_SHIFT | 251 | srl t0, t0, MVPCONF0_PVPE_SHIFT |
| 252 | andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT) | 252 | andi t0, t0, (MVPCONF0_PVPE >> MVPCONF0_PVPE_SHIFT) |
| 253 | addiu t7, t0, 1 | 253 | addiu ta3, t0, 1 |
| 254 | 254 | ||
| 255 | /* If there's only 1, we're done */ | 255 | /* If there's only 1, we're done */ |
| 256 | beqz t0, 2f | 256 | beqz t0, 2f |
| 257 | nop | 257 | nop |
| 258 | 258 | ||
| 259 | /* Loop through each VPE within this core */ | 259 | /* Loop through each VPE within this core */ |
| 260 | li t5, 1 | 260 | li ta1, 1 |
| 261 | 261 | ||
| 262 | 1: /* Operate on the appropriate TC */ | 262 | 1: /* Operate on the appropriate TC */ |
| 263 | mtc0 t5, CP0_VPECONTROL | 263 | mtc0 ta1, CP0_VPECONTROL |
| 264 | ehb | 264 | ehb |
| 265 | 265 | ||
| 266 | /* Bind TC to VPE (1:1 TC:VPE mapping) */ | 266 | /* Bind TC to VPE (1:1 TC:VPE mapping) */ |
| 267 | mttc0 t5, CP0_TCBIND | 267 | mttc0 ta1, CP0_TCBIND |
| 268 | 268 | ||
| 269 | /* Set exclusive TC, non-active, master */ | 269 | /* Set exclusive TC, non-active, master */ |
| 270 | li t0, VPECONF0_MVP | 270 | li t0, VPECONF0_MVP |
| 271 | sll t1, t5, VPECONF0_XTC_SHIFT | 271 | sll t1, ta1, VPECONF0_XTC_SHIFT |
| 272 | or t0, t0, t1 | 272 | or t0, t0, t1 |
| 273 | mttc0 t0, CP0_VPECONF0 | 273 | mttc0 t0, CP0_VPECONF0 |
| 274 | 274 | ||
| @@ -280,8 +280,8 @@ LEAF(mips_cps_core_init) | |||
| 280 | mttc0 t0, CP0_TCHALT | 280 | mttc0 t0, CP0_TCHALT |
| 281 | 281 | ||
| 282 | /* Next VPE */ | 282 | /* Next VPE */ |
| 283 | addiu t5, t5, 1 | 283 | addiu ta1, ta1, 1 |
| 284 | slt t0, t5, t7 | 284 | slt t0, ta1, ta3 |
| 285 | bnez t0, 1b | 285 | bnez t0, 1b |
| 286 | nop | 286 | nop |
| 287 | 287 | ||
| @@ -298,19 +298,19 @@ LEAF(mips_cps_core_init) | |||
| 298 | 298 | ||
| 299 | LEAF(mips_cps_boot_vpes) | 299 | LEAF(mips_cps_boot_vpes) |
| 300 | /* Retrieve CM base address */ | 300 | /* Retrieve CM base address */ |
| 301 | la t0, mips_cm_base | 301 | PTR_LA t0, mips_cm_base |
| 302 | lw t0, 0(t0) | 302 | PTR_L t0, 0(t0) |
| 303 | 303 | ||
| 304 | /* Calculate a pointer to this cores struct core_boot_config */ | 304 | /* Calculate a pointer to this cores struct core_boot_config */ |
| 305 | lw t0, GCR_CL_ID_OFS(t0) | 305 | PTR_L t0, GCR_CL_ID_OFS(t0) |
| 306 | li t1, COREBOOTCFG_SIZE | 306 | li t1, COREBOOTCFG_SIZE |
| 307 | mul t0, t0, t1 | 307 | mul t0, t0, t1 |
| 308 | la t1, mips_cps_core_bootcfg | 308 | PTR_LA t1, mips_cps_core_bootcfg |
| 309 | lw t1, 0(t1) | 309 | PTR_L t1, 0(t1) |
| 310 | addu t0, t0, t1 | 310 | PTR_ADDU t0, t0, t1 |
| 311 | 311 | ||
| 312 | /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ | 312 | /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ |
| 313 | has_mt t6, 1f | 313 | has_mt ta2, 1f |
| 314 | li t9, 0 | 314 | li t9, 0 |
| 315 | 315 | ||
| 316 | /* Find the number of VPEs present in the core */ | 316 | /* Find the number of VPEs present in the core */ |
| @@ -334,24 +334,24 @@ LEAF(mips_cps_boot_vpes) | |||
| 334 | 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ | 334 | 1: /* Calculate a pointer to this VPEs struct vpe_boot_config */ |
| 335 | li t1, VPEBOOTCFG_SIZE | 335 | li t1, VPEBOOTCFG_SIZE |
| 336 | mul v0, t9, t1 | 336 | mul v0, t9, t1 |
| 337 | lw t7, COREBOOTCFG_VPECONFIG(t0) | 337 | PTR_L ta3, COREBOOTCFG_VPECONFIG(t0) |
| 338 | addu v0, v0, t7 | 338 | PTR_ADDU v0, v0, ta3 |
| 339 | 339 | ||
| 340 | #ifdef CONFIG_MIPS_MT | 340 | #ifdef CONFIG_MIPS_MT |
| 341 | 341 | ||
| 342 | /* If the core doesn't support MT then return */ | 342 | /* If the core doesn't support MT then return */ |
| 343 | bnez t6, 1f | 343 | bnez ta2, 1f |
| 344 | nop | 344 | nop |
| 345 | jr ra | 345 | jr ra |
| 346 | nop | 346 | nop |
| 347 | 347 | ||
| 348 | .set push | 348 | .set push |
| 349 | .set mips32r2 | 349 | .set mips64r2 |
| 350 | .set mt | 350 | .set mt |
| 351 | 351 | ||
| 352 | 1: /* Enter VPE configuration state */ | 352 | 1: /* Enter VPE configuration state */ |
| 353 | dvpe | 353 | dvpe |
| 354 | la t1, 1f | 354 | PTR_LA t1, 1f |
| 355 | jr.hb t1 | 355 | jr.hb t1 |
| 356 | nop | 356 | nop |
| 357 | 1: mfc0 t1, CP0_MVPCONTROL | 357 | 1: mfc0 t1, CP0_MVPCONTROL |
| @@ -360,12 +360,12 @@ LEAF(mips_cps_boot_vpes) | |||
| 360 | ehb | 360 | ehb |
| 361 | 361 | ||
| 362 | /* Loop through each VPE */ | 362 | /* Loop through each VPE */ |
| 363 | lw t6, COREBOOTCFG_VPEMASK(t0) | 363 | PTR_L ta2, COREBOOTCFG_VPEMASK(t0) |
| 364 | move t8, t6 | 364 | move t8, ta2 |
| 365 | li t5, 0 | 365 | li ta1, 0 |
| 366 | 366 | ||
| 367 | /* Check whether the VPE should be running. If not, skip it */ | 367 | /* Check whether the VPE should be running. If not, skip it */ |
| 368 | 1: andi t0, t6, 1 | 368 | 1: andi t0, ta2, 1 |
| 369 | beqz t0, 2f | 369 | beqz t0, 2f |
| 370 | nop | 370 | nop |
| 371 | 371 | ||
| @@ -373,7 +373,7 @@ LEAF(mips_cps_boot_vpes) | |||
| 373 | mfc0 t0, CP0_VPECONTROL | 373 | mfc0 t0, CP0_VPECONTROL |
| 374 | ori t0, t0, VPECONTROL_TARGTC | 374 | ori t0, t0, VPECONTROL_TARGTC |
| 375 | xori t0, t0, VPECONTROL_TARGTC | 375 | xori t0, t0, VPECONTROL_TARGTC |
| 376 | or t0, t0, t5 | 376 | or t0, t0, ta1 |
| 377 | mtc0 t0, CP0_VPECONTROL | 377 | mtc0 t0, CP0_VPECONTROL |
| 378 | ehb | 378 | ehb |
| 379 | 379 | ||
| @@ -384,8 +384,8 @@ LEAF(mips_cps_boot_vpes) | |||
| 384 | 384 | ||
| 385 | /* Calculate a pointer to the VPEs struct vpe_boot_config */ | 385 | /* Calculate a pointer to the VPEs struct vpe_boot_config */ |
| 386 | li t0, VPEBOOTCFG_SIZE | 386 | li t0, VPEBOOTCFG_SIZE |
| 387 | mul t0, t0, t5 | 387 | mul t0, t0, ta1 |
| 388 | addu t0, t0, t7 | 388 | addu t0, t0, ta3 |
| 389 | 389 | ||
| 390 | /* Set the TC restart PC */ | 390 | /* Set the TC restart PC */ |
| 391 | lw t1, VPEBOOTCFG_PC(t0) | 391 | lw t1, VPEBOOTCFG_PC(t0) |
| @@ -423,9 +423,9 @@ LEAF(mips_cps_boot_vpes) | |||
| 423 | mttc0 t0, CP0_VPECONF0 | 423 | mttc0 t0, CP0_VPECONF0 |
| 424 | 424 | ||
| 425 | /* Next VPE */ | 425 | /* Next VPE */ |
| 426 | 2: srl t6, t6, 1 | 426 | 2: srl ta2, ta2, 1 |
| 427 | addiu t5, t5, 1 | 427 | addiu ta1, ta1, 1 |
| 428 | bnez t6, 1b | 428 | bnez ta2, 1b |
| 429 | nop | 429 | nop |
| 430 | 430 | ||
| 431 | /* Leave VPE configuration state */ | 431 | /* Leave VPE configuration state */ |
| @@ -445,7 +445,7 @@ LEAF(mips_cps_boot_vpes) | |||
| 445 | /* This VPE should be offline, halt the TC */ | 445 | /* This VPE should be offline, halt the TC */ |
| 446 | li t0, TCHALT_H | 446 | li t0, TCHALT_H |
| 447 | mtc0 t0, CP0_TCHALT | 447 | mtc0 t0, CP0_TCHALT |
| 448 | la t0, 1f | 448 | PTR_LA t0, 1f |
| 449 | 1: jr.hb t0 | 449 | 1: jr.hb t0 |
| 450 | nop | 450 | nop |
| 451 | 451 | ||
| @@ -466,10 +466,10 @@ LEAF(mips_cps_boot_vpes) | |||
| 466 | .set noat | 466 | .set noat |
| 467 | lw $1, TI_CPU(gp) | 467 | lw $1, TI_CPU(gp) |
| 468 | sll $1, $1, LONGLOG | 468 | sll $1, $1, LONGLOG |
| 469 | la \dest, __per_cpu_offset | 469 | PTR_LA \dest, __per_cpu_offset |
| 470 | addu $1, $1, \dest | 470 | addu $1, $1, \dest |
| 471 | lw $1, 0($1) | 471 | lw $1, 0($1) |
| 472 | la \dest, cps_cpu_state | 472 | PTR_LA \dest, cps_cpu_state |
| 473 | addu \dest, \dest, $1 | 473 | addu \dest, \dest, $1 |
| 474 | .set pop | 474 | .set pop |
| 475 | .endm | 475 | .endm |
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 6e8de80bb446..4cc13508d967 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S | |||
| @@ -73,10 +73,11 @@ NESTED(handle_sys, PT_SIZE, sp) | |||
| 73 | .set noreorder | 73 | .set noreorder |
| 74 | .set nomacro | 74 | .set nomacro |
| 75 | 75 | ||
| 76 | 1: user_lw(t5, 16(t0)) # argument #5 from usp | 76 | load_a4: user_lw(t5, 16(t0)) # argument #5 from usp |
| 77 | 4: user_lw(t6, 20(t0)) # argument #6 from usp | 77 | load_a5: user_lw(t6, 20(t0)) # argument #6 from usp |
| 78 | 3: user_lw(t7, 24(t0)) # argument #7 from usp | 78 | load_a6: user_lw(t7, 24(t0)) # argument #7 from usp |
| 79 | 2: user_lw(t8, 28(t0)) # argument #8 from usp | 79 | load_a7: user_lw(t8, 28(t0)) # argument #8 from usp |
| 80 | loads_done: | ||
| 80 | 81 | ||
| 81 | sw t5, 16(sp) # argument #5 to ksp | 82 | sw t5, 16(sp) # argument #5 to ksp |
| 82 | sw t6, 20(sp) # argument #6 to ksp | 83 | sw t6, 20(sp) # argument #6 to ksp |
| @@ -85,10 +86,10 @@ NESTED(handle_sys, PT_SIZE, sp) | |||
| 85 | .set pop | 86 | .set pop |
| 86 | 87 | ||
| 87 | .section __ex_table,"a" | 88 | .section __ex_table,"a" |
| 88 | PTR 1b,bad_stack | 89 | PTR load_a4, bad_stack_a4 |
| 89 | PTR 2b,bad_stack | 90 | PTR load_a5, bad_stack_a5 |
| 90 | PTR 3b,bad_stack | 91 | PTR load_a6, bad_stack_a6 |
| 91 | PTR 4b,bad_stack | 92 | PTR load_a7, bad_stack_a7 |
| 92 | .previous | 93 | .previous |
| 93 | 94 | ||
| 94 | lw t0, TI_FLAGS($28) # syscall tracing enabled? | 95 | lw t0, TI_FLAGS($28) # syscall tracing enabled? |
| @@ -153,8 +154,8 @@ syscall_trace_entry: | |||
| 153 | /* ------------------------------------------------------------------------ */ | 154 | /* ------------------------------------------------------------------------ */ |
| 154 | 155 | ||
| 155 | /* | 156 | /* |
| 156 | * The stackpointer for a call with more than 4 arguments is bad. | 157 | * Our open-coded access area sanity test for the stack pointer |
| 157 | * We probably should handle this case a bit more drastic. | 158 | * failed. We probably should handle this case a bit more drastic. |
| 158 | */ | 159 | */ |
| 159 | bad_stack: | 160 | bad_stack: |
| 160 | li v0, EFAULT | 161 | li v0, EFAULT |
| @@ -163,6 +164,22 @@ bad_stack: | |||
| 163 | sw t0, PT_R7(sp) | 164 | sw t0, PT_R7(sp) |
| 164 | j o32_syscall_exit | 165 | j o32_syscall_exit |
| 165 | 166 | ||
| 167 | bad_stack_a4: | ||
| 168 | li t5, 0 | ||
| 169 | b load_a5 | ||
| 170 | |||
| 171 | bad_stack_a5: | ||
| 172 | li t6, 0 | ||
| 173 | b load_a6 | ||
| 174 | |||
| 175 | bad_stack_a6: | ||
| 176 | li t7, 0 | ||
| 177 | b load_a7 | ||
| 178 | |||
| 179 | bad_stack_a7: | ||
| 180 | li t8, 0 | ||
| 181 | b loads_done | ||
| 182 | |||
| 166 | /* | 183 | /* |
| 167 | * The system call does not exist in this kernel | 184 | * The system call does not exist in this kernel |
| 168 | */ | 185 | */ |
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d07b210fbeff..f543ff4feef9 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S | |||
| @@ -69,16 +69,17 @@ NESTED(handle_sys, PT_SIZE, sp) | |||
| 69 | daddu t1, t0, 32 | 69 | daddu t1, t0, 32 |
| 70 | bltz t1, bad_stack | 70 | bltz t1, bad_stack |
| 71 | 71 | ||
| 72 | 1: lw a4, 16(t0) # argument #5 from usp | 72 | load_a4: lw a4, 16(t0) # argument #5 from usp |
| 73 | 2: lw a5, 20(t0) # argument #6 from usp | 73 | load_a5: lw a5, 20(t0) # argument #6 from usp |
| 74 | 3: lw a6, 24(t0) # argument #7 from usp | 74 | load_a6: lw a6, 24(t0) # argument #7 from usp |
| 75 | 4: lw a7, 28(t0) # argument #8 from usp (for indirect syscalls) | 75 | load_a7: lw a7, 28(t0) # argument #8 from usp |
| 76 | loads_done: | ||
| 76 | 77 | ||
| 77 | .section __ex_table,"a" | 78 | .section __ex_table,"a" |
| 78 | PTR 1b, bad_stack | 79 | PTR load_a4, bad_stack_a4 |
| 79 | PTR 2b, bad_stack | 80 | PTR load_a5, bad_stack_a5 |
| 80 | PTR 3b, bad_stack | 81 | PTR load_a6, bad_stack_a6 |
| 81 | PTR 4b, bad_stack | 82 | PTR load_a7, bad_stack_a7 |
| 82 | .previous | 83 | .previous |
| 83 | 84 | ||
| 84 | li t1, _TIF_WORK_SYSCALL_ENTRY | 85 | li t1, _TIF_WORK_SYSCALL_ENTRY |
| @@ -167,6 +168,22 @@ bad_stack: | |||
| 167 | sd t0, PT_R7(sp) | 168 | sd t0, PT_R7(sp) |
| 168 | j o32_syscall_exit | 169 | j o32_syscall_exit |
| 169 | 170 | ||
| 171 | bad_stack_a4: | ||
| 172 | li a4, 0 | ||
| 173 | b load_a5 | ||
| 174 | |||
| 175 | bad_stack_a5: | ||
| 176 | li a5, 0 | ||
| 177 | b load_a6 | ||
| 178 | |||
| 179 | bad_stack_a6: | ||
| 180 | li a6, 0 | ||
| 181 | b load_a7 | ||
| 182 | |||
| 183 | bad_stack_a7: | ||
| 184 | li a7, 0 | ||
| 185 | b loads_done | ||
| 186 | |||
| 170 | not_o32_scall: | 187 | not_o32_scall: |
| 171 | /* | 188 | /* |
| 172 | * This is not an o32 compatibility syscall, pass it on | 189 | * This is not an o32 compatibility syscall, pass it on |
| @@ -383,7 +400,7 @@ EXPORT(sys32_call_table) | |||
| 383 | PTR sys_connect /* 4170 */ | 400 | PTR sys_connect /* 4170 */ |
| 384 | PTR sys_getpeername | 401 | PTR sys_getpeername |
| 385 | PTR sys_getsockname | 402 | PTR sys_getsockname |
| 386 | PTR sys_getsockopt | 403 | PTR compat_sys_getsockopt |
| 387 | PTR sys_listen | 404 | PTR sys_listen |
| 388 | PTR compat_sys_recv /* 4175 */ | 405 | PTR compat_sys_recv /* 4175 */ |
| 389 | PTR compat_sys_recvfrom | 406 | PTR compat_sys_recvfrom |
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index be73c491182b..008b3378653a 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c | |||
| @@ -337,6 +337,11 @@ static void __init bootmem_init(void) | |||
| 337 | min_low_pfn = start; | 337 | min_low_pfn = start; |
| 338 | if (end <= reserved_end) | 338 | if (end <= reserved_end) |
| 339 | continue; | 339 | continue; |
| 340 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 341 | /* mapstart should be after initrd_end */ | ||
| 342 | if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end))) | ||
| 343 | continue; | ||
| 344 | #endif | ||
| 340 | if (start >= mapstart) | 345 | if (start >= mapstart) |
| 341 | continue; | 346 | continue; |
| 342 | mapstart = max(reserved_end, start); | 347 | mapstart = max(reserved_end, start); |
| @@ -366,14 +371,6 @@ static void __init bootmem_init(void) | |||
| 366 | max_low_pfn = PFN_DOWN(HIGHMEM_START); | 371 | max_low_pfn = PFN_DOWN(HIGHMEM_START); |
| 367 | } | 372 | } |
| 368 | 373 | ||
| 369 | #ifdef CONFIG_BLK_DEV_INITRD | ||
| 370 | /* | ||
| 371 | * mapstart should be after initrd_end | ||
| 372 | */ | ||
| 373 | if (initrd_end) | ||
| 374 | mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end))); | ||
| 375 | #endif | ||
| 376 | |||
| 377 | /* | 374 | /* |
| 378 | * Initialize the boot-time allocator with low memory only. | 375 | * Initialize the boot-time allocator with low memory only. |
| 379 | */ | 376 | */ |
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 4251d390b5b6..c88937745b4e 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c | |||
| @@ -133,7 +133,7 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) | |||
| 133 | /* | 133 | /* |
| 134 | * Patch the start of mips_cps_core_entry to provide: | 134 | * Patch the start of mips_cps_core_entry to provide: |
| 135 | * | 135 | * |
| 136 | * v0 = CM base address | 136 | * v1 = CM base address |
| 137 | * s0 = kseg0 CCA | 137 | * s0 = kseg0 CCA |
| 138 | */ | 138 | */ |
| 139 | entry_code = (u32 *)&mips_cps_core_entry; | 139 | entry_code = (u32 *)&mips_cps_core_entry; |
| @@ -369,7 +369,7 @@ void play_dead(void) | |||
| 369 | 369 | ||
| 370 | static void wait_for_sibling_halt(void *ptr_cpu) | 370 | static void wait_for_sibling_halt(void *ptr_cpu) |
| 371 | { | 371 | { |
| 372 | unsigned cpu = (unsigned)ptr_cpu; | 372 | unsigned cpu = (unsigned long)ptr_cpu; |
| 373 | unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); | 373 | unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); |
| 374 | unsigned halted; | 374 | unsigned halted; |
| 375 | unsigned long flags; | 375 | unsigned long flags; |
| @@ -430,7 +430,7 @@ static void cps_cpu_die(unsigned int cpu) | |||
| 430 | */ | 430 | */ |
| 431 | err = smp_call_function_single(cpu_death_sibling, | 431 | err = smp_call_function_single(cpu_death_sibling, |
| 432 | wait_for_sibling_halt, | 432 | wait_for_sibling_halt, |
| 433 | (void *)cpu, 1); | 433 | (void *)(unsigned long)cpu, 1); |
| 434 | if (err) | 434 | if (err) |
| 435 | panic("Failed to call remote sibling CPU\n"); | 435 | panic("Failed to call remote sibling CPU\n"); |
| 436 | } | 436 | } |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index faa46ebd9dda..d0744cc77ea7 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
| @@ -63,6 +63,13 @@ EXPORT_SYMBOL(cpu_sibling_map); | |||
| 63 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 63 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
| 64 | EXPORT_SYMBOL(cpu_core_map); | 64 | EXPORT_SYMBOL(cpu_core_map); |
| 65 | 65 | ||
| 66 | /* | ||
| 67 | * A logcal cpu mask containing only one VPE per core to | ||
| 68 | * reduce the number of IPIs on large MT systems. | ||
| 69 | */ | ||
| 70 | cpumask_t cpu_foreign_map __read_mostly; | ||
| 71 | EXPORT_SYMBOL(cpu_foreign_map); | ||
| 72 | |||
| 66 | /* representing cpus for which sibling maps can be computed */ | 73 | /* representing cpus for which sibling maps can be computed */ |
| 67 | static cpumask_t cpu_sibling_setup_map; | 74 | static cpumask_t cpu_sibling_setup_map; |
| 68 | 75 | ||
| @@ -103,6 +110,29 @@ static inline void set_cpu_core_map(int cpu) | |||
| 103 | } | 110 | } |
| 104 | } | 111 | } |
| 105 | 112 | ||
| 113 | /* | ||
| 114 | * Calculate a new cpu_foreign_map mask whenever a | ||
| 115 | * new cpu appears or disappears. | ||
| 116 | */ | ||
| 117 | static inline void calculate_cpu_foreign_map(void) | ||
| 118 | { | ||
| 119 | int i, k, core_present; | ||
| 120 | cpumask_t temp_foreign_map; | ||
| 121 | |||
| 122 | /* Re-calculate the mask */ | ||
| 123 | for_each_online_cpu(i) { | ||
| 124 | core_present = 0; | ||
| 125 | for_each_cpu(k, &temp_foreign_map) | ||
| 126 | if (cpu_data[i].package == cpu_data[k].package && | ||
| 127 | cpu_data[i].core == cpu_data[k].core) | ||
| 128 | core_present = 1; | ||
| 129 | if (!core_present) | ||
| 130 | cpumask_set_cpu(i, &temp_foreign_map); | ||
| 131 | } | ||
| 132 | |||
| 133 | cpumask_copy(&cpu_foreign_map, &temp_foreign_map); | ||
| 134 | } | ||
| 135 | |||
| 106 | struct plat_smp_ops *mp_ops; | 136 | struct plat_smp_ops *mp_ops; |
| 107 | EXPORT_SYMBOL(mp_ops); | 137 | EXPORT_SYMBOL(mp_ops); |
| 108 | 138 | ||
| @@ -146,6 +176,8 @@ asmlinkage void start_secondary(void) | |||
| 146 | set_cpu_sibling_map(cpu); | 176 | set_cpu_sibling_map(cpu); |
| 147 | set_cpu_core_map(cpu); | 177 | set_cpu_core_map(cpu); |
| 148 | 178 | ||
| 179 | calculate_cpu_foreign_map(); | ||
| 180 | |||
| 149 | cpumask_set_cpu(cpu, &cpu_callin_map); | 181 | cpumask_set_cpu(cpu, &cpu_callin_map); |
| 150 | 182 | ||
| 151 | synchronise_count_slave(cpu); | 183 | synchronise_count_slave(cpu); |
| @@ -173,9 +205,18 @@ void __irq_entry smp_call_function_interrupt(void) | |||
| 173 | static void stop_this_cpu(void *dummy) | 205 | static void stop_this_cpu(void *dummy) |
| 174 | { | 206 | { |
| 175 | /* | 207 | /* |
| 176 | * Remove this CPU: | 208 | * Remove this CPU. Be a bit slow here and |
| 209 | * set the bits for every online CPU so we don't miss | ||
| 210 | * any IPI whilst taking this VPE down. | ||
| 177 | */ | 211 | */ |
| 212 | |||
| 213 | cpumask_copy(&cpu_foreign_map, cpu_online_mask); | ||
| 214 | |||
| 215 | /* Make it visible to every other CPU */ | ||
| 216 | smp_mb(); | ||
| 217 | |||
| 178 | set_cpu_online(smp_processor_id(), false); | 218 | set_cpu_online(smp_processor_id(), false); |
| 219 | calculate_cpu_foreign_map(); | ||
| 179 | local_irq_disable(); | 220 | local_irq_disable(); |
| 180 | while (1); | 221 | while (1); |
| 181 | } | 222 | } |
| @@ -197,6 +238,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
| 197 | mp_ops->prepare_cpus(max_cpus); | 238 | mp_ops->prepare_cpus(max_cpus); |
| 198 | set_cpu_sibling_map(0); | 239 | set_cpu_sibling_map(0); |
| 199 | set_cpu_core_map(0); | 240 | set_cpu_core_map(0); |
| 241 | calculate_cpu_foreign_map(); | ||
| 200 | #ifndef CONFIG_HOTPLUG_CPU | 242 | #ifndef CONFIG_HOTPLUG_CPU |
| 201 | init_cpu_present(cpu_possible_mask); | 243 | init_cpu_present(cpu_possible_mask); |
| 202 | #endif | 244 | #endif |
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 2a7b38ed23f0..e207a43b5f8f 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
| @@ -2130,10 +2130,10 @@ void per_cpu_trap_init(bool is_boot_cpu) | |||
| 2130 | BUG_ON(current->mm); | 2130 | BUG_ON(current->mm); |
| 2131 | enter_lazy_tlb(&init_mm, current); | 2131 | enter_lazy_tlb(&init_mm, current); |
| 2132 | 2132 | ||
| 2133 | /* Boot CPU's cache setup in setup_arch(). */ | 2133 | /* Boot CPU's cache setup in setup_arch(). */ |
| 2134 | if (!is_boot_cpu) | 2134 | if (!is_boot_cpu) |
| 2135 | cpu_cache_init(); | 2135 | cpu_cache_init(); |
| 2136 | tlb_init(); | 2136 | tlb_init(); |
| 2137 | TLBMISS_HANDLER_SETUP(); | 2137 | TLBMISS_HANDLER_SETUP(); |
| 2138 | } | 2138 | } |
| 2139 | 2139 | ||
diff --git a/arch/mips/loongson64/common/bonito-irq.c b/arch/mips/loongson64/common/bonito-irq.c index cc0e4fd548e6..4e116d23bab3 100644 --- a/arch/mips/loongson64/common/bonito-irq.c +++ b/arch/mips/loongson64/common/bonito-irq.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | 3 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net |
| 4 | * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) | 4 | * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 6 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 7 | * Author: Fuxin Zhang, zhangfx@lemote.com | 7 | * Author: Fuxin Zhang, zhangfx@lemote.com |
| 8 | * | 8 | * |
| 9 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/arch/mips/loongson64/common/cmdline.c b/arch/mips/loongson64/common/cmdline.c index 72fed003a536..01fbed137028 100644 --- a/arch/mips/loongson64/common/cmdline.c +++ b/arch/mips/loongson64/common/cmdline.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Copyright 2003 ICT CAS | 6 | * Copyright 2003 ICT CAS |
| 7 | * Author: Michael Guo <guoyi@ict.ac.cn> | 7 | * Author: Michael Guo <guoyi@ict.ac.cn> |
| 8 | * | 8 | * |
| 9 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 9 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 10 | * Author: Fuxin Zhang, zhangfx@lemote.com | 10 | * Author: Fuxin Zhang, zhangfx@lemote.com |
| 11 | * | 11 | * |
| 12 | * Copyright (C) 2009 Lemote Inc. | 12 | * Copyright (C) 2009 Lemote Inc. |
diff --git a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c index 12c75db23420..875037063a80 100644 --- a/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c +++ b/arch/mips/loongson64/common/cs5536/cs5536_mfgpt.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * CS5536 General timer functions | 2 | * CS5536 General timer functions |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 4 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 5 | * Author: Yanhua, yanh@lemote.com | 5 | * Author: Yanhua, yanh@lemote.com |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2009 Lemote Inc. | 7 | * Copyright (C) 2009 Lemote Inc. |
diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c index 22f04ca2ff3e..f6c44dd332e2 100644 --- a/arch/mips/loongson64/common/env.c +++ b/arch/mips/loongson64/common/env.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Copyright 2003 ICT CAS | 6 | * Copyright 2003 ICT CAS |
| 7 | * Author: Michael Guo <guoyi@ict.ac.cn> | 7 | * Author: Michael Guo <guoyi@ict.ac.cn> |
| 8 | * | 8 | * |
| 9 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 9 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 10 | * Author: Fuxin Zhang, zhangfx@lemote.com | 10 | * Author: Fuxin Zhang, zhangfx@lemote.com |
| 11 | * | 11 | * |
| 12 | * Copyright (C) 2009 Lemote Inc. | 12 | * Copyright (C) 2009 Lemote Inc. |
diff --git a/arch/mips/loongson64/common/irq.c b/arch/mips/loongson64/common/irq.c index 687003b19b45..d36d969a4a87 100644 --- a/arch/mips/loongson64/common/irq.c +++ b/arch/mips/loongson64/common/irq.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 2 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 3 | * Author: Fuxin Zhang, zhangfx@lemote.com | 3 | * Author: Fuxin Zhang, zhangfx@lemote.com |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/arch/mips/loongson64/common/setup.c b/arch/mips/loongson64/common/setup.c index d477dd6bb326..2dc5122f0e09 100644 --- a/arch/mips/loongson64/common/setup.c +++ b/arch/mips/loongson64/common/setup.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 2 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 3 | * Author: Fuxin Zhang, zhangfx@lemote.com | 3 | * Author: Fuxin Zhang, zhangfx@lemote.com |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/arch/mips/loongson64/fuloong-2e/irq.c b/arch/mips/loongson64/fuloong-2e/irq.c index ef5ec8f3de5f..892963f860b7 100644 --- a/arch/mips/loongson64/fuloong-2e/irq.c +++ b/arch/mips/loongson64/fuloong-2e/irq.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology | 2 | * Copyright (C) 2007 Lemote Inc. & Institute of Computing Technology |
| 3 | * Author: Fuxin Zhang, zhangfx@lemote.com | 3 | * Author: Fuxin Zhang, zhangfx@lemote.com |
| 4 | * | 4 | * |
| 5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
diff --git a/arch/mips/loongson64/lemote-2f/clock.c b/arch/mips/loongson64/lemote-2f/clock.c index 462e34d46b4a..a78fb657068c 100644 --- a/arch/mips/loongson64/lemote-2f/clock.c +++ b/arch/mips/loongson64/lemote-2f/clock.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology | 2 | * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology |
| 3 | * Author: Yanhua, yanh@lemote.com | 3 | * Author: Yanhua, yanh@lemote.com |
| 4 | * | 4 | * |
| 5 | * This file is subject to the terms and conditions of the GNU General Public | 5 | * This file is subject to the terms and conditions of the GNU General Public |
| @@ -15,7 +15,7 @@ | |||
| 15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
| 16 | 16 | ||
| 17 | #include <asm/clock.h> | 17 | #include <asm/clock.h> |
| 18 | #include <asm/mach-loongson/loongson.h> | 18 | #include <asm/mach-loongson64/loongson.h> |
| 19 | 19 | ||
| 20 | static LIST_HEAD(clock_list); | 20 | static LIST_HEAD(clock_list); |
| 21 | static DEFINE_SPINLOCK(clock_lock); | 21 | static DEFINE_SPINLOCK(clock_lock); |
diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c index 12d14ed48778..6f9e010cec4d 100644 --- a/arch/mips/loongson64/loongson-3/numa.c +++ b/arch/mips/loongson64/loongson-3/numa.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & | 2 | * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & |
| 3 | * Insititute of Computing Technology | 3 | * Institute of Computing Technology |
| 4 | * Author: Xiang Gao, gaoxiang@ict.ac.cn | 4 | * Author: Xiang Gao, gaoxiang@ict.ac.cn |
| 5 | * Huacai Chen, chenhc@lemote.com | 5 | * Huacai Chen, chenhc@lemote.com |
| 6 | * Xiaofu Meng, Shuangshuang Zhang | 6 | * Xiaofu Meng, Shuangshuang Zhang |
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 22b9b2cb9219..712f17a2ecf2 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c | |||
| @@ -451,7 +451,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, | |||
| 451 | /* Fall through */ | 451 | /* Fall through */ |
| 452 | case jr_op: | 452 | case jr_op: |
| 453 | /* For R6, JR already emulated in jalr_op */ | 453 | /* For R6, JR already emulated in jalr_op */ |
| 454 | if (NO_R6EMU && insn.r_format.opcode == jr_op) | 454 | if (NO_R6EMU && insn.r_format.func == jr_op) |
| 455 | break; | 455 | break; |
| 456 | *contpc = regs->regs[insn.r_format.rs]; | 456 | *contpc = regs->regs[insn.r_format.rs]; |
| 457 | return 1; | 457 | return 1; |
| @@ -551,7 +551,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, | |||
| 551 | dec_insn.next_pc_inc; | 551 | dec_insn.next_pc_inc; |
| 552 | return 1; | 552 | return 1; |
| 553 | case blezl_op: | 553 | case blezl_op: |
| 554 | if (NO_R6EMU) | 554 | if (!insn.i_format.rt && NO_R6EMU) |
| 555 | break; | 555 | break; |
| 556 | case blez_op: | 556 | case blez_op: |
| 557 | 557 | ||
| @@ -588,7 +588,7 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, | |||
| 588 | dec_insn.next_pc_inc; | 588 | dec_insn.next_pc_inc; |
| 589 | return 1; | 589 | return 1; |
| 590 | case bgtzl_op: | 590 | case bgtzl_op: |
| 591 | if (NO_R6EMU) | 591 | if (!insn.i_format.rt && NO_R6EMU) |
| 592 | break; | 592 | break; |
| 593 | case bgtz_op: | 593 | case bgtz_op: |
| 594 | /* | 594 | /* |
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 7f660dc67596..fbea4432f3f2 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <asm/cacheflush.h> /* for run_uncached() */ | 37 | #include <asm/cacheflush.h> /* for run_uncached() */ |
| 38 | #include <asm/traps.h> | 38 | #include <asm/traps.h> |
| 39 | #include <asm/dma-coherence.h> | 39 | #include <asm/dma-coherence.h> |
| 40 | #include <asm/mips-cm.h> | ||
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| 42 | * Special Variant of smp_call_function for use by cache functions: | 43 | * Special Variant of smp_call_function for use by cache functions: |
| @@ -51,9 +52,16 @@ static inline void r4k_on_each_cpu(void (*func) (void *info), void *info) | |||
| 51 | { | 52 | { |
| 52 | preempt_disable(); | 53 | preempt_disable(); |
| 53 | 54 | ||
| 54 | #ifndef CONFIG_MIPS_MT_SMP | 55 | /* |
| 55 | smp_call_function(func, info, 1); | 56 | * The Coherent Manager propagates address-based cache ops to other |
| 56 | #endif | 57 | * cores but not index-based ops. However, r4k_on_each_cpu is used |
| 58 | * in both cases so there is no easy way to tell what kind of op is | ||
| 59 | * executed to the other cores. The best we can probably do is | ||
| 60 | * to restrict that call when a CM is not present because both | ||
| 61 | * CM-based SMP protocols (CMP & CPS) restrict index-based cache ops. | ||
| 62 | */ | ||
| 63 | if (!mips_cm_present()) | ||
| 64 | smp_call_function_many(&cpu_foreign_map, func, info, 1); | ||
| 57 | func(info); | 65 | func(info); |
| 58 | preempt_enable(); | 66 | preempt_enable(); |
| 59 | } | 67 | } |
| @@ -937,7 +945,9 @@ static void b5k_instruction_hazard(void) | |||
| 937 | } | 945 | } |
| 938 | 946 | ||
| 939 | static char *way_string[] = { NULL, "direct mapped", "2-way", | 947 | static char *way_string[] = { NULL, "direct mapped", "2-way", |
| 940 | "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" | 948 | "3-way", "4-way", "5-way", "6-way", "7-way", "8-way", |
| 949 | "9-way", "10-way", "11-way", "12-way", | ||
| 950 | "13-way", "14-way", "15-way", "16-way", | ||
| 941 | }; | 951 | }; |
| 942 | 952 | ||
| 943 | static void probe_pcache(void) | 953 | static void probe_pcache(void) |
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 185e68261f45..5625b190edc0 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c | |||
| @@ -119,18 +119,24 @@ void read_persistent_clock(struct timespec *ts) | |||
| 119 | 119 | ||
| 120 | int get_c0_fdc_int(void) | 120 | int get_c0_fdc_int(void) |
| 121 | { | 121 | { |
| 122 | int mips_cpu_fdc_irq; | 122 | /* |
| 123 | * Some cores claim the FDC is routable through the GIC, but it doesn't | ||
| 124 | * actually seem to be connected for those Malta bitstreams. | ||
| 125 | */ | ||
| 126 | switch (current_cpu_type()) { | ||
| 127 | case CPU_INTERAPTIV: | ||
| 128 | case CPU_PROAPTIV: | ||
| 129 | return -1; | ||
| 130 | }; | ||
| 123 | 131 | ||
| 124 | if (cpu_has_veic) | 132 | if (cpu_has_veic) |
| 125 | mips_cpu_fdc_irq = -1; | 133 | return -1; |
| 126 | else if (gic_present) | 134 | else if (gic_present) |
| 127 | mips_cpu_fdc_irq = gic_get_c0_fdc_int(); | 135 | return gic_get_c0_fdc_int(); |
| 128 | else if (cp0_fdc_irq >= 0) | 136 | else if (cp0_fdc_irq >= 0) |
| 129 | mips_cpu_fdc_irq = MIPS_CPU_IRQ_BASE + cp0_fdc_irq; | 137 | return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; |
| 130 | else | 138 | else |
| 131 | mips_cpu_fdc_irq = -1; | 139 | return -1; |
| 132 | |||
| 133 | return mips_cpu_fdc_irq; | ||
| 134 | } | 140 | } |
| 135 | 141 | ||
| 136 | int get_c0_perfcount_int(void) | 142 | int get_c0_perfcount_int(void) |
diff --git a/arch/mips/pistachio/init.c b/arch/mips/pistachio/init.c index d2dc836523a3..8bd8ebb20a72 100644 --- a/arch/mips/pistachio/init.c +++ b/arch/mips/pistachio/init.c | |||
| @@ -63,13 +63,19 @@ void __init plat_mem_setup(void) | |||
| 63 | plat_setup_iocoherency(); | 63 | plat_setup_iocoherency(); |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | #define DEFAULT_CPC_BASE_ADDR 0x1bde0000 | 66 | #define DEFAULT_CPC_BASE_ADDR 0x1bde0000 |
| 67 | #define DEFAULT_CDMM_BASE_ADDR 0x1bdd0000 | ||
| 67 | 68 | ||
| 68 | phys_addr_t mips_cpc_default_phys_base(void) | 69 | phys_addr_t mips_cpc_default_phys_base(void) |
| 69 | { | 70 | { |
| 70 | return DEFAULT_CPC_BASE_ADDR; | 71 | return DEFAULT_CPC_BASE_ADDR; |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 74 | phys_addr_t mips_cdmm_phys_base(void) | ||
| 75 | { | ||
| 76 | return DEFAULT_CDMM_BASE_ADDR; | ||
| 77 | } | ||
| 78 | |||
| 73 | static void __init mips_nmi_setup(void) | 79 | static void __init mips_nmi_setup(void) |
| 74 | { | 80 | { |
| 75 | void *base; | 81 | void *base; |
diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c index 67889fcea8aa..7c73fcb92a10 100644 --- a/arch/mips/pistachio/time.c +++ b/arch/mips/pistachio/time.c | |||
| @@ -27,6 +27,11 @@ int get_c0_perfcount_int(void) | |||
| 27 | return gic_get_c0_perfcount_int(); | 27 | return gic_get_c0_perfcount_int(); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | int get_c0_fdc_int(void) | ||
| 31 | { | ||
| 32 | return gic_get_c0_fdc_int(); | ||
| 33 | } | ||
| 34 | |||
| 30 | void __init plat_time_init(void) | 35 | void __init plat_time_init(void) |
| 31 | { | 36 | { |
| 32 | struct device_node *np; | 37 | struct device_node *np; |
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 0a183756d6ec..f93c4a4e6580 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
| 17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
| 18 | 18 | ||
| 19 | extern spinlock_t pa_dbit_lock; | 19 | extern spinlock_t pa_tlb_lock; |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel | 22 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel |
| @@ -33,6 +33,19 @@ extern spinlock_t pa_dbit_lock; | |||
| 33 | */ | 33 | */ |
| 34 | #define kern_addr_valid(addr) (1) | 34 | #define kern_addr_valid(addr) (1) |
| 35 | 35 | ||
| 36 | /* Purge data and instruction TLB entries. Must be called holding | ||
| 37 | * the pa_tlb_lock. The TLB purge instructions are slow on SMP | ||
| 38 | * machines since the purge must be broadcast to all CPUs. | ||
| 39 | */ | ||
| 40 | |||
| 41 | static inline void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | ||
| 42 | { | ||
| 43 | mtsp(mm->context, 1); | ||
| 44 | pdtlb(addr); | ||
| 45 | if (unlikely(split_tlb)) | ||
| 46 | pitlb(addr); | ||
| 47 | } | ||
| 48 | |||
| 36 | /* Certain architectures need to do special things when PTEs | 49 | /* Certain architectures need to do special things when PTEs |
| 37 | * within a page table are directly modified. Thus, the following | 50 | * within a page table are directly modified. Thus, the following |
| 38 | * hook is made available. | 51 | * hook is made available. |
| @@ -42,15 +55,20 @@ extern spinlock_t pa_dbit_lock; | |||
| 42 | *(pteptr) = (pteval); \ | 55 | *(pteptr) = (pteval); \ |
| 43 | } while(0) | 56 | } while(0) |
| 44 | 57 | ||
| 45 | extern void purge_tlb_entries(struct mm_struct *, unsigned long); | 58 | #define pte_inserted(x) \ |
| 59 | ((pte_val(x) & (_PAGE_PRESENT|_PAGE_ACCESSED)) \ | ||
| 60 | == (_PAGE_PRESENT|_PAGE_ACCESSED)) | ||
| 46 | 61 | ||
| 47 | #define set_pte_at(mm, addr, ptep, pteval) \ | 62 | #define set_pte_at(mm, addr, ptep, pteval) \ |
| 48 | do { \ | 63 | do { \ |
| 64 | pte_t old_pte; \ | ||
| 49 | unsigned long flags; \ | 65 | unsigned long flags; \ |
| 50 | spin_lock_irqsave(&pa_dbit_lock, flags); \ | 66 | spin_lock_irqsave(&pa_tlb_lock, flags); \ |
| 51 | set_pte(ptep, pteval); \ | 67 | old_pte = *ptep; \ |
| 52 | purge_tlb_entries(mm, addr); \ | 68 | set_pte(ptep, pteval); \ |
| 53 | spin_unlock_irqrestore(&pa_dbit_lock, flags); \ | 69 | if (pte_inserted(old_pte)) \ |
| 70 | purge_tlb_entries(mm, addr); \ | ||
| 71 | spin_unlock_irqrestore(&pa_tlb_lock, flags); \ | ||
| 54 | } while (0) | 72 | } while (0) |
| 55 | 73 | ||
| 56 | #endif /* !__ASSEMBLY__ */ | 74 | #endif /* !__ASSEMBLY__ */ |
| @@ -268,7 +286,7 @@ extern unsigned long *empty_zero_page; | |||
| 268 | 286 | ||
| 269 | #define pte_none(x) (pte_val(x) == 0) | 287 | #define pte_none(x) (pte_val(x) == 0) |
| 270 | #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) | 288 | #define pte_present(x) (pte_val(x) & _PAGE_PRESENT) |
| 271 | #define pte_clear(mm,addr,xp) do { pte_val(*(xp)) = 0; } while (0) | 289 | #define pte_clear(mm, addr, xp) set_pte_at(mm, addr, xp, __pte(0)) |
| 272 | 290 | ||
| 273 | #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) | 291 | #define pmd_flag(x) (pmd_val(x) & PxD_FLAG_MASK) |
| 274 | #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) | 292 | #define pmd_address(x) ((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT) |
| @@ -435,15 +453,15 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned | |||
| 435 | if (!pte_young(*ptep)) | 453 | if (!pte_young(*ptep)) |
| 436 | return 0; | 454 | return 0; |
| 437 | 455 | ||
| 438 | spin_lock_irqsave(&pa_dbit_lock, flags); | 456 | spin_lock_irqsave(&pa_tlb_lock, flags); |
| 439 | pte = *ptep; | 457 | pte = *ptep; |
| 440 | if (!pte_young(pte)) { | 458 | if (!pte_young(pte)) { |
| 441 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | 459 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
| 442 | return 0; | 460 | return 0; |
| 443 | } | 461 | } |
| 444 | set_pte(ptep, pte_mkold(pte)); | 462 | set_pte(ptep, pte_mkold(pte)); |
| 445 | purge_tlb_entries(vma->vm_mm, addr); | 463 | purge_tlb_entries(vma->vm_mm, addr); |
| 446 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | 464 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
| 447 | return 1; | 465 | return 1; |
| 448 | } | 466 | } |
| 449 | 467 | ||
| @@ -453,11 +471,12 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
| 453 | pte_t old_pte; | 471 | pte_t old_pte; |
| 454 | unsigned long flags; | 472 | unsigned long flags; |
| 455 | 473 | ||
| 456 | spin_lock_irqsave(&pa_dbit_lock, flags); | 474 | spin_lock_irqsave(&pa_tlb_lock, flags); |
| 457 | old_pte = *ptep; | 475 | old_pte = *ptep; |
| 458 | pte_clear(mm,addr,ptep); | 476 | set_pte(ptep, __pte(0)); |
| 459 | purge_tlb_entries(mm, addr); | 477 | if (pte_inserted(old_pte)) |
| 460 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | 478 | purge_tlb_entries(mm, addr); |
| 479 | spin_unlock_irqrestore(&pa_tlb_lock, flags); | ||
| 461 | 480 | ||
| 462 | return old_pte; | 481 | return old_pte; |
| 463 | } | 482 | } |
| @@ -465,10 +484,10 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
| 465 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 484 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
| 466 | { | 485 | { |
| 467 | unsigned long flags; | 486 | unsigned long flags; |
| 468 | spin_lock_irqsave(&pa_dbit_lock, flags); | 487 | spin_lock_irqsave(&pa_tlb_lock, flags); |
| 469 | set_pte(ptep, pte_wrprotect(*ptep)); | 488 | set_pte(ptep, pte_wrprotect(*ptep)); |
| 470 | purge_tlb_entries(mm, addr); | 489 | purge_tlb_entries(mm, addr); |
| 471 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | 490 | spin_unlock_irqrestore(&pa_tlb_lock, flags); |
| 472 | } | 491 | } |
| 473 | 492 | ||
| 474 | #define pte_same(A,B) (pte_val(A) == pte_val(B)) | 493 | #define pte_same(A,B) (pte_val(A) == pte_val(B)) |
diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index 9d086a599fa0..e84b96478193 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h | |||
| @@ -13,6 +13,9 @@ | |||
| 13 | * active at any one time on the Merced bus. This tlb purge | 13 | * active at any one time on the Merced bus. This tlb purge |
| 14 | * synchronisation is fairly lightweight and harmless so we activate | 14 | * synchronisation is fairly lightweight and harmless so we activate |
| 15 | * it on all systems not just the N class. | 15 | * it on all systems not just the N class. |
| 16 | |||
| 17 | * It is also used to ensure PTE updates are atomic and consistent | ||
| 18 | * with the TLB. | ||
| 16 | */ | 19 | */ |
| 17 | extern spinlock_t pa_tlb_lock; | 20 | extern spinlock_t pa_tlb_lock; |
| 18 | 21 | ||
| @@ -24,20 +27,24 @@ extern void flush_tlb_all_local(void *); | |||
| 24 | 27 | ||
| 25 | #define smp_flush_tlb_all() flush_tlb_all() | 28 | #define smp_flush_tlb_all() flush_tlb_all() |
| 26 | 29 | ||
| 30 | int __flush_tlb_range(unsigned long sid, | ||
| 31 | unsigned long start, unsigned long end); | ||
| 32 | |||
| 33 | #define flush_tlb_range(vma, start, end) \ | ||
| 34 | __flush_tlb_range((vma)->vm_mm->context, start, end) | ||
| 35 | |||
| 36 | #define flush_tlb_kernel_range(start, end) \ | ||
| 37 | __flush_tlb_range(0, start, end) | ||
| 38 | |||
| 27 | /* | 39 | /* |
| 28 | * flush_tlb_mm() | 40 | * flush_tlb_mm() |
| 29 | * | 41 | * |
| 30 | * XXX This code is NOT valid for HP-UX compatibility processes, | 42 | * The code to switch to a new context is NOT valid for processes |
| 31 | * (although it will probably work 99% of the time). HP-UX | 43 | * which play with the space id's. Thus, we have to preserve the |
| 32 | * processes are free to play with the space id's and save them | 44 | * space and just flush the entire tlb. However, the compilers, |
| 33 | * over long periods of time, etc. so we have to preserve the | 45 | * dynamic linker, etc, do not manipulate space id's, so there |
| 34 | * space and just flush the entire tlb. We need to check the | 46 | * could be a significant performance benefit in switching contexts |
| 35 | * personality in order to do that, but the personality is not | 47 | * and not flushing the whole tlb. |
| 36 | * currently being set correctly. | ||
| 37 | * | ||
| 38 | * Of course, Linux processes could do the same thing, but | ||
| 39 | * we don't support that (and the compilers, dynamic linker, | ||
| 40 | * etc. do not do that). | ||
| 41 | */ | 48 | */ |
| 42 | 49 | ||
| 43 | static inline void flush_tlb_mm(struct mm_struct *mm) | 50 | static inline void flush_tlb_mm(struct mm_struct *mm) |
| @@ -45,10 +52,18 @@ static inline void flush_tlb_mm(struct mm_struct *mm) | |||
| 45 | BUG_ON(mm == &init_mm); /* Should never happen */ | 52 | BUG_ON(mm == &init_mm); /* Should never happen */ |
| 46 | 53 | ||
| 47 | #if 1 || defined(CONFIG_SMP) | 54 | #if 1 || defined(CONFIG_SMP) |
| 55 | /* Except for very small threads, flushing the whole TLB is | ||
| 56 | * faster than using __flush_tlb_range. The pdtlb and pitlb | ||
| 57 | * instructions are very slow because of the TLB broadcast. | ||
| 58 | * It might be faster to do local range flushes on all CPUs | ||
| 59 | * on PA 2.0 systems. | ||
| 60 | */ | ||
| 48 | flush_tlb_all(); | 61 | flush_tlb_all(); |
| 49 | #else | 62 | #else |
| 50 | /* FIXME: currently broken, causing space id and protection ids | 63 | /* FIXME: currently broken, causing space id and protection ids |
| 51 | * to go out of sync, resulting in faults on userspace accesses. | 64 | * to go out of sync, resulting in faults on userspace accesses. |
| 65 | * This approach needs further investigation since running many | ||
| 66 | * small applications (e.g., GCC testsuite) is faster on HP-UX. | ||
| 52 | */ | 67 | */ |
| 53 | if (mm) { | 68 | if (mm) { |
| 54 | if (mm->context != 0) | 69 | if (mm->context != 0) |
| @@ -65,22 +80,12 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, | |||
| 65 | { | 80 | { |
| 66 | unsigned long flags, sid; | 81 | unsigned long flags, sid; |
| 67 | 82 | ||
| 68 | /* For one page, it's not worth testing the split_tlb variable */ | ||
| 69 | |||
| 70 | mb(); | ||
| 71 | sid = vma->vm_mm->context; | 83 | sid = vma->vm_mm->context; |
| 72 | purge_tlb_start(flags); | 84 | purge_tlb_start(flags); |
| 73 | mtsp(sid, 1); | 85 | mtsp(sid, 1); |
| 74 | pdtlb(addr); | 86 | pdtlb(addr); |
| 75 | pitlb(addr); | 87 | if (unlikely(split_tlb)) |
| 88 | pitlb(addr); | ||
| 76 | purge_tlb_end(flags); | 89 | purge_tlb_end(flags); |
| 77 | } | 90 | } |
| 78 | |||
| 79 | void __flush_tlb_range(unsigned long sid, | ||
| 80 | unsigned long start, unsigned long end); | ||
| 81 | |||
| 82 | #define flush_tlb_range(vma,start,end) __flush_tlb_range((vma)->vm_mm->context,start,end) | ||
| 83 | |||
| 84 | #define flush_tlb_kernel_range(start, end) __flush_tlb_range(0,start,end) | ||
| 85 | |||
| 86 | #endif | 91 | #endif |
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index f6448c7c62b5..cda6dbbe9842 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
| @@ -342,12 +342,15 @@ EXPORT_SYMBOL(flush_data_cache_local); | |||
| 342 | EXPORT_SYMBOL(flush_kernel_icache_range_asm); | 342 | EXPORT_SYMBOL(flush_kernel_icache_range_asm); |
| 343 | 343 | ||
| 344 | #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ | 344 | #define FLUSH_THRESHOLD 0x80000 /* 0.5MB */ |
| 345 | int parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; | 345 | static unsigned long parisc_cache_flush_threshold __read_mostly = FLUSH_THRESHOLD; |
| 346 | |||
| 347 | #define FLUSH_TLB_THRESHOLD (2*1024*1024) /* 2MB initial TLB threshold */ | ||
| 348 | static unsigned long parisc_tlb_flush_threshold __read_mostly = FLUSH_TLB_THRESHOLD; | ||
| 346 | 349 | ||
| 347 | void __init parisc_setup_cache_timing(void) | 350 | void __init parisc_setup_cache_timing(void) |
| 348 | { | 351 | { |
| 349 | unsigned long rangetime, alltime; | 352 | unsigned long rangetime, alltime; |
| 350 | unsigned long size; | 353 | unsigned long size, start; |
| 351 | 354 | ||
| 352 | alltime = mfctl(16); | 355 | alltime = mfctl(16); |
| 353 | flush_data_cache(); | 356 | flush_data_cache(); |
| @@ -364,14 +367,43 @@ void __init parisc_setup_cache_timing(void) | |||
| 364 | /* Racy, but if we see an intermediate value, it's ok too... */ | 367 | /* Racy, but if we see an intermediate value, it's ok too... */ |
| 365 | parisc_cache_flush_threshold = size * alltime / rangetime; | 368 | parisc_cache_flush_threshold = size * alltime / rangetime; |
| 366 | 369 | ||
| 367 | parisc_cache_flush_threshold = (parisc_cache_flush_threshold + L1_CACHE_BYTES - 1) &~ (L1_CACHE_BYTES - 1); | 370 | parisc_cache_flush_threshold = L1_CACHE_ALIGN(parisc_cache_flush_threshold); |
| 368 | if (!parisc_cache_flush_threshold) | 371 | if (!parisc_cache_flush_threshold) |
| 369 | parisc_cache_flush_threshold = FLUSH_THRESHOLD; | 372 | parisc_cache_flush_threshold = FLUSH_THRESHOLD; |
| 370 | 373 | ||
| 371 | if (parisc_cache_flush_threshold > cache_info.dc_size) | 374 | if (parisc_cache_flush_threshold > cache_info.dc_size) |
| 372 | parisc_cache_flush_threshold = cache_info.dc_size; | 375 | parisc_cache_flush_threshold = cache_info.dc_size; |
| 373 | 376 | ||
| 374 | printk(KERN_INFO "Setting cache flush threshold to %x (%d CPUs online)\n", parisc_cache_flush_threshold, num_online_cpus()); | 377 | printk(KERN_INFO "Setting cache flush threshold to %lu kB\n", |
| 378 | parisc_cache_flush_threshold/1024); | ||
| 379 | |||
| 380 | /* calculate TLB flush threshold */ | ||
| 381 | |||
| 382 | alltime = mfctl(16); | ||
| 383 | flush_tlb_all(); | ||
| 384 | alltime = mfctl(16) - alltime; | ||
| 385 | |||
| 386 | size = PAGE_SIZE; | ||
| 387 | start = (unsigned long) _text; | ||
| 388 | rangetime = mfctl(16); | ||
| 389 | while (start < (unsigned long) _end) { | ||
| 390 | flush_tlb_kernel_range(start, start + PAGE_SIZE); | ||
| 391 | start += PAGE_SIZE; | ||
| 392 | size += PAGE_SIZE; | ||
| 393 | } | ||
| 394 | rangetime = mfctl(16) - rangetime; | ||
| 395 | |||
| 396 | printk(KERN_DEBUG "Whole TLB flush %lu cycles, flushing %lu bytes %lu cycles\n", | ||
| 397 | alltime, size, rangetime); | ||
| 398 | |||
| 399 | parisc_tlb_flush_threshold = size * alltime / rangetime; | ||
| 400 | parisc_tlb_flush_threshold *= num_online_cpus(); | ||
| 401 | parisc_tlb_flush_threshold = PAGE_ALIGN(parisc_tlb_flush_threshold); | ||
| 402 | if (!parisc_tlb_flush_threshold) | ||
| 403 | parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; | ||
| 404 | |||
| 405 | printk(KERN_INFO "Setting TLB flush threshold to %lu kB\n", | ||
| 406 | parisc_tlb_flush_threshold/1024); | ||
| 375 | } | 407 | } |
| 376 | 408 | ||
| 377 | extern void purge_kernel_dcache_page_asm(unsigned long); | 409 | extern void purge_kernel_dcache_page_asm(unsigned long); |
| @@ -403,48 +435,45 @@ void copy_user_page(void *vto, void *vfrom, unsigned long vaddr, | |||
| 403 | } | 435 | } |
| 404 | EXPORT_SYMBOL(copy_user_page); | 436 | EXPORT_SYMBOL(copy_user_page); |
| 405 | 437 | ||
| 406 | void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | 438 | /* __flush_tlb_range() |
| 407 | { | 439 | * |
| 408 | unsigned long flags; | 440 | * returns 1 if all TLBs were flushed. |
| 409 | 441 | */ | |
| 410 | /* Note: purge_tlb_entries can be called at startup with | 442 | int __flush_tlb_range(unsigned long sid, unsigned long start, |
| 411 | no context. */ | 443 | unsigned long end) |
| 412 | |||
| 413 | purge_tlb_start(flags); | ||
| 414 | mtsp(mm->context, 1); | ||
| 415 | pdtlb(addr); | ||
| 416 | pitlb(addr); | ||
| 417 | purge_tlb_end(flags); | ||
| 418 | } | ||
| 419 | EXPORT_SYMBOL(purge_tlb_entries); | ||
| 420 | |||
| 421 | void __flush_tlb_range(unsigned long sid, unsigned long start, | ||
| 422 | unsigned long end) | ||
| 423 | { | 444 | { |
| 424 | unsigned long npages; | 445 | unsigned long flags, size; |
| 425 | 446 | ||
| 426 | npages = ((end - (start & PAGE_MASK)) + (PAGE_SIZE - 1)) >> PAGE_SHIFT; | 447 | size = (end - start); |
| 427 | if (npages >= 512) /* 2MB of space: arbitrary, should be tuned */ | 448 | if (size >= parisc_tlb_flush_threshold) { |
| 428 | flush_tlb_all(); | 449 | flush_tlb_all(); |
| 429 | else { | 450 | return 1; |
| 430 | unsigned long flags; | 451 | } |
| 431 | 452 | ||
| 453 | /* Purge TLB entries for small ranges using the pdtlb and | ||
| 454 | pitlb instructions. These instructions execute locally | ||
| 455 | but cause a purge request to be broadcast to other TLBs. */ | ||
| 456 | if (likely(!split_tlb)) { | ||
| 457 | while (start < end) { | ||
| 458 | purge_tlb_start(flags); | ||
| 459 | mtsp(sid, 1); | ||
| 460 | pdtlb(start); | ||
| 461 | purge_tlb_end(flags); | ||
| 462 | start += PAGE_SIZE; | ||
| 463 | } | ||
| 464 | return 0; | ||
| 465 | } | ||
| 466 | |||
| 467 | /* split TLB case */ | ||
| 468 | while (start < end) { | ||
| 432 | purge_tlb_start(flags); | 469 | purge_tlb_start(flags); |
| 433 | mtsp(sid, 1); | 470 | mtsp(sid, 1); |
| 434 | if (split_tlb) { | 471 | pdtlb(start); |
| 435 | while (npages--) { | 472 | pitlb(start); |
| 436 | pdtlb(start); | ||
| 437 | pitlb(start); | ||
| 438 | start += PAGE_SIZE; | ||
| 439 | } | ||
| 440 | } else { | ||
| 441 | while (npages--) { | ||
| 442 | pdtlb(start); | ||
| 443 | start += PAGE_SIZE; | ||
| 444 | } | ||
| 445 | } | ||
| 446 | purge_tlb_end(flags); | 473 | purge_tlb_end(flags); |
| 474 | start += PAGE_SIZE; | ||
| 447 | } | 475 | } |
| 476 | return 0; | ||
| 448 | } | 477 | } |
| 449 | 478 | ||
| 450 | static void cacheflush_h_tmp_function(void *dummy) | 479 | static void cacheflush_h_tmp_function(void *dummy) |
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 75819617f93b..c5ef4081b01d 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | .level 2.0 | 45 | .level 2.0 |
| 46 | #endif | 46 | #endif |
| 47 | 47 | ||
| 48 | .import pa_dbit_lock,data | 48 | .import pa_tlb_lock,data |
| 49 | 49 | ||
| 50 | /* space_to_prot macro creates a prot id from a space id */ | 50 | /* space_to_prot macro creates a prot id from a space id */ |
| 51 | 51 | ||
| @@ -420,8 +420,8 @@ | |||
| 420 | SHLREG %r9,PxD_VALUE_SHIFT,\pmd | 420 | SHLREG %r9,PxD_VALUE_SHIFT,\pmd |
| 421 | extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index | 421 | extru \va,31-PAGE_SHIFT,ASM_BITS_PER_PTE,\index |
| 422 | dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */ | 422 | dep %r0,31,PAGE_SHIFT,\pmd /* clear offset */ |
| 423 | shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd | 423 | shladd \index,BITS_PER_PTE_ENTRY,\pmd,\pmd /* pmd is now pte */ |
| 424 | LDREG %r0(\pmd),\pte /* pmd is now pte */ | 424 | LDREG %r0(\pmd),\pte |
| 425 | bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault | 425 | bb,>=,n \pte,_PAGE_PRESENT_BIT,\fault |
| 426 | .endm | 426 | .endm |
| 427 | 427 | ||
| @@ -453,57 +453,53 @@ | |||
| 453 | L2_ptep \pgd,\pte,\index,\va,\fault | 453 | L2_ptep \pgd,\pte,\index,\va,\fault |
| 454 | .endm | 454 | .endm |
| 455 | 455 | ||
| 456 | /* Acquire pa_dbit_lock lock. */ | 456 | /* Acquire pa_tlb_lock lock and recheck page is still present. */ |
| 457 | .macro dbit_lock spc,tmp,tmp1 | 457 | .macro tlb_lock spc,ptp,pte,tmp,tmp1,fault |
| 458 | #ifdef CONFIG_SMP | 458 | #ifdef CONFIG_SMP |
| 459 | cmpib,COND(=),n 0,\spc,2f | 459 | cmpib,COND(=),n 0,\spc,2f |
| 460 | load32 PA(pa_dbit_lock),\tmp | 460 | load32 PA(pa_tlb_lock),\tmp |
| 461 | 1: LDCW 0(\tmp),\tmp1 | 461 | 1: LDCW 0(\tmp),\tmp1 |
| 462 | cmpib,COND(=) 0,\tmp1,1b | 462 | cmpib,COND(=) 0,\tmp1,1b |
| 463 | nop | 463 | nop |
| 464 | LDREG 0(\ptp),\pte | ||
| 465 | bb,<,n \pte,_PAGE_PRESENT_BIT,2f | ||
| 466 | b \fault | ||
| 467 | stw \spc,0(\tmp) | ||
| 464 | 2: | 468 | 2: |
| 465 | #endif | 469 | #endif |
| 466 | .endm | 470 | .endm |
| 467 | 471 | ||
| 468 | /* Release pa_dbit_lock lock without reloading lock address. */ | 472 | /* Release pa_tlb_lock lock without reloading lock address. */ |
| 469 | .macro dbit_unlock0 spc,tmp | 473 | .macro tlb_unlock0 spc,tmp |
| 470 | #ifdef CONFIG_SMP | 474 | #ifdef CONFIG_SMP |
| 471 | or,COND(=) %r0,\spc,%r0 | 475 | or,COND(=) %r0,\spc,%r0 |
| 472 | stw \spc,0(\tmp) | 476 | stw \spc,0(\tmp) |
| 473 | #endif | 477 | #endif |
| 474 | .endm | 478 | .endm |
| 475 | 479 | ||
| 476 | /* Release pa_dbit_lock lock. */ | 480 | /* Release pa_tlb_lock lock. */ |
| 477 | .macro dbit_unlock1 spc,tmp | 481 | .macro tlb_unlock1 spc,tmp |
| 478 | #ifdef CONFIG_SMP | 482 | #ifdef CONFIG_SMP |
| 479 | load32 PA(pa_dbit_lock),\tmp | 483 | load32 PA(pa_tlb_lock),\tmp |
| 480 | dbit_unlock0 \spc,\tmp | 484 | tlb_unlock0 \spc,\tmp |
| 481 | #endif | 485 | #endif |
| 482 | .endm | 486 | .endm |
| 483 | 487 | ||
| 484 | /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and | 488 | /* Set the _PAGE_ACCESSED bit of the PTE. Be clever and |
| 485 | * don't needlessly dirty the cache line if it was already set */ | 489 | * don't needlessly dirty the cache line if it was already set */ |
| 486 | .macro update_ptep spc,ptep,pte,tmp,tmp1 | 490 | .macro update_accessed ptp,pte,tmp,tmp1 |
| 487 | #ifdef CONFIG_SMP | ||
| 488 | or,COND(=) %r0,\spc,%r0 | ||
| 489 | LDREG 0(\ptep),\pte | ||
| 490 | #endif | ||
| 491 | ldi _PAGE_ACCESSED,\tmp1 | 491 | ldi _PAGE_ACCESSED,\tmp1 |
| 492 | or \tmp1,\pte,\tmp | 492 | or \tmp1,\pte,\tmp |
| 493 | and,COND(<>) \tmp1,\pte,%r0 | 493 | and,COND(<>) \tmp1,\pte,%r0 |
| 494 | STREG \tmp,0(\ptep) | 494 | STREG \tmp,0(\ptp) |
| 495 | .endm | 495 | .endm |
| 496 | 496 | ||
| 497 | /* Set the dirty bit (and accessed bit). No need to be | 497 | /* Set the dirty bit (and accessed bit). No need to be |
| 498 | * clever, this is only used from the dirty fault */ | 498 | * clever, this is only used from the dirty fault */ |
| 499 | .macro update_dirty spc,ptep,pte,tmp | 499 | .macro update_dirty ptp,pte,tmp |
| 500 | #ifdef CONFIG_SMP | ||
| 501 | or,COND(=) %r0,\spc,%r0 | ||
| 502 | LDREG 0(\ptep),\pte | ||
| 503 | #endif | ||
| 504 | ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp | 500 | ldi _PAGE_ACCESSED|_PAGE_DIRTY,\tmp |
| 505 | or \tmp,\pte,\pte | 501 | or \tmp,\pte,\pte |
| 506 | STREG \pte,0(\ptep) | 502 | STREG \pte,0(\ptp) |
| 507 | .endm | 503 | .endm |
| 508 | 504 | ||
| 509 | /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) | 505 | /* bitshift difference between a PFN (based on kernel's PAGE_SIZE) |
| @@ -1148,14 +1144,14 @@ dtlb_miss_20w: | |||
| 1148 | 1144 | ||
| 1149 | L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w | 1145 | L3_ptep ptp,pte,t0,va,dtlb_check_alias_20w |
| 1150 | 1146 | ||
| 1151 | dbit_lock spc,t0,t1 | 1147 | tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20w |
| 1152 | update_ptep spc,ptp,pte,t0,t1 | 1148 | update_accessed ptp,pte,t0,t1 |
| 1153 | 1149 | ||
| 1154 | make_insert_tlb spc,pte,prot | 1150 | make_insert_tlb spc,pte,prot |
| 1155 | 1151 | ||
| 1156 | idtlbt pte,prot | 1152 | idtlbt pte,prot |
| 1157 | dbit_unlock1 spc,t0 | ||
| 1158 | 1153 | ||
| 1154 | tlb_unlock1 spc,t0 | ||
| 1159 | rfir | 1155 | rfir |
| 1160 | nop | 1156 | nop |
| 1161 | 1157 | ||
| @@ -1174,14 +1170,14 @@ nadtlb_miss_20w: | |||
| 1174 | 1170 | ||
| 1175 | L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w | 1171 | L3_ptep ptp,pte,t0,va,nadtlb_check_alias_20w |
| 1176 | 1172 | ||
| 1177 | dbit_lock spc,t0,t1 | 1173 | tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20w |
| 1178 | update_ptep spc,ptp,pte,t0,t1 | 1174 | update_accessed ptp,pte,t0,t1 |
| 1179 | 1175 | ||
| 1180 | make_insert_tlb spc,pte,prot | 1176 | make_insert_tlb spc,pte,prot |
| 1181 | 1177 | ||
| 1182 | idtlbt pte,prot | 1178 | idtlbt pte,prot |
| 1183 | dbit_unlock1 spc,t0 | ||
| 1184 | 1179 | ||
| 1180 | tlb_unlock1 spc,t0 | ||
| 1185 | rfir | 1181 | rfir |
| 1186 | nop | 1182 | nop |
| 1187 | 1183 | ||
| @@ -1202,20 +1198,20 @@ dtlb_miss_11: | |||
| 1202 | 1198 | ||
| 1203 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 | 1199 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_11 |
| 1204 | 1200 | ||
| 1205 | dbit_lock spc,t0,t1 | 1201 | tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_11 |
| 1206 | update_ptep spc,ptp,pte,t0,t1 | 1202 | update_accessed ptp,pte,t0,t1 |
| 1207 | 1203 | ||
| 1208 | make_insert_tlb_11 spc,pte,prot | 1204 | make_insert_tlb_11 spc,pte,prot |
| 1209 | 1205 | ||
| 1210 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | 1206 | mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ |
| 1211 | mtsp spc,%sr1 | 1207 | mtsp spc,%sr1 |
| 1212 | 1208 | ||
| 1213 | idtlba pte,(%sr1,va) | 1209 | idtlba pte,(%sr1,va) |
| 1214 | idtlbp prot,(%sr1,va) | 1210 | idtlbp prot,(%sr1,va) |
| 1215 | 1211 | ||
| 1216 | mtsp t0, %sr1 /* Restore sr1 */ | 1212 | mtsp t1, %sr1 /* Restore sr1 */ |
| 1217 | dbit_unlock1 spc,t0 | ||
| 1218 | 1213 | ||
| 1214 | tlb_unlock1 spc,t0 | ||
| 1219 | rfir | 1215 | rfir |
| 1220 | nop | 1216 | nop |
| 1221 | 1217 | ||
| @@ -1235,21 +1231,20 @@ nadtlb_miss_11: | |||
| 1235 | 1231 | ||
| 1236 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 | 1232 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_11 |
| 1237 | 1233 | ||
| 1238 | dbit_lock spc,t0,t1 | 1234 | tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_11 |
| 1239 | update_ptep spc,ptp,pte,t0,t1 | 1235 | update_accessed ptp,pte,t0,t1 |
| 1240 | 1236 | ||
| 1241 | make_insert_tlb_11 spc,pte,prot | 1237 | make_insert_tlb_11 spc,pte,prot |
| 1242 | 1238 | ||
| 1243 | 1239 | mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ | |
| 1244 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | ||
| 1245 | mtsp spc,%sr1 | 1240 | mtsp spc,%sr1 |
| 1246 | 1241 | ||
| 1247 | idtlba pte,(%sr1,va) | 1242 | idtlba pte,(%sr1,va) |
| 1248 | idtlbp prot,(%sr1,va) | 1243 | idtlbp prot,(%sr1,va) |
| 1249 | 1244 | ||
| 1250 | mtsp t0, %sr1 /* Restore sr1 */ | 1245 | mtsp t1, %sr1 /* Restore sr1 */ |
| 1251 | dbit_unlock1 spc,t0 | ||
| 1252 | 1246 | ||
| 1247 | tlb_unlock1 spc,t0 | ||
| 1253 | rfir | 1248 | rfir |
| 1254 | nop | 1249 | nop |
| 1255 | 1250 | ||
| @@ -1269,16 +1264,16 @@ dtlb_miss_20: | |||
| 1269 | 1264 | ||
| 1270 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 | 1265 | L2_ptep ptp,pte,t0,va,dtlb_check_alias_20 |
| 1271 | 1266 | ||
| 1272 | dbit_lock spc,t0,t1 | 1267 | tlb_lock spc,ptp,pte,t0,t1,dtlb_check_alias_20 |
| 1273 | update_ptep spc,ptp,pte,t0,t1 | 1268 | update_accessed ptp,pte,t0,t1 |
| 1274 | 1269 | ||
| 1275 | make_insert_tlb spc,pte,prot | 1270 | make_insert_tlb spc,pte,prot |
| 1276 | 1271 | ||
| 1277 | f_extend pte,t0 | 1272 | f_extend pte,t1 |
| 1278 | 1273 | ||
| 1279 | idtlbt pte,prot | 1274 | idtlbt pte,prot |
| 1280 | dbit_unlock1 spc,t0 | ||
| 1281 | 1275 | ||
| 1276 | tlb_unlock1 spc,t0 | ||
| 1282 | rfir | 1277 | rfir |
| 1283 | nop | 1278 | nop |
| 1284 | 1279 | ||
| @@ -1297,16 +1292,16 @@ nadtlb_miss_20: | |||
| 1297 | 1292 | ||
| 1298 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 | 1293 | L2_ptep ptp,pte,t0,va,nadtlb_check_alias_20 |
| 1299 | 1294 | ||
| 1300 | dbit_lock spc,t0,t1 | 1295 | tlb_lock spc,ptp,pte,t0,t1,nadtlb_check_alias_20 |
| 1301 | update_ptep spc,ptp,pte,t0,t1 | 1296 | update_accessed ptp,pte,t0,t1 |
| 1302 | 1297 | ||
| 1303 | make_insert_tlb spc,pte,prot | 1298 | make_insert_tlb spc,pte,prot |
| 1304 | 1299 | ||
| 1305 | f_extend pte,t0 | 1300 | f_extend pte,t1 |
| 1306 | 1301 | ||
| 1307 | idtlbt pte,prot | 1302 | idtlbt pte,prot |
| 1308 | dbit_unlock1 spc,t0 | ||
| 1309 | 1303 | ||
| 1304 | tlb_unlock1 spc,t0 | ||
| 1310 | rfir | 1305 | rfir |
| 1311 | nop | 1306 | nop |
| 1312 | 1307 | ||
| @@ -1406,14 +1401,14 @@ itlb_miss_20w: | |||
| 1406 | 1401 | ||
| 1407 | L3_ptep ptp,pte,t0,va,itlb_fault | 1402 | L3_ptep ptp,pte,t0,va,itlb_fault |
| 1408 | 1403 | ||
| 1409 | dbit_lock spc,t0,t1 | 1404 | tlb_lock spc,ptp,pte,t0,t1,itlb_fault |
| 1410 | update_ptep spc,ptp,pte,t0,t1 | 1405 | update_accessed ptp,pte,t0,t1 |
| 1411 | 1406 | ||
| 1412 | make_insert_tlb spc,pte,prot | 1407 | make_insert_tlb spc,pte,prot |
| 1413 | 1408 | ||
| 1414 | iitlbt pte,prot | 1409 | iitlbt pte,prot |
| 1415 | dbit_unlock1 spc,t0 | ||
| 1416 | 1410 | ||
| 1411 | tlb_unlock1 spc,t0 | ||
| 1417 | rfir | 1412 | rfir |
| 1418 | nop | 1413 | nop |
| 1419 | 1414 | ||
| @@ -1430,14 +1425,14 @@ naitlb_miss_20w: | |||
| 1430 | 1425 | ||
| 1431 | L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w | 1426 | L3_ptep ptp,pte,t0,va,naitlb_check_alias_20w |
| 1432 | 1427 | ||
| 1433 | dbit_lock spc,t0,t1 | 1428 | tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20w |
| 1434 | update_ptep spc,ptp,pte,t0,t1 | 1429 | update_accessed ptp,pte,t0,t1 |
| 1435 | 1430 | ||
| 1436 | make_insert_tlb spc,pte,prot | 1431 | make_insert_tlb spc,pte,prot |
| 1437 | 1432 | ||
| 1438 | iitlbt pte,prot | 1433 | iitlbt pte,prot |
| 1439 | dbit_unlock1 spc,t0 | ||
| 1440 | 1434 | ||
| 1435 | tlb_unlock1 spc,t0 | ||
| 1441 | rfir | 1436 | rfir |
| 1442 | nop | 1437 | nop |
| 1443 | 1438 | ||
| @@ -1458,20 +1453,20 @@ itlb_miss_11: | |||
| 1458 | 1453 | ||
| 1459 | L2_ptep ptp,pte,t0,va,itlb_fault | 1454 | L2_ptep ptp,pte,t0,va,itlb_fault |
| 1460 | 1455 | ||
| 1461 | dbit_lock spc,t0,t1 | 1456 | tlb_lock spc,ptp,pte,t0,t1,itlb_fault |
| 1462 | update_ptep spc,ptp,pte,t0,t1 | 1457 | update_accessed ptp,pte,t0,t1 |
| 1463 | 1458 | ||
| 1464 | make_insert_tlb_11 spc,pte,prot | 1459 | make_insert_tlb_11 spc,pte,prot |
| 1465 | 1460 | ||
| 1466 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | 1461 | mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ |
| 1467 | mtsp spc,%sr1 | 1462 | mtsp spc,%sr1 |
| 1468 | 1463 | ||
| 1469 | iitlba pte,(%sr1,va) | 1464 | iitlba pte,(%sr1,va) |
| 1470 | iitlbp prot,(%sr1,va) | 1465 | iitlbp prot,(%sr1,va) |
| 1471 | 1466 | ||
| 1472 | mtsp t0, %sr1 /* Restore sr1 */ | 1467 | mtsp t1, %sr1 /* Restore sr1 */ |
| 1473 | dbit_unlock1 spc,t0 | ||
| 1474 | 1468 | ||
| 1469 | tlb_unlock1 spc,t0 | ||
| 1475 | rfir | 1470 | rfir |
| 1476 | nop | 1471 | nop |
| 1477 | 1472 | ||
| @@ -1482,20 +1477,20 @@ naitlb_miss_11: | |||
| 1482 | 1477 | ||
| 1483 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 | 1478 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_11 |
| 1484 | 1479 | ||
| 1485 | dbit_lock spc,t0,t1 | 1480 | tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_11 |
| 1486 | update_ptep spc,ptp,pte,t0,t1 | 1481 | update_accessed ptp,pte,t0,t1 |
| 1487 | 1482 | ||
| 1488 | make_insert_tlb_11 spc,pte,prot | 1483 | make_insert_tlb_11 spc,pte,prot |
| 1489 | 1484 | ||
| 1490 | mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ | 1485 | mfsp %sr1,t1 /* Save sr1 so we can use it in tlb inserts */ |
| 1491 | mtsp spc,%sr1 | 1486 | mtsp spc,%sr1 |
| 1492 | 1487 | ||
| 1493 | iitlba pte,(%sr1,va) | 1488 | iitlba pte,(%sr1,va) |
| 1494 | iitlbp prot,(%sr1,va) | 1489 | iitlbp prot,(%sr1,va) |
| 1495 | 1490 | ||
| 1496 | mtsp t0, %sr1 /* Restore sr1 */ | 1491 | mtsp t1, %sr1 /* Restore sr1 */ |
| 1497 | dbit_unlock1 spc,t0 | ||
| 1498 | 1492 | ||
| 1493 | tlb_unlock1 spc,t0 | ||
| 1499 | rfir | 1494 | rfir |
| 1500 | nop | 1495 | nop |
| 1501 | 1496 | ||
| @@ -1516,16 +1511,16 @@ itlb_miss_20: | |||
| 1516 | 1511 | ||
| 1517 | L2_ptep ptp,pte,t0,va,itlb_fault | 1512 | L2_ptep ptp,pte,t0,va,itlb_fault |
| 1518 | 1513 | ||
| 1519 | dbit_lock spc,t0,t1 | 1514 | tlb_lock spc,ptp,pte,t0,t1,itlb_fault |
| 1520 | update_ptep spc,ptp,pte,t0,t1 | 1515 | update_accessed ptp,pte,t0,t1 |
| 1521 | 1516 | ||
| 1522 | make_insert_tlb spc,pte,prot | 1517 | make_insert_tlb spc,pte,prot |
| 1523 | 1518 | ||
| 1524 | f_extend pte,t0 | 1519 | f_extend pte,t1 |
| 1525 | 1520 | ||
| 1526 | iitlbt pte,prot | 1521 | iitlbt pte,prot |
| 1527 | dbit_unlock1 spc,t0 | ||
| 1528 | 1522 | ||
| 1523 | tlb_unlock1 spc,t0 | ||
| 1529 | rfir | 1524 | rfir |
| 1530 | nop | 1525 | nop |
| 1531 | 1526 | ||
| @@ -1536,16 +1531,16 @@ naitlb_miss_20: | |||
| 1536 | 1531 | ||
| 1537 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 | 1532 | L2_ptep ptp,pte,t0,va,naitlb_check_alias_20 |
| 1538 | 1533 | ||
| 1539 | dbit_lock spc,t0,t1 | 1534 | tlb_lock spc,ptp,pte,t0,t1,naitlb_check_alias_20 |
| 1540 | update_ptep spc,ptp,pte,t0,t1 | 1535 | update_accessed ptp,pte,t0,t1 |
| 1541 | 1536 | ||
| 1542 | make_insert_tlb spc,pte,prot | 1537 | make_insert_tlb spc,pte,prot |
| 1543 | 1538 | ||
| 1544 | f_extend pte,t0 | 1539 | f_extend pte,t1 |
| 1545 | 1540 | ||
| 1546 | iitlbt pte,prot | 1541 | iitlbt pte,prot |
| 1547 | dbit_unlock1 spc,t0 | ||
| 1548 | 1542 | ||
| 1543 | tlb_unlock1 spc,t0 | ||
| 1549 | rfir | 1544 | rfir |
| 1550 | nop | 1545 | nop |
| 1551 | 1546 | ||
| @@ -1568,14 +1563,14 @@ dbit_trap_20w: | |||
| 1568 | 1563 | ||
| 1569 | L3_ptep ptp,pte,t0,va,dbit_fault | 1564 | L3_ptep ptp,pte,t0,va,dbit_fault |
| 1570 | 1565 | ||
| 1571 | dbit_lock spc,t0,t1 | 1566 | tlb_lock spc,ptp,pte,t0,t1,dbit_fault |
| 1572 | update_dirty spc,ptp,pte,t1 | 1567 | update_dirty ptp,pte,t1 |
| 1573 | 1568 | ||
| 1574 | make_insert_tlb spc,pte,prot | 1569 | make_insert_tlb spc,pte,prot |
| 1575 | 1570 | ||
| 1576 | idtlbt pte,prot | 1571 | idtlbt pte,prot |
| 1577 | dbit_unlock0 spc,t0 | ||
| 1578 | 1572 | ||
| 1573 | tlb_unlock0 spc,t0 | ||
| 1579 | rfir | 1574 | rfir |
| 1580 | nop | 1575 | nop |
| 1581 | #else | 1576 | #else |
| @@ -1588,8 +1583,8 @@ dbit_trap_11: | |||
| 1588 | 1583 | ||
| 1589 | L2_ptep ptp,pte,t0,va,dbit_fault | 1584 | L2_ptep ptp,pte,t0,va,dbit_fault |
| 1590 | 1585 | ||
| 1591 | dbit_lock spc,t0,t1 | 1586 | tlb_lock spc,ptp,pte,t0,t1,dbit_fault |
| 1592 | update_dirty spc,ptp,pte,t1 | 1587 | update_dirty ptp,pte,t1 |
| 1593 | 1588 | ||
| 1594 | make_insert_tlb_11 spc,pte,prot | 1589 | make_insert_tlb_11 spc,pte,prot |
| 1595 | 1590 | ||
| @@ -1600,8 +1595,8 @@ dbit_trap_11: | |||
| 1600 | idtlbp prot,(%sr1,va) | 1595 | idtlbp prot,(%sr1,va) |
| 1601 | 1596 | ||
| 1602 | mtsp t1, %sr1 /* Restore sr1 */ | 1597 | mtsp t1, %sr1 /* Restore sr1 */ |
| 1603 | dbit_unlock0 spc,t0 | ||
| 1604 | 1598 | ||
| 1599 | tlb_unlock0 spc,t0 | ||
| 1605 | rfir | 1600 | rfir |
| 1606 | nop | 1601 | nop |
| 1607 | 1602 | ||
| @@ -1612,16 +1607,16 @@ dbit_trap_20: | |||
| 1612 | 1607 | ||
| 1613 | L2_ptep ptp,pte,t0,va,dbit_fault | 1608 | L2_ptep ptp,pte,t0,va,dbit_fault |
| 1614 | 1609 | ||
| 1615 | dbit_lock spc,t0,t1 | 1610 | tlb_lock spc,ptp,pte,t0,t1,dbit_fault |
| 1616 | update_dirty spc,ptp,pte,t1 | 1611 | update_dirty ptp,pte,t1 |
| 1617 | 1612 | ||
| 1618 | make_insert_tlb spc,pte,prot | 1613 | make_insert_tlb spc,pte,prot |
| 1619 | 1614 | ||
| 1620 | f_extend pte,t1 | 1615 | f_extend pte,t1 |
| 1621 | 1616 | ||
| 1622 | idtlbt pte,prot | 1617 | idtlbt pte,prot |
| 1623 | dbit_unlock0 spc,t0 | ||
| 1624 | 1618 | ||
| 1619 | tlb_unlock0 spc,t0 | ||
| 1625 | rfir | 1620 | rfir |
| 1626 | nop | 1621 | nop |
| 1627 | #endif | 1622 | #endif |
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 6548fd1d2e62..b99b39f1da02 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c | |||
| @@ -43,10 +43,6 @@ | |||
| 43 | 43 | ||
| 44 | #include "../math-emu/math-emu.h" /* for handle_fpe() */ | 44 | #include "../math-emu/math-emu.h" /* for handle_fpe() */ |
| 45 | 45 | ||
| 46 | #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK) | ||
| 47 | DEFINE_SPINLOCK(pa_dbit_lock); | ||
| 48 | #endif | ||
| 49 | |||
| 50 | static void parisc_show_stack(struct task_struct *task, unsigned long *sp, | 46 | static void parisc_show_stack(struct task_struct *task, unsigned long *sp, |
| 51 | struct pt_regs *regs); | 47 | struct pt_regs *regs); |
| 52 | 48 | ||
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index ccde8f084ce4..112ccf497562 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S | |||
| @@ -52,6 +52,22 @@ | |||
| 52 | .text | 52 | .text |
| 53 | 53 | ||
| 54 | /* | 54 | /* |
| 55 | * Used by threads when the lock bit of core_idle_state is set. | ||
| 56 | * Threads will spin in HMT_LOW until the lock bit is cleared. | ||
| 57 | * r14 - pointer to core_idle_state | ||
| 58 | * r15 - used to load contents of core_idle_state | ||
| 59 | */ | ||
| 60 | |||
| 61 | core_idle_lock_held: | ||
| 62 | HMT_LOW | ||
| 63 | 3: lwz r15,0(r14) | ||
| 64 | andi. r15,r15,PNV_CORE_IDLE_LOCK_BIT | ||
| 65 | bne 3b | ||
| 66 | HMT_MEDIUM | ||
| 67 | lwarx r15,0,r14 | ||
| 68 | blr | ||
| 69 | |||
| 70 | /* | ||
| 55 | * Pass requested state in r3: | 71 | * Pass requested state in r3: |
| 56 | * r3 - PNV_THREAD_NAP/SLEEP/WINKLE | 72 | * r3 - PNV_THREAD_NAP/SLEEP/WINKLE |
| 57 | * | 73 | * |
| @@ -150,6 +166,10 @@ power7_enter_nap_mode: | |||
| 150 | ld r14,PACA_CORE_IDLE_STATE_PTR(r13) | 166 | ld r14,PACA_CORE_IDLE_STATE_PTR(r13) |
| 151 | lwarx_loop1: | 167 | lwarx_loop1: |
| 152 | lwarx r15,0,r14 | 168 | lwarx r15,0,r14 |
| 169 | |||
| 170 | andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT | ||
| 171 | bnel core_idle_lock_held | ||
| 172 | |||
| 153 | andc r15,r15,r7 /* Clear thread bit */ | 173 | andc r15,r15,r7 /* Clear thread bit */ |
| 154 | 174 | ||
| 155 | andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS | 175 | andi. r15,r15,PNV_CORE_IDLE_THREAD_BITS |
| @@ -294,7 +314,7 @@ lwarx_loop2: | |||
| 294 | * workaround undo code or resyncing timebase or restoring context | 314 | * workaround undo code or resyncing timebase or restoring context |
| 295 | * In either case loop until the lock bit is cleared. | 315 | * In either case loop until the lock bit is cleared. |
| 296 | */ | 316 | */ |
| 297 | bne core_idle_lock_held | 317 | bnel core_idle_lock_held |
| 298 | 318 | ||
| 299 | cmpwi cr2,r15,0 | 319 | cmpwi cr2,r15,0 |
| 300 | lbz r4,PACA_SUBCORE_SIBLING_MASK(r13) | 320 | lbz r4,PACA_SUBCORE_SIBLING_MASK(r13) |
| @@ -319,15 +339,6 @@ lwarx_loop2: | |||
| 319 | isync | 339 | isync |
| 320 | b common_exit | 340 | b common_exit |
| 321 | 341 | ||
| 322 | core_idle_lock_held: | ||
| 323 | HMT_LOW | ||
| 324 | core_idle_lock_loop: | ||
| 325 | lwz r15,0(14) | ||
| 326 | andi. r9,r15,PNV_CORE_IDLE_LOCK_BIT | ||
| 327 | bne core_idle_lock_loop | ||
| 328 | HMT_MEDIUM | ||
| 329 | b lwarx_loop2 | ||
| 330 | |||
| 331 | first_thread_in_subcore: | 342 | first_thread_in_subcore: |
| 332 | /* First thread in subcore to wakeup */ | 343 | /* First thread in subcore to wakeup */ |
| 333 | ori r15,r15,PNV_CORE_IDLE_LOCK_BIT | 344 | ori r15,r15,PNV_CORE_IDLE_LOCK_BIT |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6530f1b8874d..37de90f8a845 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
| @@ -297,6 +297,8 @@ long machine_check_early(struct pt_regs *regs) | |||
| 297 | 297 | ||
| 298 | __this_cpu_inc(irq_stat.mce_exceptions); | 298 | __this_cpu_inc(irq_stat.mce_exceptions); |
| 299 | 299 | ||
| 300 | add_taint(TAINT_MACHINE_CHECK, LOCKDEP_NOW_UNRELIABLE); | ||
| 301 | |||
| 300 | if (cur_cpu_spec && cur_cpu_spec->machine_check_early) | 302 | if (cur_cpu_spec && cur_cpu_spec->machine_check_early) |
| 301 | handled = cur_cpu_spec->machine_check_early(regs); | 303 | handled = cur_cpu_spec->machine_check_early(regs); |
| 302 | return handled; | 304 | return handled; |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 6d535973b200..a67c6d781c52 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -529,6 +529,10 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | |||
| 529 | printk(KERN_ALERT "Unable to handle kernel paging request for " | 529 | printk(KERN_ALERT "Unable to handle kernel paging request for " |
| 530 | "instruction fetch\n"); | 530 | "instruction fetch\n"); |
| 531 | break; | 531 | break; |
| 532 | case 0x600: | ||
| 533 | printk(KERN_ALERT "Unable to handle kernel paging request for " | ||
| 534 | "unaligned access at address 0x%08lx\n", regs->dar); | ||
| 535 | break; | ||
| 532 | default: | 536 | default: |
| 533 | printk(KERN_ALERT "Unable to handle kernel paging request for " | 537 | printk(KERN_ALERT "Unable to handle kernel paging request for " |
| 534 | "unknown fault\n"); | 538 | "unknown fault\n"); |
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index ec2eb20631d1..df956295c2a7 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c | |||
| @@ -320,6 +320,8 @@ static struct attribute *device_str_attr_create_(char *name, char *str) | |||
| 320 | if (!attr) | 320 | if (!attr) |
| 321 | return NULL; | 321 | return NULL; |
| 322 | 322 | ||
| 323 | sysfs_attr_init(&attr->attr.attr); | ||
| 324 | |||
| 323 | attr->var = str; | 325 | attr->var = str; |
| 324 | attr->attr.attr.name = name; | 326 | attr->attr.attr.name = name; |
| 325 | attr->attr.attr.mode = 0444; | 327 | attr->attr.attr.mode = 0444; |
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c index 4949ef0d9400..37f959bf392e 100644 --- a/arch/powerpc/platforms/powernv/opal-elog.c +++ b/arch/powerpc/platforms/powernv/opal-elog.c | |||
| @@ -237,7 +237,7 @@ static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) | |||
| 237 | return elog; | 237 | return elog; |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | static void elog_work_fn(struct work_struct *work) | 240 | static irqreturn_t elog_event(int irq, void *data) |
| 241 | { | 241 | { |
| 242 | __be64 size; | 242 | __be64 size; |
| 243 | __be64 id; | 243 | __be64 id; |
| @@ -251,7 +251,7 @@ static void elog_work_fn(struct work_struct *work) | |||
| 251 | rc = opal_get_elog_size(&id, &size, &type); | 251 | rc = opal_get_elog_size(&id, &size, &type); |
| 252 | if (rc != OPAL_SUCCESS) { | 252 | if (rc != OPAL_SUCCESS) { |
| 253 | pr_err("ELOG: OPAL log info read failed\n"); | 253 | pr_err("ELOG: OPAL log info read failed\n"); |
| 254 | return; | 254 | return IRQ_HANDLED; |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | elog_size = be64_to_cpu(size); | 257 | elog_size = be64_to_cpu(size); |
| @@ -270,16 +270,10 @@ static void elog_work_fn(struct work_struct *work) | |||
| 270 | * entries. | 270 | * entries. |
| 271 | */ | 271 | */ |
| 272 | if (kset_find_obj(elog_kset, name)) | 272 | if (kset_find_obj(elog_kset, name)) |
| 273 | return; | 273 | return IRQ_HANDLED; |
| 274 | 274 | ||
| 275 | create_elog_obj(log_id, elog_size, elog_type); | 275 | create_elog_obj(log_id, elog_size, elog_type); |
| 276 | } | ||
| 277 | |||
| 278 | static DECLARE_WORK(elog_work, elog_work_fn); | ||
| 279 | 276 | ||
| 280 | static irqreturn_t elog_event(int irq, void *data) | ||
| 281 | { | ||
| 282 | schedule_work(&elog_work); | ||
| 283 | return IRQ_HANDLED; | 277 | return IRQ_HANDLED; |
| 284 | } | 278 | } |
| 285 | 279 | ||
| @@ -304,8 +298,8 @@ int __init opal_elog_init(void) | |||
| 304 | return irq; | 298 | return irq; |
| 305 | } | 299 | } |
| 306 | 300 | ||
| 307 | rc = request_irq(irq, elog_event, | 301 | rc = request_threaded_irq(irq, NULL, elog_event, |
| 308 | IRQ_TYPE_LEVEL_HIGH, "opal-elog", NULL); | 302 | IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "opal-elog", NULL); |
| 309 | if (rc) { | 303 | if (rc) { |
| 310 | pr_err("%s: Can't request OPAL event irq (%d)\n", | 304 | pr_err("%s: Can't request OPAL event irq (%d)\n", |
| 311 | __func__, rc); | 305 | __func__, rc); |
diff --git a/arch/powerpc/platforms/powernv/opal-prd.c b/arch/powerpc/platforms/powernv/opal-prd.c index 46cb3feb0a13..4ece8e40dd54 100644 --- a/arch/powerpc/platforms/powernv/opal-prd.c +++ b/arch/powerpc/platforms/powernv/opal-prd.c | |||
| @@ -112,6 +112,7 @@ static int opal_prd_open(struct inode *inode, struct file *file) | |||
| 112 | static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) | 112 | static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) |
| 113 | { | 113 | { |
| 114 | size_t addr, size; | 114 | size_t addr, size; |
| 115 | pgprot_t page_prot; | ||
| 115 | int rc; | 116 | int rc; |
| 116 | 117 | ||
| 117 | pr_devel("opal_prd_mmap(0x%016lx, 0x%016lx, 0x%lx, 0x%lx)\n", | 118 | pr_devel("opal_prd_mmap(0x%016lx, 0x%016lx, 0x%lx, 0x%lx)\n", |
| @@ -125,13 +126,11 @@ static int opal_prd_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 125 | if (!opal_prd_range_is_valid(addr, size)) | 126 | if (!opal_prd_range_is_valid(addr, size)) |
| 126 | return -EINVAL; | 127 | return -EINVAL; |
| 127 | 128 | ||
| 128 | vma->vm_page_prot = __pgprot(pgprot_val(phys_mem_access_prot(file, | 129 | page_prot = phys_mem_access_prot(file, vma->vm_pgoff, |
| 129 | vma->vm_pgoff, | 130 | size, vma->vm_page_prot); |
| 130 | size, vma->vm_page_prot)) | ||
| 131 | | _PAGE_SPECIAL); | ||
| 132 | 131 | ||
| 133 | rc = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, | 132 | rc = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, size, |
| 134 | vma->vm_page_prot); | 133 | page_prot); |
| 135 | 134 | ||
| 136 | return rc; | 135 | return rc; |
| 137 | } | 136 | } |
diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c index 2bc33674ebfc..87f9623ca805 100644 --- a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c +++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/pci.h> | 18 | #include <linux/pci.h> |
| 19 | #include <linux/semaphore.h> | 19 | #include <linux/semaphore.h> |
| 20 | #include <asm/msi_bitmap.h> | 20 | #include <asm/msi_bitmap.h> |
| 21 | #include <asm/ppc-pci.h> | ||
| 21 | 22 | ||
| 22 | struct ppc4xx_hsta_msi { | 23 | struct ppc4xx_hsta_msi { |
| 23 | struct device *dev; | 24 | struct device *dev; |
diff --git a/arch/tile/lib/memcpy_user_64.c b/arch/tile/lib/memcpy_user_64.c index 88c7016492c4..97bbb6060b25 100644 --- a/arch/tile/lib/memcpy_user_64.c +++ b/arch/tile/lib/memcpy_user_64.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #define _ST(p, inst, v) \ | 28 | #define _ST(p, inst, v) \ |
| 29 | ({ \ | 29 | ({ \ |
| 30 | asm("1: " #inst " %0, %1;" \ | 30 | asm("1: " #inst " %0, %1;" \ |
| 31 | ".pushsection .coldtext.memcpy,\"ax\";" \ | 31 | ".pushsection .coldtext,\"ax\";" \ |
| 32 | "2: { move r0, %2; jrp lr };" \ | 32 | "2: { move r0, %2; jrp lr };" \ |
| 33 | ".section __ex_table,\"a\";" \ | 33 | ".section __ex_table,\"a\";" \ |
| 34 | ".align 8;" \ | 34 | ".align 8;" \ |
| @@ -41,7 +41,7 @@ | |||
| 41 | ({ \ | 41 | ({ \ |
| 42 | unsigned long __v; \ | 42 | unsigned long __v; \ |
| 43 | asm("1: " #inst " %0, %1;" \ | 43 | asm("1: " #inst " %0, %1;" \ |
| 44 | ".pushsection .coldtext.memcpy,\"ax\";" \ | 44 | ".pushsection .coldtext,\"ax\";" \ |
| 45 | "2: { move r0, %2; jrp lr };" \ | 45 | "2: { move r0, %2; jrp lr };" \ |
| 46 | ".section __ex_table,\"a\";" \ | 46 | ".section __ex_table,\"a\";" \ |
| 47 | ".align 8;" \ | 47 | ".align 8;" \ |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 55bced17dc95..3dbb7e7909ca 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -254,6 +254,11 @@ config ARCH_SUPPORTS_OPTIMIZED_INLINING | |||
| 254 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC | 254 | config ARCH_SUPPORTS_DEBUG_PAGEALLOC |
| 255 | def_bool y | 255 | def_bool y |
| 256 | 256 | ||
| 257 | config KASAN_SHADOW_OFFSET | ||
| 258 | hex | ||
| 259 | depends on KASAN | ||
| 260 | default 0xdffffc0000000000 | ||
| 261 | |||
| 257 | config HAVE_INTEL_TXT | 262 | config HAVE_INTEL_TXT |
| 258 | def_bool y | 263 | def_bool y |
| 259 | depends on INTEL_IOMMU && ACPI | 264 | depends on INTEL_IOMMU && ACPI |
| @@ -2015,7 +2020,7 @@ config CMDLINE_BOOL | |||
| 2015 | 2020 | ||
| 2016 | To compile command line arguments into the kernel, | 2021 | To compile command line arguments into the kernel, |
| 2017 | set this option to 'Y', then fill in the | 2022 | set this option to 'Y', then fill in the |
| 2018 | the boot arguments in CONFIG_CMDLINE. | 2023 | boot arguments in CONFIG_CMDLINE. |
| 2019 | 2024 | ||
| 2020 | Systems with fully functional boot loaders (i.e. non-embedded) | 2025 | Systems with fully functional boot loaders (i.e. non-embedded) |
| 2021 | should leave this option set to 'N'. | 2026 | should leave this option set to 'N'. |
diff --git a/arch/x86/include/asm/espfix.h b/arch/x86/include/asm/espfix.h index 99efebb2f69d..ca3ce9ab9385 100644 --- a/arch/x86/include/asm/espfix.h +++ b/arch/x86/include/asm/espfix.h | |||
| @@ -9,7 +9,7 @@ DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_stack); | |||
| 9 | DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); | 9 | DECLARE_PER_CPU_READ_MOSTLY(unsigned long, espfix_waddr); |
| 10 | 10 | ||
| 11 | extern void init_espfix_bsp(void); | 11 | extern void init_espfix_bsp(void); |
| 12 | extern void init_espfix_ap(void); | 12 | extern void init_espfix_ap(int cpu); |
| 13 | 13 | ||
| 14 | #endif /* CONFIG_X86_64 */ | 14 | #endif /* CONFIG_X86_64 */ |
| 15 | 15 | ||
diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h index 8b22422fbad8..74a2a8dc9908 100644 --- a/arch/x86/include/asm/kasan.h +++ b/arch/x86/include/asm/kasan.h | |||
| @@ -14,15 +14,11 @@ | |||
| 14 | 14 | ||
| 15 | #ifndef __ASSEMBLY__ | 15 | #ifndef __ASSEMBLY__ |
| 16 | 16 | ||
| 17 | extern pte_t kasan_zero_pte[]; | ||
| 18 | extern pte_t kasan_zero_pmd[]; | ||
| 19 | extern pte_t kasan_zero_pud[]; | ||
| 20 | |||
| 21 | #ifdef CONFIG_KASAN | 17 | #ifdef CONFIG_KASAN |
| 22 | void __init kasan_map_early_shadow(pgd_t *pgd); | 18 | void __init kasan_early_init(void); |
| 23 | void __init kasan_init(void); | 19 | void __init kasan_init(void); |
| 24 | #else | 20 | #else |
| 25 | static inline void kasan_map_early_shadow(pgd_t *pgd) { } | 21 | static inline void kasan_early_init(void) { } |
| 26 | static inline void kasan_init(void) { } | 22 | static inline void kasan_init(void) { } |
| 27 | #endif | 23 | #endif |
| 28 | 24 | ||
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 28eba2d38b15..f813261d9740 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
| @@ -409,12 +409,6 @@ static void __setup_vector_irq(int cpu) | |||
| 409 | int irq, vector; | 409 | int irq, vector; |
| 410 | struct apic_chip_data *data; | 410 | struct apic_chip_data *data; |
| 411 | 411 | ||
| 412 | /* | ||
| 413 | * vector_lock will make sure that we don't run into irq vector | ||
| 414 | * assignments that might be happening on another cpu in parallel, | ||
| 415 | * while we setup our initial vector to irq mappings. | ||
| 416 | */ | ||
| 417 | raw_spin_lock(&vector_lock); | ||
| 418 | /* Mark the inuse vectors */ | 412 | /* Mark the inuse vectors */ |
| 419 | for_each_active_irq(irq) { | 413 | for_each_active_irq(irq) { |
| 420 | data = apic_chip_data(irq_get_irq_data(irq)); | 414 | data = apic_chip_data(irq_get_irq_data(irq)); |
| @@ -436,16 +430,16 @@ static void __setup_vector_irq(int cpu) | |||
| 436 | if (!cpumask_test_cpu(cpu, data->domain)) | 430 | if (!cpumask_test_cpu(cpu, data->domain)) |
| 437 | per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; | 431 | per_cpu(vector_irq, cpu)[vector] = VECTOR_UNDEFINED; |
| 438 | } | 432 | } |
| 439 | raw_spin_unlock(&vector_lock); | ||
| 440 | } | 433 | } |
| 441 | 434 | ||
| 442 | /* | 435 | /* |
| 443 | * Setup the vector to irq mappings. | 436 | * Setup the vector to irq mappings. Must be called with vector_lock held. |
| 444 | */ | 437 | */ |
| 445 | void setup_vector_irq(int cpu) | 438 | void setup_vector_irq(int cpu) |
| 446 | { | 439 | { |
| 447 | int irq; | 440 | int irq; |
| 448 | 441 | ||
| 442 | lockdep_assert_held(&vector_lock); | ||
| 449 | /* | 443 | /* |
| 450 | * On most of the platforms, legacy PIC delivers the interrupts on the | 444 | * On most of the platforms, legacy PIC delivers the interrupts on the |
| 451 | * boot cpu. But there are certain platforms where PIC interrupts are | 445 | * boot cpu. But there are certain platforms where PIC interrupts are |
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 89427d8d4fc5..eec40f595ab9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c | |||
| @@ -175,7 +175,9 @@ static __init void early_serial_init(char *s) | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | if (*s) { | 177 | if (*s) { |
| 178 | if (kstrtoul(s, 0, &baud) < 0 || baud == 0) | 178 | baud = simple_strtoull(s, &e, 0); |
| 179 | |||
| 180 | if (baud == 0 || s == e) | ||
| 179 | baud = DEFAULT_BAUD; | 181 | baud = DEFAULT_BAUD; |
| 180 | } | 182 | } |
| 181 | 183 | ||
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c index f5d0730e7b08..ce95676abd60 100644 --- a/arch/x86/kernel/espfix_64.c +++ b/arch/x86/kernel/espfix_64.c | |||
| @@ -131,25 +131,24 @@ void __init init_espfix_bsp(void) | |||
| 131 | init_espfix_random(); | 131 | init_espfix_random(); |
| 132 | 132 | ||
| 133 | /* The rest is the same as for any other processor */ | 133 | /* The rest is the same as for any other processor */ |
| 134 | init_espfix_ap(); | 134 | init_espfix_ap(0); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | void init_espfix_ap(void) | 137 | void init_espfix_ap(int cpu) |
| 138 | { | 138 | { |
| 139 | unsigned int cpu, page; | 139 | unsigned int page; |
| 140 | unsigned long addr; | 140 | unsigned long addr; |
| 141 | pud_t pud, *pud_p; | 141 | pud_t pud, *pud_p; |
| 142 | pmd_t pmd, *pmd_p; | 142 | pmd_t pmd, *pmd_p; |
| 143 | pte_t pte, *pte_p; | 143 | pte_t pte, *pte_p; |
| 144 | int n; | 144 | int n, node; |
| 145 | void *stack_page; | 145 | void *stack_page; |
| 146 | pteval_t ptemask; | 146 | pteval_t ptemask; |
| 147 | 147 | ||
| 148 | /* We only have to do this once... */ | 148 | /* We only have to do this once... */ |
| 149 | if (likely(this_cpu_read(espfix_stack))) | 149 | if (likely(per_cpu(espfix_stack, cpu))) |
| 150 | return; /* Already initialized */ | 150 | return; /* Already initialized */ |
| 151 | 151 | ||
| 152 | cpu = smp_processor_id(); | ||
| 153 | addr = espfix_base_addr(cpu); | 152 | addr = espfix_base_addr(cpu); |
| 154 | page = cpu/ESPFIX_STACKS_PER_PAGE; | 153 | page = cpu/ESPFIX_STACKS_PER_PAGE; |
| 155 | 154 | ||
| @@ -165,12 +164,15 @@ void init_espfix_ap(void) | |||
| 165 | if (stack_page) | 164 | if (stack_page) |
| 166 | goto unlock_done; | 165 | goto unlock_done; |
| 167 | 166 | ||
| 167 | node = cpu_to_node(cpu); | ||
| 168 | ptemask = __supported_pte_mask; | 168 | ptemask = __supported_pte_mask; |
| 169 | 169 | ||
| 170 | pud_p = &espfix_pud_page[pud_index(addr)]; | 170 | pud_p = &espfix_pud_page[pud_index(addr)]; |
| 171 | pud = *pud_p; | 171 | pud = *pud_p; |
| 172 | if (!pud_present(pud)) { | 172 | if (!pud_present(pud)) { |
| 173 | pmd_p = (pmd_t *)__get_free_page(PGALLOC_GFP); | 173 | struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); |
| 174 | |||
| 175 | pmd_p = (pmd_t *)page_address(page); | ||
| 174 | pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); | 176 | pud = __pud(__pa(pmd_p) | (PGTABLE_PROT & ptemask)); |
| 175 | paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); | 177 | paravirt_alloc_pmd(&init_mm, __pa(pmd_p) >> PAGE_SHIFT); |
| 176 | for (n = 0; n < ESPFIX_PUD_CLONES; n++) | 178 | for (n = 0; n < ESPFIX_PUD_CLONES; n++) |
| @@ -180,7 +182,9 @@ void init_espfix_ap(void) | |||
| 180 | pmd_p = pmd_offset(&pud, addr); | 182 | pmd_p = pmd_offset(&pud, addr); |
| 181 | pmd = *pmd_p; | 183 | pmd = *pmd_p; |
| 182 | if (!pmd_present(pmd)) { | 184 | if (!pmd_present(pmd)) { |
| 183 | pte_p = (pte_t *)__get_free_page(PGALLOC_GFP); | 185 | struct page *page = alloc_pages_node(node, PGALLOC_GFP, 0); |
| 186 | |||
| 187 | pte_p = (pte_t *)page_address(page); | ||
| 184 | pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); | 188 | pmd = __pmd(__pa(pte_p) | (PGTABLE_PROT & ptemask)); |
| 185 | paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); | 189 | paravirt_alloc_pte(&init_mm, __pa(pte_p) >> PAGE_SHIFT); |
| 186 | for (n = 0; n < ESPFIX_PMD_CLONES; n++) | 190 | for (n = 0; n < ESPFIX_PMD_CLONES; n++) |
| @@ -188,7 +192,7 @@ void init_espfix_ap(void) | |||
| 188 | } | 192 | } |
| 189 | 193 | ||
| 190 | pte_p = pte_offset_kernel(&pmd, addr); | 194 | pte_p = pte_offset_kernel(&pmd, addr); |
| 191 | stack_page = (void *)__get_free_page(GFP_KERNEL); | 195 | stack_page = page_address(alloc_pages_node(node, GFP_KERNEL, 0)); |
| 192 | pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); | 196 | pte = __pte(__pa(stack_page) | (__PAGE_KERNEL_RO & ptemask)); |
| 193 | for (n = 0; n < ESPFIX_PTE_CLONES; n++) | 197 | for (n = 0; n < ESPFIX_PTE_CLONES; n++) |
| 194 | set_pte(&pte_p[n*PTE_STRIDE], pte); | 198 | set_pte(&pte_p[n*PTE_STRIDE], pte); |
| @@ -199,7 +203,7 @@ void init_espfix_ap(void) | |||
| 199 | unlock_done: | 203 | unlock_done: |
| 200 | mutex_unlock(&espfix_init_mutex); | 204 | mutex_unlock(&espfix_init_mutex); |
| 201 | done: | 205 | done: |
| 202 | this_cpu_write(espfix_stack, addr); | 206 | per_cpu(espfix_stack, cpu) = addr; |
| 203 | this_cpu_write(espfix_waddr, (unsigned long)stack_page | 207 | per_cpu(espfix_waddr, cpu) = (unsigned long)stack_page |
| 204 | + (addr & ~PAGE_MASK)); | 208 | + (addr & ~PAGE_MASK); |
| 205 | } | 209 | } |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 5a4668136e98..f129a9af6357 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
| @@ -161,11 +161,12 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) | |||
| 161 | /* Kill off the identity-map trampoline */ | 161 | /* Kill off the identity-map trampoline */ |
| 162 | reset_early_page_tables(); | 162 | reset_early_page_tables(); |
| 163 | 163 | ||
| 164 | kasan_map_early_shadow(early_level4_pgt); | ||
| 165 | |||
| 166 | /* clear bss before set_intr_gate with early_idt_handler */ | ||
| 167 | clear_bss(); | 164 | clear_bss(); |
| 168 | 165 | ||
| 166 | clear_page(init_level4_pgt); | ||
| 167 | |||
| 168 | kasan_early_init(); | ||
| 169 | |||
| 169 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) | 170 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) |
| 170 | set_intr_gate(i, early_idt_handler_array[i]); | 171 | set_intr_gate(i, early_idt_handler_array[i]); |
| 171 | load_idt((const struct desc_ptr *)&idt_descr); | 172 | load_idt((const struct desc_ptr *)&idt_descr); |
| @@ -177,12 +178,9 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) | |||
| 177 | */ | 178 | */ |
| 178 | load_ucode_bsp(); | 179 | load_ucode_bsp(); |
| 179 | 180 | ||
| 180 | clear_page(init_level4_pgt); | ||
| 181 | /* set init_level4_pgt kernel high mapping*/ | 181 | /* set init_level4_pgt kernel high mapping*/ |
| 182 | init_level4_pgt[511] = early_level4_pgt[511]; | 182 | init_level4_pgt[511] = early_level4_pgt[511]; |
| 183 | 183 | ||
| 184 | kasan_map_early_shadow(init_level4_pgt); | ||
| 185 | |||
| 186 | x86_64_start_reservations(real_mode_data); | 184 | x86_64_start_reservations(real_mode_data); |
| 187 | } | 185 | } |
| 188 | 186 | ||
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index e5c27f729a38..1d40ca8a73f2 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S | |||
| @@ -516,38 +516,9 @@ ENTRY(phys_base) | |||
| 516 | /* This must match the first entry in level2_kernel_pgt */ | 516 | /* This must match the first entry in level2_kernel_pgt */ |
| 517 | .quad 0x0000000000000000 | 517 | .quad 0x0000000000000000 |
| 518 | 518 | ||
| 519 | #ifdef CONFIG_KASAN | ||
| 520 | #define FILL(VAL, COUNT) \ | ||
| 521 | .rept (COUNT) ; \ | ||
| 522 | .quad (VAL) ; \ | ||
| 523 | .endr | ||
| 524 | |||
| 525 | NEXT_PAGE(kasan_zero_pte) | ||
| 526 | FILL(kasan_zero_page - __START_KERNEL_map + _KERNPG_TABLE, 512) | ||
| 527 | NEXT_PAGE(kasan_zero_pmd) | ||
| 528 | FILL(kasan_zero_pte - __START_KERNEL_map + _KERNPG_TABLE, 512) | ||
| 529 | NEXT_PAGE(kasan_zero_pud) | ||
| 530 | FILL(kasan_zero_pmd - __START_KERNEL_map + _KERNPG_TABLE, 512) | ||
| 531 | |||
| 532 | #undef FILL | ||
| 533 | #endif | ||
| 534 | |||
| 535 | |||
| 536 | #include "../../x86/xen/xen-head.S" | 519 | #include "../../x86/xen/xen-head.S" |
| 537 | 520 | ||
| 538 | __PAGE_ALIGNED_BSS | 521 | __PAGE_ALIGNED_BSS |
| 539 | NEXT_PAGE(empty_zero_page) | 522 | NEXT_PAGE(empty_zero_page) |
| 540 | .skip PAGE_SIZE | 523 | .skip PAGE_SIZE |
| 541 | 524 | ||
| 542 | #ifdef CONFIG_KASAN | ||
| 543 | /* | ||
| 544 | * This page used as early shadow. We don't use empty_zero_page | ||
| 545 | * at early stages, stack instrumentation could write some garbage | ||
| 546 | * to this page. | ||
| 547 | * Latter we reuse it as zero shadow for large ranges of memory | ||
| 548 | * that allowed to access, but not instrumented by kasan | ||
| 549 | * (vmalloc/vmemmap ...). | ||
| 550 | */ | ||
| 551 | NEXT_PAGE(kasan_zero_page) | ||
| 552 | .skip PAGE_SIZE | ||
| 553 | #endif | ||
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 88b366487b0e..c7dfe1be784e 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
| @@ -347,14 +347,22 @@ int check_irq_vectors_for_cpu_disable(void) | |||
| 347 | if (!desc) | 347 | if (!desc) |
| 348 | continue; | 348 | continue; |
| 349 | 349 | ||
| 350 | /* | ||
| 351 | * Protect against concurrent action removal, | ||
| 352 | * affinity changes etc. | ||
| 353 | */ | ||
| 354 | raw_spin_lock(&desc->lock); | ||
| 350 | data = irq_desc_get_irq_data(desc); | 355 | data = irq_desc_get_irq_data(desc); |
| 351 | cpumask_copy(&affinity_new, data->affinity); | 356 | cpumask_copy(&affinity_new, data->affinity); |
| 352 | cpumask_clear_cpu(this_cpu, &affinity_new); | 357 | cpumask_clear_cpu(this_cpu, &affinity_new); |
| 353 | 358 | ||
| 354 | /* Do not count inactive or per-cpu irqs. */ | 359 | /* Do not count inactive or per-cpu irqs. */ |
| 355 | if (!irq_has_action(irq) || irqd_is_per_cpu(data)) | 360 | if (!irq_has_action(irq) || irqd_is_per_cpu(data)) { |
| 361 | raw_spin_unlock(&desc->lock); | ||
| 356 | continue; | 362 | continue; |
| 363 | } | ||
| 357 | 364 | ||
| 365 | raw_spin_unlock(&desc->lock); | ||
| 358 | /* | 366 | /* |
| 359 | * A single irq may be mapped to multiple | 367 | * A single irq may be mapped to multiple |
| 360 | * cpu's vector_irq[] (for example IOAPIC cluster | 368 | * cpu's vector_irq[] (for example IOAPIC cluster |
| @@ -385,6 +393,9 @@ int check_irq_vectors_for_cpu_disable(void) | |||
| 385 | * vector. If the vector is marked in the used vectors | 393 | * vector. If the vector is marked in the used vectors |
| 386 | * bitmap or an irq is assigned to it, we don't count | 394 | * bitmap or an irq is assigned to it, we don't count |
| 387 | * it as available. | 395 | * it as available. |
| 396 | * | ||
| 397 | * As this is an inaccurate snapshot anyway, we can do | ||
| 398 | * this w/o holding vector_lock. | ||
| 388 | */ | 399 | */ |
| 389 | for (vector = FIRST_EXTERNAL_VECTOR; | 400 | for (vector = FIRST_EXTERNAL_VECTOR; |
| 390 | vector < first_system_vector; vector++) { | 401 | vector < first_system_vector; vector++) { |
| @@ -486,6 +497,11 @@ void fixup_irqs(void) | |||
| 486 | */ | 497 | */ |
| 487 | mdelay(1); | 498 | mdelay(1); |
| 488 | 499 | ||
| 500 | /* | ||
| 501 | * We can walk the vector array of this cpu without holding | ||
| 502 | * vector_lock because the cpu is already marked !online, so | ||
| 503 | * nothing else will touch it. | ||
| 504 | */ | ||
| 489 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { | 505 | for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) { |
| 490 | unsigned int irr; | 506 | unsigned int irr; |
| 491 | 507 | ||
| @@ -497,9 +513,9 @@ void fixup_irqs(void) | |||
| 497 | irq = __this_cpu_read(vector_irq[vector]); | 513 | irq = __this_cpu_read(vector_irq[vector]); |
| 498 | 514 | ||
| 499 | desc = irq_to_desc(irq); | 515 | desc = irq_to_desc(irq); |
| 516 | raw_spin_lock(&desc->lock); | ||
| 500 | data = irq_desc_get_irq_data(desc); | 517 | data = irq_desc_get_irq_data(desc); |
| 501 | chip = irq_data_get_irq_chip(data); | 518 | chip = irq_data_get_irq_chip(data); |
| 502 | raw_spin_lock(&desc->lock); | ||
| 503 | if (chip->irq_retrigger) { | 519 | if (chip->irq_retrigger) { |
| 504 | chip->irq_retrigger(data); | 520 | chip->irq_retrigger(data); |
| 505 | __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); | 521 | __this_cpu_write(vector_irq[vector], VECTOR_RETRIGGERED); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 8add66b22f33..d3010aa79daf 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
| @@ -171,11 +171,6 @@ static void smp_callin(void) | |||
| 171 | apic_ap_setup(); | 171 | apic_ap_setup(); |
| 172 | 172 | ||
| 173 | /* | 173 | /* |
| 174 | * Need to setup vector mappings before we enable interrupts. | ||
| 175 | */ | ||
| 176 | setup_vector_irq(smp_processor_id()); | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Save our processor parameters. Note: this information | 174 | * Save our processor parameters. Note: this information |
| 180 | * is needed for clock calibration. | 175 | * is needed for clock calibration. |
| 181 | */ | 176 | */ |
| @@ -239,18 +234,13 @@ static void notrace start_secondary(void *unused) | |||
| 239 | check_tsc_sync_target(); | 234 | check_tsc_sync_target(); |
| 240 | 235 | ||
| 241 | /* | 236 | /* |
| 242 | * Enable the espfix hack for this CPU | 237 | * Lock vector_lock and initialize the vectors on this cpu |
| 243 | */ | 238 | * before setting the cpu online. We must set it online with |
| 244 | #ifdef CONFIG_X86_ESPFIX64 | 239 | * vector_lock held to prevent a concurrent setup/teardown |
| 245 | init_espfix_ap(); | 240 | * from seeing a half valid vector space. |
| 246 | #endif | ||
| 247 | |||
| 248 | /* | ||
| 249 | * We need to hold vector_lock so there the set of online cpus | ||
| 250 | * does not change while we are assigning vectors to cpus. Holding | ||
| 251 | * this lock ensures we don't half assign or remove an irq from a cpu. | ||
| 252 | */ | 241 | */ |
| 253 | lock_vector_lock(); | 242 | lock_vector_lock(); |
| 243 | setup_vector_irq(smp_processor_id()); | ||
| 254 | set_cpu_online(smp_processor_id(), true); | 244 | set_cpu_online(smp_processor_id(), true); |
| 255 | unlock_vector_lock(); | 245 | unlock_vector_lock(); |
| 256 | cpu_set_state_online(smp_processor_id()); | 246 | cpu_set_state_online(smp_processor_id()); |
| @@ -854,6 +844,13 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle) | |||
| 854 | initial_code = (unsigned long)start_secondary; | 844 | initial_code = (unsigned long)start_secondary; |
| 855 | stack_start = idle->thread.sp; | 845 | stack_start = idle->thread.sp; |
| 856 | 846 | ||
| 847 | /* | ||
| 848 | * Enable the espfix hack for this CPU | ||
| 849 | */ | ||
| 850 | #ifdef CONFIG_X86_ESPFIX64 | ||
| 851 | init_espfix_ap(cpu); | ||
| 852 | #endif | ||
| 853 | |||
| 857 | /* So we see what's up */ | 854 | /* So we see what's up */ |
| 858 | announce_cpu(cpu, apicid); | 855 | announce_cpu(cpu, apicid); |
| 859 | 856 | ||
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index 505449700e0c..7437b41f6a47 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c | |||
| @@ -598,10 +598,19 @@ static unsigned long quick_pit_calibrate(void) | |||
| 598 | if (!pit_expect_msb(0xff-i, &delta, &d2)) | 598 | if (!pit_expect_msb(0xff-i, &delta, &d2)) |
| 599 | break; | 599 | break; |
| 600 | 600 | ||
| 601 | delta -= tsc; | ||
| 602 | |||
| 603 | /* | ||
| 604 | * Extrapolate the error and fail fast if the error will | ||
| 605 | * never be below 500 ppm. | ||
| 606 | */ | ||
| 607 | if (i == 1 && | ||
| 608 | d1 + d2 >= (delta * MAX_QUICK_PIT_ITERATIONS) >> 11) | ||
| 609 | return 0; | ||
| 610 | |||
| 601 | /* | 611 | /* |
| 602 | * Iterate until the error is less than 500 ppm | 612 | * Iterate until the error is less than 500 ppm |
| 603 | */ | 613 | */ |
| 604 | delta -= tsc; | ||
| 605 | if (d1+d2 >= delta >> 11) | 614 | if (d1+d2 >= delta >> 11) |
| 606 | continue; | 615 | continue; |
| 607 | 616 | ||
diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c index ddf9ecb53cc3..e342586db6e4 100644 --- a/arch/x86/lib/usercopy.c +++ b/arch/x86/lib/usercopy.c | |||
| @@ -20,7 +20,7 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n) | |||
| 20 | unsigned long ret; | 20 | unsigned long ret; |
| 21 | 21 | ||
| 22 | if (__range_not_ok(from, n, TASK_SIZE)) | 22 | if (__range_not_ok(from, n, TASK_SIZE)) |
| 23 | return 0; | 23 | return n; |
| 24 | 24 | ||
| 25 | /* | 25 | /* |
| 26 | * Even though this function is typically called from NMI/IRQ context | 26 | * Even though this function is typically called from NMI/IRQ context |
diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c index 4860906c6b9f..e1840f3db5b5 100644 --- a/arch/x86/mm/kasan_init_64.c +++ b/arch/x86/mm/kasan_init_64.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | #define pr_fmt(fmt) "kasan: " fmt | ||
| 1 | #include <linux/bootmem.h> | 2 | #include <linux/bootmem.h> |
| 2 | #include <linux/kasan.h> | 3 | #include <linux/kasan.h> |
| 3 | #include <linux/kdebug.h> | 4 | #include <linux/kdebug.h> |
| @@ -11,7 +12,19 @@ | |||
| 11 | extern pgd_t early_level4_pgt[PTRS_PER_PGD]; | 12 | extern pgd_t early_level4_pgt[PTRS_PER_PGD]; |
| 12 | extern struct range pfn_mapped[E820_X_MAX]; | 13 | extern struct range pfn_mapped[E820_X_MAX]; |
| 13 | 14 | ||
| 14 | extern unsigned char kasan_zero_page[PAGE_SIZE]; | 15 | static pud_t kasan_zero_pud[PTRS_PER_PUD] __page_aligned_bss; |
| 16 | static pmd_t kasan_zero_pmd[PTRS_PER_PMD] __page_aligned_bss; | ||
| 17 | static pte_t kasan_zero_pte[PTRS_PER_PTE] __page_aligned_bss; | ||
| 18 | |||
| 19 | /* | ||
| 20 | * This page used as early shadow. We don't use empty_zero_page | ||
| 21 | * at early stages, stack instrumentation could write some garbage | ||
| 22 | * to this page. | ||
| 23 | * Latter we reuse it as zero shadow for large ranges of memory | ||
| 24 | * that allowed to access, but not instrumented by kasan | ||
| 25 | * (vmalloc/vmemmap ...). | ||
| 26 | */ | ||
| 27 | static unsigned char kasan_zero_page[PAGE_SIZE] __page_aligned_bss; | ||
| 15 | 28 | ||
| 16 | static int __init map_range(struct range *range) | 29 | static int __init map_range(struct range *range) |
| 17 | { | 30 | { |
| @@ -36,7 +49,7 @@ static void __init clear_pgds(unsigned long start, | |||
| 36 | pgd_clear(pgd_offset_k(start)); | 49 | pgd_clear(pgd_offset_k(start)); |
| 37 | } | 50 | } |
| 38 | 51 | ||
| 39 | void __init kasan_map_early_shadow(pgd_t *pgd) | 52 | static void __init kasan_map_early_shadow(pgd_t *pgd) |
| 40 | { | 53 | { |
| 41 | int i; | 54 | int i; |
| 42 | unsigned long start = KASAN_SHADOW_START; | 55 | unsigned long start = KASAN_SHADOW_START; |
| @@ -73,7 +86,7 @@ static int __init zero_pmd_populate(pud_t *pud, unsigned long addr, | |||
| 73 | while (IS_ALIGNED(addr, PMD_SIZE) && addr + PMD_SIZE <= end) { | 86 | while (IS_ALIGNED(addr, PMD_SIZE) && addr + PMD_SIZE <= end) { |
| 74 | WARN_ON(!pmd_none(*pmd)); | 87 | WARN_ON(!pmd_none(*pmd)); |
| 75 | set_pmd(pmd, __pmd(__pa_nodebug(kasan_zero_pte) | 88 | set_pmd(pmd, __pmd(__pa_nodebug(kasan_zero_pte) |
| 76 | | __PAGE_KERNEL_RO)); | 89 | | _KERNPG_TABLE)); |
| 77 | addr += PMD_SIZE; | 90 | addr += PMD_SIZE; |
| 78 | pmd = pmd_offset(pud, addr); | 91 | pmd = pmd_offset(pud, addr); |
| 79 | } | 92 | } |
| @@ -99,7 +112,7 @@ static int __init zero_pud_populate(pgd_t *pgd, unsigned long addr, | |||
| 99 | while (IS_ALIGNED(addr, PUD_SIZE) && addr + PUD_SIZE <= end) { | 112 | while (IS_ALIGNED(addr, PUD_SIZE) && addr + PUD_SIZE <= end) { |
| 100 | WARN_ON(!pud_none(*pud)); | 113 | WARN_ON(!pud_none(*pud)); |
| 101 | set_pud(pud, __pud(__pa_nodebug(kasan_zero_pmd) | 114 | set_pud(pud, __pud(__pa_nodebug(kasan_zero_pmd) |
| 102 | | __PAGE_KERNEL_RO)); | 115 | | _KERNPG_TABLE)); |
| 103 | addr += PUD_SIZE; | 116 | addr += PUD_SIZE; |
| 104 | pud = pud_offset(pgd, addr); | 117 | pud = pud_offset(pgd, addr); |
| 105 | } | 118 | } |
| @@ -124,7 +137,7 @@ static int __init zero_pgd_populate(unsigned long addr, unsigned long end) | |||
| 124 | while (IS_ALIGNED(addr, PGDIR_SIZE) && addr + PGDIR_SIZE <= end) { | 137 | while (IS_ALIGNED(addr, PGDIR_SIZE) && addr + PGDIR_SIZE <= end) { |
| 125 | WARN_ON(!pgd_none(*pgd)); | 138 | WARN_ON(!pgd_none(*pgd)); |
| 126 | set_pgd(pgd, __pgd(__pa_nodebug(kasan_zero_pud) | 139 | set_pgd(pgd, __pgd(__pa_nodebug(kasan_zero_pud) |
| 127 | | __PAGE_KERNEL_RO)); | 140 | | _KERNPG_TABLE)); |
| 128 | addr += PGDIR_SIZE; | 141 | addr += PGDIR_SIZE; |
| 129 | pgd = pgd_offset_k(addr); | 142 | pgd = pgd_offset_k(addr); |
| 130 | } | 143 | } |
| @@ -166,6 +179,26 @@ static struct notifier_block kasan_die_notifier = { | |||
| 166 | }; | 179 | }; |
| 167 | #endif | 180 | #endif |
| 168 | 181 | ||
| 182 | void __init kasan_early_init(void) | ||
| 183 | { | ||
| 184 | int i; | ||
| 185 | pteval_t pte_val = __pa_nodebug(kasan_zero_page) | __PAGE_KERNEL; | ||
| 186 | pmdval_t pmd_val = __pa_nodebug(kasan_zero_pte) | _KERNPG_TABLE; | ||
| 187 | pudval_t pud_val = __pa_nodebug(kasan_zero_pmd) | _KERNPG_TABLE; | ||
| 188 | |||
| 189 | for (i = 0; i < PTRS_PER_PTE; i++) | ||
| 190 | kasan_zero_pte[i] = __pte(pte_val); | ||
| 191 | |||
| 192 | for (i = 0; i < PTRS_PER_PMD; i++) | ||
| 193 | kasan_zero_pmd[i] = __pmd(pmd_val); | ||
| 194 | |||
| 195 | for (i = 0; i < PTRS_PER_PUD; i++) | ||
| 196 | kasan_zero_pud[i] = __pud(pud_val); | ||
| 197 | |||
| 198 | kasan_map_early_shadow(early_level4_pgt); | ||
| 199 | kasan_map_early_shadow(init_level4_pgt); | ||
| 200 | } | ||
| 201 | |||
| 169 | void __init kasan_init(void) | 202 | void __init kasan_init(void) |
| 170 | { | 203 | { |
| 171 | int i; | 204 | int i; |
| @@ -176,6 +209,7 @@ void __init kasan_init(void) | |||
| 176 | 209 | ||
| 177 | memcpy(early_level4_pgt, init_level4_pgt, sizeof(early_level4_pgt)); | 210 | memcpy(early_level4_pgt, init_level4_pgt, sizeof(early_level4_pgt)); |
| 178 | load_cr3(early_level4_pgt); | 211 | load_cr3(early_level4_pgt); |
| 212 | __flush_tlb_all(); | ||
| 179 | 213 | ||
| 180 | clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); | 214 | clear_pgds(KASAN_SHADOW_START, KASAN_SHADOW_END); |
| 181 | 215 | ||
| @@ -202,5 +236,8 @@ void __init kasan_init(void) | |||
| 202 | memset(kasan_zero_page, 0, PAGE_SIZE); | 236 | memset(kasan_zero_page, 0, PAGE_SIZE); |
| 203 | 237 | ||
| 204 | load_cr3(init_level4_pgt); | 238 | load_cr3(init_level4_pgt); |
| 239 | __flush_tlb_all(); | ||
| 205 | init_task.kasan_depth = 0; | 240 | init_task.kasan_depth = 0; |
| 241 | |||
| 242 | pr_info("Kernel address sanitizer initialized\n"); | ||
| 206 | } | 243 | } |
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index 569ee090343f..46b58abb08c5 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c | |||
| @@ -352,13 +352,16 @@ static int acpi_lpss_create_device(struct acpi_device *adev, | |||
| 352 | pdata->mmio_size = resource_size(rentry->res); | 352 | pdata->mmio_size = resource_size(rentry->res); |
| 353 | pdata->mmio_base = ioremap(rentry->res->start, | 353 | pdata->mmio_base = ioremap(rentry->res->start, |
| 354 | pdata->mmio_size); | 354 | pdata->mmio_size); |
| 355 | if (!pdata->mmio_base) | ||
| 356 | goto err_out; | ||
| 357 | break; | 355 | break; |
| 358 | } | 356 | } |
| 359 | 357 | ||
| 360 | acpi_dev_free_resource_list(&resource_list); | 358 | acpi_dev_free_resource_list(&resource_list); |
| 361 | 359 | ||
| 360 | if (!pdata->mmio_base) { | ||
| 361 | ret = -ENOMEM; | ||
| 362 | goto err_out; | ||
| 363 | } | ||
| 364 | |||
| 362 | pdata->dev_desc = dev_desc; | 365 | pdata->dev_desc = dev_desc; |
| 363 | 366 | ||
| 364 | if (dev_desc->setup) | 367 | if (dev_desc->setup) |
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c index 2161fa178c8d..628a42c41ab1 100644 --- a/drivers/acpi/nfit.c +++ b/drivers/acpi/nfit.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
| 19 | #include <linux/acpi.h> | 19 | #include <linux/acpi.h> |
| 20 | #include <linux/sort.h> | 20 | #include <linux/sort.h> |
| 21 | #include <linux/pmem.h> | ||
| 21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 22 | #include "nfit.h" | 23 | #include "nfit.h" |
| 23 | 24 | ||
| @@ -305,6 +306,23 @@ static bool add_idt(struct acpi_nfit_desc *acpi_desc, | |||
| 305 | return true; | 306 | return true; |
| 306 | } | 307 | } |
| 307 | 308 | ||
| 309 | static bool add_flush(struct acpi_nfit_desc *acpi_desc, | ||
| 310 | struct acpi_nfit_flush_address *flush) | ||
| 311 | { | ||
| 312 | struct device *dev = acpi_desc->dev; | ||
| 313 | struct nfit_flush *nfit_flush = devm_kzalloc(dev, sizeof(*nfit_flush), | ||
| 314 | GFP_KERNEL); | ||
| 315 | |||
| 316 | if (!nfit_flush) | ||
| 317 | return false; | ||
| 318 | INIT_LIST_HEAD(&nfit_flush->list); | ||
| 319 | nfit_flush->flush = flush; | ||
| 320 | list_add_tail(&nfit_flush->list, &acpi_desc->flushes); | ||
| 321 | dev_dbg(dev, "%s: nfit_flush handle: %d hint_count: %d\n", __func__, | ||
| 322 | flush->device_handle, flush->hint_count); | ||
| 323 | return true; | ||
| 324 | } | ||
| 325 | |||
| 308 | static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, | 326 | static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, |
| 309 | const void *end) | 327 | const void *end) |
| 310 | { | 328 | { |
| @@ -338,7 +356,8 @@ static void *add_table(struct acpi_nfit_desc *acpi_desc, void *table, | |||
| 338 | return err; | 356 | return err; |
| 339 | break; | 357 | break; |
| 340 | case ACPI_NFIT_TYPE_FLUSH_ADDRESS: | 358 | case ACPI_NFIT_TYPE_FLUSH_ADDRESS: |
| 341 | dev_dbg(dev, "%s: flush\n", __func__); | 359 | if (!add_flush(acpi_desc, table)) |
| 360 | return err; | ||
| 342 | break; | 361 | break; |
| 343 | case ACPI_NFIT_TYPE_SMBIOS: | 362 | case ACPI_NFIT_TYPE_SMBIOS: |
| 344 | dev_dbg(dev, "%s: smbios\n", __func__); | 363 | dev_dbg(dev, "%s: smbios\n", __func__); |
| @@ -389,6 +408,7 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, | |||
| 389 | { | 408 | { |
| 390 | u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; | 409 | u16 dcr = __to_nfit_memdev(nfit_mem)->region_index; |
| 391 | struct nfit_memdev *nfit_memdev; | 410 | struct nfit_memdev *nfit_memdev; |
| 411 | struct nfit_flush *nfit_flush; | ||
| 392 | struct nfit_dcr *nfit_dcr; | 412 | struct nfit_dcr *nfit_dcr; |
| 393 | struct nfit_bdw *nfit_bdw; | 413 | struct nfit_bdw *nfit_bdw; |
| 394 | struct nfit_idt *nfit_idt; | 414 | struct nfit_idt *nfit_idt; |
| @@ -442,6 +462,14 @@ static int nfit_mem_add(struct acpi_nfit_desc *acpi_desc, | |||
| 442 | nfit_mem->idt_bdw = nfit_idt->idt; | 462 | nfit_mem->idt_bdw = nfit_idt->idt; |
| 443 | break; | 463 | break; |
| 444 | } | 464 | } |
| 465 | |||
| 466 | list_for_each_entry(nfit_flush, &acpi_desc->flushes, list) { | ||
| 467 | if (nfit_flush->flush->device_handle != | ||
| 468 | nfit_memdev->memdev->device_handle) | ||
| 469 | continue; | ||
| 470 | nfit_mem->nfit_flush = nfit_flush; | ||
| 471 | break; | ||
| 472 | } | ||
| 445 | break; | 473 | break; |
| 446 | } | 474 | } |
| 447 | 475 | ||
| @@ -978,6 +1006,24 @@ static u64 to_interleave_offset(u64 offset, struct nfit_blk_mmio *mmio) | |||
| 978 | return mmio->base_offset + line_offset + table_offset + sub_line_offset; | 1006 | return mmio->base_offset + line_offset + table_offset + sub_line_offset; |
| 979 | } | 1007 | } |
| 980 | 1008 | ||
| 1009 | static void wmb_blk(struct nfit_blk *nfit_blk) | ||
| 1010 | { | ||
| 1011 | |||
| 1012 | if (nfit_blk->nvdimm_flush) { | ||
| 1013 | /* | ||
| 1014 | * The first wmb() is needed to 'sfence' all previous writes | ||
| 1015 | * such that they are architecturally visible for the platform | ||
| 1016 | * buffer flush. Note that we've already arranged for pmem | ||
| 1017 | * writes to avoid the cache via arch_memcpy_to_pmem(). The | ||
| 1018 | * final wmb() ensures ordering for the NVDIMM flush write. | ||
| 1019 | */ | ||
| 1020 | wmb(); | ||
| 1021 | writeq(1, nfit_blk->nvdimm_flush); | ||
| 1022 | wmb(); | ||
| 1023 | } else | ||
| 1024 | wmb_pmem(); | ||
| 1025 | } | ||
| 1026 | |||
| 981 | static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw) | 1027 | static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw) |
| 982 | { | 1028 | { |
| 983 | struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR]; | 1029 | struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR]; |
| @@ -1012,7 +1058,10 @@ static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw, | |||
| 1012 | offset = to_interleave_offset(offset, mmio); | 1058 | offset = to_interleave_offset(offset, mmio); |
| 1013 | 1059 | ||
| 1014 | writeq(cmd, mmio->base + offset); | 1060 | writeq(cmd, mmio->base + offset); |
| 1015 | /* FIXME: conditionally perform read-back if mandated by firmware */ | 1061 | wmb_blk(nfit_blk); |
| 1062 | |||
| 1063 | if (nfit_blk->dimm_flags & ND_BLK_DCR_LATCH) | ||
| 1064 | readq(mmio->base + offset); | ||
| 1016 | } | 1065 | } |
| 1017 | 1066 | ||
| 1018 | static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, | 1067 | static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, |
| @@ -1026,7 +1075,6 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, | |||
| 1026 | 1075 | ||
| 1027 | base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES | 1076 | base_offset = nfit_blk->bdw_offset + dpa % L1_CACHE_BYTES |
| 1028 | + lane * mmio->size; | 1077 | + lane * mmio->size; |
| 1029 | /* TODO: non-temporal access, flush hints, cache management etc... */ | ||
| 1030 | write_blk_ctl(nfit_blk, lane, dpa, len, rw); | 1078 | write_blk_ctl(nfit_blk, lane, dpa, len, rw); |
| 1031 | while (len) { | 1079 | while (len) { |
| 1032 | unsigned int c; | 1080 | unsigned int c; |
| @@ -1045,13 +1093,19 @@ static int acpi_nfit_blk_single_io(struct nfit_blk *nfit_blk, | |||
| 1045 | } | 1093 | } |
| 1046 | 1094 | ||
| 1047 | if (rw) | 1095 | if (rw) |
| 1048 | memcpy(mmio->aperture + offset, iobuf + copied, c); | 1096 | memcpy_to_pmem(mmio->aperture + offset, |
| 1097 | iobuf + copied, c); | ||
| 1049 | else | 1098 | else |
| 1050 | memcpy(iobuf + copied, mmio->aperture + offset, c); | 1099 | memcpy_from_pmem(iobuf + copied, |
| 1100 | mmio->aperture + offset, c); | ||
| 1051 | 1101 | ||
| 1052 | copied += c; | 1102 | copied += c; |
| 1053 | len -= c; | 1103 | len -= c; |
| 1054 | } | 1104 | } |
| 1105 | |||
| 1106 | if (rw) | ||
| 1107 | wmb_blk(nfit_blk); | ||
| 1108 | |||
| 1055 | rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0; | 1109 | rc = read_blk_stat(nfit_blk, lane) ? -EIO : 0; |
| 1056 | return rc; | 1110 | return rc; |
| 1057 | } | 1111 | } |
| @@ -1124,7 +1178,7 @@ static void nfit_spa_unmap(struct acpi_nfit_desc *acpi_desc, | |||
| 1124 | } | 1178 | } |
| 1125 | 1179 | ||
| 1126 | static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | 1180 | static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, |
| 1127 | struct acpi_nfit_system_address *spa) | 1181 | struct acpi_nfit_system_address *spa, enum spa_map_type type) |
| 1128 | { | 1182 | { |
| 1129 | resource_size_t start = spa->address; | 1183 | resource_size_t start = spa->address; |
| 1130 | resource_size_t n = spa->length; | 1184 | resource_size_t n = spa->length; |
| @@ -1152,8 +1206,15 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | |||
| 1152 | if (!res) | 1206 | if (!res) |
| 1153 | goto err_mem; | 1207 | goto err_mem; |
| 1154 | 1208 | ||
| 1155 | /* TODO: cacheability based on the spa type */ | 1209 | if (type == SPA_MAP_APERTURE) { |
| 1156 | spa_map->iomem = ioremap_nocache(start, n); | 1210 | /* |
| 1211 | * TODO: memremap_pmem() support, but that requires cache | ||
| 1212 | * flushing when the aperture is moved. | ||
| 1213 | */ | ||
| 1214 | spa_map->iomem = ioremap_wc(start, n); | ||
| 1215 | } else | ||
| 1216 | spa_map->iomem = ioremap_nocache(start, n); | ||
| 1217 | |||
| 1157 | if (!spa_map->iomem) | 1218 | if (!spa_map->iomem) |
| 1158 | goto err_map; | 1219 | goto err_map; |
| 1159 | 1220 | ||
| @@ -1171,6 +1232,7 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | |||
| 1171 | * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges | 1232 | * nfit_spa_map - interleave-aware managed-mappings of acpi_nfit_system_address ranges |
| 1172 | * @nvdimm_bus: NFIT-bus that provided the spa table entry | 1233 | * @nvdimm_bus: NFIT-bus that provided the spa table entry |
| 1173 | * @nfit_spa: spa table to map | 1234 | * @nfit_spa: spa table to map |
| 1235 | * @type: aperture or control region | ||
| 1174 | * | 1236 | * |
| 1175 | * In the case where block-data-window apertures and | 1237 | * In the case where block-data-window apertures and |
| 1176 | * dimm-control-regions are interleaved they will end up sharing a | 1238 | * dimm-control-regions are interleaved they will end up sharing a |
| @@ -1180,12 +1242,12 @@ static void __iomem *__nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | |||
| 1180 | * unbound. | 1242 | * unbound. |
| 1181 | */ | 1243 | */ |
| 1182 | static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc, | 1244 | static void __iomem *nfit_spa_map(struct acpi_nfit_desc *acpi_desc, |
| 1183 | struct acpi_nfit_system_address *spa) | 1245 | struct acpi_nfit_system_address *spa, enum spa_map_type type) |
| 1184 | { | 1246 | { |
| 1185 | void __iomem *iomem; | 1247 | void __iomem *iomem; |
| 1186 | 1248 | ||
| 1187 | mutex_lock(&acpi_desc->spa_map_mutex); | 1249 | mutex_lock(&acpi_desc->spa_map_mutex); |
| 1188 | iomem = __nfit_spa_map(acpi_desc, spa); | 1250 | iomem = __nfit_spa_map(acpi_desc, spa, type); |
| 1189 | mutex_unlock(&acpi_desc->spa_map_mutex); | 1251 | mutex_unlock(&acpi_desc->spa_map_mutex); |
| 1190 | 1252 | ||
| 1191 | return iomem; | 1253 | return iomem; |
| @@ -1206,12 +1268,35 @@ static int nfit_blk_init_interleave(struct nfit_blk_mmio *mmio, | |||
| 1206 | return 0; | 1268 | return 0; |
| 1207 | } | 1269 | } |
| 1208 | 1270 | ||
| 1271 | static int acpi_nfit_blk_get_flags(struct nvdimm_bus_descriptor *nd_desc, | ||
| 1272 | struct nvdimm *nvdimm, struct nfit_blk *nfit_blk) | ||
| 1273 | { | ||
| 1274 | struct nd_cmd_dimm_flags flags; | ||
| 1275 | int rc; | ||
| 1276 | |||
| 1277 | memset(&flags, 0, sizeof(flags)); | ||
| 1278 | rc = nd_desc->ndctl(nd_desc, nvdimm, ND_CMD_DIMM_FLAGS, &flags, | ||
| 1279 | sizeof(flags)); | ||
| 1280 | |||
| 1281 | if (rc >= 0 && flags.status == 0) | ||
| 1282 | nfit_blk->dimm_flags = flags.flags; | ||
| 1283 | else if (rc == -ENOTTY) { | ||
| 1284 | /* fall back to a conservative default */ | ||
| 1285 | nfit_blk->dimm_flags = ND_BLK_DCR_LATCH; | ||
| 1286 | rc = 0; | ||
| 1287 | } else | ||
| 1288 | rc = -ENXIO; | ||
| 1289 | |||
| 1290 | return rc; | ||
| 1291 | } | ||
| 1292 | |||
| 1209 | static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | 1293 | static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, |
| 1210 | struct device *dev) | 1294 | struct device *dev) |
| 1211 | { | 1295 | { |
| 1212 | struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); | 1296 | struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus); |
| 1213 | struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); | 1297 | struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); |
| 1214 | struct nd_blk_region *ndbr = to_nd_blk_region(dev); | 1298 | struct nd_blk_region *ndbr = to_nd_blk_region(dev); |
| 1299 | struct nfit_flush *nfit_flush; | ||
| 1215 | struct nfit_blk_mmio *mmio; | 1300 | struct nfit_blk_mmio *mmio; |
| 1216 | struct nfit_blk *nfit_blk; | 1301 | struct nfit_blk *nfit_blk; |
| 1217 | struct nfit_mem *nfit_mem; | 1302 | struct nfit_mem *nfit_mem; |
| @@ -1223,8 +1308,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | |||
| 1223 | if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) { | 1308 | if (!nfit_mem || !nfit_mem->dcr || !nfit_mem->bdw) { |
| 1224 | dev_dbg(dev, "%s: missing%s%s%s\n", __func__, | 1309 | dev_dbg(dev, "%s: missing%s%s%s\n", __func__, |
| 1225 | nfit_mem ? "" : " nfit_mem", | 1310 | nfit_mem ? "" : " nfit_mem", |
| 1226 | nfit_mem->dcr ? "" : " dcr", | 1311 | (nfit_mem && nfit_mem->dcr) ? "" : " dcr", |
| 1227 | nfit_mem->bdw ? "" : " bdw"); | 1312 | (nfit_mem && nfit_mem->bdw) ? "" : " bdw"); |
| 1228 | return -ENXIO; | 1313 | return -ENXIO; |
| 1229 | } | 1314 | } |
| 1230 | 1315 | ||
| @@ -1237,7 +1322,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | |||
| 1237 | /* map block aperture memory */ | 1322 | /* map block aperture memory */ |
| 1238 | nfit_blk->bdw_offset = nfit_mem->bdw->offset; | 1323 | nfit_blk->bdw_offset = nfit_mem->bdw->offset; |
| 1239 | mmio = &nfit_blk->mmio[BDW]; | 1324 | mmio = &nfit_blk->mmio[BDW]; |
| 1240 | mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw); | 1325 | mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_bdw, |
| 1326 | SPA_MAP_APERTURE); | ||
| 1241 | if (!mmio->base) { | 1327 | if (!mmio->base) { |
| 1242 | dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, | 1328 | dev_dbg(dev, "%s: %s failed to map bdw\n", __func__, |
| 1243 | nvdimm_name(nvdimm)); | 1329 | nvdimm_name(nvdimm)); |
| @@ -1259,7 +1345,8 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | |||
| 1259 | nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; | 1345 | nfit_blk->cmd_offset = nfit_mem->dcr->command_offset; |
| 1260 | nfit_blk->stat_offset = nfit_mem->dcr->status_offset; | 1346 | nfit_blk->stat_offset = nfit_mem->dcr->status_offset; |
| 1261 | mmio = &nfit_blk->mmio[DCR]; | 1347 | mmio = &nfit_blk->mmio[DCR]; |
| 1262 | mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr); | 1348 | mmio->base = nfit_spa_map(acpi_desc, nfit_mem->spa_dcr, |
| 1349 | SPA_MAP_CONTROL); | ||
| 1263 | if (!mmio->base) { | 1350 | if (!mmio->base) { |
| 1264 | dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, | 1351 | dev_dbg(dev, "%s: %s failed to map dcr\n", __func__, |
| 1265 | nvdimm_name(nvdimm)); | 1352 | nvdimm_name(nvdimm)); |
| @@ -1277,6 +1364,24 @@ static int acpi_nfit_blk_region_enable(struct nvdimm_bus *nvdimm_bus, | |||
| 1277 | return rc; | 1364 | return rc; |
| 1278 | } | 1365 | } |
| 1279 | 1366 | ||
| 1367 | rc = acpi_nfit_blk_get_flags(nd_desc, nvdimm, nfit_blk); | ||
| 1368 | if (rc < 0) { | ||
| 1369 | dev_dbg(dev, "%s: %s failed get DIMM flags\n", | ||
| 1370 | __func__, nvdimm_name(nvdimm)); | ||
| 1371 | return rc; | ||
| 1372 | } | ||
| 1373 | |||
| 1374 | nfit_flush = nfit_mem->nfit_flush; | ||
| 1375 | if (nfit_flush && nfit_flush->flush->hint_count != 0) { | ||
| 1376 | nfit_blk->nvdimm_flush = devm_ioremap_nocache(dev, | ||
| 1377 | nfit_flush->flush->hint_address[0], 8); | ||
| 1378 | if (!nfit_blk->nvdimm_flush) | ||
| 1379 | return -ENOMEM; | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | if (!arch_has_pmem_api() && !nfit_blk->nvdimm_flush) | ||
| 1383 | dev_warn(dev, "unable to guarantee persistence of writes\n"); | ||
| 1384 | |||
| 1280 | if (mmio->line_size == 0) | 1385 | if (mmio->line_size == 0) |
| 1281 | return 0; | 1386 | return 0; |
| 1282 | 1387 | ||
| @@ -1459,6 +1564,7 @@ int acpi_nfit_init(struct acpi_nfit_desc *acpi_desc, acpi_size sz) | |||
| 1459 | INIT_LIST_HEAD(&acpi_desc->dcrs); | 1564 | INIT_LIST_HEAD(&acpi_desc->dcrs); |
| 1460 | INIT_LIST_HEAD(&acpi_desc->bdws); | 1565 | INIT_LIST_HEAD(&acpi_desc->bdws); |
| 1461 | INIT_LIST_HEAD(&acpi_desc->idts); | 1566 | INIT_LIST_HEAD(&acpi_desc->idts); |
| 1567 | INIT_LIST_HEAD(&acpi_desc->flushes); | ||
| 1462 | INIT_LIST_HEAD(&acpi_desc->memdevs); | 1568 | INIT_LIST_HEAD(&acpi_desc->memdevs); |
| 1463 | INIT_LIST_HEAD(&acpi_desc->dimms); | 1569 | INIT_LIST_HEAD(&acpi_desc->dimms); |
| 1464 | mutex_init(&acpi_desc->spa_map_mutex); | 1570 | mutex_init(&acpi_desc->spa_map_mutex); |
diff --git a/drivers/acpi/nfit.h b/drivers/acpi/nfit.h index 81f2e8c5a79c..79b6d83875c1 100644 --- a/drivers/acpi/nfit.h +++ b/drivers/acpi/nfit.h | |||
| @@ -40,6 +40,10 @@ enum nfit_uuids { | |||
| 40 | NFIT_UUID_MAX, | 40 | NFIT_UUID_MAX, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | enum { | ||
| 44 | ND_BLK_DCR_LATCH = 2, | ||
| 45 | }; | ||
| 46 | |||
| 43 | struct nfit_spa { | 47 | struct nfit_spa { |
| 44 | struct acpi_nfit_system_address *spa; | 48 | struct acpi_nfit_system_address *spa; |
| 45 | struct list_head list; | 49 | struct list_head list; |
| @@ -60,6 +64,11 @@ struct nfit_idt { | |||
| 60 | struct list_head list; | 64 | struct list_head list; |
| 61 | }; | 65 | }; |
| 62 | 66 | ||
| 67 | struct nfit_flush { | ||
| 68 | struct acpi_nfit_flush_address *flush; | ||
| 69 | struct list_head list; | ||
| 70 | }; | ||
| 71 | |||
| 63 | struct nfit_memdev { | 72 | struct nfit_memdev { |
| 64 | struct acpi_nfit_memory_map *memdev; | 73 | struct acpi_nfit_memory_map *memdev; |
| 65 | struct list_head list; | 74 | struct list_head list; |
| @@ -77,6 +86,7 @@ struct nfit_mem { | |||
| 77 | struct acpi_nfit_system_address *spa_bdw; | 86 | struct acpi_nfit_system_address *spa_bdw; |
| 78 | struct acpi_nfit_interleave *idt_dcr; | 87 | struct acpi_nfit_interleave *idt_dcr; |
| 79 | struct acpi_nfit_interleave *idt_bdw; | 88 | struct acpi_nfit_interleave *idt_bdw; |
| 89 | struct nfit_flush *nfit_flush; | ||
| 80 | struct list_head list; | 90 | struct list_head list; |
| 81 | struct acpi_device *adev; | 91 | struct acpi_device *adev; |
| 82 | unsigned long dsm_mask; | 92 | unsigned long dsm_mask; |
| @@ -88,6 +98,7 @@ struct acpi_nfit_desc { | |||
| 88 | struct mutex spa_map_mutex; | 98 | struct mutex spa_map_mutex; |
| 89 | struct list_head spa_maps; | 99 | struct list_head spa_maps; |
| 90 | struct list_head memdevs; | 100 | struct list_head memdevs; |
| 101 | struct list_head flushes; | ||
| 91 | struct list_head dimms; | 102 | struct list_head dimms; |
| 92 | struct list_head spas; | 103 | struct list_head spas; |
| 93 | struct list_head dcrs; | 104 | struct list_head dcrs; |
| @@ -109,7 +120,7 @@ struct nfit_blk { | |||
| 109 | struct nfit_blk_mmio { | 120 | struct nfit_blk_mmio { |
| 110 | union { | 121 | union { |
| 111 | void __iomem *base; | 122 | void __iomem *base; |
| 112 | void *aperture; | 123 | void __pmem *aperture; |
| 113 | }; | 124 | }; |
| 114 | u64 size; | 125 | u64 size; |
| 115 | u64 base_offset; | 126 | u64 base_offset; |
| @@ -123,6 +134,13 @@ struct nfit_blk { | |||
| 123 | u64 bdw_offset; /* post interleave offset */ | 134 | u64 bdw_offset; /* post interleave offset */ |
| 124 | u64 stat_offset; | 135 | u64 stat_offset; |
| 125 | u64 cmd_offset; | 136 | u64 cmd_offset; |
| 137 | void __iomem *nvdimm_flush; | ||
| 138 | u32 dimm_flags; | ||
| 139 | }; | ||
| 140 | |||
| 141 | enum spa_map_type { | ||
| 142 | SPA_MAP_CONTROL, | ||
| 143 | SPA_MAP_APERTURE, | ||
| 126 | }; | 144 | }; |
| 127 | 145 | ||
| 128 | struct nfit_spa_mapping { | 146 | struct nfit_spa_mapping { |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c262e4acd68d..3b8963f21b36 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -175,10 +175,14 @@ static void __init acpi_request_region (struct acpi_generic_address *gas, | |||
| 175 | if (!addr || !length) | 175 | if (!addr || !length) |
| 176 | return; | 176 | return; |
| 177 | 177 | ||
| 178 | acpi_reserve_region(addr, length, gas->space_id, 0, desc); | 178 | /* Resources are never freed */ |
| 179 | if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_IO) | ||
| 180 | request_region(addr, length, desc); | ||
| 181 | else if (gas->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
| 182 | request_mem_region(addr, length, desc); | ||
| 179 | } | 183 | } |
| 180 | 184 | ||
| 181 | static void __init acpi_reserve_resources(void) | 185 | static int __init acpi_reserve_resources(void) |
| 182 | { | 186 | { |
| 183 | acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, | 187 | acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length, |
| 184 | "ACPI PM1a_EVT_BLK"); | 188 | "ACPI PM1a_EVT_BLK"); |
| @@ -207,7 +211,10 @@ static void __init acpi_reserve_resources(void) | |||
| 207 | if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) | 211 | if (!(acpi_gbl_FADT.gpe1_block_length & 0x1)) |
| 208 | acpi_request_region(&acpi_gbl_FADT.xgpe1_block, | 212 | acpi_request_region(&acpi_gbl_FADT.xgpe1_block, |
| 209 | acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); | 213 | acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK"); |
| 214 | |||
| 215 | return 0; | ||
| 210 | } | 216 | } |
| 217 | fs_initcall_sync(acpi_reserve_resources); | ||
| 211 | 218 | ||
| 212 | void acpi_os_printf(const char *fmt, ...) | 219 | void acpi_os_printf(const char *fmt, ...) |
| 213 | { | 220 | { |
| @@ -1862,7 +1869,6 @@ acpi_status __init acpi_os_initialize(void) | |||
| 1862 | 1869 | ||
| 1863 | acpi_status __init acpi_os_initialize1(void) | 1870 | acpi_status __init acpi_os_initialize1(void) |
| 1864 | { | 1871 | { |
| 1865 | acpi_reserve_resources(); | ||
| 1866 | kacpid_wq = alloc_workqueue("kacpid", 0, 1); | 1872 | kacpid_wq = alloc_workqueue("kacpid", 0, 1); |
| 1867 | kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); | 1873 | kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1); |
| 1868 | kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); | 1874 | kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0); |
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 10561ce16ed1..8244f013f210 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
| 27 | #include <linux/export.h> | 27 | #include <linux/export.h> |
| 28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
| 29 | #include <linux/list.h> | ||
| 30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 31 | 30 | ||
| 32 | #ifdef CONFIG_X86 | 31 | #ifdef CONFIG_X86 |
| @@ -622,164 +621,3 @@ int acpi_dev_filter_resource_type(struct acpi_resource *ares, | |||
| 622 | return (type & types) ? 0 : 1; | 621 | return (type & types) ? 0 : 1; |
| 623 | } | 622 | } |
| 624 | EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); | 623 | EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); |
| 625 | |||
| 626 | struct reserved_region { | ||
| 627 | struct list_head node; | ||
| 628 | u64 start; | ||
| 629 | u64 end; | ||
| 630 | }; | ||
| 631 | |||
| 632 | static LIST_HEAD(reserved_io_regions); | ||
| 633 | static LIST_HEAD(reserved_mem_regions); | ||
| 634 | |||
| 635 | static int request_range(u64 start, u64 end, u8 space_id, unsigned long flags, | ||
| 636 | char *desc) | ||
| 637 | { | ||
| 638 | unsigned int length = end - start + 1; | ||
| 639 | struct resource *res; | ||
| 640 | |||
| 641 | res = space_id == ACPI_ADR_SPACE_SYSTEM_IO ? | ||
| 642 | request_region(start, length, desc) : | ||
| 643 | request_mem_region(start, length, desc); | ||
| 644 | if (!res) | ||
| 645 | return -EIO; | ||
| 646 | |||
| 647 | res->flags &= ~flags; | ||
| 648 | return 0; | ||
| 649 | } | ||
| 650 | |||
| 651 | static int add_region_before(u64 start, u64 end, u8 space_id, | ||
| 652 | unsigned long flags, char *desc, | ||
| 653 | struct list_head *head) | ||
| 654 | { | ||
| 655 | struct reserved_region *reg; | ||
| 656 | int error; | ||
| 657 | |||
| 658 | reg = kmalloc(sizeof(*reg), GFP_KERNEL); | ||
| 659 | if (!reg) | ||
| 660 | return -ENOMEM; | ||
| 661 | |||
| 662 | error = request_range(start, end, space_id, flags, desc); | ||
| 663 | if (error) { | ||
| 664 | kfree(reg); | ||
| 665 | return error; | ||
| 666 | } | ||
| 667 | |||
| 668 | reg->start = start; | ||
| 669 | reg->end = end; | ||
| 670 | list_add_tail(®->node, head); | ||
| 671 | return 0; | ||
| 672 | } | ||
| 673 | |||
| 674 | /** | ||
| 675 | * acpi_reserve_region - Reserve an I/O or memory region as a system resource. | ||
| 676 | * @start: Starting address of the region. | ||
| 677 | * @length: Length of the region. | ||
| 678 | * @space_id: Identifier of address space to reserve the region from. | ||
| 679 | * @flags: Resource flags to clear for the region after requesting it. | ||
| 680 | * @desc: Region description (for messages). | ||
| 681 | * | ||
| 682 | * Reserve an I/O or memory region as a system resource to prevent others from | ||
| 683 | * using it. If the new region overlaps with one of the regions (in the given | ||
| 684 | * address space) already reserved by this routine, only the non-overlapping | ||
| 685 | * parts of it will be reserved. | ||
| 686 | * | ||
| 687 | * Returned is either 0 (success) or a negative error code indicating a resource | ||
| 688 | * reservation problem. It is the code of the first encountered error, but the | ||
| 689 | * routine doesn't abort until it has attempted to request all of the parts of | ||
| 690 | * the new region that don't overlap with other regions reserved previously. | ||
| 691 | * | ||
| 692 | * The resources requested by this routine are never released. | ||
| 693 | */ | ||
| 694 | int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, | ||
| 695 | unsigned long flags, char *desc) | ||
| 696 | { | ||
| 697 | struct list_head *regions; | ||
| 698 | struct reserved_region *reg; | ||
| 699 | u64 end = start + length - 1; | ||
| 700 | int ret = 0, error = 0; | ||
| 701 | |||
| 702 | if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) | ||
| 703 | regions = &reserved_io_regions; | ||
| 704 | else if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
| 705 | regions = &reserved_mem_regions; | ||
| 706 | else | ||
| 707 | return -EINVAL; | ||
| 708 | |||
| 709 | if (list_empty(regions)) | ||
| 710 | return add_region_before(start, end, space_id, flags, desc, regions); | ||
| 711 | |||
| 712 | list_for_each_entry(reg, regions, node) | ||
| 713 | if (reg->start == end + 1) { | ||
| 714 | /* The new region can be prepended to this one. */ | ||
| 715 | ret = request_range(start, end, space_id, flags, desc); | ||
| 716 | if (!ret) | ||
| 717 | reg->start = start; | ||
| 718 | |||
| 719 | return ret; | ||
| 720 | } else if (reg->start > end) { | ||
| 721 | /* No overlap. Add the new region here and get out. */ | ||
| 722 | return add_region_before(start, end, space_id, flags, | ||
| 723 | desc, ®->node); | ||
| 724 | } else if (reg->end == start - 1) { | ||
| 725 | goto combine; | ||
| 726 | } else if (reg->end >= start) { | ||
| 727 | goto overlap; | ||
| 728 | } | ||
| 729 | |||
| 730 | /* The new region goes after the last existing one. */ | ||
| 731 | return add_region_before(start, end, space_id, flags, desc, regions); | ||
| 732 | |||
| 733 | overlap: | ||
| 734 | /* | ||
| 735 | * The new region overlaps an existing one. | ||
| 736 | * | ||
| 737 | * The head part of the new region immediately preceding the existing | ||
| 738 | * overlapping one can be combined with it right away. | ||
| 739 | */ | ||
| 740 | if (reg->start > start) { | ||
| 741 | error = request_range(start, reg->start - 1, space_id, flags, desc); | ||
| 742 | if (error) | ||
| 743 | ret = error; | ||
| 744 | else | ||
| 745 | reg->start = start; | ||
| 746 | } | ||
| 747 | |||
| 748 | combine: | ||
| 749 | /* | ||
| 750 | * The new region is adjacent to an existing one. If it extends beyond | ||
| 751 | * that region all the way to the next one, it is possible to combine | ||
| 752 | * all three of them. | ||
| 753 | */ | ||
| 754 | while (reg->end < end) { | ||
| 755 | struct reserved_region *next = NULL; | ||
| 756 | u64 a = reg->end + 1, b = end; | ||
| 757 | |||
| 758 | if (!list_is_last(®->node, regions)) { | ||
| 759 | next = list_next_entry(reg, node); | ||
| 760 | if (next->start <= end) | ||
| 761 | b = next->start - 1; | ||
| 762 | } | ||
| 763 | error = request_range(a, b, space_id, flags, desc); | ||
| 764 | if (!error) { | ||
| 765 | if (next && next->start == b + 1) { | ||
| 766 | reg->end = next->end; | ||
| 767 | list_del(&next->node); | ||
| 768 | kfree(next); | ||
| 769 | } else { | ||
| 770 | reg->end = end; | ||
| 771 | break; | ||
| 772 | } | ||
| 773 | } else if (next) { | ||
| 774 | if (!ret) | ||
| 775 | ret = error; | ||
| 776 | |||
| 777 | reg = next; | ||
| 778 | } else { | ||
| 779 | break; | ||
| 780 | } | ||
| 781 | } | ||
| 782 | |||
| 783 | return ret ? ret : error; | ||
| 784 | } | ||
| 785 | EXPORT_SYMBOL_GPL(acpi_reserve_region); | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 2649a068671d..ec256352f423 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -1019,6 +1019,29 @@ static bool acpi_of_match_device(struct acpi_device *adev, | |||
| 1019 | return false; | 1019 | return false; |
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | static bool __acpi_match_device_cls(const struct acpi_device_id *id, | ||
| 1023 | struct acpi_hardware_id *hwid) | ||
| 1024 | { | ||
| 1025 | int i, msk, byte_shift; | ||
| 1026 | char buf[3]; | ||
| 1027 | |||
| 1028 | if (!id->cls) | ||
| 1029 | return false; | ||
| 1030 | |||
| 1031 | /* Apply class-code bitmask, before checking each class-code byte */ | ||
| 1032 | for (i = 1; i <= 3; i++) { | ||
| 1033 | byte_shift = 8 * (3 - i); | ||
| 1034 | msk = (id->cls_msk >> byte_shift) & 0xFF; | ||
| 1035 | if (!msk) | ||
| 1036 | continue; | ||
| 1037 | |||
| 1038 | sprintf(buf, "%02x", (id->cls >> byte_shift) & msk); | ||
| 1039 | if (strncmp(buf, &hwid->id[(i - 1) * 2], 2)) | ||
| 1040 | return false; | ||
| 1041 | } | ||
| 1042 | return true; | ||
| 1043 | } | ||
| 1044 | |||
| 1022 | static const struct acpi_device_id *__acpi_match_device( | 1045 | static const struct acpi_device_id *__acpi_match_device( |
| 1023 | struct acpi_device *device, | 1046 | struct acpi_device *device, |
| 1024 | const struct acpi_device_id *ids, | 1047 | const struct acpi_device_id *ids, |
| @@ -1036,9 +1059,12 @@ static const struct acpi_device_id *__acpi_match_device( | |||
| 1036 | 1059 | ||
| 1037 | list_for_each_entry(hwid, &device->pnp.ids, list) { | 1060 | list_for_each_entry(hwid, &device->pnp.ids, list) { |
| 1038 | /* First, check the ACPI/PNP IDs provided by the caller. */ | 1061 | /* First, check the ACPI/PNP IDs provided by the caller. */ |
| 1039 | for (id = ids; id->id[0]; id++) | 1062 | for (id = ids; id->id[0] || id->cls; id++) { |
| 1040 | if (!strcmp((char *) id->id, hwid->id)) | 1063 | if (id->id[0] && !strcmp((char *) id->id, hwid->id)) |
| 1041 | return id; | 1064 | return id; |
| 1065 | else if (id->cls && __acpi_match_device_cls(id, hwid)) | ||
| 1066 | return id; | ||
| 1067 | } | ||
| 1042 | 1068 | ||
| 1043 | /* | 1069 | /* |
| 1044 | * Next, check ACPI_DT_NAMESPACE_HID and try to match the | 1070 | * Next, check ACPI_DT_NAMESPACE_HID and try to match the |
| @@ -2101,6 +2127,8 @@ static void acpi_set_pnp_ids(acpi_handle handle, struct acpi_device_pnp *pnp, | |||
| 2101 | if (info->valid & ACPI_VALID_UID) | 2127 | if (info->valid & ACPI_VALID_UID) |
| 2102 | pnp->unique_id = kstrdup(info->unique_id.string, | 2128 | pnp->unique_id = kstrdup(info->unique_id.string, |
| 2103 | GFP_KERNEL); | 2129 | GFP_KERNEL); |
| 2130 | if (info->valid & ACPI_VALID_CLS) | ||
| 2131 | acpi_add_id(pnp, info->class_code.string); | ||
| 2104 | 2132 | ||
| 2105 | kfree(info); | 2133 | kfree(info); |
| 2106 | 2134 | ||
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6d17a3b65ef7..15e40ee62a94 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
| @@ -48,7 +48,7 @@ config ATA_VERBOSE_ERROR | |||
| 48 | 48 | ||
| 49 | config ATA_ACPI | 49 | config ATA_ACPI |
| 50 | bool "ATA ACPI Support" | 50 | bool "ATA ACPI Support" |
| 51 | depends on ACPI && PCI | 51 | depends on ACPI |
| 52 | default y | 52 | default y |
| 53 | help | 53 | help |
| 54 | This option adds support for ATA-related ACPI objects. | 54 | This option adds support for ATA-related ACPI objects. |
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 614c78f510f0..1befb114c384 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c | |||
| @@ -20,6 +20,8 @@ | |||
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/libata.h> | 21 | #include <linux/libata.h> |
| 22 | #include <linux/ahci_platform.h> | 22 | #include <linux/ahci_platform.h> |
| 23 | #include <linux/acpi.h> | ||
| 24 | #include <linux/pci_ids.h> | ||
| 23 | #include "ahci.h" | 25 | #include "ahci.h" |
| 24 | 26 | ||
| 25 | #define DRV_NAME "ahci" | 27 | #define DRV_NAME "ahci" |
| @@ -79,12 +81,19 @@ static const struct of_device_id ahci_of_match[] = { | |||
| 79 | }; | 81 | }; |
| 80 | MODULE_DEVICE_TABLE(of, ahci_of_match); | 82 | MODULE_DEVICE_TABLE(of, ahci_of_match); |
| 81 | 83 | ||
| 84 | static const struct acpi_device_id ahci_acpi_match[] = { | ||
| 85 | { ACPI_DEVICE_CLASS(PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff) }, | ||
| 86 | {}, | ||
| 87 | }; | ||
| 88 | MODULE_DEVICE_TABLE(acpi, ahci_acpi_match); | ||
| 89 | |||
| 82 | static struct platform_driver ahci_driver = { | 90 | static struct platform_driver ahci_driver = { |
| 83 | .probe = ahci_probe, | 91 | .probe = ahci_probe, |
| 84 | .remove = ata_platform_remove_one, | 92 | .remove = ata_platform_remove_one, |
| 85 | .driver = { | 93 | .driver = { |
| 86 | .name = DRV_NAME, | 94 | .name = DRV_NAME, |
| 87 | .of_match_table = ahci_of_match, | 95 | .of_match_table = ahci_of_match, |
| 96 | .acpi_match_table = ahci_acpi_match, | ||
| 88 | .pm = &ahci_pm_ops, | 97 | .pm = &ahci_pm_ops, |
| 89 | }, | 98 | }, |
| 90 | }; | 99 | }; |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 9c4288362a8e..894bda114224 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
| @@ -563,10 +563,8 @@ static void fw_dev_release(struct device *dev) | |||
| 563 | kfree(fw_priv); | 563 | kfree(fw_priv); |
| 564 | } | 564 | } |
| 565 | 565 | ||
| 566 | static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) | 566 | static int do_firmware_uevent(struct firmware_priv *fw_priv, struct kobj_uevent_env *env) |
| 567 | { | 567 | { |
| 568 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | ||
| 569 | |||
| 570 | if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) | 568 | if (add_uevent_var(env, "FIRMWARE=%s", fw_priv->buf->fw_id)) |
| 571 | return -ENOMEM; | 569 | return -ENOMEM; |
| 572 | if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) | 570 | if (add_uevent_var(env, "TIMEOUT=%i", loading_timeout)) |
| @@ -577,6 +575,18 @@ static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
| 577 | return 0; | 575 | return 0; |
| 578 | } | 576 | } |
| 579 | 577 | ||
| 578 | static int firmware_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 579 | { | ||
| 580 | struct firmware_priv *fw_priv = to_firmware_priv(dev); | ||
| 581 | int err = 0; | ||
| 582 | |||
| 583 | mutex_lock(&fw_lock); | ||
| 584 | if (fw_priv->buf) | ||
| 585 | err = do_firmware_uevent(fw_priv, env); | ||
| 586 | mutex_unlock(&fw_lock); | ||
| 587 | return err; | ||
| 588 | } | ||
| 589 | |||
| 580 | static struct class firmware_class = { | 590 | static struct class firmware_class = { |
| 581 | .name = "firmware", | 591 | .name = "firmware", |
| 582 | .class_attrs = firmware_class_attrs, | 592 | .class_attrs = firmware_class_attrs, |
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index cdd547bd67df..0ee43c1056e0 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | * This file is released under the GPLv2. | 6 | * This file is released under the GPLv2. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/delay.h> | ||
| 9 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
| 10 | #include <linux/io.h> | 11 | #include <linux/io.h> |
| 11 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
| @@ -19,6 +20,8 @@ | |||
| 19 | #include <linux/suspend.h> | 20 | #include <linux/suspend.h> |
| 20 | #include <linux/export.h> | 21 | #include <linux/export.h> |
| 21 | 22 | ||
| 23 | #define GENPD_RETRY_MAX_MS 250 /* Approximate */ | ||
| 24 | |||
| 22 | #define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ | 25 | #define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \ |
| 23 | ({ \ | 26 | ({ \ |
| 24 | type (*__routine)(struct device *__d); \ | 27 | type (*__routine)(struct device *__d); \ |
| @@ -2131,6 +2134,7 @@ EXPORT_SYMBOL_GPL(of_genpd_get_from_provider); | |||
| 2131 | static void genpd_dev_pm_detach(struct device *dev, bool power_off) | 2134 | static void genpd_dev_pm_detach(struct device *dev, bool power_off) |
| 2132 | { | 2135 | { |
| 2133 | struct generic_pm_domain *pd; | 2136 | struct generic_pm_domain *pd; |
| 2137 | unsigned int i; | ||
| 2134 | int ret = 0; | 2138 | int ret = 0; |
| 2135 | 2139 | ||
| 2136 | pd = pm_genpd_lookup_dev(dev); | 2140 | pd = pm_genpd_lookup_dev(dev); |
| @@ -2139,10 +2143,12 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) | |||
| 2139 | 2143 | ||
| 2140 | dev_dbg(dev, "removing from PM domain %s\n", pd->name); | 2144 | dev_dbg(dev, "removing from PM domain %s\n", pd->name); |
| 2141 | 2145 | ||
| 2142 | while (1) { | 2146 | for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { |
| 2143 | ret = pm_genpd_remove_device(pd, dev); | 2147 | ret = pm_genpd_remove_device(pd, dev); |
| 2144 | if (ret != -EAGAIN) | 2148 | if (ret != -EAGAIN) |
| 2145 | break; | 2149 | break; |
| 2150 | |||
| 2151 | mdelay(i); | ||
| 2146 | cond_resched(); | 2152 | cond_resched(); |
| 2147 | } | 2153 | } |
| 2148 | 2154 | ||
| @@ -2183,6 +2189,7 @@ int genpd_dev_pm_attach(struct device *dev) | |||
| 2183 | { | 2189 | { |
| 2184 | struct of_phandle_args pd_args; | 2190 | struct of_phandle_args pd_args; |
| 2185 | struct generic_pm_domain *pd; | 2191 | struct generic_pm_domain *pd; |
| 2192 | unsigned int i; | ||
| 2186 | int ret; | 2193 | int ret; |
| 2187 | 2194 | ||
| 2188 | if (!dev->of_node) | 2195 | if (!dev->of_node) |
| @@ -2218,10 +2225,12 @@ int genpd_dev_pm_attach(struct device *dev) | |||
| 2218 | 2225 | ||
| 2219 | dev_dbg(dev, "adding to PM domain %s\n", pd->name); | 2226 | dev_dbg(dev, "adding to PM domain %s\n", pd->name); |
| 2220 | 2227 | ||
| 2221 | while (1) { | 2228 | for (i = 1; i < GENPD_RETRY_MAX_MS; i <<= 1) { |
| 2222 | ret = pm_genpd_add_device(pd, dev); | 2229 | ret = pm_genpd_add_device(pd, dev); |
| 2223 | if (ret != -EAGAIN) | 2230 | if (ret != -EAGAIN) |
| 2224 | break; | 2231 | break; |
| 2232 | |||
| 2233 | mdelay(i); | ||
| 2225 | cond_resched(); | 2234 | cond_resched(); |
| 2226 | } | 2235 | } |
| 2227 | 2236 | ||
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index 7470004ca810..eb6e67451dec 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c | |||
| @@ -45,14 +45,12 @@ static int dev_pm_attach_wake_irq(struct device *dev, int irq, | |||
| 45 | return -EEXIST; | 45 | return -EEXIST; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | dev->power.wakeirq = wirq; | ||
| 49 | spin_unlock_irqrestore(&dev->power.lock, flags); | ||
| 50 | |||
| 51 | err = device_wakeup_attach_irq(dev, wirq); | 48 | err = device_wakeup_attach_irq(dev, wirq); |
| 52 | if (err) | 49 | if (!err) |
| 53 | return err; | 50 | dev->power.wakeirq = wirq; |
| 54 | 51 | ||
| 55 | return 0; | 52 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 53 | return err; | ||
| 56 | } | 54 | } |
| 57 | 55 | ||
| 58 | /** | 56 | /** |
| @@ -105,10 +103,10 @@ void dev_pm_clear_wake_irq(struct device *dev) | |||
| 105 | return; | 103 | return; |
| 106 | 104 | ||
| 107 | spin_lock_irqsave(&dev->power.lock, flags); | 105 | spin_lock_irqsave(&dev->power.lock, flags); |
| 106 | device_wakeup_detach_irq(dev); | ||
| 108 | dev->power.wakeirq = NULL; | 107 | dev->power.wakeirq = NULL; |
| 109 | spin_unlock_irqrestore(&dev->power.lock, flags); | 108 | spin_unlock_irqrestore(&dev->power.lock, flags); |
| 110 | 109 | ||
| 111 | device_wakeup_detach_irq(dev); | ||
| 112 | if (wirq->dedicated_irq) | 110 | if (wirq->dedicated_irq) |
| 113 | free_irq(wirq->irq, wirq); | 111 | free_irq(wirq->irq, wirq); |
| 114 | kfree(wirq); | 112 | kfree(wirq); |
diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 40f71603378c..51f15bc15774 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c | |||
| @@ -281,32 +281,25 @@ EXPORT_SYMBOL_GPL(device_wakeup_enable); | |||
| 281 | * Attach a device wakeirq to the wakeup source so the device | 281 | * Attach a device wakeirq to the wakeup source so the device |
| 282 | * wake IRQ can be configured automatically for suspend and | 282 | * wake IRQ can be configured automatically for suspend and |
| 283 | * resume. | 283 | * resume. |
| 284 | * | ||
| 285 | * Call under the device's power.lock lock. | ||
| 284 | */ | 286 | */ |
| 285 | int device_wakeup_attach_irq(struct device *dev, | 287 | int device_wakeup_attach_irq(struct device *dev, |
| 286 | struct wake_irq *wakeirq) | 288 | struct wake_irq *wakeirq) |
| 287 | { | 289 | { |
| 288 | struct wakeup_source *ws; | 290 | struct wakeup_source *ws; |
| 289 | int ret = 0; | ||
| 290 | 291 | ||
| 291 | spin_lock_irq(&dev->power.lock); | ||
| 292 | ws = dev->power.wakeup; | 292 | ws = dev->power.wakeup; |
| 293 | if (!ws) { | 293 | if (!ws) { |
| 294 | dev_err(dev, "forgot to call call device_init_wakeup?\n"); | 294 | dev_err(dev, "forgot to call call device_init_wakeup?\n"); |
| 295 | ret = -EINVAL; | 295 | return -EINVAL; |
| 296 | goto unlock; | ||
| 297 | } | 296 | } |
| 298 | 297 | ||
| 299 | if (ws->wakeirq) { | 298 | if (ws->wakeirq) |
| 300 | ret = -EEXIST; | 299 | return -EEXIST; |
| 301 | goto unlock; | ||
| 302 | } | ||
| 303 | 300 | ||
| 304 | ws->wakeirq = wakeirq; | 301 | ws->wakeirq = wakeirq; |
| 305 | 302 | return 0; | |
| 306 | unlock: | ||
| 307 | spin_unlock_irq(&dev->power.lock); | ||
| 308 | |||
| 309 | return ret; | ||
| 310 | } | 303 | } |
| 311 | 304 | ||
| 312 | /** | 305 | /** |
| @@ -314,20 +307,16 @@ unlock: | |||
| 314 | * @dev: Device to handle | 307 | * @dev: Device to handle |
| 315 | * | 308 | * |
| 316 | * Removes a device wakeirq from the wakeup source. | 309 | * Removes a device wakeirq from the wakeup source. |
| 310 | * | ||
| 311 | * Call under the device's power.lock lock. | ||
| 317 | */ | 312 | */ |
| 318 | void device_wakeup_detach_irq(struct device *dev) | 313 | void device_wakeup_detach_irq(struct device *dev) |
| 319 | { | 314 | { |
| 320 | struct wakeup_source *ws; | 315 | struct wakeup_source *ws; |
| 321 | 316 | ||
| 322 | spin_lock_irq(&dev->power.lock); | ||
| 323 | ws = dev->power.wakeup; | 317 | ws = dev->power.wakeup; |
| 324 | if (!ws) | 318 | if (ws) |
| 325 | goto unlock; | 319 | ws->wakeirq = NULL; |
| 326 | |||
| 327 | ws->wakeirq = NULL; | ||
| 328 | |||
| 329 | unlock: | ||
| 330 | spin_unlock_irq(&dev->power.lock); | ||
| 331 | } | 320 | } |
| 332 | 321 | ||
| 333 | /** | 322 | /** |
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c index 152dcb3f7b5f..61566bcefa53 100644 --- a/drivers/clk/at91/clk-h32mx.c +++ b/drivers/clk/at91/clk-h32mx.c | |||
| @@ -116,8 +116,10 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np, | |||
| 116 | h32mxclk->pmc = pmc; | 116 | h32mxclk->pmc = pmc; |
| 117 | 117 | ||
| 118 | clk = clk_register(NULL, &h32mxclk->hw); | 118 | clk = clk_register(NULL, &h32mxclk->hw); |
| 119 | if (!clk) | 119 | if (!clk) { |
| 120 | kfree(h32mxclk); | ||
| 120 | return; | 121 | return; |
| 122 | } | ||
| 121 | 123 | ||
| 122 | of_clk_add_provider(np, of_clk_src_simple_get, clk); | 124 | of_clk_add_provider(np, of_clk_src_simple_get, clk); |
| 123 | } | 125 | } |
diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index c2400456a044..27dfa965cfed 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c | |||
| @@ -171,8 +171,10 @@ at91_clk_register_main_osc(struct at91_pmc *pmc, | |||
| 171 | irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); | 171 | irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); |
| 172 | ret = request_irq(osc->irq, clk_main_osc_irq_handler, | 172 | ret = request_irq(osc->irq, clk_main_osc_irq_handler, |
| 173 | IRQF_TRIGGER_HIGH, name, osc); | 173 | IRQF_TRIGGER_HIGH, name, osc); |
| 174 | if (ret) | 174 | if (ret) { |
| 175 | kfree(osc); | ||
| 175 | return ERR_PTR(ret); | 176 | return ERR_PTR(ret); |
| 177 | } | ||
| 176 | 178 | ||
| 177 | if (bypass) | 179 | if (bypass) |
| 178 | pmc_write(pmc, AT91_CKGR_MOR, | 180 | pmc_write(pmc, AT91_CKGR_MOR, |
diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c index f98eafe9b12d..5b3ded5205a2 100644 --- a/drivers/clk/at91/clk-master.c +++ b/drivers/clk/at91/clk-master.c | |||
| @@ -165,12 +165,16 @@ at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq, | |||
| 165 | irq_set_status_flags(master->irq, IRQ_NOAUTOEN); | 165 | irq_set_status_flags(master->irq, IRQ_NOAUTOEN); |
| 166 | ret = request_irq(master->irq, clk_master_irq_handler, | 166 | ret = request_irq(master->irq, clk_master_irq_handler, |
| 167 | IRQF_TRIGGER_HIGH, "clk-master", master); | 167 | IRQF_TRIGGER_HIGH, "clk-master", master); |
| 168 | if (ret) | 168 | if (ret) { |
| 169 | kfree(master); | ||
| 169 | return ERR_PTR(ret); | 170 | return ERR_PTR(ret); |
| 171 | } | ||
| 170 | 172 | ||
| 171 | clk = clk_register(NULL, &master->hw); | 173 | clk = clk_register(NULL, &master->hw); |
| 172 | if (IS_ERR(clk)) | 174 | if (IS_ERR(clk)) { |
| 175 | free_irq(master->irq, master); | ||
| 173 | kfree(master); | 176 | kfree(master); |
| 177 | } | ||
| 174 | 178 | ||
| 175 | return clk; | 179 | return clk; |
| 176 | } | 180 | } |
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index cbbe40377ad6..18b60f4895a6 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c | |||
| @@ -346,12 +346,16 @@ at91_clk_register_pll(struct at91_pmc *pmc, unsigned int irq, const char *name, | |||
| 346 | irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); | 346 | irq_set_status_flags(pll->irq, IRQ_NOAUTOEN); |
| 347 | ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, | 347 | ret = request_irq(pll->irq, clk_pll_irq_handler, IRQF_TRIGGER_HIGH, |
| 348 | id ? "clk-pllb" : "clk-plla", pll); | 348 | id ? "clk-pllb" : "clk-plla", pll); |
| 349 | if (ret) | 349 | if (ret) { |
| 350 | kfree(pll); | ||
| 350 | return ERR_PTR(ret); | 351 | return ERR_PTR(ret); |
| 352 | } | ||
| 351 | 353 | ||
| 352 | clk = clk_register(NULL, &pll->hw); | 354 | clk = clk_register(NULL, &pll->hw); |
| 353 | if (IS_ERR(clk)) | 355 | if (IS_ERR(clk)) { |
| 356 | free_irq(pll->irq, pll); | ||
| 354 | kfree(pll); | 357 | kfree(pll); |
| 358 | } | ||
| 355 | 359 | ||
| 356 | return clk; | 360 | return clk; |
| 357 | } | 361 | } |
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index a76d03fd577b..58008b3e8bc1 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c | |||
| @@ -130,13 +130,17 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name, | |||
| 130 | irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); | 130 | irq_set_status_flags(sys->irq, IRQ_NOAUTOEN); |
| 131 | ret = request_irq(sys->irq, clk_system_irq_handler, | 131 | ret = request_irq(sys->irq, clk_system_irq_handler, |
| 132 | IRQF_TRIGGER_HIGH, name, sys); | 132 | IRQF_TRIGGER_HIGH, name, sys); |
| 133 | if (ret) | 133 | if (ret) { |
| 134 | kfree(sys); | ||
| 134 | return ERR_PTR(ret); | 135 | return ERR_PTR(ret); |
| 136 | } | ||
| 135 | } | 137 | } |
| 136 | 138 | ||
| 137 | clk = clk_register(NULL, &sys->hw); | 139 | clk = clk_register(NULL, &sys->hw); |
| 138 | if (IS_ERR(clk)) | 140 | if (IS_ERR(clk)) { |
| 141 | free_irq(sys->irq, sys); | ||
| 139 | kfree(sys); | 142 | kfree(sys); |
| 143 | } | ||
| 140 | 144 | ||
| 141 | return clk; | 145 | return clk; |
| 142 | } | 146 | } |
diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c index ae3263bc1476..30dd697b1668 100644 --- a/drivers/clk/at91/clk-utmi.c +++ b/drivers/clk/at91/clk-utmi.c | |||
| @@ -118,12 +118,16 @@ at91_clk_register_utmi(struct at91_pmc *pmc, unsigned int irq, | |||
| 118 | irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); | 118 | irq_set_status_flags(utmi->irq, IRQ_NOAUTOEN); |
| 119 | ret = request_irq(utmi->irq, clk_utmi_irq_handler, | 119 | ret = request_irq(utmi->irq, clk_utmi_irq_handler, |
| 120 | IRQF_TRIGGER_HIGH, "clk-utmi", utmi); | 120 | IRQF_TRIGGER_HIGH, "clk-utmi", utmi); |
| 121 | if (ret) | 121 | if (ret) { |
| 122 | kfree(utmi); | ||
| 122 | return ERR_PTR(ret); | 123 | return ERR_PTR(ret); |
| 124 | } | ||
| 123 | 125 | ||
| 124 | clk = clk_register(NULL, &utmi->hw); | 126 | clk = clk_register(NULL, &utmi->hw); |
| 125 | if (IS_ERR(clk)) | 127 | if (IS_ERR(clk)) { |
| 128 | free_irq(utmi->irq, utmi); | ||
| 126 | kfree(utmi); | 129 | kfree(utmi); |
| 130 | } | ||
| 127 | 131 | ||
| 128 | return clk; | 132 | return clk; |
| 129 | } | 133 | } |
diff --git a/drivers/clk/bcm/clk-iproc-asiu.c b/drivers/clk/bcm/clk-iproc-asiu.c index e19c09cd9645..f630e1bbdcfe 100644 --- a/drivers/clk/bcm/clk-iproc-asiu.c +++ b/drivers/clk/bcm/clk-iproc-asiu.c | |||
| @@ -222,10 +222,6 @@ void __init iproc_asiu_setup(struct device_node *node, | |||
| 222 | struct iproc_asiu_clk *asiu_clk; | 222 | struct iproc_asiu_clk *asiu_clk; |
| 223 | const char *clk_name; | 223 | const char *clk_name; |
| 224 | 224 | ||
| 225 | clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); | ||
| 226 | if (WARN_ON(!clk_name)) | ||
| 227 | goto err_clk_register; | ||
| 228 | |||
| 229 | ret = of_property_read_string_index(node, "clock-output-names", | 225 | ret = of_property_read_string_index(node, "clock-output-names", |
| 230 | i, &clk_name); | 226 | i, &clk_name); |
| 231 | if (WARN_ON(ret)) | 227 | if (WARN_ON(ret)) |
| @@ -259,7 +255,7 @@ void __init iproc_asiu_setup(struct device_node *node, | |||
| 259 | 255 | ||
| 260 | err_clk_register: | 256 | err_clk_register: |
| 261 | for (i = 0; i < num_clks; i++) | 257 | for (i = 0; i < num_clks; i++) |
| 262 | kfree(asiu->clks[i].name); | 258 | clk_unregister(asiu->clk_data.clks[i]); |
| 263 | iounmap(asiu->gate_base); | 259 | iounmap(asiu->gate_base); |
| 264 | 260 | ||
| 265 | err_iomap_gate: | 261 | err_iomap_gate: |
diff --git a/drivers/clk/bcm/clk-iproc-pll.c b/drivers/clk/bcm/clk-iproc-pll.c index 46fb84bc2674..2dda4e8295a9 100644 --- a/drivers/clk/bcm/clk-iproc-pll.c +++ b/drivers/clk/bcm/clk-iproc-pll.c | |||
| @@ -366,7 +366,7 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, | |||
| 366 | val = readl(pll->pll_base + ctrl->ndiv_int.offset); | 366 | val = readl(pll->pll_base + ctrl->ndiv_int.offset); |
| 367 | ndiv_int = (val >> ctrl->ndiv_int.shift) & | 367 | ndiv_int = (val >> ctrl->ndiv_int.shift) & |
| 368 | bit_mask(ctrl->ndiv_int.width); | 368 | bit_mask(ctrl->ndiv_int.width); |
| 369 | ndiv = ndiv_int << ctrl->ndiv_int.shift; | 369 | ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift; |
| 370 | 370 | ||
| 371 | if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { | 371 | if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) { |
| 372 | val = readl(pll->pll_base + ctrl->ndiv_frac.offset); | 372 | val = readl(pll->pll_base + ctrl->ndiv_frac.offset); |
| @@ -374,7 +374,8 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw, | |||
| 374 | bit_mask(ctrl->ndiv_frac.width); | 374 | bit_mask(ctrl->ndiv_frac.width); |
| 375 | 375 | ||
| 376 | if (ndiv_frac != 0) | 376 | if (ndiv_frac != 0) |
| 377 | ndiv = (ndiv_int << ctrl->ndiv_int.shift) | ndiv_frac; | 377 | ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) | |
| 378 | ndiv_frac; | ||
| 378 | } | 379 | } |
| 379 | 380 | ||
| 380 | val = readl(pll->pll_base + ctrl->pdiv.offset); | 381 | val = readl(pll->pll_base + ctrl->pdiv.offset); |
| @@ -655,10 +656,6 @@ void __init iproc_pll_clk_setup(struct device_node *node, | |||
| 655 | memset(&init, 0, sizeof(init)); | 656 | memset(&init, 0, sizeof(init)); |
| 656 | parent_name = node->name; | 657 | parent_name = node->name; |
| 657 | 658 | ||
| 658 | clk_name = kzalloc(IPROC_CLK_NAME_LEN, GFP_KERNEL); | ||
| 659 | if (WARN_ON(!clk_name)) | ||
| 660 | goto err_clk_register; | ||
| 661 | |||
| 662 | ret = of_property_read_string_index(node, "clock-output-names", | 659 | ret = of_property_read_string_index(node, "clock-output-names", |
| 663 | i, &clk_name); | 660 | i, &clk_name); |
| 664 | if (WARN_ON(ret)) | 661 | if (WARN_ON(ret)) |
| @@ -690,10 +687,8 @@ void __init iproc_pll_clk_setup(struct device_node *node, | |||
| 690 | return; | 687 | return; |
| 691 | 688 | ||
| 692 | err_clk_register: | 689 | err_clk_register: |
| 693 | for (i = 0; i < num_clks; i++) { | 690 | for (i = 0; i < num_clks; i++) |
| 694 | kfree(pll->clks[i].name); | ||
| 695 | clk_unregister(pll->clk_data.clks[i]); | 691 | clk_unregister(pll->clk_data.clks[i]); |
| 696 | } | ||
| 697 | 692 | ||
| 698 | err_pll_register: | 693 | err_pll_register: |
| 699 | if (pll->asiu_base) | 694 | if (pll->asiu_base) |
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c index b9b12a742970..3f6f7ad39490 100644 --- a/drivers/clk/clk-stm32f4.c +++ b/drivers/clk/clk-stm32f4.c | |||
| @@ -268,7 +268,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) | |||
| 268 | memcpy(table, stm32f42xx_gate_map, sizeof(table)); | 268 | memcpy(table, stm32f42xx_gate_map, sizeof(table)); |
| 269 | 269 | ||
| 270 | /* only bits set in table can be used as indices */ | 270 | /* only bits set in table can be used as indices */ |
| 271 | if (WARN_ON(secondary > 8 * sizeof(table) || | 271 | if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) || |
| 272 | 0 == (table[BIT_ULL_WORD(secondary)] & | 272 | 0 == (table[BIT_ULL_WORD(secondary)] & |
| 273 | BIT_ULL_MASK(secondary)))) | 273 | BIT_ULL_MASK(secondary)))) |
| 274 | return -EINVAL; | 274 | return -EINVAL; |
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 4b9e04cdf7e8..8b6523d15fb8 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c | |||
| @@ -700,6 +700,22 @@ static const struct mtk_composite peri_clks[] __initconst = { | |||
| 700 | MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), | 700 | MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), |
| 701 | }; | 701 | }; |
| 702 | 702 | ||
| 703 | static struct clk_onecell_data *mt8173_top_clk_data __initdata; | ||
| 704 | static struct clk_onecell_data *mt8173_pll_clk_data __initdata; | ||
| 705 | |||
| 706 | static void __init mtk_clk_enable_critical(void) | ||
| 707 | { | ||
| 708 | if (!mt8173_top_clk_data || !mt8173_pll_clk_data) | ||
| 709 | return; | ||
| 710 | |||
| 711 | clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA15PLL]); | ||
| 712 | clk_prepare_enable(mt8173_pll_clk_data->clks[CLK_APMIXED_ARMCA7PLL]); | ||
| 713 | clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_MEM_SEL]); | ||
| 714 | clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_DDRPHYCFG_SEL]); | ||
| 715 | clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_CCI400_SEL]); | ||
| 716 | clk_prepare_enable(mt8173_top_clk_data->clks[CLK_TOP_RTC_SEL]); | ||
| 717 | } | ||
| 718 | |||
| 703 | static void __init mtk_topckgen_init(struct device_node *node) | 719 | static void __init mtk_topckgen_init(struct device_node *node) |
| 704 | { | 720 | { |
| 705 | struct clk_onecell_data *clk_data; | 721 | struct clk_onecell_data *clk_data; |
| @@ -712,19 +728,19 @@ static void __init mtk_topckgen_init(struct device_node *node) | |||
| 712 | return; | 728 | return; |
| 713 | } | 729 | } |
| 714 | 730 | ||
| 715 | clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); | 731 | mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); |
| 716 | 732 | ||
| 717 | mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); | 733 | mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); |
| 718 | mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); | 734 | mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); |
| 719 | mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, | 735 | mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, |
| 720 | &mt8173_clk_lock, clk_data); | 736 | &mt8173_clk_lock, clk_data); |
| 721 | 737 | ||
| 722 | clk_prepare_enable(clk_data->clks[CLK_TOP_CCI400_SEL]); | ||
| 723 | |||
| 724 | r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); | 738 | r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); |
| 725 | if (r) | 739 | if (r) |
| 726 | pr_err("%s(): could not register clock provider: %d\n", | 740 | pr_err("%s(): could not register clock provider: %d\n", |
| 727 | __func__, r); | 741 | __func__, r); |
| 742 | |||
| 743 | mtk_clk_enable_critical(); | ||
| 728 | } | 744 | } |
| 729 | CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); | 745 | CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); |
| 730 | 746 | ||
| @@ -818,13 +834,13 @@ static void __init mtk_apmixedsys_init(struct device_node *node) | |||
| 818 | { | 834 | { |
| 819 | struct clk_onecell_data *clk_data; | 835 | struct clk_onecell_data *clk_data; |
| 820 | 836 | ||
| 821 | clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); | 837 | mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); |
| 822 | if (!clk_data) | 838 | if (!clk_data) |
| 823 | return; | 839 | return; |
| 824 | 840 | ||
| 825 | mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); | 841 | mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); |
| 826 | 842 | ||
| 827 | clk_prepare_enable(clk_data->clks[CLK_APMIXED_ARMCA15PLL]); | 843 | mtk_clk_enable_critical(); |
| 828 | } | 844 | } |
| 829 | CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", | 845 | CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", |
| 830 | mtk_apmixedsys_init); | 846 | mtk_apmixedsys_init); |
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index b95d17fbb8d7..92936f0912d2 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c | |||
| @@ -530,19 +530,16 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 530 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); | 530 | struct clk_rcg2 *rcg = to_clk_rcg2(hw); |
| 531 | struct freq_tbl f = *rcg->freq_tbl; | 531 | struct freq_tbl f = *rcg->freq_tbl; |
| 532 | const struct frac_entry *frac = frac_table_pixel; | 532 | const struct frac_entry *frac = frac_table_pixel; |
| 533 | unsigned long request, src_rate; | 533 | unsigned long request; |
| 534 | int delta = 100000; | 534 | int delta = 100000; |
| 535 | u32 mask = BIT(rcg->hid_width) - 1; | 535 | u32 mask = BIT(rcg->hid_width) - 1; |
| 536 | u32 hid_div; | 536 | u32 hid_div; |
| 537 | int index = qcom_find_src_index(hw, rcg->parent_map, f.src); | ||
| 538 | struct clk *parent = clk_get_parent_by_index(hw->clk, index); | ||
| 539 | 537 | ||
| 540 | for (; frac->num; frac++) { | 538 | for (; frac->num; frac++) { |
| 541 | request = (rate * frac->den) / frac->num; | 539 | request = (rate * frac->den) / frac->num; |
| 542 | 540 | ||
| 543 | src_rate = __clk_round_rate(parent, request); | 541 | if ((parent_rate < (request - delta)) || |
| 544 | if ((src_rate < (request - delta)) || | 542 | (parent_rate > (request + delta))) |
| 545 | (src_rate > (request + delta))) | ||
| 546 | continue; | 543 | continue; |
| 547 | 544 | ||
| 548 | regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, | 545 | regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, |
diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c index 657ca14ba709..8dd8cce27361 100644 --- a/drivers/clk/st/clk-flexgen.c +++ b/drivers/clk/st/clk-flexgen.c | |||
| @@ -190,7 +190,7 @@ static struct clk *clk_register_flexgen(const char *name, | |||
| 190 | 190 | ||
| 191 | init.name = name; | 191 | init.name = name; |
| 192 | init.ops = &flexgen_ops; | 192 | init.ops = &flexgen_ops; |
| 193 | init.flags = CLK_IS_BASIC | flexgen_flags; | 193 | init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE | flexgen_flags; |
| 194 | init.parent_names = parent_names; | 194 | init.parent_names = parent_names; |
| 195 | init.num_parents = num_parents; | 195 | init.num_parents = num_parents; |
| 196 | 196 | ||
| @@ -303,6 +303,8 @@ static void __init st_of_flexgen_setup(struct device_node *np) | |||
| 303 | if (!rlock) | 303 | if (!rlock) |
| 304 | goto err; | 304 | goto err; |
| 305 | 305 | ||
| 306 | spin_lock_init(rlock); | ||
| 307 | |||
| 306 | for (i = 0; i < clk_data->clk_num; i++) { | 308 | for (i = 0; i < clk_data->clk_num; i++) { |
| 307 | struct clk *clk; | 309 | struct clk *clk; |
| 308 | const char *clk_name; | 310 | const char *clk_name; |
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index e94197f04b0b..d9eb2e1d8471 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c | |||
| @@ -340,7 +340,7 @@ static const struct clkgen_quadfs_data st_fs660c32_C_407 = { | |||
| 340 | CLKGEN_FIELD(0x30c, 0xf, 20), | 340 | CLKGEN_FIELD(0x30c, 0xf, 20), |
| 341 | CLKGEN_FIELD(0x310, 0xf, 20) }, | 341 | CLKGEN_FIELD(0x310, 0xf, 20) }, |
| 342 | .lockstatus_present = true, | 342 | .lockstatus_present = true, |
| 343 | .lock_status = CLKGEN_FIELD(0x2A0, 0x1, 24), | 343 | .lock_status = CLKGEN_FIELD(0x2f0, 0x1, 24), |
| 344 | .powerup_polarity = 1, | 344 | .powerup_polarity = 1, |
| 345 | .standby_polarity = 1, | 345 | .standby_polarity = 1, |
| 346 | .pll_ops = &st_quadfs_pll_c32_ops, | 346 | .pll_ops = &st_quadfs_pll_c32_ops, |
| @@ -489,7 +489,7 @@ static int quadfs_pll_is_enabled(struct clk_hw *hw) | |||
| 489 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); | 489 | struct st_clk_quadfs_pll *pll = to_quadfs_pll(hw); |
| 490 | u32 npda = CLKGEN_READ(pll, npda); | 490 | u32 npda = CLKGEN_READ(pll, npda); |
| 491 | 491 | ||
| 492 | return !!npda; | 492 | return pll->data->powerup_polarity ? !npda : !!npda; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs, | 495 | static int clk_fs660c32_vco_get_rate(unsigned long input, struct stm_fs *fs, |
| @@ -635,7 +635,7 @@ static struct clk * __init st_clk_register_quadfs_pll( | |||
| 635 | 635 | ||
| 636 | init.name = name; | 636 | init.name = name; |
| 637 | init.ops = quadfs->pll_ops; | 637 | init.ops = quadfs->pll_ops; |
| 638 | init.flags = CLK_IS_BASIC; | 638 | init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; |
| 639 | init.parent_names = &parent_name; | 639 | init.parent_names = &parent_name; |
| 640 | init.num_parents = 1; | 640 | init.num_parents = 1; |
| 641 | 641 | ||
| @@ -774,7 +774,7 @@ static void quadfs_fsynth_disable(struct clk_hw *hw) | |||
| 774 | if (fs->lock) | 774 | if (fs->lock) |
| 775 | spin_lock_irqsave(fs->lock, flags); | 775 | spin_lock_irqsave(fs->lock, flags); |
| 776 | 776 | ||
| 777 | CLKGEN_WRITE(fs, nsb[fs->chan], !fs->data->standby_polarity); | 777 | CLKGEN_WRITE(fs, nsb[fs->chan], fs->data->standby_polarity); |
| 778 | 778 | ||
| 779 | if (fs->lock) | 779 | if (fs->lock) |
| 780 | spin_unlock_irqrestore(fs->lock, flags); | 780 | spin_unlock_irqrestore(fs->lock, flags); |
| @@ -1082,10 +1082,6 @@ static const struct of_device_id quadfs_of_match[] = { | |||
| 1082 | .compatible = "st,stih407-quadfs660-D", | 1082 | .compatible = "st,stih407-quadfs660-D", |
| 1083 | .data = &st_fs660c32_D_407 | 1083 | .data = &st_fs660c32_D_407 |
| 1084 | }, | 1084 | }, |
| 1085 | { | ||
| 1086 | .compatible = "st,stih407-quadfs660-D", | ||
| 1087 | .data = (void *)&st_fs660c32_D_407 | ||
| 1088 | }, | ||
| 1089 | {} | 1085 | {} |
| 1090 | }; | 1086 | }; |
| 1091 | 1087 | ||
diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c index 4fbe6e099587..717c4a91a17b 100644 --- a/drivers/clk/st/clkgen-mux.c +++ b/drivers/clk/st/clkgen-mux.c | |||
| @@ -237,7 +237,7 @@ static struct clk *clk_register_genamux(const char *name, | |||
| 237 | 237 | ||
| 238 | init.name = name; | 238 | init.name = name; |
| 239 | init.ops = &clkgena_divmux_ops; | 239 | init.ops = &clkgena_divmux_ops; |
| 240 | init.flags = CLK_IS_BASIC; | 240 | init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; |
| 241 | init.parent_names = parent_names; | 241 | init.parent_names = parent_names; |
| 242 | init.num_parents = num_parents; | 242 | init.num_parents = num_parents; |
| 243 | 243 | ||
| @@ -513,7 +513,8 @@ static void __init st_of_clkgena_prediv_setup(struct device_node *np) | |||
| 513 | 0, &clk_name)) | 513 | 0, &clk_name)) |
| 514 | return; | 514 | return; |
| 515 | 515 | ||
| 516 | clk = clk_register_divider_table(NULL, clk_name, parent_name, 0, | 516 | clk = clk_register_divider_table(NULL, clk_name, parent_name, |
| 517 | CLK_GET_RATE_NOCACHE, | ||
| 517 | reg + data->offset, data->shift, 1, | 518 | reg + data->offset, data->shift, 1, |
| 518 | 0, data->table, NULL); | 519 | 0, data->table, NULL); |
| 519 | if (IS_ERR(clk)) | 520 | if (IS_ERR(clk)) |
| @@ -582,7 +583,7 @@ static struct clkgen_mux_data stih416_a9_mux_data = { | |||
| 582 | }; | 583 | }; |
| 583 | static struct clkgen_mux_data stih407_a9_mux_data = { | 584 | static struct clkgen_mux_data stih407_a9_mux_data = { |
| 584 | .offset = 0x1a4, | 585 | .offset = 0x1a4, |
| 585 | .shift = 1, | 586 | .shift = 0, |
| 586 | .width = 2, | 587 | .width = 2, |
| 587 | }; | 588 | }; |
| 588 | 589 | ||
| @@ -786,7 +787,8 @@ static void __init st_of_clkgen_vcc_setup(struct device_node *np) | |||
| 786 | &mux->hw, &clk_mux_ops, | 787 | &mux->hw, &clk_mux_ops, |
| 787 | &div->hw, &clk_divider_ops, | 788 | &div->hw, &clk_divider_ops, |
| 788 | &gate->hw, &clk_gate_ops, | 789 | &gate->hw, &clk_gate_ops, |
| 789 | data->clk_flags); | 790 | data->clk_flags | |
| 791 | CLK_GET_RATE_NOCACHE); | ||
| 790 | if (IS_ERR(clk)) { | 792 | if (IS_ERR(clk)) { |
| 791 | kfree(gate); | 793 | kfree(gate); |
| 792 | kfree(div); | 794 | kfree(div); |
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 106532207213..72d1c27eaffa 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c | |||
| @@ -406,7 +406,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name, | |||
| 406 | init.name = clk_name; | 406 | init.name = clk_name; |
| 407 | init.ops = pll_data->ops; | 407 | init.ops = pll_data->ops; |
| 408 | 408 | ||
| 409 | init.flags = CLK_IS_BASIC; | 409 | init.flags = CLK_IS_BASIC | CLK_GET_RATE_NOCACHE; |
| 410 | init.parent_names = &parent_name; | 410 | init.parent_names = &parent_name; |
| 411 | init.num_parents = 1; | 411 | init.num_parents = 1; |
| 412 | 412 | ||
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c index 879c78423546..2d59038dec43 100644 --- a/drivers/clocksource/timer-imx-gpt.c +++ b/drivers/clocksource/timer-imx-gpt.c | |||
| @@ -529,6 +529,7 @@ static void __init imx6dl_timer_init_dt(struct device_node *np) | |||
| 529 | 529 | ||
| 530 | CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); | 530 | CLOCKSOURCE_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); |
| 531 | CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); | 531 | CLOCKSOURCE_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); |
| 532 | CLOCKSOURCE_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt); | ||
| 532 | CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); | 533 | CLOCKSOURCE_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); |
| 533 | CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); | 534 | CLOCKSOURCE_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); |
| 534 | CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); | 535 | CLOCKSOURCE_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); |
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index fc897babab55..e362860c2b50 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * The 2E revision of loongson processor not support this feature. | 4 | * The 2E revision of loongson processor not support this feature. |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2006 - 2008 Lemote Inc. & Insititute of Computing Technology | 6 | * Copyright (C) 2006 - 2008 Lemote Inc. & Institute of Computing Technology |
| 7 | * Author: Yanhua, yanh@lemote.com | 7 | * Author: Yanhua, yanh@lemote.com |
| 8 | * | 8 | * |
| 9 | * This file is subject to the terms and conditions of the GNU General Public | 9 | * This file is subject to the terms and conditions of the GNU General Public |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 975edb1000a2..ae43b58c9733 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
| @@ -352,7 +352,7 @@ unsigned long amdgpu_gem_timeout(uint64_t timeout_ns) | |||
| 352 | if (((int64_t)timeout_ns) < 0) | 352 | if (((int64_t)timeout_ns) < 0) |
| 353 | return MAX_SCHEDULE_TIMEOUT; | 353 | return MAX_SCHEDULE_TIMEOUT; |
| 354 | 354 | ||
| 355 | timeout = ktime_sub_ns(ktime_get(), timeout_ns); | 355 | timeout = ktime_sub(ns_to_ktime(timeout_ns), ktime_get()); |
| 356 | if (ktime_to_ns(timeout) < 0) | 356 | if (ktime_to_ns(timeout) < 0) |
| 357 | return 0; | 357 | return 0; |
| 358 | 358 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 5cde635978f9..6e77964f1b64 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | |||
| @@ -3403,19 +3403,25 @@ static int dce_v10_0_crtc_irq(struct amdgpu_device *adev, | |||
| 3403 | 3403 | ||
| 3404 | switch (entry->src_data) { | 3404 | switch (entry->src_data) { |
| 3405 | case 0: /* vblank */ | 3405 | case 0: /* vblank */ |
| 3406 | if (disp_int & interrupt_status_offsets[crtc].vblank) { | 3406 | if (disp_int & interrupt_status_offsets[crtc].vblank) |
| 3407 | dce_v10_0_crtc_vblank_int_ack(adev, crtc); | 3407 | dce_v10_0_crtc_vblank_int_ack(adev, crtc); |
| 3408 | if (amdgpu_irq_enabled(adev, source, irq_type)) { | 3408 | else |
| 3409 | drm_handle_vblank(adev->ddev, crtc); | 3409 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 3410 | } | 3410 | |
| 3411 | DRM_DEBUG("IH: D%d vblank\n", crtc + 1); | 3411 | if (amdgpu_irq_enabled(adev, source, irq_type)) { |
| 3412 | drm_handle_vblank(adev->ddev, crtc); | ||
| 3412 | } | 3413 | } |
| 3414 | DRM_DEBUG("IH: D%d vblank\n", crtc + 1); | ||
| 3415 | |||
| 3413 | break; | 3416 | break; |
| 3414 | case 1: /* vline */ | 3417 | case 1: /* vline */ |
| 3415 | if (disp_int & interrupt_status_offsets[crtc].vline) { | 3418 | if (disp_int & interrupt_status_offsets[crtc].vline) |
| 3416 | dce_v10_0_crtc_vline_int_ack(adev, crtc); | 3419 | dce_v10_0_crtc_vline_int_ack(adev, crtc); |
| 3417 | DRM_DEBUG("IH: D%d vline\n", crtc + 1); | 3420 | else |
| 3418 | } | 3421 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 3422 | |||
| 3423 | DRM_DEBUG("IH: D%d vline\n", crtc + 1); | ||
| 3424 | |||
| 3419 | break; | 3425 | break; |
| 3420 | default: | 3426 | default: |
| 3421 | DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); | 3427 | DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 95efd98b202d..7f7abb0e0be5 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | |||
| @@ -3402,19 +3402,25 @@ static int dce_v11_0_crtc_irq(struct amdgpu_device *adev, | |||
| 3402 | 3402 | ||
| 3403 | switch (entry->src_data) { | 3403 | switch (entry->src_data) { |
| 3404 | case 0: /* vblank */ | 3404 | case 0: /* vblank */ |
| 3405 | if (disp_int & interrupt_status_offsets[crtc].vblank) { | 3405 | if (disp_int & interrupt_status_offsets[crtc].vblank) |
| 3406 | dce_v11_0_crtc_vblank_int_ack(adev, crtc); | 3406 | dce_v11_0_crtc_vblank_int_ack(adev, crtc); |
| 3407 | if (amdgpu_irq_enabled(adev, source, irq_type)) { | 3407 | else |
| 3408 | drm_handle_vblank(adev->ddev, crtc); | 3408 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 3409 | } | 3409 | |
| 3410 | DRM_DEBUG("IH: D%d vblank\n", crtc + 1); | 3410 | if (amdgpu_irq_enabled(adev, source, irq_type)) { |
| 3411 | drm_handle_vblank(adev->ddev, crtc); | ||
| 3411 | } | 3412 | } |
| 3413 | DRM_DEBUG("IH: D%d vblank\n", crtc + 1); | ||
| 3414 | |||
| 3412 | break; | 3415 | break; |
| 3413 | case 1: /* vline */ | 3416 | case 1: /* vline */ |
| 3414 | if (disp_int & interrupt_status_offsets[crtc].vline) { | 3417 | if (disp_int & interrupt_status_offsets[crtc].vline) |
| 3415 | dce_v11_0_crtc_vline_int_ack(adev, crtc); | 3418 | dce_v11_0_crtc_vline_int_ack(adev, crtc); |
| 3416 | DRM_DEBUG("IH: D%d vline\n", crtc + 1); | 3419 | else |
| 3417 | } | 3420 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 3421 | |||
| 3422 | DRM_DEBUG("IH: D%d vline\n", crtc + 1); | ||
| 3423 | |||
| 3418 | break; | 3424 | break; |
| 3419 | default: | 3425 | default: |
| 3420 | DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); | 3426 | DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index aaca8d663f2c..08387dfd98a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | |||
| @@ -3237,19 +3237,25 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, | |||
| 3237 | 3237 | ||
| 3238 | switch (entry->src_data) { | 3238 | switch (entry->src_data) { |
| 3239 | case 0: /* vblank */ | 3239 | case 0: /* vblank */ |
| 3240 | if (disp_int & interrupt_status_offsets[crtc].vblank) { | 3240 | if (disp_int & interrupt_status_offsets[crtc].vblank) |
| 3241 | WREG32(mmLB_VBLANK_STATUS + crtc_offsets[crtc], LB_VBLANK_STATUS__VBLANK_ACK_MASK); | 3241 | WREG32(mmLB_VBLANK_STATUS + crtc_offsets[crtc], LB_VBLANK_STATUS__VBLANK_ACK_MASK); |
| 3242 | if (amdgpu_irq_enabled(adev, source, irq_type)) { | 3242 | else |
| 3243 | drm_handle_vblank(adev->ddev, crtc); | 3243 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 3244 | } | 3244 | |
| 3245 | DRM_DEBUG("IH: D%d vblank\n", crtc + 1); | 3245 | if (amdgpu_irq_enabled(adev, source, irq_type)) { |
| 3246 | drm_handle_vblank(adev->ddev, crtc); | ||
| 3246 | } | 3247 | } |
| 3248 | DRM_DEBUG("IH: D%d vblank\n", crtc + 1); | ||
| 3249 | |||
| 3247 | break; | 3250 | break; |
| 3248 | case 1: /* vline */ | 3251 | case 1: /* vline */ |
| 3249 | if (disp_int & interrupt_status_offsets[crtc].vline) { | 3252 | if (disp_int & interrupt_status_offsets[crtc].vline) |
| 3250 | WREG32(mmLB_VLINE_STATUS + crtc_offsets[crtc], LB_VLINE_STATUS__VLINE_ACK_MASK); | 3253 | WREG32(mmLB_VLINE_STATUS + crtc_offsets[crtc], LB_VLINE_STATUS__VLINE_ACK_MASK); |
| 3251 | DRM_DEBUG("IH: D%d vline\n", crtc + 1); | 3254 | else |
| 3252 | } | 3255 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 3256 | |||
| 3257 | DRM_DEBUG("IH: D%d vline\n", crtc + 1); | ||
| 3258 | |||
| 3253 | break; | 3259 | break; |
| 3254 | default: | 3260 | default: |
| 3255 | DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); | 3261 | DRM_DEBUG("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data); |
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 8a1f999daa24..9be007081b72 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c | |||
| @@ -420,6 +420,12 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) | |||
| 420 | pqm_uninit(&p->pqm); | 420 | pqm_uninit(&p->pqm); |
| 421 | 421 | ||
| 422 | pdd = kfd_get_process_device_data(dev, p); | 422 | pdd = kfd_get_process_device_data(dev, p); |
| 423 | |||
| 424 | if (!pdd) { | ||
| 425 | mutex_unlock(&p->mutex); | ||
| 426 | return; | ||
| 427 | } | ||
| 428 | |||
| 423 | if (pdd->reset_wavefronts) { | 429 | if (pdd->reset_wavefronts) { |
| 424 | dbgdev_wave_reset_wavefronts(pdd->dev, p); | 430 | dbgdev_wave_reset_wavefronts(pdd->dev, p); |
| 425 | pdd->reset_wavefronts = false; | 431 | pdd->reset_wavefronts = false; |
| @@ -431,8 +437,7 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) | |||
| 431 | * We don't call amd_iommu_unbind_pasid() here | 437 | * We don't call amd_iommu_unbind_pasid() here |
| 432 | * because the IOMMU called us. | 438 | * because the IOMMU called us. |
| 433 | */ | 439 | */ |
| 434 | if (pdd) | 440 | pdd->bound = false; |
| 435 | pdd->bound = false; | ||
| 436 | 441 | ||
| 437 | mutex_unlock(&p->mutex); | 442 | mutex_unlock(&p->mutex); |
| 438 | } | 443 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 8867818b1401..d65cbe6afb92 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -157,9 +157,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) | |||
| 157 | struct drm_i915_gem_object *obj; | 157 | struct drm_i915_gem_object *obj; |
| 158 | int ret; | 158 | int ret; |
| 159 | 159 | ||
| 160 | obj = i915_gem_object_create_stolen(dev, size); | 160 | obj = i915_gem_alloc_object(dev, size); |
| 161 | if (obj == NULL) | ||
| 162 | obj = i915_gem_alloc_object(dev, size); | ||
| 163 | if (obj == NULL) | 161 | if (obj == NULL) |
| 164 | return ERR_PTR(-ENOMEM); | 162 | return ERR_PTR(-ENOMEM); |
| 165 | 163 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 9daa2883ac18..dcc6a88c560e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
| @@ -2546,6 +2546,8 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) | |||
| 2546 | struct drm_i915_private *dev_priv = dev->dev_private; | 2546 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 2547 | struct drm_i915_gem_object *obj; | 2547 | struct drm_i915_gem_object *obj; |
| 2548 | struct i915_address_space *vm; | 2548 | struct i915_address_space *vm; |
| 2549 | struct i915_vma *vma; | ||
| 2550 | bool flush; | ||
| 2549 | 2551 | ||
| 2550 | i915_check_and_clear_faults(dev); | 2552 | i915_check_and_clear_faults(dev); |
| 2551 | 2553 | ||
| @@ -2555,16 +2557,23 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) | |||
| 2555 | dev_priv->gtt.base.total, | 2557 | dev_priv->gtt.base.total, |
| 2556 | true); | 2558 | true); |
| 2557 | 2559 | ||
| 2560 | /* Cache flush objects bound into GGTT and rebind them. */ | ||
| 2561 | vm = &dev_priv->gtt.base; | ||
| 2558 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { | 2562 | list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { |
| 2559 | struct i915_vma *vma = i915_gem_obj_to_vma(obj, | 2563 | flush = false; |
| 2560 | &dev_priv->gtt.base); | 2564 | list_for_each_entry(vma, &obj->vma_list, vma_link) { |
| 2561 | if (!vma) | 2565 | if (vma->vm != vm) |
| 2562 | continue; | 2566 | continue; |
| 2563 | 2567 | ||
| 2564 | i915_gem_clflush_object(obj, obj->pin_display); | 2568 | WARN_ON(i915_vma_bind(vma, obj->cache_level, |
| 2565 | WARN_ON(i915_vma_bind(vma, obj->cache_level, PIN_UPDATE)); | 2569 | PIN_UPDATE)); |
| 2566 | } | ||
| 2567 | 2570 | ||
| 2571 | flush = true; | ||
| 2572 | } | ||
| 2573 | |||
| 2574 | if (flush) | ||
| 2575 | i915_gem_clflush_object(obj, obj->pin_display); | ||
| 2576 | } | ||
| 2568 | 2577 | ||
| 2569 | if (INTEL_INFO(dev)->gen >= 8) { | 2578 | if (INTEL_INFO(dev)->gen >= 8) { |
| 2570 | if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) | 2579 | if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 633bd1fcab69..d61e74a08f82 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -183,8 +183,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) | |||
| 183 | if (IS_GEN4(dev)) { | 183 | if (IS_GEN4(dev)) { |
| 184 | uint32_t ddc2 = I915_READ(DCC2); | 184 | uint32_t ddc2 = I915_READ(DCC2); |
| 185 | 185 | ||
| 186 | if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE)) | 186 | if (!(ddc2 & DCC2_MODIFIED_ENHANCED_DISABLE)) { |
| 187 | /* Since the swizzling may vary within an | ||
| 188 | * object, we have no idea what the swizzling | ||
| 189 | * is for any page in particular. Thus we | ||
| 190 | * cannot migrate tiled pages using the GPU, | ||
| 191 | * nor can we tell userspace what the exact | ||
| 192 | * swizzling is for any object. | ||
| 193 | */ | ||
| 187 | dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES; | 194 | dev_priv->quirks |= QUIRK_PIN_SWIZZLED_PAGES; |
| 195 | swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; | ||
| 196 | swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; | ||
| 197 | } | ||
| 188 | } | 198 | } |
| 189 | 199 | ||
| 190 | if (dcc == 0xffffffff) { | 200 | if (dcc == 0xffffffff) { |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1b61f9810387..647b1404c441 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -4854,6 +4854,9 @@ static void intel_crtc_disable_planes(struct drm_crtc *crtc) | |||
| 4854 | struct intel_plane *intel_plane; | 4854 | struct intel_plane *intel_plane; |
| 4855 | int pipe = intel_crtc->pipe; | 4855 | int pipe = intel_crtc->pipe; |
| 4856 | 4856 | ||
| 4857 | if (!intel_crtc->active) | ||
| 4858 | return; | ||
| 4859 | |||
| 4857 | intel_crtc_wait_for_pending_flips(crtc); | 4860 | intel_crtc_wait_for_pending_flips(crtc); |
| 4858 | 4861 | ||
| 4859 | intel_pre_disable_primary(crtc); | 4862 | intel_pre_disable_primary(crtc); |
| @@ -7887,7 +7890,7 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, | |||
| 7887 | int pipe = pipe_config->cpu_transcoder; | 7890 | int pipe = pipe_config->cpu_transcoder; |
| 7888 | enum dpio_channel port = vlv_pipe_to_channel(pipe); | 7891 | enum dpio_channel port = vlv_pipe_to_channel(pipe); |
| 7889 | intel_clock_t clock; | 7892 | intel_clock_t clock; |
| 7890 | u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2; | 7893 | u32 cmn_dw13, pll_dw0, pll_dw1, pll_dw2, pll_dw3; |
| 7891 | int refclk = 100000; | 7894 | int refclk = 100000; |
| 7892 | 7895 | ||
| 7893 | mutex_lock(&dev_priv->sb_lock); | 7896 | mutex_lock(&dev_priv->sb_lock); |
| @@ -7895,10 +7898,13 @@ static void chv_crtc_clock_get(struct intel_crtc *crtc, | |||
| 7895 | pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port)); | 7898 | pll_dw0 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW0(port)); |
| 7896 | pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port)); | 7899 | pll_dw1 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW1(port)); |
| 7897 | pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port)); | 7900 | pll_dw2 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW2(port)); |
| 7901 | pll_dw3 = vlv_dpio_read(dev_priv, pipe, CHV_PLL_DW3(port)); | ||
| 7898 | mutex_unlock(&dev_priv->sb_lock); | 7902 | mutex_unlock(&dev_priv->sb_lock); |
| 7899 | 7903 | ||
| 7900 | clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; | 7904 | clock.m1 = (pll_dw1 & 0x7) == DPIO_CHV_M1_DIV_BY_2 ? 2 : 0; |
| 7901 | clock.m2 = ((pll_dw0 & 0xff) << 22) | (pll_dw2 & 0x3fffff); | 7905 | clock.m2 = (pll_dw0 & 0xff) << 22; |
| 7906 | if (pll_dw3 & DPIO_CHV_FRAC_DIV_EN) | ||
| 7907 | clock.m2 |= pll_dw2 & 0x3fffff; | ||
| 7902 | clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf; | 7908 | clock.n = (pll_dw1 >> DPIO_CHV_N_DIV_SHIFT) & 0xf; |
| 7903 | clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7; | 7909 | clock.p1 = (cmn_dw13 >> DPIO_CHV_P1_DIV_SHIFT) & 0x7; |
| 7904 | clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f; | 7910 | clock.p2 = (cmn_dw13 >> DPIO_CHV_P2_DIV_SHIFT) & 0x1f; |
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index f2daad8c3d96..7841970de48d 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | |||
| @@ -285,7 +285,7 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait) | |||
| 285 | 285 | ||
| 286 | if (wait) { | 286 | if (wait) { |
| 287 | if (!wait_for_completion_timeout(&engine->compl, | 287 | if (!wait_for_completion_timeout(&engine->compl, |
| 288 | msecs_to_jiffies(1))) { | 288 | msecs_to_jiffies(100))) { |
| 289 | dev_err(dmm->dev, "timed out waiting for done\n"); | 289 | dev_err(dmm->dev, "timed out waiting for done\n"); |
| 290 | ret = -ETIMEDOUT; | 290 | ret = -ETIMEDOUT; |
| 291 | } | 291 | } |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index ae2df41f216f..12081e61d45a 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
| @@ -177,7 +177,7 @@ struct drm_framebuffer *omap_framebuffer_init(struct drm_device *dev, | |||
| 177 | struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); | 177 | struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object **bos); |
| 178 | struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p); | 178 | struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p); |
| 179 | int omap_framebuffer_pin(struct drm_framebuffer *fb); | 179 | int omap_framebuffer_pin(struct drm_framebuffer *fb); |
| 180 | int omap_framebuffer_unpin(struct drm_framebuffer *fb); | 180 | void omap_framebuffer_unpin(struct drm_framebuffer *fb); |
| 181 | void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, | 181 | void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, |
| 182 | struct omap_drm_window *win, struct omap_overlay_info *info); | 182 | struct omap_drm_window *win, struct omap_overlay_info *info); |
| 183 | struct drm_connector *omap_framebuffer_get_next_connector( | 183 | struct drm_connector *omap_framebuffer_get_next_connector( |
| @@ -211,7 +211,7 @@ void omap_gem_dma_sync(struct drm_gem_object *obj, | |||
| 211 | enum dma_data_direction dir); | 211 | enum dma_data_direction dir); |
| 212 | int omap_gem_get_paddr(struct drm_gem_object *obj, | 212 | int omap_gem_get_paddr(struct drm_gem_object *obj, |
| 213 | dma_addr_t *paddr, bool remap); | 213 | dma_addr_t *paddr, bool remap); |
| 214 | int omap_gem_put_paddr(struct drm_gem_object *obj); | 214 | void omap_gem_put_paddr(struct drm_gem_object *obj); |
| 215 | int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, | 215 | int omap_gem_get_pages(struct drm_gem_object *obj, struct page ***pages, |
| 216 | bool remap); | 216 | bool remap); |
| 217 | int omap_gem_put_pages(struct drm_gem_object *obj); | 217 | int omap_gem_put_pages(struct drm_gem_object *obj); |
| @@ -236,7 +236,7 @@ static inline int align_pitch(int pitch, int width, int bpp) | |||
| 236 | /* PVR needs alignment to 8 pixels.. right now that is the most | 236 | /* PVR needs alignment to 8 pixels.. right now that is the most |
| 237 | * restrictive stride requirement.. | 237 | * restrictive stride requirement.. |
| 238 | */ | 238 | */ |
| 239 | return ALIGN(pitch, 8 * bytespp); | 239 | return roundup(pitch, 8 * bytespp); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | /* map crtc to vblank mask */ | 242 | /* map crtc to vblank mask */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 0b967e76df1a..51b1219af87f 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c | |||
| @@ -287,10 +287,10 @@ fail: | |||
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | /* unpin, no longer being scanned out: */ | 289 | /* unpin, no longer being scanned out: */ |
| 290 | int omap_framebuffer_unpin(struct drm_framebuffer *fb) | 290 | void omap_framebuffer_unpin(struct drm_framebuffer *fb) |
| 291 | { | 291 | { |
| 292 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); | 292 | struct omap_framebuffer *omap_fb = to_omap_framebuffer(fb); |
| 293 | int ret, i, n = drm_format_num_planes(fb->pixel_format); | 293 | int i, n = drm_format_num_planes(fb->pixel_format); |
| 294 | 294 | ||
| 295 | mutex_lock(&omap_fb->lock); | 295 | mutex_lock(&omap_fb->lock); |
| 296 | 296 | ||
| @@ -298,24 +298,16 @@ int omap_framebuffer_unpin(struct drm_framebuffer *fb) | |||
| 298 | 298 | ||
| 299 | if (omap_fb->pin_count > 0) { | 299 | if (omap_fb->pin_count > 0) { |
| 300 | mutex_unlock(&omap_fb->lock); | 300 | mutex_unlock(&omap_fb->lock); |
| 301 | return 0; | 301 | return; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | for (i = 0; i < n; i++) { | 304 | for (i = 0; i < n; i++) { |
| 305 | struct plane *plane = &omap_fb->planes[i]; | 305 | struct plane *plane = &omap_fb->planes[i]; |
| 306 | ret = omap_gem_put_paddr(plane->bo); | 306 | omap_gem_put_paddr(plane->bo); |
| 307 | if (ret) | ||
| 308 | goto fail; | ||
| 309 | plane->paddr = 0; | 307 | plane->paddr = 0; |
| 310 | } | 308 | } |
| 311 | 309 | ||
| 312 | mutex_unlock(&omap_fb->lock); | 310 | mutex_unlock(&omap_fb->lock); |
| 313 | |||
| 314 | return 0; | ||
| 315 | |||
| 316 | fail: | ||
| 317 | mutex_unlock(&omap_fb->lock); | ||
| 318 | return ret; | ||
| 319 | } | 311 | } |
| 320 | 312 | ||
| 321 | struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p) | 313 | struct drm_gem_object *omap_framebuffer_bo(struct drm_framebuffer *fb, int p) |
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 23b5a84389e3..720d16bce7e8 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c | |||
| @@ -135,7 +135,7 @@ static int omap_fbdev_create(struct drm_fb_helper *helper, | |||
| 135 | fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled; | 135 | fbdev->ywrap_enabled = priv->has_dmm && ywrap_enabled; |
| 136 | if (fbdev->ywrap_enabled) { | 136 | if (fbdev->ywrap_enabled) { |
| 137 | /* need to align pitch to page size if using DMM scrolling */ | 137 | /* need to align pitch to page size if using DMM scrolling */ |
| 138 | mode_cmd.pitches[0] = ALIGN(mode_cmd.pitches[0], PAGE_SIZE); | 138 | mode_cmd.pitches[0] = PAGE_ALIGN(mode_cmd.pitches[0]); |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | /* allocate backing bo */ | 141 | /* allocate backing bo */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 2ab77801cf5f..7ed08fdc4c42 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c | |||
| @@ -808,10 +808,10 @@ fail: | |||
| 808 | /* Release physical address, when DMA is no longer being performed.. this | 808 | /* Release physical address, when DMA is no longer being performed.. this |
| 809 | * could potentially unpin and unmap buffers from TILER | 809 | * could potentially unpin and unmap buffers from TILER |
| 810 | */ | 810 | */ |
| 811 | int omap_gem_put_paddr(struct drm_gem_object *obj) | 811 | void omap_gem_put_paddr(struct drm_gem_object *obj) |
| 812 | { | 812 | { |
| 813 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 813 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
| 814 | int ret = 0; | 814 | int ret; |
| 815 | 815 | ||
| 816 | mutex_lock(&obj->dev->struct_mutex); | 816 | mutex_lock(&obj->dev->struct_mutex); |
| 817 | if (omap_obj->paddr_cnt > 0) { | 817 | if (omap_obj->paddr_cnt > 0) { |
| @@ -821,7 +821,6 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) | |||
| 821 | if (ret) { | 821 | if (ret) { |
| 822 | dev_err(obj->dev->dev, | 822 | dev_err(obj->dev->dev, |
| 823 | "could not unpin pages: %d\n", ret); | 823 | "could not unpin pages: %d\n", ret); |
| 824 | goto fail; | ||
| 825 | } | 824 | } |
| 826 | ret = tiler_release(omap_obj->block); | 825 | ret = tiler_release(omap_obj->block); |
| 827 | if (ret) { | 826 | if (ret) { |
| @@ -832,9 +831,8 @@ int omap_gem_put_paddr(struct drm_gem_object *obj) | |||
| 832 | omap_obj->block = NULL; | 831 | omap_obj->block = NULL; |
| 833 | } | 832 | } |
| 834 | } | 833 | } |
| 835 | fail: | 834 | |
| 836 | mutex_unlock(&obj->dev->struct_mutex); | 835 | mutex_unlock(&obj->dev->struct_mutex); |
| 837 | return ret; | ||
| 838 | } | 836 | } |
| 839 | 837 | ||
| 840 | /* Get rotated scanout address (only valid if already pinned), at the | 838 | /* Get rotated scanout address (only valid if already pinned), at the |
| @@ -1378,11 +1376,7 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
| 1378 | 1376 | ||
| 1379 | omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL); | 1377 | omap_obj = kzalloc(sizeof(*omap_obj), GFP_KERNEL); |
| 1380 | if (!omap_obj) | 1378 | if (!omap_obj) |
| 1381 | goto fail; | 1379 | return NULL; |
| 1382 | |||
| 1383 | spin_lock(&priv->list_lock); | ||
| 1384 | list_add(&omap_obj->mm_list, &priv->obj_list); | ||
| 1385 | spin_unlock(&priv->list_lock); | ||
| 1386 | 1380 | ||
| 1387 | obj = &omap_obj->base; | 1381 | obj = &omap_obj->base; |
| 1388 | 1382 | ||
| @@ -1392,11 +1386,19 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, | |||
| 1392 | */ | 1386 | */ |
| 1393 | omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size, | 1387 | omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size, |
| 1394 | &omap_obj->paddr, GFP_KERNEL); | 1388 | &omap_obj->paddr, GFP_KERNEL); |
| 1395 | if (omap_obj->vaddr) | 1389 | if (!omap_obj->vaddr) { |
| 1396 | flags |= OMAP_BO_DMA; | 1390 | kfree(omap_obj); |
| 1391 | |||
| 1392 | return NULL; | ||
| 1393 | } | ||
| 1397 | 1394 | ||
| 1395 | flags |= OMAP_BO_DMA; | ||
| 1398 | } | 1396 | } |
| 1399 | 1397 | ||
| 1398 | spin_lock(&priv->list_lock); | ||
| 1399 | list_add(&omap_obj->mm_list, &priv->obj_list); | ||
| 1400 | spin_unlock(&priv->list_lock); | ||
| 1401 | |||
| 1400 | omap_obj->flags = flags; | 1402 | omap_obj->flags = flags; |
| 1401 | 1403 | ||
| 1402 | if (flags & OMAP_BO_TILED) { | 1404 | if (flags & OMAP_BO_TILED) { |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index cfa8276c4deb..098904696a5c 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | * this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <drm/drm_atomic.h> | ||
| 20 | #include <drm/drm_atomic_helper.h> | 21 | #include <drm/drm_atomic_helper.h> |
| 21 | #include <drm/drm_plane_helper.h> | 22 | #include <drm/drm_plane_helper.h> |
| 22 | 23 | ||
| @@ -153,9 +154,34 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, | |||
| 153 | dispc_ovl_enable(omap_plane->id, false); | 154 | dispc_ovl_enable(omap_plane->id, false); |
| 154 | } | 155 | } |
| 155 | 156 | ||
| 157 | static int omap_plane_atomic_check(struct drm_plane *plane, | ||
| 158 | struct drm_plane_state *state) | ||
| 159 | { | ||
| 160 | struct drm_crtc_state *crtc_state; | ||
| 161 | |||
| 162 | if (!state->crtc) | ||
| 163 | return 0; | ||
| 164 | |||
| 165 | crtc_state = drm_atomic_get_crtc_state(state->state, state->crtc); | ||
| 166 | if (IS_ERR(crtc_state)) | ||
| 167 | return PTR_ERR(crtc_state); | ||
| 168 | |||
| 169 | if (state->crtc_x < 0 || state->crtc_y < 0) | ||
| 170 | return -EINVAL; | ||
| 171 | |||
| 172 | if (state->crtc_x + state->crtc_w > crtc_state->adjusted_mode.hdisplay) | ||
| 173 | return -EINVAL; | ||
| 174 | |||
| 175 | if (state->crtc_y + state->crtc_h > crtc_state->adjusted_mode.vdisplay) | ||
| 176 | return -EINVAL; | ||
| 177 | |||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 156 | static const struct drm_plane_helper_funcs omap_plane_helper_funcs = { | 181 | static const struct drm_plane_helper_funcs omap_plane_helper_funcs = { |
| 157 | .prepare_fb = omap_plane_prepare_fb, | 182 | .prepare_fb = omap_plane_prepare_fb, |
| 158 | .cleanup_fb = omap_plane_cleanup_fb, | 183 | .cleanup_fb = omap_plane_cleanup_fb, |
| 184 | .atomic_check = omap_plane_atomic_check, | ||
| 159 | .atomic_update = omap_plane_atomic_update, | 185 | .atomic_update = omap_plane_atomic_update, |
| 160 | .atomic_disable = omap_plane_atomic_disable, | 186 | .atomic_disable = omap_plane_atomic_disable, |
| 161 | }; | 187 | }; |
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 4ecf5caa8c6d..248953d2fdb7 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c | |||
| @@ -7964,23 +7964,27 @@ restart_ih: | |||
| 7964 | case 1: /* D1 vblank/vline */ | 7964 | case 1: /* D1 vblank/vline */ |
| 7965 | switch (src_data) { | 7965 | switch (src_data) { |
| 7966 | case 0: /* D1 vblank */ | 7966 | case 0: /* D1 vblank */ |
| 7967 | if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT) { | 7967 | if (!(rdev->irq.stat_regs.cik.disp_int & LB_D1_VBLANK_INTERRUPT)) |
| 7968 | if (rdev->irq.crtc_vblank_int[0]) { | 7968 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 7969 | drm_handle_vblank(rdev->ddev, 0); | 7969 | |
| 7970 | rdev->pm.vblank_sync = true; | 7970 | if (rdev->irq.crtc_vblank_int[0]) { |
| 7971 | wake_up(&rdev->irq.vblank_queue); | 7971 | drm_handle_vblank(rdev->ddev, 0); |
| 7972 | } | 7972 | rdev->pm.vblank_sync = true; |
| 7973 | if (atomic_read(&rdev->irq.pflip[0])) | 7973 | wake_up(&rdev->irq.vblank_queue); |
| 7974 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 7975 | rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 7976 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 7977 | } | 7974 | } |
| 7975 | if (atomic_read(&rdev->irq.pflip[0])) | ||
| 7976 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 7977 | rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 7978 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 7979 | |||
| 7978 | break; | 7980 | break; |
| 7979 | case 1: /* D1 vline */ | 7981 | case 1: /* D1 vline */ |
| 7980 | if (rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT) { | 7982 | if (!(rdev->irq.stat_regs.cik.disp_int & LB_D1_VLINE_INTERRUPT)) |
| 7981 | rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT; | 7983 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 7982 | DRM_DEBUG("IH: D1 vline\n"); | 7984 | |
| 7983 | } | 7985 | rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VLINE_INTERRUPT; |
| 7986 | DRM_DEBUG("IH: D1 vline\n"); | ||
| 7987 | |||
| 7984 | break; | 7988 | break; |
| 7985 | default: | 7989 | default: |
| 7986 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 7990 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -7990,23 +7994,27 @@ restart_ih: | |||
| 7990 | case 2: /* D2 vblank/vline */ | 7994 | case 2: /* D2 vblank/vline */ |
| 7991 | switch (src_data) { | 7995 | switch (src_data) { |
| 7992 | case 0: /* D2 vblank */ | 7996 | case 0: /* D2 vblank */ |
| 7993 | if (rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { | 7997 | if (!(rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) |
| 7994 | if (rdev->irq.crtc_vblank_int[1]) { | 7998 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 7995 | drm_handle_vblank(rdev->ddev, 1); | 7999 | |
| 7996 | rdev->pm.vblank_sync = true; | 8000 | if (rdev->irq.crtc_vblank_int[1]) { |
| 7997 | wake_up(&rdev->irq.vblank_queue); | 8001 | drm_handle_vblank(rdev->ddev, 1); |
| 7998 | } | 8002 | rdev->pm.vblank_sync = true; |
| 7999 | if (atomic_read(&rdev->irq.pflip[1])) | 8003 | wake_up(&rdev->irq.vblank_queue); |
| 8000 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 8001 | rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 8002 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 8003 | } | 8004 | } |
| 8005 | if (atomic_read(&rdev->irq.pflip[1])) | ||
| 8006 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 8007 | rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 8008 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 8009 | |||
| 8004 | break; | 8010 | break; |
| 8005 | case 1: /* D2 vline */ | 8011 | case 1: /* D2 vline */ |
| 8006 | if (rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VLINE_INTERRUPT) { | 8012 | if (!(rdev->irq.stat_regs.cik.disp_int_cont & LB_D2_VLINE_INTERRUPT)) |
| 8007 | rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; | 8013 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8008 | DRM_DEBUG("IH: D2 vline\n"); | 8014 | |
| 8009 | } | 8015 | rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; |
| 8016 | DRM_DEBUG("IH: D2 vline\n"); | ||
| 8017 | |||
| 8010 | break; | 8018 | break; |
| 8011 | default: | 8019 | default: |
| 8012 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 8020 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -8016,23 +8024,27 @@ restart_ih: | |||
| 8016 | case 3: /* D3 vblank/vline */ | 8024 | case 3: /* D3 vblank/vline */ |
| 8017 | switch (src_data) { | 8025 | switch (src_data) { |
| 8018 | case 0: /* D3 vblank */ | 8026 | case 0: /* D3 vblank */ |
| 8019 | if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { | 8027 | if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) |
| 8020 | if (rdev->irq.crtc_vblank_int[2]) { | 8028 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8021 | drm_handle_vblank(rdev->ddev, 2); | 8029 | |
| 8022 | rdev->pm.vblank_sync = true; | 8030 | if (rdev->irq.crtc_vblank_int[2]) { |
| 8023 | wake_up(&rdev->irq.vblank_queue); | 8031 | drm_handle_vblank(rdev->ddev, 2); |
| 8024 | } | 8032 | rdev->pm.vblank_sync = true; |
| 8025 | if (atomic_read(&rdev->irq.pflip[2])) | 8033 | wake_up(&rdev->irq.vblank_queue); |
| 8026 | radeon_crtc_handle_vblank(rdev, 2); | ||
| 8027 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | ||
| 8028 | DRM_DEBUG("IH: D3 vblank\n"); | ||
| 8029 | } | 8034 | } |
| 8035 | if (atomic_read(&rdev->irq.pflip[2])) | ||
| 8036 | radeon_crtc_handle_vblank(rdev, 2); | ||
| 8037 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | ||
| 8038 | DRM_DEBUG("IH: D3 vblank\n"); | ||
| 8039 | |||
| 8030 | break; | 8040 | break; |
| 8031 | case 1: /* D3 vline */ | 8041 | case 1: /* D3 vline */ |
| 8032 | if (rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { | 8042 | if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) |
| 8033 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; | 8043 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8034 | DRM_DEBUG("IH: D3 vline\n"); | 8044 | |
| 8035 | } | 8045 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; |
| 8046 | DRM_DEBUG("IH: D3 vline\n"); | ||
| 8047 | |||
| 8036 | break; | 8048 | break; |
| 8037 | default: | 8049 | default: |
| 8038 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 8050 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -8042,23 +8054,27 @@ restart_ih: | |||
| 8042 | case 4: /* D4 vblank/vline */ | 8054 | case 4: /* D4 vblank/vline */ |
| 8043 | switch (src_data) { | 8055 | switch (src_data) { |
| 8044 | case 0: /* D4 vblank */ | 8056 | case 0: /* D4 vblank */ |
| 8045 | if (rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { | 8057 | if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) |
| 8046 | if (rdev->irq.crtc_vblank_int[3]) { | 8058 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8047 | drm_handle_vblank(rdev->ddev, 3); | 8059 | |
| 8048 | rdev->pm.vblank_sync = true; | 8060 | if (rdev->irq.crtc_vblank_int[3]) { |
| 8049 | wake_up(&rdev->irq.vblank_queue); | 8061 | drm_handle_vblank(rdev->ddev, 3); |
| 8050 | } | 8062 | rdev->pm.vblank_sync = true; |
| 8051 | if (atomic_read(&rdev->irq.pflip[3])) | 8063 | wake_up(&rdev->irq.vblank_queue); |
| 8052 | radeon_crtc_handle_vblank(rdev, 3); | ||
| 8053 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | ||
| 8054 | DRM_DEBUG("IH: D4 vblank\n"); | ||
| 8055 | } | 8064 | } |
| 8065 | if (atomic_read(&rdev->irq.pflip[3])) | ||
| 8066 | radeon_crtc_handle_vblank(rdev, 3); | ||
| 8067 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | ||
| 8068 | DRM_DEBUG("IH: D4 vblank\n"); | ||
| 8069 | |||
| 8056 | break; | 8070 | break; |
| 8057 | case 1: /* D4 vline */ | 8071 | case 1: /* D4 vline */ |
| 8058 | if (rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { | 8072 | if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) |
| 8059 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; | 8073 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8060 | DRM_DEBUG("IH: D4 vline\n"); | 8074 | |
| 8061 | } | 8075 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; |
| 8076 | DRM_DEBUG("IH: D4 vline\n"); | ||
| 8077 | |||
| 8062 | break; | 8078 | break; |
| 8063 | default: | 8079 | default: |
| 8064 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 8080 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -8068,23 +8084,27 @@ restart_ih: | |||
| 8068 | case 5: /* D5 vblank/vline */ | 8084 | case 5: /* D5 vblank/vline */ |
| 8069 | switch (src_data) { | 8085 | switch (src_data) { |
| 8070 | case 0: /* D5 vblank */ | 8086 | case 0: /* D5 vblank */ |
| 8071 | if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { | 8087 | if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) |
| 8072 | if (rdev->irq.crtc_vblank_int[4]) { | 8088 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8073 | drm_handle_vblank(rdev->ddev, 4); | 8089 | |
| 8074 | rdev->pm.vblank_sync = true; | 8090 | if (rdev->irq.crtc_vblank_int[4]) { |
| 8075 | wake_up(&rdev->irq.vblank_queue); | 8091 | drm_handle_vblank(rdev->ddev, 4); |
| 8076 | } | 8092 | rdev->pm.vblank_sync = true; |
| 8077 | if (atomic_read(&rdev->irq.pflip[4])) | 8093 | wake_up(&rdev->irq.vblank_queue); |
| 8078 | radeon_crtc_handle_vblank(rdev, 4); | ||
| 8079 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | ||
| 8080 | DRM_DEBUG("IH: D5 vblank\n"); | ||
| 8081 | } | 8094 | } |
| 8095 | if (atomic_read(&rdev->irq.pflip[4])) | ||
| 8096 | radeon_crtc_handle_vblank(rdev, 4); | ||
| 8097 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | ||
| 8098 | DRM_DEBUG("IH: D5 vblank\n"); | ||
| 8099 | |||
| 8082 | break; | 8100 | break; |
| 8083 | case 1: /* D5 vline */ | 8101 | case 1: /* D5 vline */ |
| 8084 | if (rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { | 8102 | if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) |
| 8085 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; | 8103 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8086 | DRM_DEBUG("IH: D5 vline\n"); | 8104 | |
| 8087 | } | 8105 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; |
| 8106 | DRM_DEBUG("IH: D5 vline\n"); | ||
| 8107 | |||
| 8088 | break; | 8108 | break; |
| 8089 | default: | 8109 | default: |
| 8090 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 8110 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -8094,23 +8114,27 @@ restart_ih: | |||
| 8094 | case 6: /* D6 vblank/vline */ | 8114 | case 6: /* D6 vblank/vline */ |
| 8095 | switch (src_data) { | 8115 | switch (src_data) { |
| 8096 | case 0: /* D6 vblank */ | 8116 | case 0: /* D6 vblank */ |
| 8097 | if (rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { | 8117 | if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) |
| 8098 | if (rdev->irq.crtc_vblank_int[5]) { | 8118 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8099 | drm_handle_vblank(rdev->ddev, 5); | 8119 | |
| 8100 | rdev->pm.vblank_sync = true; | 8120 | if (rdev->irq.crtc_vblank_int[5]) { |
| 8101 | wake_up(&rdev->irq.vblank_queue); | 8121 | drm_handle_vblank(rdev->ddev, 5); |
| 8102 | } | 8122 | rdev->pm.vblank_sync = true; |
| 8103 | if (atomic_read(&rdev->irq.pflip[5])) | 8123 | wake_up(&rdev->irq.vblank_queue); |
| 8104 | radeon_crtc_handle_vblank(rdev, 5); | ||
| 8105 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | ||
| 8106 | DRM_DEBUG("IH: D6 vblank\n"); | ||
| 8107 | } | 8124 | } |
| 8125 | if (atomic_read(&rdev->irq.pflip[5])) | ||
| 8126 | radeon_crtc_handle_vblank(rdev, 5); | ||
| 8127 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | ||
| 8128 | DRM_DEBUG("IH: D6 vblank\n"); | ||
| 8129 | |||
| 8108 | break; | 8130 | break; |
| 8109 | case 1: /* D6 vline */ | 8131 | case 1: /* D6 vline */ |
| 8110 | if (rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { | 8132 | if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) |
| 8111 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; | 8133 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8112 | DRM_DEBUG("IH: D6 vline\n"); | 8134 | |
| 8113 | } | 8135 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; |
| 8136 | DRM_DEBUG("IH: D6 vline\n"); | ||
| 8137 | |||
| 8114 | break; | 8138 | break; |
| 8115 | default: | 8139 | default: |
| 8116 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 8140 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -8130,88 +8154,112 @@ restart_ih: | |||
| 8130 | case 42: /* HPD hotplug */ | 8154 | case 42: /* HPD hotplug */ |
| 8131 | switch (src_data) { | 8155 | switch (src_data) { |
| 8132 | case 0: | 8156 | case 0: |
| 8133 | if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_INTERRUPT) { | 8157 | if (!(rdev->irq.stat_regs.cik.disp_int & DC_HPD1_INTERRUPT)) |
| 8134 | rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT; | 8158 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8135 | queue_hotplug = true; | 8159 | |
| 8136 | DRM_DEBUG("IH: HPD1\n"); | 8160 | rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_INTERRUPT; |
| 8137 | } | 8161 | queue_hotplug = true; |
| 8162 | DRM_DEBUG("IH: HPD1\n"); | ||
| 8163 | |||
| 8138 | break; | 8164 | break; |
| 8139 | case 1: | 8165 | case 1: |
| 8140 | if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_INTERRUPT) { | 8166 | if (!(rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_INTERRUPT)) |
| 8141 | rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT; | 8167 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8142 | queue_hotplug = true; | 8168 | |
| 8143 | DRM_DEBUG("IH: HPD2\n"); | 8169 | rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_INTERRUPT; |
| 8144 | } | 8170 | queue_hotplug = true; |
| 8171 | DRM_DEBUG("IH: HPD2\n"); | ||
| 8172 | |||
| 8145 | break; | 8173 | break; |
| 8146 | case 2: | 8174 | case 2: |
| 8147 | if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_INTERRUPT) { | 8175 | if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_INTERRUPT)) |
| 8148 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; | 8176 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8149 | queue_hotplug = true; | 8177 | |
| 8150 | DRM_DEBUG("IH: HPD3\n"); | 8178 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; |
| 8151 | } | 8179 | queue_hotplug = true; |
| 8180 | DRM_DEBUG("IH: HPD3\n"); | ||
| 8181 | |||
| 8152 | break; | 8182 | break; |
| 8153 | case 3: | 8183 | case 3: |
| 8154 | if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_INTERRUPT) { | 8184 | if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_INTERRUPT)) |
| 8155 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; | 8185 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8156 | queue_hotplug = true; | 8186 | |
| 8157 | DRM_DEBUG("IH: HPD4\n"); | 8187 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; |
| 8158 | } | 8188 | queue_hotplug = true; |
| 8189 | DRM_DEBUG("IH: HPD4\n"); | ||
| 8190 | |||
| 8159 | break; | 8191 | break; |
| 8160 | case 4: | 8192 | case 4: |
| 8161 | if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_INTERRUPT) { | 8193 | if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_INTERRUPT)) |
| 8162 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; | 8194 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8163 | queue_hotplug = true; | 8195 | |
| 8164 | DRM_DEBUG("IH: HPD5\n"); | 8196 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; |
| 8165 | } | 8197 | queue_hotplug = true; |
| 8198 | DRM_DEBUG("IH: HPD5\n"); | ||
| 8199 | |||
| 8166 | break; | 8200 | break; |
| 8167 | case 5: | 8201 | case 5: |
| 8168 | if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT) { | 8202 | if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_INTERRUPT)) |
| 8169 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; | 8203 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8170 | queue_hotplug = true; | 8204 | |
| 8171 | DRM_DEBUG("IH: HPD6\n"); | 8205 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; |
| 8172 | } | 8206 | queue_hotplug = true; |
| 8207 | DRM_DEBUG("IH: HPD6\n"); | ||
| 8208 | |||
| 8173 | break; | 8209 | break; |
| 8174 | case 6: | 8210 | case 6: |
| 8175 | if (rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT) { | 8211 | if (!(rdev->irq.stat_regs.cik.disp_int & DC_HPD1_RX_INTERRUPT)) |
| 8176 | rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT; | 8212 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8177 | queue_dp = true; | 8213 | |
| 8178 | DRM_DEBUG("IH: HPD_RX 1\n"); | 8214 | rdev->irq.stat_regs.cik.disp_int &= ~DC_HPD1_RX_INTERRUPT; |
| 8179 | } | 8215 | queue_dp = true; |
| 8216 | DRM_DEBUG("IH: HPD_RX 1\n"); | ||
| 8217 | |||
| 8180 | break; | 8218 | break; |
| 8181 | case 7: | 8219 | case 7: |
| 8182 | if (rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT) { | 8220 | if (!(rdev->irq.stat_regs.cik.disp_int_cont & DC_HPD2_RX_INTERRUPT)) |
| 8183 | rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; | 8221 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8184 | queue_dp = true; | 8222 | |
| 8185 | DRM_DEBUG("IH: HPD_RX 2\n"); | 8223 | rdev->irq.stat_regs.cik.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; |
| 8186 | } | 8224 | queue_dp = true; |
| 8225 | DRM_DEBUG("IH: HPD_RX 2\n"); | ||
| 8226 | |||
| 8187 | break; | 8227 | break; |
| 8188 | case 8: | 8228 | case 8: |
| 8189 | if (rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { | 8229 | if (!(rdev->irq.stat_regs.cik.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) |
| 8190 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; | 8230 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8191 | queue_dp = true; | 8231 | |
| 8192 | DRM_DEBUG("IH: HPD_RX 3\n"); | 8232 | rdev->irq.stat_regs.cik.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; |
| 8193 | } | 8233 | queue_dp = true; |
| 8234 | DRM_DEBUG("IH: HPD_RX 3\n"); | ||
| 8235 | |||
| 8194 | break; | 8236 | break; |
| 8195 | case 9: | 8237 | case 9: |
| 8196 | if (rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { | 8238 | if (!(rdev->irq.stat_regs.cik.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) |
| 8197 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; | 8239 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8198 | queue_dp = true; | 8240 | |
| 8199 | DRM_DEBUG("IH: HPD_RX 4\n"); | 8241 | rdev->irq.stat_regs.cik.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; |
| 8200 | } | 8242 | queue_dp = true; |
| 8243 | DRM_DEBUG("IH: HPD_RX 4\n"); | ||
| 8244 | |||
| 8201 | break; | 8245 | break; |
| 8202 | case 10: | 8246 | case 10: |
| 8203 | if (rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { | 8247 | if (!(rdev->irq.stat_regs.cik.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) |
| 8204 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; | 8248 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8205 | queue_dp = true; | 8249 | |
| 8206 | DRM_DEBUG("IH: HPD_RX 5\n"); | 8250 | rdev->irq.stat_regs.cik.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; |
| 8207 | } | 8251 | queue_dp = true; |
| 8252 | DRM_DEBUG("IH: HPD_RX 5\n"); | ||
| 8253 | |||
| 8208 | break; | 8254 | break; |
| 8209 | case 11: | 8255 | case 11: |
| 8210 | if (rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { | 8256 | if (!(rdev->irq.stat_regs.cik.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) |
| 8211 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; | 8257 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 8212 | queue_dp = true; | 8258 | |
| 8213 | DRM_DEBUG("IH: HPD_RX 6\n"); | 8259 | rdev->irq.stat_regs.cik.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; |
| 8214 | } | 8260 | queue_dp = true; |
| 8261 | DRM_DEBUG("IH: HPD_RX 6\n"); | ||
| 8262 | |||
| 8215 | break; | 8263 | break; |
| 8216 | default: | 8264 | default: |
| 8217 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 8265 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 3a6d483a2c36..0acde1949c18 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
| @@ -4924,7 +4924,7 @@ restart_ih: | |||
| 4924 | return IRQ_NONE; | 4924 | return IRQ_NONE; |
| 4925 | 4925 | ||
| 4926 | rptr = rdev->ih.rptr; | 4926 | rptr = rdev->ih.rptr; |
| 4927 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 4927 | DRM_DEBUG("evergreen_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
| 4928 | 4928 | ||
| 4929 | /* Order reading of wptr vs. reading of IH ring data */ | 4929 | /* Order reading of wptr vs. reading of IH ring data */ |
| 4930 | rmb(); | 4930 | rmb(); |
| @@ -4942,23 +4942,27 @@ restart_ih: | |||
| 4942 | case 1: /* D1 vblank/vline */ | 4942 | case 1: /* D1 vblank/vline */ |
| 4943 | switch (src_data) { | 4943 | switch (src_data) { |
| 4944 | case 0: /* D1 vblank */ | 4944 | case 0: /* D1 vblank */ |
| 4945 | if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { | 4945 | if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)) |
| 4946 | if (rdev->irq.crtc_vblank_int[0]) { | 4946 | DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); |
| 4947 | drm_handle_vblank(rdev->ddev, 0); | 4947 | |
| 4948 | rdev->pm.vblank_sync = true; | 4948 | if (rdev->irq.crtc_vblank_int[0]) { |
| 4949 | wake_up(&rdev->irq.vblank_queue); | 4949 | drm_handle_vblank(rdev->ddev, 0); |
| 4950 | } | 4950 | rdev->pm.vblank_sync = true; |
| 4951 | if (atomic_read(&rdev->irq.pflip[0])) | 4951 | wake_up(&rdev->irq.vblank_queue); |
| 4952 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 4953 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 4954 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 4955 | } | 4952 | } |
| 4953 | if (atomic_read(&rdev->irq.pflip[0])) | ||
| 4954 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 4955 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 4956 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 4957 | |||
| 4956 | break; | 4958 | break; |
| 4957 | case 1: /* D1 vline */ | 4959 | case 1: /* D1 vline */ |
| 4958 | if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { | 4960 | if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)) |
| 4959 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; | 4961 | DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); |
| 4960 | DRM_DEBUG("IH: D1 vline\n"); | 4962 | |
| 4961 | } | 4963 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; |
| 4964 | DRM_DEBUG("IH: D1 vline\n"); | ||
| 4965 | |||
| 4962 | break; | 4966 | break; |
| 4963 | default: | 4967 | default: |
| 4964 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 4968 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -4968,23 +4972,27 @@ restart_ih: | |||
| 4968 | case 2: /* D2 vblank/vline */ | 4972 | case 2: /* D2 vblank/vline */ |
| 4969 | switch (src_data) { | 4973 | switch (src_data) { |
| 4970 | case 0: /* D2 vblank */ | 4974 | case 0: /* D2 vblank */ |
| 4971 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { | 4975 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) |
| 4972 | if (rdev->irq.crtc_vblank_int[1]) { | 4976 | DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); |
| 4973 | drm_handle_vblank(rdev->ddev, 1); | 4977 | |
| 4974 | rdev->pm.vblank_sync = true; | 4978 | if (rdev->irq.crtc_vblank_int[1]) { |
| 4975 | wake_up(&rdev->irq.vblank_queue); | 4979 | drm_handle_vblank(rdev->ddev, 1); |
| 4976 | } | 4980 | rdev->pm.vblank_sync = true; |
| 4977 | if (atomic_read(&rdev->irq.pflip[1])) | 4981 | wake_up(&rdev->irq.vblank_queue); |
| 4978 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 4979 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 4980 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 4981 | } | 4982 | } |
| 4983 | if (atomic_read(&rdev->irq.pflip[1])) | ||
| 4984 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 4985 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 4986 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 4987 | |||
| 4982 | break; | 4988 | break; |
| 4983 | case 1: /* D2 vline */ | 4989 | case 1: /* D2 vline */ |
| 4984 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { | 4990 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)) |
| 4985 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; | 4991 | DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); |
| 4986 | DRM_DEBUG("IH: D2 vline\n"); | 4992 | |
| 4987 | } | 4993 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; |
| 4994 | DRM_DEBUG("IH: D2 vline\n"); | ||
| 4995 | |||
| 4988 | break; | 4996 | break; |
| 4989 | default: | 4997 | default: |
| 4990 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 4998 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -4994,23 +5002,27 @@ restart_ih: | |||
| 4994 | case 3: /* D3 vblank/vline */ | 5002 | case 3: /* D3 vblank/vline */ |
| 4995 | switch (src_data) { | 5003 | switch (src_data) { |
| 4996 | case 0: /* D3 vblank */ | 5004 | case 0: /* D3 vblank */ |
| 4997 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { | 5005 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) |
| 4998 | if (rdev->irq.crtc_vblank_int[2]) { | 5006 | DRM_DEBUG("IH: D3 vblank - IH event w/o asserted irq bit?\n"); |
| 4999 | drm_handle_vblank(rdev->ddev, 2); | 5007 | |
| 5000 | rdev->pm.vblank_sync = true; | 5008 | if (rdev->irq.crtc_vblank_int[2]) { |
| 5001 | wake_up(&rdev->irq.vblank_queue); | 5009 | drm_handle_vblank(rdev->ddev, 2); |
| 5002 | } | 5010 | rdev->pm.vblank_sync = true; |
| 5003 | if (atomic_read(&rdev->irq.pflip[2])) | 5011 | wake_up(&rdev->irq.vblank_queue); |
| 5004 | radeon_crtc_handle_vblank(rdev, 2); | ||
| 5005 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | ||
| 5006 | DRM_DEBUG("IH: D3 vblank\n"); | ||
| 5007 | } | 5012 | } |
| 5013 | if (atomic_read(&rdev->irq.pflip[2])) | ||
| 5014 | radeon_crtc_handle_vblank(rdev, 2); | ||
| 5015 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | ||
| 5016 | DRM_DEBUG("IH: D3 vblank\n"); | ||
| 5017 | |||
| 5008 | break; | 5018 | break; |
| 5009 | case 1: /* D3 vline */ | 5019 | case 1: /* D3 vline */ |
| 5010 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { | 5020 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) |
| 5011 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; | 5021 | DRM_DEBUG("IH: D3 vline - IH event w/o asserted irq bit?\n"); |
| 5012 | DRM_DEBUG("IH: D3 vline\n"); | 5022 | |
| 5013 | } | 5023 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; |
| 5024 | DRM_DEBUG("IH: D3 vline\n"); | ||
| 5025 | |||
| 5014 | break; | 5026 | break; |
| 5015 | default: | 5027 | default: |
| 5016 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 5028 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -5020,23 +5032,27 @@ restart_ih: | |||
| 5020 | case 4: /* D4 vblank/vline */ | 5032 | case 4: /* D4 vblank/vline */ |
| 5021 | switch (src_data) { | 5033 | switch (src_data) { |
| 5022 | case 0: /* D4 vblank */ | 5034 | case 0: /* D4 vblank */ |
| 5023 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { | 5035 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) |
| 5024 | if (rdev->irq.crtc_vblank_int[3]) { | 5036 | DRM_DEBUG("IH: D4 vblank - IH event w/o asserted irq bit?\n"); |
| 5025 | drm_handle_vblank(rdev->ddev, 3); | 5037 | |
| 5026 | rdev->pm.vblank_sync = true; | 5038 | if (rdev->irq.crtc_vblank_int[3]) { |
| 5027 | wake_up(&rdev->irq.vblank_queue); | 5039 | drm_handle_vblank(rdev->ddev, 3); |
| 5028 | } | 5040 | rdev->pm.vblank_sync = true; |
| 5029 | if (atomic_read(&rdev->irq.pflip[3])) | 5041 | wake_up(&rdev->irq.vblank_queue); |
| 5030 | radeon_crtc_handle_vblank(rdev, 3); | ||
| 5031 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | ||
| 5032 | DRM_DEBUG("IH: D4 vblank\n"); | ||
| 5033 | } | 5042 | } |
| 5043 | if (atomic_read(&rdev->irq.pflip[3])) | ||
| 5044 | radeon_crtc_handle_vblank(rdev, 3); | ||
| 5045 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | ||
| 5046 | DRM_DEBUG("IH: D4 vblank\n"); | ||
| 5047 | |||
| 5034 | break; | 5048 | break; |
| 5035 | case 1: /* D4 vline */ | 5049 | case 1: /* D4 vline */ |
| 5036 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { | 5050 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) |
| 5037 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; | 5051 | DRM_DEBUG("IH: D4 vline - IH event w/o asserted irq bit?\n"); |
| 5038 | DRM_DEBUG("IH: D4 vline\n"); | 5052 | |
| 5039 | } | 5053 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; |
| 5054 | DRM_DEBUG("IH: D4 vline\n"); | ||
| 5055 | |||
| 5040 | break; | 5056 | break; |
| 5041 | default: | 5057 | default: |
| 5042 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 5058 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -5046,23 +5062,27 @@ restart_ih: | |||
| 5046 | case 5: /* D5 vblank/vline */ | 5062 | case 5: /* D5 vblank/vline */ |
| 5047 | switch (src_data) { | 5063 | switch (src_data) { |
| 5048 | case 0: /* D5 vblank */ | 5064 | case 0: /* D5 vblank */ |
| 5049 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { | 5065 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) |
| 5050 | if (rdev->irq.crtc_vblank_int[4]) { | 5066 | DRM_DEBUG("IH: D5 vblank - IH event w/o asserted irq bit?\n"); |
| 5051 | drm_handle_vblank(rdev->ddev, 4); | 5067 | |
| 5052 | rdev->pm.vblank_sync = true; | 5068 | if (rdev->irq.crtc_vblank_int[4]) { |
| 5053 | wake_up(&rdev->irq.vblank_queue); | 5069 | drm_handle_vblank(rdev->ddev, 4); |
| 5054 | } | 5070 | rdev->pm.vblank_sync = true; |
| 5055 | if (atomic_read(&rdev->irq.pflip[4])) | 5071 | wake_up(&rdev->irq.vblank_queue); |
| 5056 | radeon_crtc_handle_vblank(rdev, 4); | ||
| 5057 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | ||
| 5058 | DRM_DEBUG("IH: D5 vblank\n"); | ||
| 5059 | } | 5072 | } |
| 5073 | if (atomic_read(&rdev->irq.pflip[4])) | ||
| 5074 | radeon_crtc_handle_vblank(rdev, 4); | ||
| 5075 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | ||
| 5076 | DRM_DEBUG("IH: D5 vblank\n"); | ||
| 5077 | |||
| 5060 | break; | 5078 | break; |
| 5061 | case 1: /* D5 vline */ | 5079 | case 1: /* D5 vline */ |
| 5062 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { | 5080 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) |
| 5063 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; | 5081 | DRM_DEBUG("IH: D5 vline - IH event w/o asserted irq bit?\n"); |
| 5064 | DRM_DEBUG("IH: D5 vline\n"); | 5082 | |
| 5065 | } | 5083 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; |
| 5084 | DRM_DEBUG("IH: D5 vline\n"); | ||
| 5085 | |||
| 5066 | break; | 5086 | break; |
| 5067 | default: | 5087 | default: |
| 5068 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 5088 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -5072,23 +5092,27 @@ restart_ih: | |||
| 5072 | case 6: /* D6 vblank/vline */ | 5092 | case 6: /* D6 vblank/vline */ |
| 5073 | switch (src_data) { | 5093 | switch (src_data) { |
| 5074 | case 0: /* D6 vblank */ | 5094 | case 0: /* D6 vblank */ |
| 5075 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { | 5095 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) |
| 5076 | if (rdev->irq.crtc_vblank_int[5]) { | 5096 | DRM_DEBUG("IH: D6 vblank - IH event w/o asserted irq bit?\n"); |
| 5077 | drm_handle_vblank(rdev->ddev, 5); | 5097 | |
| 5078 | rdev->pm.vblank_sync = true; | 5098 | if (rdev->irq.crtc_vblank_int[5]) { |
| 5079 | wake_up(&rdev->irq.vblank_queue); | 5099 | drm_handle_vblank(rdev->ddev, 5); |
| 5080 | } | 5100 | rdev->pm.vblank_sync = true; |
| 5081 | if (atomic_read(&rdev->irq.pflip[5])) | 5101 | wake_up(&rdev->irq.vblank_queue); |
| 5082 | radeon_crtc_handle_vblank(rdev, 5); | ||
| 5083 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | ||
| 5084 | DRM_DEBUG("IH: D6 vblank\n"); | ||
| 5085 | } | 5102 | } |
| 5103 | if (atomic_read(&rdev->irq.pflip[5])) | ||
| 5104 | radeon_crtc_handle_vblank(rdev, 5); | ||
| 5105 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | ||
| 5106 | DRM_DEBUG("IH: D6 vblank\n"); | ||
| 5107 | |||
| 5086 | break; | 5108 | break; |
| 5087 | case 1: /* D6 vline */ | 5109 | case 1: /* D6 vline */ |
| 5088 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { | 5110 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) |
| 5089 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; | 5111 | DRM_DEBUG("IH: D6 vline - IH event w/o asserted irq bit?\n"); |
| 5090 | DRM_DEBUG("IH: D6 vline\n"); | 5112 | |
| 5091 | } | 5113 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; |
| 5114 | DRM_DEBUG("IH: D6 vline\n"); | ||
| 5115 | |||
| 5092 | break; | 5116 | break; |
| 5093 | default: | 5117 | default: |
| 5094 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 5118 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -5108,88 +5132,100 @@ restart_ih: | |||
| 5108 | case 42: /* HPD hotplug */ | 5132 | case 42: /* HPD hotplug */ |
| 5109 | switch (src_data) { | 5133 | switch (src_data) { |
| 5110 | case 0: | 5134 | case 0: |
| 5111 | if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { | 5135 | if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT)) |
| 5112 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; | 5136 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5113 | queue_hotplug = true; | 5137 | |
| 5114 | DRM_DEBUG("IH: HPD1\n"); | 5138 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; |
| 5115 | } | 5139 | queue_hotplug = true; |
| 5140 | DRM_DEBUG("IH: HPD1\n"); | ||
| 5116 | break; | 5141 | break; |
| 5117 | case 1: | 5142 | case 1: |
| 5118 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { | 5143 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT)) |
| 5119 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; | 5144 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5120 | queue_hotplug = true; | 5145 | |
| 5121 | DRM_DEBUG("IH: HPD2\n"); | 5146 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; |
| 5122 | } | 5147 | queue_hotplug = true; |
| 5148 | DRM_DEBUG("IH: HPD2\n"); | ||
| 5123 | break; | 5149 | break; |
| 5124 | case 2: | 5150 | case 2: |
| 5125 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { | 5151 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT)) |
| 5126 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; | 5152 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5127 | queue_hotplug = true; | 5153 | |
| 5128 | DRM_DEBUG("IH: HPD3\n"); | 5154 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; |
| 5129 | } | 5155 | queue_hotplug = true; |
| 5156 | DRM_DEBUG("IH: HPD3\n"); | ||
| 5130 | break; | 5157 | break; |
| 5131 | case 3: | 5158 | case 3: |
| 5132 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { | 5159 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT)) |
| 5133 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; | 5160 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5134 | queue_hotplug = true; | 5161 | |
| 5135 | DRM_DEBUG("IH: HPD4\n"); | 5162 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; |
| 5136 | } | 5163 | queue_hotplug = true; |
| 5164 | DRM_DEBUG("IH: HPD4\n"); | ||
| 5137 | break; | 5165 | break; |
| 5138 | case 4: | 5166 | case 4: |
| 5139 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { | 5167 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT)) |
| 5140 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; | 5168 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5141 | queue_hotplug = true; | 5169 | |
| 5142 | DRM_DEBUG("IH: HPD5\n"); | 5170 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; |
| 5143 | } | 5171 | queue_hotplug = true; |
| 5172 | DRM_DEBUG("IH: HPD5\n"); | ||
| 5144 | break; | 5173 | break; |
| 5145 | case 5: | 5174 | case 5: |
| 5146 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { | 5175 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT)) |
| 5147 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; | 5176 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5148 | queue_hotplug = true; | 5177 | |
| 5149 | DRM_DEBUG("IH: HPD6\n"); | 5178 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; |
| 5150 | } | 5179 | queue_hotplug = true; |
| 5180 | DRM_DEBUG("IH: HPD6\n"); | ||
| 5151 | break; | 5181 | break; |
| 5152 | case 6: | 5182 | case 6: |
| 5153 | if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) { | 5183 | if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT)) |
| 5154 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; | 5184 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5155 | queue_dp = true; | 5185 | |
| 5156 | DRM_DEBUG("IH: HPD_RX 1\n"); | 5186 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; |
| 5157 | } | 5187 | queue_dp = true; |
| 5188 | DRM_DEBUG("IH: HPD_RX 1\n"); | ||
| 5158 | break; | 5189 | break; |
| 5159 | case 7: | 5190 | case 7: |
| 5160 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) { | 5191 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT)) |
| 5161 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; | 5192 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5162 | queue_dp = true; | 5193 | |
| 5163 | DRM_DEBUG("IH: HPD_RX 2\n"); | 5194 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; |
| 5164 | } | 5195 | queue_dp = true; |
| 5196 | DRM_DEBUG("IH: HPD_RX 2\n"); | ||
| 5165 | break; | 5197 | break; |
| 5166 | case 8: | 5198 | case 8: |
| 5167 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { | 5199 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) |
| 5168 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; | 5200 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5169 | queue_dp = true; | 5201 | |
| 5170 | DRM_DEBUG("IH: HPD_RX 3\n"); | 5202 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; |
| 5171 | } | 5203 | queue_dp = true; |
| 5204 | DRM_DEBUG("IH: HPD_RX 3\n"); | ||
| 5172 | break; | 5205 | break; |
| 5173 | case 9: | 5206 | case 9: |
| 5174 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { | 5207 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) |
| 5175 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; | 5208 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5176 | queue_dp = true; | 5209 | |
| 5177 | DRM_DEBUG("IH: HPD_RX 4\n"); | 5210 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; |
| 5178 | } | 5211 | queue_dp = true; |
| 5212 | DRM_DEBUG("IH: HPD_RX 4\n"); | ||
| 5179 | break; | 5213 | break; |
| 5180 | case 10: | 5214 | case 10: |
| 5181 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { | 5215 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) |
| 5182 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; | 5216 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5183 | queue_dp = true; | 5217 | |
| 5184 | DRM_DEBUG("IH: HPD_RX 5\n"); | 5218 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; |
| 5185 | } | 5219 | queue_dp = true; |
| 5220 | DRM_DEBUG("IH: HPD_RX 5\n"); | ||
| 5186 | break; | 5221 | break; |
| 5187 | case 11: | 5222 | case 11: |
| 5188 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { | 5223 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) |
| 5189 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; | 5224 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5190 | queue_dp = true; | 5225 | |
| 5191 | DRM_DEBUG("IH: HPD_RX 6\n"); | 5226 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; |
| 5192 | } | 5227 | queue_dp = true; |
| 5228 | DRM_DEBUG("IH: HPD_RX 6\n"); | ||
| 5193 | break; | 5229 | break; |
| 5194 | default: | 5230 | default: |
| 5195 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 5231 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -5199,46 +5235,52 @@ restart_ih: | |||
| 5199 | case 44: /* hdmi */ | 5235 | case 44: /* hdmi */ |
| 5200 | switch (src_data) { | 5236 | switch (src_data) { |
| 5201 | case 0: | 5237 | case 0: |
| 5202 | if (rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG) { | 5238 | if (!(rdev->irq.stat_regs.evergreen.afmt_status1 & AFMT_AZ_FORMAT_WTRIG)) |
| 5203 | rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; | 5239 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5204 | queue_hdmi = true; | 5240 | |
| 5205 | DRM_DEBUG("IH: HDMI0\n"); | 5241 | rdev->irq.stat_regs.evergreen.afmt_status1 &= ~AFMT_AZ_FORMAT_WTRIG; |
| 5206 | } | 5242 | queue_hdmi = true; |
| 5243 | DRM_DEBUG("IH: HDMI0\n"); | ||
| 5207 | break; | 5244 | break; |
| 5208 | case 1: | 5245 | case 1: |
| 5209 | if (rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG) { | 5246 | if (!(rdev->irq.stat_regs.evergreen.afmt_status2 & AFMT_AZ_FORMAT_WTRIG)) |
| 5210 | rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; | 5247 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5211 | queue_hdmi = true; | 5248 | |
| 5212 | DRM_DEBUG("IH: HDMI1\n"); | 5249 | rdev->irq.stat_regs.evergreen.afmt_status2 &= ~AFMT_AZ_FORMAT_WTRIG; |
| 5213 | } | 5250 | queue_hdmi = true; |
| 5251 | DRM_DEBUG("IH: HDMI1\n"); | ||
| 5214 | break; | 5252 | break; |
| 5215 | case 2: | 5253 | case 2: |
| 5216 | if (rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG) { | 5254 | if (!(rdev->irq.stat_regs.evergreen.afmt_status3 & AFMT_AZ_FORMAT_WTRIG)) |
| 5217 | rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; | 5255 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5218 | queue_hdmi = true; | 5256 | |
| 5219 | DRM_DEBUG("IH: HDMI2\n"); | 5257 | rdev->irq.stat_regs.evergreen.afmt_status3 &= ~AFMT_AZ_FORMAT_WTRIG; |
| 5220 | } | 5258 | queue_hdmi = true; |
| 5259 | DRM_DEBUG("IH: HDMI2\n"); | ||
| 5221 | break; | 5260 | break; |
| 5222 | case 3: | 5261 | case 3: |
| 5223 | if (rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG) { | 5262 | if (!(rdev->irq.stat_regs.evergreen.afmt_status4 & AFMT_AZ_FORMAT_WTRIG)) |
| 5224 | rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; | 5263 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5225 | queue_hdmi = true; | 5264 | |
| 5226 | DRM_DEBUG("IH: HDMI3\n"); | 5265 | rdev->irq.stat_regs.evergreen.afmt_status4 &= ~AFMT_AZ_FORMAT_WTRIG; |
| 5227 | } | 5266 | queue_hdmi = true; |
| 5267 | DRM_DEBUG("IH: HDMI3\n"); | ||
| 5228 | break; | 5268 | break; |
| 5229 | case 4: | 5269 | case 4: |
| 5230 | if (rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG) { | 5270 | if (!(rdev->irq.stat_regs.evergreen.afmt_status5 & AFMT_AZ_FORMAT_WTRIG)) |
| 5231 | rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; | 5271 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5232 | queue_hdmi = true; | 5272 | |
| 5233 | DRM_DEBUG("IH: HDMI4\n"); | 5273 | rdev->irq.stat_regs.evergreen.afmt_status5 &= ~AFMT_AZ_FORMAT_WTRIG; |
| 5234 | } | 5274 | queue_hdmi = true; |
| 5275 | DRM_DEBUG("IH: HDMI4\n"); | ||
| 5235 | break; | 5276 | break; |
| 5236 | case 5: | 5277 | case 5: |
| 5237 | if (rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG) { | 5278 | if (!(rdev->irq.stat_regs.evergreen.afmt_status6 & AFMT_AZ_FORMAT_WTRIG)) |
| 5238 | rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; | 5279 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 5239 | queue_hdmi = true; | 5280 | |
| 5240 | DRM_DEBUG("IH: HDMI5\n"); | 5281 | rdev->irq.stat_regs.evergreen.afmt_status6 &= ~AFMT_AZ_FORMAT_WTRIG; |
| 5241 | } | 5282 | queue_hdmi = true; |
| 5283 | DRM_DEBUG("IH: HDMI5\n"); | ||
| 5242 | break; | 5284 | break; |
| 5243 | default: | 5285 | default: |
| 5244 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | 5286 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 8e5aeeb058a5..158872eb78e4 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
| @@ -2162,18 +2162,20 @@ static int cayman_startup(struct radeon_device *rdev) | |||
| 2162 | DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); | 2162 | DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); |
| 2163 | } | 2163 | } |
| 2164 | 2164 | ||
| 2165 | ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; | 2165 | if (rdev->family == CHIP_ARUBA) { |
| 2166 | if (ring->ring_size) | 2166 | ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; |
| 2167 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); | 2167 | if (ring->ring_size) |
| 2168 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); | ||
| 2168 | 2169 | ||
| 2169 | ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; | 2170 | ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; |
| 2170 | if (ring->ring_size) | 2171 | if (ring->ring_size) |
| 2171 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); | 2172 | r = radeon_ring_init(rdev, ring, ring->ring_size, 0, 0x0); |
| 2172 | 2173 | ||
| 2173 | if (!r) | 2174 | if (!r) |
| 2174 | r = vce_v1_0_init(rdev); | 2175 | r = vce_v1_0_init(rdev); |
| 2175 | else if (r != -ENOENT) | 2176 | if (r) |
| 2176 | DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); | 2177 | DRM_ERROR("radeon: failed initializing VCE (%d).\n", r); |
| 2178 | } | ||
| 2177 | 2179 | ||
| 2178 | r = radeon_ib_pool_init(rdev); | 2180 | r = radeon_ib_pool_init(rdev); |
| 2179 | if (r) { | 2181 | if (r) { |
| @@ -2396,7 +2398,8 @@ void cayman_fini(struct radeon_device *rdev) | |||
| 2396 | radeon_irq_kms_fini(rdev); | 2398 | radeon_irq_kms_fini(rdev); |
| 2397 | uvd_v1_0_fini(rdev); | 2399 | uvd_v1_0_fini(rdev); |
| 2398 | radeon_uvd_fini(rdev); | 2400 | radeon_uvd_fini(rdev); |
| 2399 | radeon_vce_fini(rdev); | 2401 | if (rdev->family == CHIP_ARUBA) |
| 2402 | radeon_vce_fini(rdev); | ||
| 2400 | cayman_pcie_gart_fini(rdev); | 2403 | cayman_pcie_gart_fini(rdev); |
| 2401 | r600_vram_scratch_fini(rdev); | 2404 | r600_vram_scratch_fini(rdev); |
| 2402 | radeon_gem_fini(rdev); | 2405 | radeon_gem_fini(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 35dafd77a639..4ea5b10ff5f4 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -4086,23 +4086,27 @@ restart_ih: | |||
| 4086 | case 1: /* D1 vblank/vline */ | 4086 | case 1: /* D1 vblank/vline */ |
| 4087 | switch (src_data) { | 4087 | switch (src_data) { |
| 4088 | case 0: /* D1 vblank */ | 4088 | case 0: /* D1 vblank */ |
| 4089 | if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) { | 4089 | if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)) |
| 4090 | if (rdev->irq.crtc_vblank_int[0]) { | 4090 | DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); |
| 4091 | drm_handle_vblank(rdev->ddev, 0); | 4091 | |
| 4092 | rdev->pm.vblank_sync = true; | 4092 | if (rdev->irq.crtc_vblank_int[0]) { |
| 4093 | wake_up(&rdev->irq.vblank_queue); | 4093 | drm_handle_vblank(rdev->ddev, 0); |
| 4094 | } | 4094 | rdev->pm.vblank_sync = true; |
| 4095 | if (atomic_read(&rdev->irq.pflip[0])) | 4095 | wake_up(&rdev->irq.vblank_queue); |
| 4096 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 4097 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 4098 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 4099 | } | 4096 | } |
| 4097 | if (atomic_read(&rdev->irq.pflip[0])) | ||
| 4098 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 4099 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 4100 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 4101 | |||
| 4100 | break; | 4102 | break; |
| 4101 | case 1: /* D1 vline */ | 4103 | case 1: /* D1 vline */ |
| 4102 | if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) { | 4104 | if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)) |
| 4103 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; | 4105 | DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); |
| 4104 | DRM_DEBUG("IH: D1 vline\n"); | 4106 | |
| 4105 | } | 4107 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; |
| 4108 | DRM_DEBUG("IH: D1 vline\n"); | ||
| 4109 | |||
| 4106 | break; | 4110 | break; |
| 4107 | default: | 4111 | default: |
| 4108 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 4112 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -4112,23 +4116,27 @@ restart_ih: | |||
| 4112 | case 5: /* D2 vblank/vline */ | 4116 | case 5: /* D2 vblank/vline */ |
| 4113 | switch (src_data) { | 4117 | switch (src_data) { |
| 4114 | case 0: /* D2 vblank */ | 4118 | case 0: /* D2 vblank */ |
| 4115 | if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) { | 4119 | if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)) |
| 4116 | if (rdev->irq.crtc_vblank_int[1]) { | 4120 | DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); |
| 4117 | drm_handle_vblank(rdev->ddev, 1); | 4121 | |
| 4118 | rdev->pm.vblank_sync = true; | 4122 | if (rdev->irq.crtc_vblank_int[1]) { |
| 4119 | wake_up(&rdev->irq.vblank_queue); | 4123 | drm_handle_vblank(rdev->ddev, 1); |
| 4120 | } | 4124 | rdev->pm.vblank_sync = true; |
| 4121 | if (atomic_read(&rdev->irq.pflip[1])) | 4125 | wake_up(&rdev->irq.vblank_queue); |
| 4122 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 4123 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 4124 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 4125 | } | 4126 | } |
| 4127 | if (atomic_read(&rdev->irq.pflip[1])) | ||
| 4128 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 4129 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 4130 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 4131 | |||
| 4126 | break; | 4132 | break; |
| 4127 | case 1: /* D1 vline */ | 4133 | case 1: /* D1 vline */ |
| 4128 | if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) { | 4134 | if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)) |
| 4129 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; | 4135 | DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); |
| 4130 | DRM_DEBUG("IH: D2 vline\n"); | 4136 | |
| 4131 | } | 4137 | rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; |
| 4138 | DRM_DEBUG("IH: D2 vline\n"); | ||
| 4139 | |||
| 4132 | break; | 4140 | break; |
| 4133 | default: | 4141 | default: |
| 4134 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 4142 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -4148,46 +4156,53 @@ restart_ih: | |||
| 4148 | case 19: /* HPD/DAC hotplug */ | 4156 | case 19: /* HPD/DAC hotplug */ |
| 4149 | switch (src_data) { | 4157 | switch (src_data) { |
| 4150 | case 0: | 4158 | case 0: |
| 4151 | if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { | 4159 | if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT)) |
| 4152 | rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; | 4160 | DRM_DEBUG("IH: HPD1 - IH event w/o asserted irq bit?\n"); |
| 4153 | queue_hotplug = true; | 4161 | |
| 4154 | DRM_DEBUG("IH: HPD1\n"); | 4162 | rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; |
| 4155 | } | 4163 | queue_hotplug = true; |
| 4164 | DRM_DEBUG("IH: HPD1\n"); | ||
| 4156 | break; | 4165 | break; |
| 4157 | case 1: | 4166 | case 1: |
| 4158 | if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { | 4167 | if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT)) |
| 4159 | rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; | 4168 | DRM_DEBUG("IH: HPD2 - IH event w/o asserted irq bit?\n"); |
| 4160 | queue_hotplug = true; | 4169 | |
| 4161 | DRM_DEBUG("IH: HPD2\n"); | 4170 | rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; |
| 4162 | } | 4171 | queue_hotplug = true; |
| 4172 | DRM_DEBUG("IH: HPD2\n"); | ||
| 4163 | break; | 4173 | break; |
| 4164 | case 4: | 4174 | case 4: |
| 4165 | if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { | 4175 | if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT)) |
| 4166 | rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; | 4176 | DRM_DEBUG("IH: HPD3 - IH event w/o asserted irq bit?\n"); |
| 4167 | queue_hotplug = true; | 4177 | |
| 4168 | DRM_DEBUG("IH: HPD3\n"); | 4178 | rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; |
| 4169 | } | 4179 | queue_hotplug = true; |
| 4180 | DRM_DEBUG("IH: HPD3\n"); | ||
| 4170 | break; | 4181 | break; |
| 4171 | case 5: | 4182 | case 5: |
| 4172 | if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { | 4183 | if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT)) |
| 4173 | rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; | 4184 | DRM_DEBUG("IH: HPD4 - IH event w/o asserted irq bit?\n"); |
| 4174 | queue_hotplug = true; | 4185 | |
| 4175 | DRM_DEBUG("IH: HPD4\n"); | 4186 | rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; |
| 4176 | } | 4187 | queue_hotplug = true; |
| 4188 | DRM_DEBUG("IH: HPD4\n"); | ||
| 4177 | break; | 4189 | break; |
| 4178 | case 10: | 4190 | case 10: |
| 4179 | if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { | 4191 | if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT)) |
| 4180 | rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; | 4192 | DRM_DEBUG("IH: HPD5 - IH event w/o asserted irq bit?\n"); |
| 4181 | queue_hotplug = true; | 4193 | |
| 4182 | DRM_DEBUG("IH: HPD5\n"); | 4194 | rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; |
| 4183 | } | 4195 | queue_hotplug = true; |
| 4196 | DRM_DEBUG("IH: HPD5\n"); | ||
| 4184 | break; | 4197 | break; |
| 4185 | case 12: | 4198 | case 12: |
| 4186 | if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { | 4199 | if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT)) |
| 4187 | rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; | 4200 | DRM_DEBUG("IH: HPD6 - IH event w/o asserted irq bit?\n"); |
| 4188 | queue_hotplug = true; | 4201 | |
| 4189 | DRM_DEBUG("IH: HPD6\n"); | 4202 | rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; |
| 4190 | } | 4203 | queue_hotplug = true; |
| 4204 | DRM_DEBUG("IH: HPD6\n"); | ||
| 4205 | |||
| 4191 | break; | 4206 | break; |
| 4192 | default: | 4207 | default: |
| 4193 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 4208 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -4197,18 +4212,22 @@ restart_ih: | |||
| 4197 | case 21: /* hdmi */ | 4212 | case 21: /* hdmi */ |
| 4198 | switch (src_data) { | 4213 | switch (src_data) { |
| 4199 | case 4: | 4214 | case 4: |
| 4200 | if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { | 4215 | if (!(rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG)) |
| 4201 | rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; | 4216 | DRM_DEBUG("IH: HDMI0 - IH event w/o asserted irq bit?\n"); |
| 4202 | queue_hdmi = true; | 4217 | |
| 4203 | DRM_DEBUG("IH: HDMI0\n"); | 4218 | rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; |
| 4204 | } | 4219 | queue_hdmi = true; |
| 4220 | DRM_DEBUG("IH: HDMI0\n"); | ||
| 4221 | |||
| 4205 | break; | 4222 | break; |
| 4206 | case 5: | 4223 | case 5: |
| 4207 | if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { | 4224 | if (!(rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG)) |
| 4208 | rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; | 4225 | DRM_DEBUG("IH: HDMI1 - IH event w/o asserted irq bit?\n"); |
| 4209 | queue_hdmi = true; | 4226 | |
| 4210 | DRM_DEBUG("IH: HDMI1\n"); | 4227 | rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; |
| 4211 | } | 4228 | queue_hdmi = true; |
| 4229 | DRM_DEBUG("IH: HDMI1\n"); | ||
| 4230 | |||
| 4212 | break; | 4231 | break; |
| 4213 | default: | 4232 | default: |
| 4214 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); | 4233 | DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); |
diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c index 09e3f39925fa..98f9adaccc3d 100644 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ b/drivers/gpu/drm/radeon/r600_cp.c | |||
| @@ -2483,7 +2483,7 @@ int r600_cp_dispatch_texture(struct drm_device *dev, | |||
| 2483 | struct drm_buf *buf; | 2483 | struct drm_buf *buf; |
| 2484 | u32 *buffer; | 2484 | u32 *buffer; |
| 2485 | const u8 __user *data; | 2485 | const u8 __user *data; |
| 2486 | int size, pass_size; | 2486 | unsigned int size, pass_size; |
| 2487 | u64 src_offset, dst_offset; | 2487 | u64 src_offset, dst_offset; |
| 2488 | 2488 | ||
| 2489 | if (!radeon_check_offset(dev_priv, tex->offset)) { | 2489 | if (!radeon_check_offset(dev_priv, tex->offset)) { |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 45e54060ee97..afaf346bd50e 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
| @@ -91,15 +91,34 @@ static void radeon_show_cursor(struct drm_crtc *crtc) | |||
| 91 | struct radeon_device *rdev = crtc->dev->dev_private; | 91 | struct radeon_device *rdev = crtc->dev->dev_private; |
| 92 | 92 | ||
| 93 | if (ASIC_IS_DCE4(rdev)) { | 93 | if (ASIC_IS_DCE4(rdev)) { |
| 94 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, | ||
| 95 | upper_32_bits(radeon_crtc->cursor_addr)); | ||
| 96 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
| 97 | lower_32_bits(radeon_crtc->cursor_addr)); | ||
| 94 | WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); | 98 | WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); |
| 95 | WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | | 99 | WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | |
| 96 | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | | 100 | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | |
| 97 | EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); | 101 | EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); |
| 98 | } else if (ASIC_IS_AVIVO(rdev)) { | 102 | } else if (ASIC_IS_AVIVO(rdev)) { |
| 103 | if (rdev->family >= CHIP_RV770) { | ||
| 104 | if (radeon_crtc->crtc_id) | ||
| 105 | WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, | ||
| 106 | upper_32_bits(radeon_crtc->cursor_addr)); | ||
| 107 | else | ||
| 108 | WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, | ||
| 109 | upper_32_bits(radeon_crtc->cursor_addr)); | ||
| 110 | } | ||
| 111 | |||
| 112 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
| 113 | lower_32_bits(radeon_crtc->cursor_addr)); | ||
| 99 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); | 114 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); |
| 100 | WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | | 115 | WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | |
| 101 | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); | 116 | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); |
| 102 | } else { | 117 | } else { |
| 118 | /* offset is from DISP(2)_BASE_ADDRESS */ | ||
| 119 | WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, | ||
| 120 | radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr); | ||
| 121 | |||
| 103 | switch (radeon_crtc->crtc_id) { | 122 | switch (radeon_crtc->crtc_id) { |
| 104 | case 0: | 123 | case 0: |
| 105 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); | 124 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); |
| @@ -205,8 +224,9 @@ static int radeon_cursor_move_locked(struct drm_crtc *crtc, int x, int y) | |||
| 205 | | (x << 16) | 224 | | (x << 16) |
| 206 | | y)); | 225 | | y)); |
| 207 | /* offset is from DISP(2)_BASE_ADDRESS */ | 226 | /* offset is from DISP(2)_BASE_ADDRESS */ |
| 208 | WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset + | 227 | WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, |
| 209 | (yorigin * 256))); | 228 | radeon_crtc->cursor_addr - radeon_crtc->legacy_display_base_addr + |
| 229 | yorigin * 256); | ||
| 210 | } | 230 | } |
| 211 | 231 | ||
| 212 | radeon_crtc->cursor_x = x; | 232 | radeon_crtc->cursor_x = x; |
| @@ -227,53 +247,6 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
| 227 | return ret; | 247 | return ret; |
| 228 | } | 248 | } |
| 229 | 249 | ||
| 230 | static int radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj) | ||
| 231 | { | ||
| 232 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 233 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 234 | struct radeon_bo *robj = gem_to_radeon_bo(obj); | ||
| 235 | uint64_t gpu_addr; | ||
| 236 | int ret; | ||
| 237 | |||
| 238 | ret = radeon_bo_reserve(robj, false); | ||
| 239 | if (unlikely(ret != 0)) | ||
| 240 | goto fail; | ||
| 241 | /* Only 27 bit offset for legacy cursor */ | ||
| 242 | ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, | ||
| 243 | ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, | ||
| 244 | &gpu_addr); | ||
| 245 | radeon_bo_unreserve(robj); | ||
| 246 | if (ret) | ||
| 247 | goto fail; | ||
| 248 | |||
| 249 | if (ASIC_IS_DCE4(rdev)) { | ||
| 250 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset, | ||
| 251 | upper_32_bits(gpu_addr)); | ||
| 252 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
| 253 | gpu_addr & 0xffffffff); | ||
| 254 | } else if (ASIC_IS_AVIVO(rdev)) { | ||
| 255 | if (rdev->family >= CHIP_RV770) { | ||
| 256 | if (radeon_crtc->crtc_id) | ||
| 257 | WREG32(R700_D2CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); | ||
| 258 | else | ||
| 259 | WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, upper_32_bits(gpu_addr)); | ||
| 260 | } | ||
| 261 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
| 262 | gpu_addr & 0xffffffff); | ||
| 263 | } else { | ||
| 264 | radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr; | ||
| 265 | /* offset is from DISP(2)_BASE_ADDRESS */ | ||
| 266 | WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset); | ||
| 267 | } | ||
| 268 | |||
| 269 | return 0; | ||
| 270 | |||
| 271 | fail: | ||
| 272 | drm_gem_object_unreference_unlocked(obj); | ||
| 273 | |||
| 274 | return ret; | ||
| 275 | } | ||
| 276 | |||
| 277 | int radeon_crtc_cursor_set2(struct drm_crtc *crtc, | 250 | int radeon_crtc_cursor_set2(struct drm_crtc *crtc, |
| 278 | struct drm_file *file_priv, | 251 | struct drm_file *file_priv, |
| 279 | uint32_t handle, | 252 | uint32_t handle, |
| @@ -283,7 +256,9 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, | |||
| 283 | int32_t hot_y) | 256 | int32_t hot_y) |
| 284 | { | 257 | { |
| 285 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 258 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| 259 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 286 | struct drm_gem_object *obj; | 260 | struct drm_gem_object *obj; |
| 261 | struct radeon_bo *robj; | ||
| 287 | int ret; | 262 | int ret; |
| 288 | 263 | ||
| 289 | if (!handle) { | 264 | if (!handle) { |
| @@ -305,6 +280,23 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, | |||
| 305 | return -ENOENT; | 280 | return -ENOENT; |
| 306 | } | 281 | } |
| 307 | 282 | ||
| 283 | robj = gem_to_radeon_bo(obj); | ||
| 284 | ret = radeon_bo_reserve(robj, false); | ||
| 285 | if (ret != 0) { | ||
| 286 | drm_gem_object_unreference_unlocked(obj); | ||
| 287 | return ret; | ||
| 288 | } | ||
| 289 | /* Only 27 bit offset for legacy cursor */ | ||
| 290 | ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, | ||
| 291 | ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, | ||
| 292 | &radeon_crtc->cursor_addr); | ||
| 293 | radeon_bo_unreserve(robj); | ||
| 294 | if (ret) { | ||
| 295 | DRM_ERROR("Failed to pin new cursor BO (%d)\n", ret); | ||
| 296 | drm_gem_object_unreference_unlocked(obj); | ||
| 297 | return ret; | ||
| 298 | } | ||
| 299 | |||
| 308 | radeon_crtc->cursor_width = width; | 300 | radeon_crtc->cursor_width = width; |
| 309 | radeon_crtc->cursor_height = height; | 301 | radeon_crtc->cursor_height = height; |
| 310 | 302 | ||
| @@ -323,13 +315,7 @@ int radeon_crtc_cursor_set2(struct drm_crtc *crtc, | |||
| 323 | radeon_crtc->cursor_hot_y = hot_y; | 315 | radeon_crtc->cursor_hot_y = hot_y; |
| 324 | } | 316 | } |
| 325 | 317 | ||
| 326 | ret = radeon_set_cursor(crtc, obj); | 318 | radeon_show_cursor(crtc); |
| 327 | |||
| 328 | if (ret) | ||
| 329 | DRM_ERROR("radeon_set_cursor returned %d, not changing cursor\n", | ||
| 330 | ret); | ||
| 331 | else | ||
| 332 | radeon_show_cursor(crtc); | ||
| 333 | 319 | ||
| 334 | radeon_lock_cursor(crtc, false); | 320 | radeon_lock_cursor(crtc, false); |
| 335 | 321 | ||
| @@ -341,8 +327,7 @@ unpin: | |||
| 341 | radeon_bo_unpin(robj); | 327 | radeon_bo_unpin(robj); |
| 342 | radeon_bo_unreserve(robj); | 328 | radeon_bo_unreserve(robj); |
| 343 | } | 329 | } |
| 344 | if (radeon_crtc->cursor_bo != obj) | 330 | drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); |
| 345 | drm_gem_object_unreference_unlocked(radeon_crtc->cursor_bo); | ||
| 346 | } | 331 | } |
| 347 | 332 | ||
| 348 | radeon_crtc->cursor_bo = obj; | 333 | radeon_crtc->cursor_bo = obj; |
| @@ -360,7 +345,6 @@ unpin: | |||
| 360 | void radeon_cursor_reset(struct drm_crtc *crtc) | 345 | void radeon_cursor_reset(struct drm_crtc *crtc) |
| 361 | { | 346 | { |
| 362 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 347 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
| 363 | int ret; | ||
| 364 | 348 | ||
| 365 | if (radeon_crtc->cursor_bo) { | 349 | if (radeon_crtc->cursor_bo) { |
| 366 | radeon_lock_cursor(crtc, true); | 350 | radeon_lock_cursor(crtc, true); |
| @@ -368,12 +352,7 @@ void radeon_cursor_reset(struct drm_crtc *crtc) | |||
| 368 | radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, | 352 | radeon_cursor_move_locked(crtc, radeon_crtc->cursor_x, |
| 369 | radeon_crtc->cursor_y); | 353 | radeon_crtc->cursor_y); |
| 370 | 354 | ||
| 371 | ret = radeon_set_cursor(crtc, radeon_crtc->cursor_bo); | 355 | radeon_show_cursor(crtc); |
| 372 | if (ret) | ||
| 373 | DRM_ERROR("radeon_set_cursor returned %d, not showing " | ||
| 374 | "cursor\n", ret); | ||
| 375 | else | ||
| 376 | radeon_show_cursor(crtc); | ||
| 377 | 356 | ||
| 378 | radeon_lock_cursor(crtc, false); | 357 | radeon_lock_cursor(crtc, false); |
| 379 | } | 358 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 2593b1168bd6..d8319dae8358 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -1080,6 +1080,22 @@ static bool radeon_check_pot_argument(int arg) | |||
| 1080 | } | 1080 | } |
| 1081 | 1081 | ||
| 1082 | /** | 1082 | /** |
| 1083 | * Determine a sensible default GART size according to ASIC family. | ||
| 1084 | * | ||
| 1085 | * @family ASIC family name | ||
| 1086 | */ | ||
| 1087 | static int radeon_gart_size_auto(enum radeon_family family) | ||
| 1088 | { | ||
| 1089 | /* default to a larger gart size on newer asics */ | ||
| 1090 | if (family >= CHIP_TAHITI) | ||
| 1091 | return 2048; | ||
| 1092 | else if (family >= CHIP_RV770) | ||
| 1093 | return 1024; | ||
| 1094 | else | ||
| 1095 | return 512; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | /** | ||
| 1083 | * radeon_check_arguments - validate module params | 1099 | * radeon_check_arguments - validate module params |
| 1084 | * | 1100 | * |
| 1085 | * @rdev: radeon_device pointer | 1101 | * @rdev: radeon_device pointer |
| @@ -1097,27 +1113,17 @@ static void radeon_check_arguments(struct radeon_device *rdev) | |||
| 1097 | } | 1113 | } |
| 1098 | 1114 | ||
| 1099 | if (radeon_gart_size == -1) { | 1115 | if (radeon_gart_size == -1) { |
| 1100 | /* default to a larger gart size on newer asics */ | 1116 | radeon_gart_size = radeon_gart_size_auto(rdev->family); |
| 1101 | if (rdev->family >= CHIP_RV770) | ||
| 1102 | radeon_gart_size = 1024; | ||
| 1103 | else | ||
| 1104 | radeon_gart_size = 512; | ||
| 1105 | } | 1117 | } |
| 1106 | /* gtt size must be power of two and greater or equal to 32M */ | 1118 | /* gtt size must be power of two and greater or equal to 32M */ |
| 1107 | if (radeon_gart_size < 32) { | 1119 | if (radeon_gart_size < 32) { |
| 1108 | dev_warn(rdev->dev, "gart size (%d) too small\n", | 1120 | dev_warn(rdev->dev, "gart size (%d) too small\n", |
| 1109 | radeon_gart_size); | 1121 | radeon_gart_size); |
| 1110 | if (rdev->family >= CHIP_RV770) | 1122 | radeon_gart_size = radeon_gart_size_auto(rdev->family); |
| 1111 | radeon_gart_size = 1024; | ||
| 1112 | else | ||
| 1113 | radeon_gart_size = 512; | ||
| 1114 | } else if (!radeon_check_pot_argument(radeon_gart_size)) { | 1123 | } else if (!radeon_check_pot_argument(radeon_gart_size)) { |
| 1115 | dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", | 1124 | dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", |
| 1116 | radeon_gart_size); | 1125 | radeon_gart_size); |
| 1117 | if (rdev->family >= CHIP_RV770) | 1126 | radeon_gart_size = radeon_gart_size_auto(rdev->family); |
| 1118 | radeon_gart_size = 1024; | ||
| 1119 | else | ||
| 1120 | radeon_gart_size = 512; | ||
| 1121 | } | 1127 | } |
| 1122 | rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; | 1128 | rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20; |
| 1123 | 1129 | ||
| @@ -1572,11 +1578,21 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend, bool fbcon) | |||
| 1572 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); | 1578 | drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); |
| 1573 | } | 1579 | } |
| 1574 | 1580 | ||
| 1575 | /* unpin the front buffers */ | 1581 | /* unpin the front buffers and cursors */ |
| 1576 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 1582 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 1583 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 1577 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb); | 1584 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->primary->fb); |
| 1578 | struct radeon_bo *robj; | 1585 | struct radeon_bo *robj; |
| 1579 | 1586 | ||
| 1587 | if (radeon_crtc->cursor_bo) { | ||
| 1588 | struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); | ||
| 1589 | r = radeon_bo_reserve(robj, false); | ||
| 1590 | if (r == 0) { | ||
| 1591 | radeon_bo_unpin(robj); | ||
| 1592 | radeon_bo_unreserve(robj); | ||
| 1593 | } | ||
| 1594 | } | ||
| 1595 | |||
| 1580 | if (rfb == NULL || rfb->obj == NULL) { | 1596 | if (rfb == NULL || rfb->obj == NULL) { |
| 1581 | continue; | 1597 | continue; |
| 1582 | } | 1598 | } |
| @@ -1639,6 +1655,7 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) | |||
| 1639 | { | 1655 | { |
| 1640 | struct drm_connector *connector; | 1656 | struct drm_connector *connector; |
| 1641 | struct radeon_device *rdev = dev->dev_private; | 1657 | struct radeon_device *rdev = dev->dev_private; |
| 1658 | struct drm_crtc *crtc; | ||
| 1642 | int r; | 1659 | int r; |
| 1643 | 1660 | ||
| 1644 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) | 1661 | if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) |
| @@ -1678,6 +1695,27 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) | |||
| 1678 | 1695 | ||
| 1679 | radeon_restore_bios_scratch_regs(rdev); | 1696 | radeon_restore_bios_scratch_regs(rdev); |
| 1680 | 1697 | ||
| 1698 | /* pin cursors */ | ||
| 1699 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 1700 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 1701 | |||
| 1702 | if (radeon_crtc->cursor_bo) { | ||
| 1703 | struct radeon_bo *robj = gem_to_radeon_bo(radeon_crtc->cursor_bo); | ||
| 1704 | r = radeon_bo_reserve(robj, false); | ||
| 1705 | if (r == 0) { | ||
| 1706 | /* Only 27 bit offset for legacy cursor */ | ||
| 1707 | r = radeon_bo_pin_restricted(robj, | ||
| 1708 | RADEON_GEM_DOMAIN_VRAM, | ||
| 1709 | ASIC_IS_AVIVO(rdev) ? | ||
| 1710 | 0 : 1 << 27, | ||
| 1711 | &radeon_crtc->cursor_addr); | ||
| 1712 | if (r != 0) | ||
| 1713 | DRM_ERROR("Failed to pin cursor BO (%d)\n", r); | ||
| 1714 | radeon_bo_unreserve(robj); | ||
| 1715 | } | ||
| 1716 | } | ||
| 1717 | } | ||
| 1718 | |||
| 1681 | /* init dig PHYs, disp eng pll */ | 1719 | /* init dig PHYs, disp eng pll */ |
| 1682 | if (rdev->is_atom_bios) { | 1720 | if (rdev->is_atom_bios) { |
| 1683 | radeon_atom_encoder_init(rdev); | 1721 | radeon_atom_encoder_init(rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index 634793ea8418..aeb676708e60 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -257,6 +257,7 @@ static int radeonfb_create(struct drm_fb_helper *helper, | |||
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | info->par = rfbdev; | 259 | info->par = rfbdev; |
| 260 | info->skip_vt_switch = true; | ||
| 260 | 261 | ||
| 261 | ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); | 262 | ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj); |
| 262 | if (ret) { | 263 | if (ret) { |
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index ac3c1310b953..013ec7106e55 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -428,7 +428,6 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | |||
| 428 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | 428 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, |
| 429 | struct drm_file *filp) | 429 | struct drm_file *filp) |
| 430 | { | 430 | { |
| 431 | struct radeon_device *rdev = dev->dev_private; | ||
| 432 | struct drm_radeon_gem_busy *args = data; | 431 | struct drm_radeon_gem_busy *args = data; |
| 433 | struct drm_gem_object *gobj; | 432 | struct drm_gem_object *gobj; |
| 434 | struct radeon_bo *robj; | 433 | struct radeon_bo *robj; |
| @@ -440,10 +439,16 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
| 440 | return -ENOENT; | 439 | return -ENOENT; |
| 441 | } | 440 | } |
| 442 | robj = gem_to_radeon_bo(gobj); | 441 | robj = gem_to_radeon_bo(gobj); |
| 443 | r = radeon_bo_wait(robj, &cur_placement, true); | 442 | |
| 443 | r = reservation_object_test_signaled_rcu(robj->tbo.resv, true); | ||
| 444 | if (r == 0) | ||
| 445 | r = -EBUSY; | ||
| 446 | else | ||
| 447 | r = 0; | ||
| 448 | |||
| 449 | cur_placement = ACCESS_ONCE(robj->tbo.mem.mem_type); | ||
| 444 | args->domain = radeon_mem_type_to_domain(cur_placement); | 450 | args->domain = radeon_mem_type_to_domain(cur_placement); |
| 445 | drm_gem_object_unreference_unlocked(gobj); | 451 | drm_gem_object_unreference_unlocked(gobj); |
| 446 | r = radeon_gem_handle_lockup(rdev, r); | ||
| 447 | return r; | 452 | return r; |
| 448 | } | 453 | } |
| 449 | 454 | ||
| @@ -471,6 +476,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | |||
| 471 | r = ret; | 476 | r = ret; |
| 472 | 477 | ||
| 473 | /* Flush HDP cache via MMIO if necessary */ | 478 | /* Flush HDP cache via MMIO if necessary */ |
| 479 | cur_placement = ACCESS_ONCE(robj->tbo.mem.mem_type); | ||
| 474 | if (rdev->asic->mmio_hdp_flush && | 480 | if (rdev->asic->mmio_hdp_flush && |
| 475 | radeon_mem_type_to_domain(cur_placement) == RADEON_GEM_DOMAIN_VRAM) | 481 | radeon_mem_type_to_domain(cur_placement) == RADEON_GEM_DOMAIN_VRAM) |
| 476 | robj->rdev->asic->mmio_hdp_flush(rdev); | 482 | robj->rdev->asic->mmio_hdp_flush(rdev); |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 6de5459316b5..07909d817381 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -343,7 +343,6 @@ struct radeon_crtc { | |||
| 343 | int max_cursor_width; | 343 | int max_cursor_width; |
| 344 | int max_cursor_height; | 344 | int max_cursor_height; |
| 345 | uint32_t legacy_display_base_addr; | 345 | uint32_t legacy_display_base_addr; |
| 346 | uint32_t legacy_cursor_offset; | ||
| 347 | enum radeon_rmx_type rmx_type; | 346 | enum radeon_rmx_type rmx_type; |
| 348 | u8 h_border; | 347 | u8 h_border; |
| 349 | u8 v_border; | 348 | u8 v_border; |
diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index ec10533a49b8..48d97c040f49 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c | |||
| @@ -493,38 +493,35 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, | |||
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | if (bo_va->it.start || bo_va->it.last) { | 495 | if (bo_va->it.start || bo_va->it.last) { |
| 496 | spin_lock(&vm->status_lock); | 496 | /* add a clone of the bo_va to clear the old address */ |
| 497 | if (list_empty(&bo_va->vm_status)) { | 497 | struct radeon_bo_va *tmp; |
| 498 | /* add a clone of the bo_va to clear the old address */ | 498 | tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); |
| 499 | struct radeon_bo_va *tmp; | 499 | if (!tmp) { |
| 500 | spin_unlock(&vm->status_lock); | 500 | mutex_unlock(&vm->mutex); |
| 501 | tmp = kzalloc(sizeof(struct radeon_bo_va), GFP_KERNEL); | 501 | r = -ENOMEM; |
| 502 | if (!tmp) { | 502 | goto error_unreserve; |
| 503 | mutex_unlock(&vm->mutex); | ||
| 504 | r = -ENOMEM; | ||
| 505 | goto error_unreserve; | ||
| 506 | } | ||
| 507 | tmp->it.start = bo_va->it.start; | ||
| 508 | tmp->it.last = bo_va->it.last; | ||
| 509 | tmp->vm = vm; | ||
| 510 | tmp->bo = radeon_bo_ref(bo_va->bo); | ||
| 511 | spin_lock(&vm->status_lock); | ||
| 512 | list_add(&tmp->vm_status, &vm->freed); | ||
| 513 | } | 503 | } |
| 514 | spin_unlock(&vm->status_lock); | 504 | tmp->it.start = bo_va->it.start; |
| 505 | tmp->it.last = bo_va->it.last; | ||
| 506 | tmp->vm = vm; | ||
| 507 | tmp->bo = radeon_bo_ref(bo_va->bo); | ||
| 515 | 508 | ||
| 516 | interval_tree_remove(&bo_va->it, &vm->va); | 509 | interval_tree_remove(&bo_va->it, &vm->va); |
| 510 | spin_lock(&vm->status_lock); | ||
| 517 | bo_va->it.start = 0; | 511 | bo_va->it.start = 0; |
| 518 | bo_va->it.last = 0; | 512 | bo_va->it.last = 0; |
| 513 | list_del_init(&bo_va->vm_status); | ||
| 514 | list_add(&tmp->vm_status, &vm->freed); | ||
| 515 | spin_unlock(&vm->status_lock); | ||
| 519 | } | 516 | } |
| 520 | 517 | ||
| 521 | if (soffset || eoffset) { | 518 | if (soffset || eoffset) { |
| 519 | spin_lock(&vm->status_lock); | ||
| 522 | bo_va->it.start = soffset; | 520 | bo_va->it.start = soffset; |
| 523 | bo_va->it.last = eoffset - 1; | 521 | bo_va->it.last = eoffset - 1; |
| 524 | interval_tree_insert(&bo_va->it, &vm->va); | ||
| 525 | spin_lock(&vm->status_lock); | ||
| 526 | list_add(&bo_va->vm_status, &vm->cleared); | 522 | list_add(&bo_va->vm_status, &vm->cleared); |
| 527 | spin_unlock(&vm->status_lock); | 523 | spin_unlock(&vm->status_lock); |
| 524 | interval_tree_insert(&bo_va->it, &vm->va); | ||
| 528 | } | 525 | } |
| 529 | 526 | ||
| 530 | bo_va->flags = flags; | 527 | bo_va->flags = flags; |
| @@ -1158,7 +1155,8 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev, | |||
| 1158 | 1155 | ||
| 1159 | list_for_each_entry(bo_va, &bo->va, bo_list) { | 1156 | list_for_each_entry(bo_va, &bo->va, bo_list) { |
| 1160 | spin_lock(&bo_va->vm->status_lock); | 1157 | spin_lock(&bo_va->vm->status_lock); |
| 1161 | if (list_empty(&bo_va->vm_status)) | 1158 | if (list_empty(&bo_va->vm_status) && |
| 1159 | (bo_va->it.start || bo_va->it.last)) | ||
| 1162 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); | 1160 | list_add(&bo_va->vm_status, &bo_va->vm->invalidated); |
| 1163 | spin_unlock(&bo_va->vm->status_lock); | 1161 | spin_unlock(&bo_va->vm->status_lock); |
| 1164 | } | 1162 | } |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 26388b5dd6ed..07037e32dea3 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -6466,23 +6466,27 @@ restart_ih: | |||
| 6466 | case 1: /* D1 vblank/vline */ | 6466 | case 1: /* D1 vblank/vline */ |
| 6467 | switch (src_data) { | 6467 | switch (src_data) { |
| 6468 | case 0: /* D1 vblank */ | 6468 | case 0: /* D1 vblank */ |
| 6469 | if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT) { | 6469 | if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)) |
| 6470 | if (rdev->irq.crtc_vblank_int[0]) { | 6470 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6471 | drm_handle_vblank(rdev->ddev, 0); | 6471 | |
| 6472 | rdev->pm.vblank_sync = true; | 6472 | if (rdev->irq.crtc_vblank_int[0]) { |
| 6473 | wake_up(&rdev->irq.vblank_queue); | 6473 | drm_handle_vblank(rdev->ddev, 0); |
| 6474 | } | 6474 | rdev->pm.vblank_sync = true; |
| 6475 | if (atomic_read(&rdev->irq.pflip[0])) | 6475 | wake_up(&rdev->irq.vblank_queue); |
| 6476 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 6477 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 6478 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 6479 | } | 6476 | } |
| 6477 | if (atomic_read(&rdev->irq.pflip[0])) | ||
| 6478 | radeon_crtc_handle_vblank(rdev, 0); | ||
| 6479 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; | ||
| 6480 | DRM_DEBUG("IH: D1 vblank\n"); | ||
| 6481 | |||
| 6480 | break; | 6482 | break; |
| 6481 | case 1: /* D1 vline */ | 6483 | case 1: /* D1 vline */ |
| 6482 | if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT) { | 6484 | if (!(rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)) |
| 6483 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; | 6485 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6484 | DRM_DEBUG("IH: D1 vline\n"); | 6486 | |
| 6485 | } | 6487 | rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VLINE_INTERRUPT; |
| 6488 | DRM_DEBUG("IH: D1 vline\n"); | ||
| 6489 | |||
| 6486 | break; | 6490 | break; |
| 6487 | default: | 6491 | default: |
| 6488 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6492 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -6492,23 +6496,27 @@ restart_ih: | |||
| 6492 | case 2: /* D2 vblank/vline */ | 6496 | case 2: /* D2 vblank/vline */ |
| 6493 | switch (src_data) { | 6497 | switch (src_data) { |
| 6494 | case 0: /* D2 vblank */ | 6498 | case 0: /* D2 vblank */ |
| 6495 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT) { | 6499 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)) |
| 6496 | if (rdev->irq.crtc_vblank_int[1]) { | 6500 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6497 | drm_handle_vblank(rdev->ddev, 1); | 6501 | |
| 6498 | rdev->pm.vblank_sync = true; | 6502 | if (rdev->irq.crtc_vblank_int[1]) { |
| 6499 | wake_up(&rdev->irq.vblank_queue); | 6503 | drm_handle_vblank(rdev->ddev, 1); |
| 6500 | } | 6504 | rdev->pm.vblank_sync = true; |
| 6501 | if (atomic_read(&rdev->irq.pflip[1])) | 6505 | wake_up(&rdev->irq.vblank_queue); |
| 6502 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 6503 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 6504 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 6505 | } | 6506 | } |
| 6507 | if (atomic_read(&rdev->irq.pflip[1])) | ||
| 6508 | radeon_crtc_handle_vblank(rdev, 1); | ||
| 6509 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; | ||
| 6510 | DRM_DEBUG("IH: D2 vblank\n"); | ||
| 6511 | |||
| 6506 | break; | 6512 | break; |
| 6507 | case 1: /* D2 vline */ | 6513 | case 1: /* D2 vline */ |
| 6508 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT) { | 6514 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)) |
| 6509 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; | 6515 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6510 | DRM_DEBUG("IH: D2 vline\n"); | 6516 | |
| 6511 | } | 6517 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VLINE_INTERRUPT; |
| 6518 | DRM_DEBUG("IH: D2 vline\n"); | ||
| 6519 | |||
| 6512 | break; | 6520 | break; |
| 6513 | default: | 6521 | default: |
| 6514 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6522 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -6518,23 +6526,27 @@ restart_ih: | |||
| 6518 | case 3: /* D3 vblank/vline */ | 6526 | case 3: /* D3 vblank/vline */ |
| 6519 | switch (src_data) { | 6527 | switch (src_data) { |
| 6520 | case 0: /* D3 vblank */ | 6528 | case 0: /* D3 vblank */ |
| 6521 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) { | 6529 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)) |
| 6522 | if (rdev->irq.crtc_vblank_int[2]) { | 6530 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6523 | drm_handle_vblank(rdev->ddev, 2); | 6531 | |
| 6524 | rdev->pm.vblank_sync = true; | 6532 | if (rdev->irq.crtc_vblank_int[2]) { |
| 6525 | wake_up(&rdev->irq.vblank_queue); | 6533 | drm_handle_vblank(rdev->ddev, 2); |
| 6526 | } | 6534 | rdev->pm.vblank_sync = true; |
| 6527 | if (atomic_read(&rdev->irq.pflip[2])) | 6535 | wake_up(&rdev->irq.vblank_queue); |
| 6528 | radeon_crtc_handle_vblank(rdev, 2); | ||
| 6529 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | ||
| 6530 | DRM_DEBUG("IH: D3 vblank\n"); | ||
| 6531 | } | 6536 | } |
| 6537 | if (atomic_read(&rdev->irq.pflip[2])) | ||
| 6538 | radeon_crtc_handle_vblank(rdev, 2); | ||
| 6539 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; | ||
| 6540 | DRM_DEBUG("IH: D3 vblank\n"); | ||
| 6541 | |||
| 6532 | break; | 6542 | break; |
| 6533 | case 1: /* D3 vline */ | 6543 | case 1: /* D3 vline */ |
| 6534 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) { | 6544 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)) |
| 6535 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; | 6545 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6536 | DRM_DEBUG("IH: D3 vline\n"); | 6546 | |
| 6537 | } | 6547 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VLINE_INTERRUPT; |
| 6548 | DRM_DEBUG("IH: D3 vline\n"); | ||
| 6549 | |||
| 6538 | break; | 6550 | break; |
| 6539 | default: | 6551 | default: |
| 6540 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6552 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -6544,23 +6556,27 @@ restart_ih: | |||
| 6544 | case 4: /* D4 vblank/vline */ | 6556 | case 4: /* D4 vblank/vline */ |
| 6545 | switch (src_data) { | 6557 | switch (src_data) { |
| 6546 | case 0: /* D4 vblank */ | 6558 | case 0: /* D4 vblank */ |
| 6547 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) { | 6559 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)) |
| 6548 | if (rdev->irq.crtc_vblank_int[3]) { | 6560 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6549 | drm_handle_vblank(rdev->ddev, 3); | 6561 | |
| 6550 | rdev->pm.vblank_sync = true; | 6562 | if (rdev->irq.crtc_vblank_int[3]) { |
| 6551 | wake_up(&rdev->irq.vblank_queue); | 6563 | drm_handle_vblank(rdev->ddev, 3); |
| 6552 | } | 6564 | rdev->pm.vblank_sync = true; |
| 6553 | if (atomic_read(&rdev->irq.pflip[3])) | 6565 | wake_up(&rdev->irq.vblank_queue); |
| 6554 | radeon_crtc_handle_vblank(rdev, 3); | ||
| 6555 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | ||
| 6556 | DRM_DEBUG("IH: D4 vblank\n"); | ||
| 6557 | } | 6566 | } |
| 6567 | if (atomic_read(&rdev->irq.pflip[3])) | ||
| 6568 | radeon_crtc_handle_vblank(rdev, 3); | ||
| 6569 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; | ||
| 6570 | DRM_DEBUG("IH: D4 vblank\n"); | ||
| 6571 | |||
| 6558 | break; | 6572 | break; |
| 6559 | case 1: /* D4 vline */ | 6573 | case 1: /* D4 vline */ |
| 6560 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) { | 6574 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)) |
| 6561 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; | 6575 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6562 | DRM_DEBUG("IH: D4 vline\n"); | 6576 | |
| 6563 | } | 6577 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VLINE_INTERRUPT; |
| 6578 | DRM_DEBUG("IH: D4 vline\n"); | ||
| 6579 | |||
| 6564 | break; | 6580 | break; |
| 6565 | default: | 6581 | default: |
| 6566 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6582 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -6570,23 +6586,27 @@ restart_ih: | |||
| 6570 | case 5: /* D5 vblank/vline */ | 6586 | case 5: /* D5 vblank/vline */ |
| 6571 | switch (src_data) { | 6587 | switch (src_data) { |
| 6572 | case 0: /* D5 vblank */ | 6588 | case 0: /* D5 vblank */ |
| 6573 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) { | 6589 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)) |
| 6574 | if (rdev->irq.crtc_vblank_int[4]) { | 6590 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6575 | drm_handle_vblank(rdev->ddev, 4); | 6591 | |
| 6576 | rdev->pm.vblank_sync = true; | 6592 | if (rdev->irq.crtc_vblank_int[4]) { |
| 6577 | wake_up(&rdev->irq.vblank_queue); | 6593 | drm_handle_vblank(rdev->ddev, 4); |
| 6578 | } | 6594 | rdev->pm.vblank_sync = true; |
| 6579 | if (atomic_read(&rdev->irq.pflip[4])) | 6595 | wake_up(&rdev->irq.vblank_queue); |
| 6580 | radeon_crtc_handle_vblank(rdev, 4); | ||
| 6581 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | ||
| 6582 | DRM_DEBUG("IH: D5 vblank\n"); | ||
| 6583 | } | 6596 | } |
| 6597 | if (atomic_read(&rdev->irq.pflip[4])) | ||
| 6598 | radeon_crtc_handle_vblank(rdev, 4); | ||
| 6599 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; | ||
| 6600 | DRM_DEBUG("IH: D5 vblank\n"); | ||
| 6601 | |||
| 6584 | break; | 6602 | break; |
| 6585 | case 1: /* D5 vline */ | 6603 | case 1: /* D5 vline */ |
| 6586 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) { | 6604 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)) |
| 6587 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; | 6605 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6588 | DRM_DEBUG("IH: D5 vline\n"); | 6606 | |
| 6589 | } | 6607 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VLINE_INTERRUPT; |
| 6608 | DRM_DEBUG("IH: D5 vline\n"); | ||
| 6609 | |||
| 6590 | break; | 6610 | break; |
| 6591 | default: | 6611 | default: |
| 6592 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6612 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -6596,23 +6616,27 @@ restart_ih: | |||
| 6596 | case 6: /* D6 vblank/vline */ | 6616 | case 6: /* D6 vblank/vline */ |
| 6597 | switch (src_data) { | 6617 | switch (src_data) { |
| 6598 | case 0: /* D6 vblank */ | 6618 | case 0: /* D6 vblank */ |
| 6599 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) { | 6619 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)) |
| 6600 | if (rdev->irq.crtc_vblank_int[5]) { | 6620 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6601 | drm_handle_vblank(rdev->ddev, 5); | 6621 | |
| 6602 | rdev->pm.vblank_sync = true; | 6622 | if (rdev->irq.crtc_vblank_int[5]) { |
| 6603 | wake_up(&rdev->irq.vblank_queue); | 6623 | drm_handle_vblank(rdev->ddev, 5); |
| 6604 | } | 6624 | rdev->pm.vblank_sync = true; |
| 6605 | if (atomic_read(&rdev->irq.pflip[5])) | 6625 | wake_up(&rdev->irq.vblank_queue); |
| 6606 | radeon_crtc_handle_vblank(rdev, 5); | ||
| 6607 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | ||
| 6608 | DRM_DEBUG("IH: D6 vblank\n"); | ||
| 6609 | } | 6626 | } |
| 6627 | if (atomic_read(&rdev->irq.pflip[5])) | ||
| 6628 | radeon_crtc_handle_vblank(rdev, 5); | ||
| 6629 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; | ||
| 6630 | DRM_DEBUG("IH: D6 vblank\n"); | ||
| 6631 | |||
| 6610 | break; | 6632 | break; |
| 6611 | case 1: /* D6 vline */ | 6633 | case 1: /* D6 vline */ |
| 6612 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) { | 6634 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)) |
| 6613 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; | 6635 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6614 | DRM_DEBUG("IH: D6 vline\n"); | 6636 | |
| 6615 | } | 6637 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VLINE_INTERRUPT; |
| 6638 | DRM_DEBUG("IH: D6 vline\n"); | ||
| 6639 | |||
| 6616 | break; | 6640 | break; |
| 6617 | default: | 6641 | default: |
| 6618 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6642 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
| @@ -6632,88 +6656,112 @@ restart_ih: | |||
| 6632 | case 42: /* HPD hotplug */ | 6656 | case 42: /* HPD hotplug */ |
| 6633 | switch (src_data) { | 6657 | switch (src_data) { |
| 6634 | case 0: | 6658 | case 0: |
| 6635 | if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) { | 6659 | if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT)) |
| 6636 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; | 6660 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6637 | queue_hotplug = true; | 6661 | |
| 6638 | DRM_DEBUG("IH: HPD1\n"); | 6662 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_INTERRUPT; |
| 6639 | } | 6663 | queue_hotplug = true; |
| 6664 | DRM_DEBUG("IH: HPD1\n"); | ||
| 6665 | |||
| 6640 | break; | 6666 | break; |
| 6641 | case 1: | 6667 | case 1: |
| 6642 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT) { | 6668 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_INTERRUPT)) |
| 6643 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; | 6669 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6644 | queue_hotplug = true; | 6670 | |
| 6645 | DRM_DEBUG("IH: HPD2\n"); | 6671 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_INTERRUPT; |
| 6646 | } | 6672 | queue_hotplug = true; |
| 6673 | DRM_DEBUG("IH: HPD2\n"); | ||
| 6674 | |||
| 6647 | break; | 6675 | break; |
| 6648 | case 2: | 6676 | case 2: |
| 6649 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT) { | 6677 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_INTERRUPT)) |
| 6650 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; | 6678 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6651 | queue_hotplug = true; | 6679 | |
| 6652 | DRM_DEBUG("IH: HPD3\n"); | 6680 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_INTERRUPT; |
| 6653 | } | 6681 | queue_hotplug = true; |
| 6682 | DRM_DEBUG("IH: HPD3\n"); | ||
| 6683 | |||
| 6654 | break; | 6684 | break; |
| 6655 | case 3: | 6685 | case 3: |
| 6656 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT) { | 6686 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_INTERRUPT)) |
| 6657 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; | 6687 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6658 | queue_hotplug = true; | 6688 | |
| 6659 | DRM_DEBUG("IH: HPD4\n"); | 6689 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_INTERRUPT; |
| 6660 | } | 6690 | queue_hotplug = true; |
| 6691 | DRM_DEBUG("IH: HPD4\n"); | ||
| 6692 | |||
| 6661 | break; | 6693 | break; |
| 6662 | case 4: | 6694 | case 4: |
| 6663 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT) { | 6695 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_INTERRUPT)) |
| 6664 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; | 6696 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6665 | queue_hotplug = true; | 6697 | |
| 6666 | DRM_DEBUG("IH: HPD5\n"); | 6698 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_INTERRUPT; |
| 6667 | } | 6699 | queue_hotplug = true; |
| 6700 | DRM_DEBUG("IH: HPD5\n"); | ||
| 6701 | |||
| 6668 | break; | 6702 | break; |
| 6669 | case 5: | 6703 | case 5: |
| 6670 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT) { | 6704 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_INTERRUPT)) |
| 6671 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; | 6705 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6672 | queue_hotplug = true; | 6706 | |
| 6673 | DRM_DEBUG("IH: HPD6\n"); | 6707 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_INTERRUPT; |
| 6674 | } | 6708 | queue_hotplug = true; |
| 6709 | DRM_DEBUG("IH: HPD6\n"); | ||
| 6710 | |||
| 6675 | break; | 6711 | break; |
| 6676 | case 6: | 6712 | case 6: |
| 6677 | if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT) { | 6713 | if (!(rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_RX_INTERRUPT)) |
| 6678 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; | 6714 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6679 | queue_dp = true; | 6715 | |
| 6680 | DRM_DEBUG("IH: HPD_RX 1\n"); | 6716 | rdev->irq.stat_regs.evergreen.disp_int &= ~DC_HPD1_RX_INTERRUPT; |
| 6681 | } | 6717 | queue_dp = true; |
| 6718 | DRM_DEBUG("IH: HPD_RX 1\n"); | ||
| 6719 | |||
| 6682 | break; | 6720 | break; |
| 6683 | case 7: | 6721 | case 7: |
| 6684 | if (rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT) { | 6722 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont & DC_HPD2_RX_INTERRUPT)) |
| 6685 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; | 6723 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6686 | queue_dp = true; | 6724 | |
| 6687 | DRM_DEBUG("IH: HPD_RX 2\n"); | 6725 | rdev->irq.stat_regs.evergreen.disp_int_cont &= ~DC_HPD2_RX_INTERRUPT; |
| 6688 | } | 6726 | queue_dp = true; |
| 6727 | DRM_DEBUG("IH: HPD_RX 2\n"); | ||
| 6728 | |||
| 6689 | break; | 6729 | break; |
| 6690 | case 8: | 6730 | case 8: |
| 6691 | if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT) { | 6731 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont2 & DC_HPD3_RX_INTERRUPT)) |
| 6692 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; | 6732 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6693 | queue_dp = true; | 6733 | |
| 6694 | DRM_DEBUG("IH: HPD_RX 3\n"); | 6734 | rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~DC_HPD3_RX_INTERRUPT; |
| 6695 | } | 6735 | queue_dp = true; |
| 6736 | DRM_DEBUG("IH: HPD_RX 3\n"); | ||
| 6737 | |||
| 6696 | break; | 6738 | break; |
| 6697 | case 9: | 6739 | case 9: |
| 6698 | if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT) { | 6740 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont3 & DC_HPD4_RX_INTERRUPT)) |
| 6699 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; | 6741 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6700 | queue_dp = true; | 6742 | |
| 6701 | DRM_DEBUG("IH: HPD_RX 4\n"); | 6743 | rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~DC_HPD4_RX_INTERRUPT; |
| 6702 | } | 6744 | queue_dp = true; |
| 6745 | DRM_DEBUG("IH: HPD_RX 4\n"); | ||
| 6746 | |||
| 6703 | break; | 6747 | break; |
| 6704 | case 10: | 6748 | case 10: |
| 6705 | if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT) { | 6749 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont4 & DC_HPD5_RX_INTERRUPT)) |
| 6706 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; | 6750 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6707 | queue_dp = true; | 6751 | |
| 6708 | DRM_DEBUG("IH: HPD_RX 5\n"); | 6752 | rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~DC_HPD5_RX_INTERRUPT; |
| 6709 | } | 6753 | queue_dp = true; |
| 6754 | DRM_DEBUG("IH: HPD_RX 5\n"); | ||
| 6755 | |||
| 6710 | break; | 6756 | break; |
| 6711 | case 11: | 6757 | case 11: |
| 6712 | if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT) { | 6758 | if (!(rdev->irq.stat_regs.evergreen.disp_int_cont5 & DC_HPD6_RX_INTERRUPT)) |
| 6713 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; | 6759 | DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); |
| 6714 | queue_dp = true; | 6760 | |
| 6715 | DRM_DEBUG("IH: HPD_RX 6\n"); | 6761 | rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~DC_HPD6_RX_INTERRUPT; |
| 6716 | } | 6762 | queue_dp = true; |
| 6763 | DRM_DEBUG("IH: HPD_RX 6\n"); | ||
| 6764 | |||
| 6717 | break; | 6765 | break; |
| 6718 | default: | 6766 | default: |
| 6719 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); | 6767 | DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 35ac23768ce9..577d58d1f1a1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
| @@ -633,6 +633,7 @@ config I2C_MPC | |||
| 633 | config I2C_MT65XX | 633 | config I2C_MT65XX |
| 634 | tristate "MediaTek I2C adapter" | 634 | tristate "MediaTek I2C adapter" |
| 635 | depends on ARCH_MEDIATEK || COMPILE_TEST | 635 | depends on ARCH_MEDIATEK || COMPILE_TEST |
| 636 | depends on HAS_DMA | ||
| 636 | help | 637 | help |
| 637 | This selects the MediaTek(R) Integrated Inter Circuit bus driver | 638 | This selects the MediaTek(R) Integrated Inter Circuit bus driver |
| 638 | for MT65xx and MT81xx. | 639 | for MT65xx and MT81xx. |
diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 19b2d689a5ef..f325663c27c5 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c | |||
| @@ -764,12 +764,15 @@ static int jz4780_i2c_probe(struct platform_device *pdev) | |||
| 764 | if (IS_ERR(i2c->clk)) | 764 | if (IS_ERR(i2c->clk)) |
| 765 | return PTR_ERR(i2c->clk); | 765 | return PTR_ERR(i2c->clk); |
| 766 | 766 | ||
| 767 | clk_prepare_enable(i2c->clk); | 767 | ret = clk_prepare_enable(i2c->clk); |
| 768 | if (ret) | ||
| 769 | return ret; | ||
| 768 | 770 | ||
| 769 | if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", | 771 | ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency", |
| 770 | &clk_freq)) { | 772 | &clk_freq); |
| 773 | if (ret) { | ||
| 771 | dev_err(&pdev->dev, "clock-frequency not specified in DT"); | 774 | dev_err(&pdev->dev, "clock-frequency not specified in DT"); |
| 772 | return clk_freq; | 775 | goto err; |
| 773 | } | 776 | } |
| 774 | 777 | ||
| 775 | i2c->speed = clk_freq / 1000; | 778 | i2c->speed = clk_freq / 1000; |
| @@ -790,10 +793,8 @@ static int jz4780_i2c_probe(struct platform_device *pdev) | |||
| 790 | i2c->irq = platform_get_irq(pdev, 0); | 793 | i2c->irq = platform_get_irq(pdev, 0); |
| 791 | ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0, | 794 | ret = devm_request_irq(&pdev->dev, i2c->irq, jz4780_i2c_irq, 0, |
| 792 | dev_name(&pdev->dev), i2c); | 795 | dev_name(&pdev->dev), i2c); |
| 793 | if (ret) { | 796 | if (ret) |
| 794 | ret = -ENODEV; | ||
| 795 | goto err; | 797 | goto err; |
| 796 | } | ||
| 797 | 798 | ||
| 798 | ret = i2c_add_adapter(&i2c->adap); | 799 | ret = i2c_add_adapter(&i2c->adap); |
| 799 | if (ret < 0) { | 800 | if (ret < 0) { |
diff --git a/drivers/i2c/busses/i2c-xgene-slimpro.c b/drivers/i2c/busses/i2c-xgene-slimpro.c index dcca7076231e..1c9cb65ac4cf 100644 --- a/drivers/i2c/busses/i2c-xgene-slimpro.c +++ b/drivers/i2c/busses/i2c-xgene-slimpro.c | |||
| @@ -419,6 +419,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev) | |||
| 419 | rc = i2c_add_adapter(adapter); | 419 | rc = i2c_add_adapter(adapter); |
| 420 | if (rc) { | 420 | if (rc) { |
| 421 | dev_err(&pdev->dev, "Adapter registeration failed\n"); | 421 | dev_err(&pdev->dev, "Adapter registeration failed\n"); |
| 422 | mbox_free_channel(ctx->mbox_chan); | ||
| 422 | return rc; | 423 | return rc; |
| 423 | } | 424 | } |
| 424 | 425 | ||
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 069a41f116dd..e6d4935161e4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
| @@ -1012,6 +1012,8 @@ EXPORT_SYMBOL_GPL(i2c_new_device); | |||
| 1012 | */ | 1012 | */ |
| 1013 | void i2c_unregister_device(struct i2c_client *client) | 1013 | void i2c_unregister_device(struct i2c_client *client) |
| 1014 | { | 1014 | { |
| 1015 | if (client->dev.of_node) | ||
| 1016 | of_node_clear_flag(client->dev.of_node, OF_POPULATED); | ||
| 1015 | device_unregister(&client->dev); | 1017 | device_unregister(&client->dev); |
| 1016 | } | 1018 | } |
| 1017 | EXPORT_SYMBOL_GPL(i2c_unregister_device); | 1019 | EXPORT_SYMBOL_GPL(i2c_unregister_device); |
| @@ -1320,8 +1322,11 @@ static void of_i2c_register_devices(struct i2c_adapter *adap) | |||
| 1320 | 1322 | ||
| 1321 | dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); | 1323 | dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); |
| 1322 | 1324 | ||
| 1323 | for_each_available_child_of_node(adap->dev.of_node, node) | 1325 | for_each_available_child_of_node(adap->dev.of_node, node) { |
| 1326 | if (of_node_test_and_set_flag(node, OF_POPULATED)) | ||
| 1327 | continue; | ||
| 1324 | of_i2c_register_device(adap, node); | 1328 | of_i2c_register_device(adap, node); |
| 1329 | } | ||
| 1325 | } | 1330 | } |
| 1326 | 1331 | ||
| 1327 | static int of_dev_node_match(struct device *dev, void *data) | 1332 | static int of_dev_node_match(struct device *dev, void *data) |
| @@ -1853,6 +1858,11 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, | |||
| 1853 | if (adap == NULL) | 1858 | if (adap == NULL) |
| 1854 | return NOTIFY_OK; /* not for us */ | 1859 | return NOTIFY_OK; /* not for us */ |
| 1855 | 1860 | ||
| 1861 | if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) { | ||
| 1862 | put_device(&adap->dev); | ||
| 1863 | return NOTIFY_OK; | ||
| 1864 | } | ||
| 1865 | |||
| 1856 | client = of_i2c_register_device(adap, rd->dn); | 1866 | client = of_i2c_register_device(adap, rd->dn); |
| 1857 | put_device(&adap->dev); | 1867 | put_device(&adap->dev); |
| 1858 | 1868 | ||
| @@ -1863,6 +1873,10 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action, | |||
| 1863 | } | 1873 | } |
| 1864 | break; | 1874 | break; |
| 1865 | case OF_RECONFIG_CHANGE_REMOVE: | 1875 | case OF_RECONFIG_CHANGE_REMOVE: |
| 1876 | /* already depopulated? */ | ||
| 1877 | if (!of_node_check_flag(rd->dn, OF_POPULATED)) | ||
| 1878 | return NOTIFY_OK; | ||
| 1879 | |||
| 1866 | /* find our device by node */ | 1880 | /* find our device by node */ |
| 1867 | client = of_find_i2c_device_by_node(rd->dn); | 1881 | client = of_find_i2c_device_by_node(rd->dn); |
| 1868 | if (client == NULL) | 1882 | if (client == NULL) |
diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 62641f2adaf7..5b5f403d8ce6 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c | |||
| @@ -771,7 +771,7 @@ static const struct attribute_group *elan_sysfs_groups[] = { | |||
| 771 | */ | 771 | */ |
| 772 | static void elan_report_contact(struct elan_tp_data *data, | 772 | static void elan_report_contact(struct elan_tp_data *data, |
| 773 | int contact_num, bool contact_valid, | 773 | int contact_num, bool contact_valid, |
| 774 | bool hover_event, u8 *finger_data) | 774 | u8 *finger_data) |
| 775 | { | 775 | { |
| 776 | struct input_dev *input = data->input; | 776 | struct input_dev *input = data->input; |
| 777 | unsigned int pos_x, pos_y; | 777 | unsigned int pos_x, pos_y; |
| @@ -815,9 +815,7 @@ static void elan_report_contact(struct elan_tp_data *data, | |||
| 815 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); | 815 | input_mt_report_slot_state(input, MT_TOOL_FINGER, true); |
| 816 | input_report_abs(input, ABS_MT_POSITION_X, pos_x); | 816 | input_report_abs(input, ABS_MT_POSITION_X, pos_x); |
| 817 | input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); | 817 | input_report_abs(input, ABS_MT_POSITION_Y, data->max_y - pos_y); |
| 818 | input_report_abs(input, ABS_MT_DISTANCE, hover_event); | 818 | input_report_abs(input, ABS_MT_PRESSURE, scaled_pressure); |
| 819 | input_report_abs(input, ABS_MT_PRESSURE, | ||
| 820 | hover_event ? 0 : scaled_pressure); | ||
| 821 | input_report_abs(input, ABS_TOOL_WIDTH, mk_x); | 819 | input_report_abs(input, ABS_TOOL_WIDTH, mk_x); |
| 822 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); | 820 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, major); |
| 823 | input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); | 821 | input_report_abs(input, ABS_MT_TOUCH_MINOR, minor); |
| @@ -839,14 +837,14 @@ static void elan_report_absolute(struct elan_tp_data *data, u8 *packet) | |||
| 839 | hover_event = hover_info & 0x40; | 837 | hover_event = hover_info & 0x40; |
| 840 | for (i = 0; i < ETP_MAX_FINGERS; i++) { | 838 | for (i = 0; i < ETP_MAX_FINGERS; i++) { |
| 841 | contact_valid = tp_info & (1U << (3 + i)); | 839 | contact_valid = tp_info & (1U << (3 + i)); |
| 842 | elan_report_contact(data, i, contact_valid, hover_event, | 840 | elan_report_contact(data, i, contact_valid, finger_data); |
| 843 | finger_data); | ||
| 844 | 841 | ||
| 845 | if (contact_valid) | 842 | if (contact_valid) |
| 846 | finger_data += ETP_FINGER_DATA_LEN; | 843 | finger_data += ETP_FINGER_DATA_LEN; |
| 847 | } | 844 | } |
| 848 | 845 | ||
| 849 | input_report_key(input, BTN_LEFT, tp_info & 0x01); | 846 | input_report_key(input, BTN_LEFT, tp_info & 0x01); |
| 847 | input_report_abs(input, ABS_DISTANCE, hover_event != 0); | ||
| 850 | input_mt_report_pointer_emulation(input, true); | 848 | input_mt_report_pointer_emulation(input, true); |
| 851 | input_sync(input); | 849 | input_sync(input); |
| 852 | } | 850 | } |
| @@ -922,6 +920,7 @@ static int elan_setup_input_device(struct elan_tp_data *data) | |||
| 922 | input_abs_set_res(input, ABS_Y, data->y_res); | 920 | input_abs_set_res(input, ABS_Y, data->y_res); |
| 923 | input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); | 921 | input_set_abs_params(input, ABS_PRESSURE, 0, ETP_MAX_PRESSURE, 0, 0); |
| 924 | input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0); | 922 | input_set_abs_params(input, ABS_TOOL_WIDTH, 0, ETP_FINGER_WIDTH, 0, 0); |
| 923 | input_set_abs_params(input, ABS_DISTANCE, 0, 1, 0, 0); | ||
| 925 | 924 | ||
| 926 | /* And MT parameters */ | 925 | /* And MT parameters */ |
| 927 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0); | 926 | input_set_abs_params(input, ABS_MT_POSITION_X, 0, data->max_x, 0, 0); |
| @@ -934,7 +933,6 @@ static int elan_setup_input_device(struct elan_tp_data *data) | |||
| 934 | ETP_FINGER_WIDTH * max_width, 0, 0); | 933 | ETP_FINGER_WIDTH * max_width, 0, 0); |
| 935 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, | 934 | input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, |
| 936 | ETP_FINGER_WIDTH * min_width, 0, 0); | 935 | ETP_FINGER_WIDTH * min_width, 0, 0); |
| 937 | input_set_abs_params(input, ABS_MT_DISTANCE, 0, 1, 0, 0); | ||
| 938 | 936 | ||
| 939 | data->input = input; | 937 | data->input = input; |
| 940 | 938 | ||
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 35c8d0ceabee..3a32caf06bf1 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -1199,7 +1199,7 @@ static void set_input_params(struct psmouse *psmouse, | |||
| 1199 | ABS_MT_POSITION_Y); | 1199 | ABS_MT_POSITION_Y); |
| 1200 | /* Image sensors can report per-contact pressure */ | 1200 | /* Image sensors can report per-contact pressure */ |
| 1201 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); | 1201 | input_set_abs_params(dev, ABS_MT_PRESSURE, 0, 255, 0, 0); |
| 1202 | input_mt_init_slots(dev, 3, INPUT_MT_POINTER | INPUT_MT_TRACK); | 1202 | input_mt_init_slots(dev, 2, INPUT_MT_POINTER | INPUT_MT_TRACK); |
| 1203 | 1203 | ||
| 1204 | /* Image sensors can signal 4 and 5 finger clicks */ | 1204 | /* Image sensors can signal 4 and 5 finger clicks */ |
| 1205 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); | 1205 | __set_bit(BTN_TOOL_QUADTAP, dev->keybit); |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 8d7e1c8b6d56..4dd88264dff5 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
| @@ -1055,7 +1055,7 @@ gic_acpi_parse_madt_cpu(struct acpi_subtable_header *header, | |||
| 1055 | 1055 | ||
| 1056 | processor = (struct acpi_madt_generic_interrupt *)header; | 1056 | processor = (struct acpi_madt_generic_interrupt *)header; |
| 1057 | 1057 | ||
| 1058 | if (BAD_MADT_ENTRY(processor, end)) | 1058 | if (BAD_MADT_GICC_ENTRY(processor, end)) |
| 1059 | return -EINVAL; | 1059 | return -EINVAL; |
| 1060 | 1060 | ||
| 1061 | /* | 1061 | /* |
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 4400edd1a6c7..b7d54d428b5e 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c | |||
| @@ -257,16 +257,6 @@ int gic_get_c0_fdc_int(void) | |||
| 257 | return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; | 257 | return MIPS_CPU_IRQ_BASE + cp0_fdc_irq; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | /* | ||
| 261 | * Some cores claim the FDC is routable but it doesn't actually seem to | ||
| 262 | * be connected. | ||
| 263 | */ | ||
| 264 | switch (current_cpu_type()) { | ||
| 265 | case CPU_INTERAPTIV: | ||
| 266 | case CPU_PROAPTIV: | ||
| 267 | return -1; | ||
| 268 | } | ||
| 269 | |||
| 270 | return irq_create_mapping(gic_irq_domain, | 260 | return irq_create_mapping(gic_irq_domain, |
| 271 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); | 261 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_FDC)); |
| 272 | } | 262 | } |
diff --git a/drivers/misc/cxl/api.c b/drivers/misc/cxl/api.c index 0c77240ae2fc..729e0851167d 100644 --- a/drivers/misc/cxl/api.c +++ b/drivers/misc/cxl/api.c | |||
| @@ -23,6 +23,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) | |||
| 23 | 23 | ||
| 24 | afu = cxl_pci_to_afu(dev); | 24 | afu = cxl_pci_to_afu(dev); |
| 25 | 25 | ||
| 26 | get_device(&afu->dev); | ||
| 26 | ctx = cxl_context_alloc(); | 27 | ctx = cxl_context_alloc(); |
| 27 | if (IS_ERR(ctx)) | 28 | if (IS_ERR(ctx)) |
| 28 | return ctx; | 29 | return ctx; |
| @@ -31,6 +32,7 @@ struct cxl_context *cxl_dev_context_init(struct pci_dev *dev) | |||
| 31 | rc = cxl_context_init(ctx, afu, false, NULL); | 32 | rc = cxl_context_init(ctx, afu, false, NULL); |
| 32 | if (rc) { | 33 | if (rc) { |
| 33 | kfree(ctx); | 34 | kfree(ctx); |
| 35 | put_device(&afu->dev); | ||
| 34 | return ERR_PTR(-ENOMEM); | 36 | return ERR_PTR(-ENOMEM); |
| 35 | } | 37 | } |
| 36 | cxl_assign_psn_space(ctx); | 38 | cxl_assign_psn_space(ctx); |
| @@ -60,6 +62,8 @@ int cxl_release_context(struct cxl_context *ctx) | |||
| 60 | if (ctx->status != CLOSED) | 62 | if (ctx->status != CLOSED) |
| 61 | return -EBUSY; | 63 | return -EBUSY; |
| 62 | 64 | ||
| 65 | put_device(&ctx->afu->dev); | ||
| 66 | |||
| 63 | cxl_context_free(ctx); | 67 | cxl_context_free(ctx); |
| 64 | 68 | ||
| 65 | return 0; | 69 | return 0; |
| @@ -159,7 +163,6 @@ int cxl_start_context(struct cxl_context *ctx, u64 wed, | |||
| 159 | } | 163 | } |
| 160 | 164 | ||
| 161 | ctx->status = STARTED; | 165 | ctx->status = STARTED; |
| 162 | get_device(&ctx->afu->dev); | ||
| 163 | out: | 166 | out: |
| 164 | mutex_unlock(&ctx->status_mutex); | 167 | mutex_unlock(&ctx->status_mutex); |
| 165 | return rc; | 168 | return rc; |
| @@ -175,12 +178,7 @@ EXPORT_SYMBOL_GPL(cxl_process_element); | |||
| 175 | /* Stop a context. Returns 0 on success, otherwise -Errno */ | 178 | /* Stop a context. Returns 0 on success, otherwise -Errno */ |
| 176 | int cxl_stop_context(struct cxl_context *ctx) | 179 | int cxl_stop_context(struct cxl_context *ctx) |
| 177 | { | 180 | { |
| 178 | int rc; | 181 | return __detach_context(ctx); |
| 179 | |||
| 180 | rc = __detach_context(ctx); | ||
| 181 | if (!rc) | ||
| 182 | put_device(&ctx->afu->dev); | ||
| 183 | return rc; | ||
| 184 | } | 182 | } |
| 185 | EXPORT_SYMBOL_GPL(cxl_stop_context); | 183 | EXPORT_SYMBOL_GPL(cxl_stop_context); |
| 186 | 184 | ||
diff --git a/drivers/misc/cxl/context.c b/drivers/misc/cxl/context.c index 2a4c80ac322a..1287148629c0 100644 --- a/drivers/misc/cxl/context.c +++ b/drivers/misc/cxl/context.c | |||
| @@ -113,11 +113,11 @@ static int cxl_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 113 | 113 | ||
| 114 | if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { | 114 | if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { |
| 115 | area = ctx->afu->psn_phys; | 115 | area = ctx->afu->psn_phys; |
| 116 | if (offset > ctx->afu->adapter->ps_size) | 116 | if (offset >= ctx->afu->adapter->ps_size) |
| 117 | return VM_FAULT_SIGBUS; | 117 | return VM_FAULT_SIGBUS; |
| 118 | } else { | 118 | } else { |
| 119 | area = ctx->psn_phys; | 119 | area = ctx->psn_phys; |
| 120 | if (offset > ctx->psn_size) | 120 | if (offset >= ctx->psn_size) |
| 121 | return VM_FAULT_SIGBUS; | 121 | return VM_FAULT_SIGBUS; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| @@ -145,8 +145,16 @@ static const struct vm_operations_struct cxl_mmap_vmops = { | |||
| 145 | */ | 145 | */ |
| 146 | int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma) | 146 | int cxl_context_iomap(struct cxl_context *ctx, struct vm_area_struct *vma) |
| 147 | { | 147 | { |
| 148 | u64 start = vma->vm_pgoff << PAGE_SHIFT; | ||
| 148 | u64 len = vma->vm_end - vma->vm_start; | 149 | u64 len = vma->vm_end - vma->vm_start; |
| 149 | len = min(len, ctx->psn_size); | 150 | |
| 151 | if (ctx->afu->current_mode == CXL_MODE_DEDICATED) { | ||
| 152 | if (start + len > ctx->afu->adapter->ps_size) | ||
| 153 | return -EINVAL; | ||
| 154 | } else { | ||
| 155 | if (start + len > ctx->psn_size) | ||
| 156 | return -EINVAL; | ||
| 157 | } | ||
| 150 | 158 | ||
| 151 | if (ctx->afu->current_mode != CXL_MODE_DEDICATED) { | 159 | if (ctx->afu->current_mode != CXL_MODE_DEDICATED) { |
| 152 | /* make sure there is a valid per process space for this AFU */ | 160 | /* make sure there is a valid per process space for this AFU */ |
diff --git a/drivers/misc/cxl/main.c b/drivers/misc/cxl/main.c index 833348e2c9cb..4a164ab8b35a 100644 --- a/drivers/misc/cxl/main.c +++ b/drivers/misc/cxl/main.c | |||
| @@ -73,7 +73,7 @@ static inline void cxl_slbia_core(struct mm_struct *mm) | |||
| 73 | spin_lock(&adapter->afu_list_lock); | 73 | spin_lock(&adapter->afu_list_lock); |
| 74 | for (slice = 0; slice < adapter->slices; slice++) { | 74 | for (slice = 0; slice < adapter->slices; slice++) { |
| 75 | afu = adapter->afu[slice]; | 75 | afu = adapter->afu[slice]; |
| 76 | if (!afu->enabled) | 76 | if (!afu || !afu->enabled) |
| 77 | continue; | 77 | continue; |
| 78 | rcu_read_lock(); | 78 | rcu_read_lock(); |
| 79 | idr_for_each_entry(&afu->contexts_idr, ctx, id) | 79 | idr_for_each_entry(&afu->contexts_idr, ctx, id) |
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index c68ef5806dbe..32ad09705949 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
| @@ -539,7 +539,7 @@ err: | |||
| 539 | 539 | ||
| 540 | static void cxl_unmap_slice_regs(struct cxl_afu *afu) | 540 | static void cxl_unmap_slice_regs(struct cxl_afu *afu) |
| 541 | { | 541 | { |
| 542 | if (afu->p1n_mmio) | 542 | if (afu->p2n_mmio) |
| 543 | iounmap(afu->p2n_mmio); | 543 | iounmap(afu->p2n_mmio); |
| 544 | if (afu->p1n_mmio) | 544 | if (afu->p1n_mmio) |
| 545 | iounmap(afu->p1n_mmio); | 545 | iounmap(afu->p1n_mmio); |
diff --git a/drivers/misc/cxl/vphb.c b/drivers/misc/cxl/vphb.c index b1d1983a84a5..2eba002b580b 100644 --- a/drivers/misc/cxl/vphb.c +++ b/drivers/misc/cxl/vphb.c | |||
| @@ -112,9 +112,10 @@ static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn, | |||
| 112 | unsigned long addr; | 112 | unsigned long addr; |
| 113 | 113 | ||
| 114 | phb = pci_bus_to_host(bus); | 114 | phb = pci_bus_to_host(bus); |
| 115 | afu = (struct cxl_afu *)phb->private_data; | ||
| 116 | if (phb == NULL) | 115 | if (phb == NULL) |
| 117 | return PCIBIOS_DEVICE_NOT_FOUND; | 116 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 117 | afu = (struct cxl_afu *)phb->private_data; | ||
| 118 | |||
| 118 | if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num) | 119 | if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num) |
| 119 | return PCIBIOS_DEVICE_NOT_FOUND; | 120 | return PCIBIOS_DEVICE_NOT_FOUND; |
| 120 | if (offset >= (unsigned long)phb->cfg_data) | 121 | if (offset >= (unsigned long)phb->cfg_data) |
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 357b6ae4d207..458aa5a09c52 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c | |||
| @@ -552,22 +552,6 @@ void mei_cl_bus_rx_event(struct mei_cl *cl) | |||
| 552 | schedule_work(&device->event_work); | 552 | schedule_work(&device->event_work); |
| 553 | } | 553 | } |
| 554 | 554 | ||
| 555 | void mei_cl_bus_remove_devices(struct mei_device *dev) | ||
| 556 | { | ||
| 557 | struct mei_cl *cl, *next; | ||
| 558 | |||
| 559 | mutex_lock(&dev->device_lock); | ||
| 560 | list_for_each_entry_safe(cl, next, &dev->device_list, device_link) { | ||
| 561 | if (cl->device) | ||
| 562 | mei_cl_remove_device(cl->device); | ||
| 563 | |||
| 564 | list_del(&cl->device_link); | ||
| 565 | mei_cl_unlink(cl); | ||
| 566 | kfree(cl); | ||
| 567 | } | ||
| 568 | mutex_unlock(&dev->device_lock); | ||
| 569 | } | ||
| 570 | |||
| 571 | int __init mei_cl_bus_init(void) | 555 | int __init mei_cl_bus_init(void) |
| 572 | { | 556 | { |
| 573 | return bus_register(&mei_cl_bus_type); | 557 | return bus_register(&mei_cl_bus_type); |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 94514b2c7a50..00c3865ca3b1 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
| @@ -333,8 +333,6 @@ void mei_stop(struct mei_device *dev) | |||
| 333 | 333 | ||
| 334 | mei_nfc_host_exit(dev); | 334 | mei_nfc_host_exit(dev); |
| 335 | 335 | ||
| 336 | mei_cl_bus_remove_devices(dev); | ||
| 337 | |||
| 338 | mutex_lock(&dev->device_lock); | 336 | mutex_lock(&dev->device_lock); |
| 339 | 337 | ||
| 340 | mei_wd_stop(dev); | 338 | mei_wd_stop(dev); |
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c index b983c4ecad38..290ef3037437 100644 --- a/drivers/misc/mei/nfc.c +++ b/drivers/misc/mei/nfc.c | |||
| @@ -402,11 +402,12 @@ void mei_nfc_host_exit(struct mei_device *dev) | |||
| 402 | 402 | ||
| 403 | cldev->priv_data = NULL; | 403 | cldev->priv_data = NULL; |
| 404 | 404 | ||
| 405 | mutex_lock(&dev->device_lock); | ||
| 406 | /* Need to remove the device here | 405 | /* Need to remove the device here |
| 407 | * since mei_nfc_free will unlink the clients | 406 | * since mei_nfc_free will unlink the clients |
| 408 | */ | 407 | */ |
| 409 | mei_cl_remove_device(cldev); | 408 | mei_cl_remove_device(cldev); |
| 409 | |||
| 410 | mutex_lock(&dev->device_lock); | ||
| 410 | mei_nfc_free(ndev); | 411 | mei_nfc_free(ndev); |
| 411 | mutex_unlock(&dev->device_lock); | 412 | mutex_unlock(&dev->device_lock); |
| 412 | } | 413 | } |
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 8eb22c0ca7ce..7e2c43f701bc 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c | |||
| @@ -535,8 +535,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, | |||
| 535 | __func__, dimm_name, cmd_name, i); | 535 | __func__, dimm_name, cmd_name, i); |
| 536 | return -ENXIO; | 536 | return -ENXIO; |
| 537 | } | 537 | } |
| 538 | if (!access_ok(VERIFY_READ, p + in_len, in_size)) | ||
| 539 | return -EFAULT; | ||
| 540 | if (in_len < sizeof(in_env)) | 538 | if (in_len < sizeof(in_env)) |
| 541 | copy = min_t(u32, sizeof(in_env) - in_len, in_size); | 539 | copy = min_t(u32, sizeof(in_env) - in_len, in_size); |
| 542 | else | 540 | else |
| @@ -557,8 +555,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, | |||
| 557 | __func__, dimm_name, cmd_name, i); | 555 | __func__, dimm_name, cmd_name, i); |
| 558 | return -EFAULT; | 556 | return -EFAULT; |
| 559 | } | 557 | } |
| 560 | if (!access_ok(VERIFY_WRITE, p + in_len + out_len, out_size)) | ||
| 561 | return -EFAULT; | ||
| 562 | if (out_len < sizeof(out_env)) | 558 | if (out_len < sizeof(out_env)) |
| 563 | copy = min_t(u32, sizeof(out_env) - out_len, out_size); | 559 | copy = min_t(u32, sizeof(out_env) - out_len, out_size); |
| 564 | else | 560 | else |
| @@ -570,9 +566,6 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm, | |||
| 570 | } | 566 | } |
| 571 | 567 | ||
| 572 | buf_len = out_len + in_len; | 568 | buf_len = out_len + in_len; |
| 573 | if (!access_ok(VERIFY_WRITE, p, sizeof(buf_len))) | ||
| 574 | return -EFAULT; | ||
| 575 | |||
| 576 | if (buf_len > ND_IOCTL_MAX_BUFLEN) { | 569 | if (buf_len > ND_IOCTL_MAX_BUFLEN) { |
| 577 | dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__, | 570 | dev_dbg(dev, "%s:%s cmd: %s buf_len: %zu > %d\n", __func__, |
| 578 | dimm_name, cmd_name, buf_len, | 571 | dimm_name, cmd_name, buf_len, |
| @@ -706,8 +699,10 @@ int __init nvdimm_bus_init(void) | |||
| 706 | nvdimm_major = rc; | 699 | nvdimm_major = rc; |
| 707 | 700 | ||
| 708 | nd_class = class_create(THIS_MODULE, "nd"); | 701 | nd_class = class_create(THIS_MODULE, "nd"); |
| 709 | if (IS_ERR(nd_class)) | 702 | if (IS_ERR(nd_class)) { |
| 703 | rc = PTR_ERR(nd_class); | ||
| 710 | goto err_class; | 704 | goto err_class; |
| 705 | } | ||
| 711 | 706 | ||
| 712 | return 0; | 707 | return 0; |
| 713 | 708 | ||
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c index 515f33882ab8..49c1720df59a 100644 --- a/drivers/pnp/system.c +++ b/drivers/pnp/system.c | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | * Bjorn Helgaas <bjorn.helgaas@hp.com> | 7 | * Bjorn Helgaas <bjorn.helgaas@hp.com> |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <linux/acpi.h> | ||
| 11 | #include <linux/pnp.h> | 10 | #include <linux/pnp.h> |
| 12 | #include <linux/device.h> | 11 | #include <linux/device.h> |
| 13 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| @@ -23,41 +22,25 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
| 23 | {"", 0} | 22 | {"", 0} |
| 24 | }; | 23 | }; |
| 25 | 24 | ||
| 26 | #ifdef CONFIG_ACPI | ||
| 27 | static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) | ||
| 28 | { | ||
| 29 | u8 space_id = io ? ACPI_ADR_SPACE_SYSTEM_IO : ACPI_ADR_SPACE_SYSTEM_MEMORY; | ||
| 30 | return !acpi_reserve_region(start, length, space_id, IORESOURCE_BUSY, desc); | ||
| 31 | } | ||
| 32 | #else | ||
| 33 | static bool __reserve_range(u64 start, unsigned int length, bool io, char *desc) | ||
| 34 | { | ||
| 35 | struct resource *res; | ||
| 36 | |||
| 37 | res = io ? request_region(start, length, desc) : | ||
| 38 | request_mem_region(start, length, desc); | ||
| 39 | if (res) { | ||
| 40 | res->flags &= ~IORESOURCE_BUSY; | ||
| 41 | return true; | ||
| 42 | } | ||
| 43 | return false; | ||
| 44 | } | ||
| 45 | #endif | ||
| 46 | |||
| 47 | static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) | 25 | static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) |
| 48 | { | 26 | { |
| 49 | char *regionid; | 27 | char *regionid; |
| 50 | const char *pnpid = dev_name(&dev->dev); | 28 | const char *pnpid = dev_name(&dev->dev); |
| 51 | resource_size_t start = r->start, end = r->end; | 29 | resource_size_t start = r->start, end = r->end; |
| 52 | bool reserved; | 30 | struct resource *res; |
| 53 | 31 | ||
| 54 | regionid = kmalloc(16, GFP_KERNEL); | 32 | regionid = kmalloc(16, GFP_KERNEL); |
| 55 | if (!regionid) | 33 | if (!regionid) |
| 56 | return; | 34 | return; |
| 57 | 35 | ||
| 58 | snprintf(regionid, 16, "pnp %s", pnpid); | 36 | snprintf(regionid, 16, "pnp %s", pnpid); |
| 59 | reserved = __reserve_range(start, end - start + 1, !!port, regionid); | 37 | if (port) |
| 60 | if (!reserved) | 38 | res = request_region(start, end - start + 1, regionid); |
| 39 | else | ||
| 40 | res = request_mem_region(start, end - start + 1, regionid); | ||
| 41 | if (res) | ||
| 42 | res->flags &= ~IORESOURCE_BUSY; | ||
| 43 | else | ||
| 61 | kfree(regionid); | 44 | kfree(regionid); |
| 62 | 45 | ||
| 63 | /* | 46 | /* |
| @@ -66,7 +49,7 @@ static void reserve_range(struct pnp_dev *dev, struct resource *r, int port) | |||
| 66 | * have double reservations. | 49 | * have double reservations. |
| 67 | */ | 50 | */ |
| 68 | dev_info(&dev->dev, "%pR %s reserved\n", r, | 51 | dev_info(&dev->dev, "%pR %s reserved\n", r, |
| 69 | reserved ? "has been" : "could not be"); | 52 | res ? "has been" : "could not be"); |
| 70 | } | 53 | } |
| 71 | 54 | ||
| 72 | static void reserve_resources_of_dev(struct pnp_dev *dev) | 55 | static void reserve_resources_of_dev(struct pnp_dev *dev) |
diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 86621fabbb8b..735355b0e023 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c | |||
| @@ -121,6 +121,7 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS]; | |||
| 121 | #define REG_3 0x0004a0 | 121 | #define REG_3 0x0004a0 |
| 122 | #define REG_4 0x000600 | 122 | #define REG_4 0x000600 |
| 123 | #define REG_6 0x000800 | 123 | #define REG_6 0x000800 |
| 124 | #define REG_7 0x000804 | ||
| 124 | #define REG_8 0x000820 | 125 | #define REG_8 0x000820 |
| 125 | #define REG_9 0x000a04 | 126 | #define REG_9 0x000a04 |
| 126 | #define REG_10 0x018000 | 127 | #define REG_10 0x018000 |
| @@ -135,6 +136,8 @@ static int __initdata stifb_bpp_pref[MAX_STI_ROMS]; | |||
| 135 | #define REG_21 0x200218 | 136 | #define REG_21 0x200218 |
| 136 | #define REG_22 0x0005a0 | 137 | #define REG_22 0x0005a0 |
| 137 | #define REG_23 0x0005c0 | 138 | #define REG_23 0x0005c0 |
| 139 | #define REG_24 0x000808 | ||
| 140 | #define REG_25 0x000b00 | ||
| 138 | #define REG_26 0x200118 | 141 | #define REG_26 0x200118 |
| 139 | #define REG_27 0x200308 | 142 | #define REG_27 0x200308 |
| 140 | #define REG_32 0x21003c | 143 | #define REG_32 0x21003c |
| @@ -429,6 +432,9 @@ ARTIST_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) | |||
| 429 | #define SET_LENXY_START_RECFILL(fb, lenxy) \ | 432 | #define SET_LENXY_START_RECFILL(fb, lenxy) \ |
| 430 | WRITE_WORD(lenxy, fb, REG_9) | 433 | WRITE_WORD(lenxy, fb, REG_9) |
| 431 | 434 | ||
| 435 | #define SETUP_COPYAREA(fb) \ | ||
| 436 | WRITE_BYTE(0, fb, REG_16b1) | ||
| 437 | |||
| 432 | static void | 438 | static void |
| 433 | HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) | 439 | HYPER_ENABLE_DISABLE_DISPLAY(struct stifb_info *fb, int enable) |
| 434 | { | 440 | { |
| @@ -1004,6 +1010,36 @@ stifb_blank(int blank_mode, struct fb_info *info) | |||
| 1004 | return 0; | 1010 | return 0; |
| 1005 | } | 1011 | } |
| 1006 | 1012 | ||
| 1013 | static void | ||
| 1014 | stifb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | ||
| 1015 | { | ||
| 1016 | struct stifb_info *fb = container_of(info, struct stifb_info, info); | ||
| 1017 | |||
| 1018 | SETUP_COPYAREA(fb); | ||
| 1019 | |||
| 1020 | SETUP_HW(fb); | ||
| 1021 | if (fb->info.var.bits_per_pixel == 32) { | ||
| 1022 | WRITE_WORD(0xBBA0A000, fb, REG_10); | ||
| 1023 | |||
| 1024 | NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffffff); | ||
| 1025 | } else { | ||
| 1026 | WRITE_WORD(fb->id == S9000_ID_HCRX ? 0x13a02000 : 0x13a01000, fb, REG_10); | ||
| 1027 | |||
| 1028 | NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xff); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, | ||
| 1032 | IBOvals(RopSrc, MaskAddrOffset(0), | ||
| 1033 | BitmapExtent08, StaticReg(1), | ||
| 1034 | DataDynamic, MaskOtc, BGx(0), FGx(0))); | ||
| 1035 | |||
| 1036 | WRITE_WORD(((area->sx << 16) | area->sy), fb, REG_24); | ||
| 1037 | WRITE_WORD(((area->width << 16) | area->height), fb, REG_7); | ||
| 1038 | WRITE_WORD(((area->dx << 16) | area->dy), fb, REG_25); | ||
| 1039 | |||
| 1040 | SETUP_FB(fb); | ||
| 1041 | } | ||
| 1042 | |||
| 1007 | static void __init | 1043 | static void __init |
| 1008 | stifb_init_display(struct stifb_info *fb) | 1044 | stifb_init_display(struct stifb_info *fb) |
| 1009 | { | 1045 | { |
| @@ -1069,7 +1105,7 @@ static struct fb_ops stifb_ops = { | |||
| 1069 | .fb_setcolreg = stifb_setcolreg, | 1105 | .fb_setcolreg = stifb_setcolreg, |
| 1070 | .fb_blank = stifb_blank, | 1106 | .fb_blank = stifb_blank, |
| 1071 | .fb_fillrect = cfb_fillrect, | 1107 | .fb_fillrect = cfb_fillrect, |
| 1072 | .fb_copyarea = cfb_copyarea, | 1108 | .fb_copyarea = stifb_copyarea, |
| 1073 | .fb_imageblit = cfb_imageblit, | 1109 | .fb_imageblit = cfb_imageblit, |
| 1074 | }; | 1110 | }; |
| 1075 | 1111 | ||
| @@ -1258,7 +1294,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
| 1258 | info->fbops = &stifb_ops; | 1294 | info->fbops = &stifb_ops; |
| 1259 | info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); | 1295 | info->screen_base = ioremap_nocache(REGION_BASE(fb,1), fix->smem_len); |
| 1260 | info->screen_size = fix->smem_len; | 1296 | info->screen_size = fix->smem_len; |
| 1261 | info->flags = FBINFO_DEFAULT; | 1297 | info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA; |
| 1262 | info->pseudo_palette = &fb->pseudo_palette; | 1298 | info->pseudo_palette = &fb->pseudo_palette; |
| 1263 | 1299 | ||
| 1264 | /* This has to be done !!! */ | 1300 | /* This has to be done !!! */ |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 510040b04c96..b1dc51888048 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -540,8 +540,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, | |||
| 540 | unlock_new_inode(inode); | 540 | unlock_new_inode(inode); |
| 541 | return inode; | 541 | return inode; |
| 542 | error: | 542 | error: |
| 543 | unlock_new_inode(inode); | 543 | iget_failed(inode); |
| 544 | iput(inode); | ||
| 545 | return ERR_PTR(retval); | 544 | return ERR_PTR(retval); |
| 546 | 545 | ||
| 547 | } | 546 | } |
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 09e4433717b8..e8aa57dc8d6d 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c | |||
| @@ -149,8 +149,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, | |||
| 149 | unlock_new_inode(inode); | 149 | unlock_new_inode(inode); |
| 150 | return inode; | 150 | return inode; |
| 151 | error: | 151 | error: |
| 152 | unlock_new_inode(inode); | 152 | iget_failed(inode); |
| 153 | iput(inode); | ||
| 154 | return ERR_PTR(retval); | 153 | return ERR_PTR(retval); |
| 155 | 154 | ||
| 156 | } | 155 | } |
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 0ef5cc13fae2..81220b2203c6 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
| @@ -44,6 +44,8 @@ | |||
| 44 | #define BTRFS_INODE_IN_DELALLOC_LIST 9 | 44 | #define BTRFS_INODE_IN_DELALLOC_LIST 9 |
| 45 | #define BTRFS_INODE_READDIO_NEED_LOCK 10 | 45 | #define BTRFS_INODE_READDIO_NEED_LOCK 10 |
| 46 | #define BTRFS_INODE_HAS_PROPS 11 | 46 | #define BTRFS_INODE_HAS_PROPS 11 |
| 47 | /* DIO is ready to submit */ | ||
| 48 | #define BTRFS_INODE_DIO_READY 12 | ||
| 47 | /* | 49 | /* |
| 48 | * The following 3 bits are meant only for the btree inode. | 50 | * The following 3 bits are meant only for the btree inode. |
| 49 | * When any of them is set, it means an error happened while writing an | 51 | * When any of them is set, it means an error happened while writing an |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 80a9aefb0c46..aac314e14188 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1778,6 +1778,7 @@ struct btrfs_fs_info { | |||
| 1778 | spinlock_t unused_bgs_lock; | 1778 | spinlock_t unused_bgs_lock; |
| 1779 | struct list_head unused_bgs; | 1779 | struct list_head unused_bgs; |
| 1780 | struct mutex unused_bg_unpin_mutex; | 1780 | struct mutex unused_bg_unpin_mutex; |
| 1781 | struct mutex delete_unused_bgs_mutex; | ||
| 1781 | 1782 | ||
| 1782 | /* For btrfs to record security options */ | 1783 | /* For btrfs to record security options */ |
| 1783 | struct security_mnt_opts security_opts; | 1784 | struct security_mnt_opts security_opts; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3f43bfea3684..a9aadb2ad525 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1751,6 +1751,7 @@ static int cleaner_kthread(void *arg) | |||
| 1751 | { | 1751 | { |
| 1752 | struct btrfs_root *root = arg; | 1752 | struct btrfs_root *root = arg; |
| 1753 | int again; | 1753 | int again; |
| 1754 | struct btrfs_trans_handle *trans; | ||
| 1754 | 1755 | ||
| 1755 | do { | 1756 | do { |
| 1756 | again = 0; | 1757 | again = 0; |
| @@ -1772,7 +1773,6 @@ static int cleaner_kthread(void *arg) | |||
| 1772 | } | 1773 | } |
| 1773 | 1774 | ||
| 1774 | btrfs_run_delayed_iputs(root); | 1775 | btrfs_run_delayed_iputs(root); |
| 1775 | btrfs_delete_unused_bgs(root->fs_info); | ||
| 1776 | again = btrfs_clean_one_deleted_snapshot(root); | 1776 | again = btrfs_clean_one_deleted_snapshot(root); |
| 1777 | mutex_unlock(&root->fs_info->cleaner_mutex); | 1777 | mutex_unlock(&root->fs_info->cleaner_mutex); |
| 1778 | 1778 | ||
| @@ -1781,6 +1781,16 @@ static int cleaner_kthread(void *arg) | |||
| 1781 | * needn't do anything special here. | 1781 | * needn't do anything special here. |
| 1782 | */ | 1782 | */ |
| 1783 | btrfs_run_defrag_inodes(root->fs_info); | 1783 | btrfs_run_defrag_inodes(root->fs_info); |
| 1784 | |||
| 1785 | /* | ||
| 1786 | * Acquires fs_info->delete_unused_bgs_mutex to avoid racing | ||
| 1787 | * with relocation (btrfs_relocate_chunk) and relocation | ||
| 1788 | * acquires fs_info->cleaner_mutex (btrfs_relocate_block_group) | ||
| 1789 | * after acquiring fs_info->delete_unused_bgs_mutex. So we | ||
| 1790 | * can't hold, nor need to, fs_info->cleaner_mutex when deleting | ||
| 1791 | * unused block groups. | ||
| 1792 | */ | ||
| 1793 | btrfs_delete_unused_bgs(root->fs_info); | ||
| 1784 | sleep: | 1794 | sleep: |
| 1785 | if (!try_to_freeze() && !again) { | 1795 | if (!try_to_freeze() && !again) { |
| 1786 | set_current_state(TASK_INTERRUPTIBLE); | 1796 | set_current_state(TASK_INTERRUPTIBLE); |
| @@ -1789,6 +1799,34 @@ sleep: | |||
| 1789 | __set_current_state(TASK_RUNNING); | 1799 | __set_current_state(TASK_RUNNING); |
| 1790 | } | 1800 | } |
| 1791 | } while (!kthread_should_stop()); | 1801 | } while (!kthread_should_stop()); |
| 1802 | |||
| 1803 | /* | ||
| 1804 | * Transaction kthread is stopped before us and wakes us up. | ||
| 1805 | * However we might have started a new transaction and COWed some | ||
| 1806 | * tree blocks when deleting unused block groups for example. So | ||
| 1807 | * make sure we commit the transaction we started to have a clean | ||
| 1808 | * shutdown when evicting the btree inode - if it has dirty pages | ||
| 1809 | * when we do the final iput() on it, eviction will trigger a | ||
| 1810 | * writeback for it which will fail with null pointer dereferences | ||
| 1811 | * since work queues and other resources were already released and | ||
| 1812 | * destroyed by the time the iput/eviction/writeback is made. | ||
| 1813 | */ | ||
| 1814 | trans = btrfs_attach_transaction(root); | ||
| 1815 | if (IS_ERR(trans)) { | ||
| 1816 | if (PTR_ERR(trans) != -ENOENT) | ||
| 1817 | btrfs_err(root->fs_info, | ||
| 1818 | "cleaner transaction attach returned %ld", | ||
| 1819 | PTR_ERR(trans)); | ||
| 1820 | } else { | ||
| 1821 | int ret; | ||
| 1822 | |||
| 1823 | ret = btrfs_commit_transaction(trans, root); | ||
| 1824 | if (ret) | ||
| 1825 | btrfs_err(root->fs_info, | ||
| 1826 | "cleaner open transaction commit returned %d", | ||
| 1827 | ret); | ||
| 1828 | } | ||
| 1829 | |||
| 1792 | return 0; | 1830 | return 0; |
| 1793 | } | 1831 | } |
| 1794 | 1832 | ||
| @@ -2492,6 +2530,7 @@ int open_ctree(struct super_block *sb, | |||
| 2492 | spin_lock_init(&fs_info->unused_bgs_lock); | 2530 | spin_lock_init(&fs_info->unused_bgs_lock); |
| 2493 | rwlock_init(&fs_info->tree_mod_log_lock); | 2531 | rwlock_init(&fs_info->tree_mod_log_lock); |
| 2494 | mutex_init(&fs_info->unused_bg_unpin_mutex); | 2532 | mutex_init(&fs_info->unused_bg_unpin_mutex); |
| 2533 | mutex_init(&fs_info->delete_unused_bgs_mutex); | ||
| 2495 | mutex_init(&fs_info->reloc_mutex); | 2534 | mutex_init(&fs_info->reloc_mutex); |
| 2496 | mutex_init(&fs_info->delalloc_root_mutex); | 2535 | mutex_init(&fs_info->delalloc_root_mutex); |
| 2497 | seqlock_init(&fs_info->profiles_lock); | 2536 | seqlock_init(&fs_info->profiles_lock); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 38b76cc02f48..1c2bd1723e40 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -9889,6 +9889,8 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
| 9889 | } | 9889 | } |
| 9890 | spin_unlock(&fs_info->unused_bgs_lock); | 9890 | spin_unlock(&fs_info->unused_bgs_lock); |
| 9891 | 9891 | ||
| 9892 | mutex_lock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 9893 | |||
| 9892 | /* Don't want to race with allocators so take the groups_sem */ | 9894 | /* Don't want to race with allocators so take the groups_sem */ |
| 9893 | down_write(&space_info->groups_sem); | 9895 | down_write(&space_info->groups_sem); |
| 9894 | spin_lock(&block_group->lock); | 9896 | spin_lock(&block_group->lock); |
| @@ -9983,6 +9985,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info) | |||
| 9983 | end_trans: | 9985 | end_trans: |
| 9984 | btrfs_end_transaction(trans, root); | 9986 | btrfs_end_transaction(trans, root); |
| 9985 | next: | 9987 | next: |
| 9988 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 9986 | btrfs_put_block_group(block_group); | 9989 | btrfs_put_block_group(block_group); |
| 9987 | spin_lock(&fs_info->unused_bgs_lock); | 9990 | spin_lock(&fs_info->unused_bgs_lock); |
| 9988 | } | 9991 | } |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index f6a596d5a637..d4a582ac3f73 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
| @@ -246,6 +246,7 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) | |||
| 246 | { | 246 | { |
| 247 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | 247 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; |
| 248 | struct rb_root *rbroot = &root->free_ino_pinned->free_space_offset; | 248 | struct rb_root *rbroot = &root->free_ino_pinned->free_space_offset; |
| 249 | spinlock_t *rbroot_lock = &root->free_ino_pinned->tree_lock; | ||
| 249 | struct btrfs_free_space *info; | 250 | struct btrfs_free_space *info; |
| 250 | struct rb_node *n; | 251 | struct rb_node *n; |
| 251 | u64 count; | 252 | u64 count; |
| @@ -254,24 +255,30 @@ void btrfs_unpin_free_ino(struct btrfs_root *root) | |||
| 254 | return; | 255 | return; |
| 255 | 256 | ||
| 256 | while (1) { | 257 | while (1) { |
| 258 | bool add_to_ctl = true; | ||
| 259 | |||
| 260 | spin_lock(rbroot_lock); | ||
| 257 | n = rb_first(rbroot); | 261 | n = rb_first(rbroot); |
| 258 | if (!n) | 262 | if (!n) { |
| 263 | spin_unlock(rbroot_lock); | ||
| 259 | break; | 264 | break; |
| 265 | } | ||
| 260 | 266 | ||
| 261 | info = rb_entry(n, struct btrfs_free_space, offset_index); | 267 | info = rb_entry(n, struct btrfs_free_space, offset_index); |
| 262 | BUG_ON(info->bitmap); /* Logic error */ | 268 | BUG_ON(info->bitmap); /* Logic error */ |
| 263 | 269 | ||
| 264 | if (info->offset > root->ino_cache_progress) | 270 | if (info->offset > root->ino_cache_progress) |
| 265 | goto free; | 271 | add_to_ctl = false; |
| 266 | else if (info->offset + info->bytes > root->ino_cache_progress) | 272 | else if (info->offset + info->bytes > root->ino_cache_progress) |
| 267 | count = root->ino_cache_progress - info->offset + 1; | 273 | count = root->ino_cache_progress - info->offset + 1; |
| 268 | else | 274 | else |
| 269 | count = info->bytes; | 275 | count = info->bytes; |
| 270 | 276 | ||
| 271 | __btrfs_add_free_space(ctl, info->offset, count); | ||
| 272 | free: | ||
| 273 | rb_erase(&info->offset_index, rbroot); | 277 | rb_erase(&info->offset_index, rbroot); |
| 274 | kfree(info); | 278 | spin_unlock(rbroot_lock); |
| 279 | if (add_to_ctl) | ||
| 280 | __btrfs_add_free_space(ctl, info->offset, count); | ||
| 281 | kmem_cache_free(btrfs_free_space_cachep, info); | ||
| 275 | } | 282 | } |
| 276 | } | 283 | } |
| 277 | 284 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 855935f6671a..b33c0cf02668 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -4989,8 +4989,9 @@ static void evict_inode_truncate_pages(struct inode *inode) | |||
| 4989 | /* | 4989 | /* |
| 4990 | * Keep looping until we have no more ranges in the io tree. | 4990 | * Keep looping until we have no more ranges in the io tree. |
| 4991 | * We can have ongoing bios started by readpages (called from readahead) | 4991 | * We can have ongoing bios started by readpages (called from readahead) |
| 4992 | * that didn't get their end io callbacks called yet or they are still | 4992 | * that have their endio callback (extent_io.c:end_bio_extent_readpage) |
| 4993 | * in progress ((extent_io.c:end_bio_extent_readpage()). This means some | 4993 | * still in progress (unlocked the pages in the bio but did not yet |
| 4994 | * unlocked the ranges in the io tree). Therefore this means some | ||
| 4994 | * ranges can still be locked and eviction started because before | 4995 | * ranges can still be locked and eviction started because before |
| 4995 | * submitting those bios, which are executed by a separate task (work | 4996 | * submitting those bios, which are executed by a separate task (work |
| 4996 | * queue kthread), inode references (inode->i_count) were not taken | 4997 | * queue kthread), inode references (inode->i_count) were not taken |
| @@ -7546,6 +7547,7 @@ unlock: | |||
| 7546 | 7547 | ||
| 7547 | current->journal_info = outstanding_extents; | 7548 | current->journal_info = outstanding_extents; |
| 7548 | btrfs_free_reserved_data_space(inode, len); | 7549 | btrfs_free_reserved_data_space(inode, len); |
| 7550 | set_bit(BTRFS_INODE_DIO_READY, &BTRFS_I(inode)->runtime_flags); | ||
| 7549 | } | 7551 | } |
| 7550 | 7552 | ||
| 7551 | /* | 7553 | /* |
| @@ -7871,8 +7873,6 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) | |||
| 7871 | struct bio *dio_bio; | 7873 | struct bio *dio_bio; |
| 7872 | int ret; | 7874 | int ret; |
| 7873 | 7875 | ||
| 7874 | if (err) | ||
| 7875 | goto out_done; | ||
| 7876 | again: | 7876 | again: |
| 7877 | ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, | 7877 | ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, |
| 7878 | &ordered_offset, | 7878 | &ordered_offset, |
| @@ -7895,7 +7895,6 @@ out_test: | |||
| 7895 | ordered = NULL; | 7895 | ordered = NULL; |
| 7896 | goto again; | 7896 | goto again; |
| 7897 | } | 7897 | } |
| 7898 | out_done: | ||
| 7899 | dio_bio = dip->dio_bio; | 7898 | dio_bio = dip->dio_bio; |
| 7900 | 7899 | ||
| 7901 | kfree(dip); | 7900 | kfree(dip); |
| @@ -8163,9 +8162,8 @@ out_err: | |||
| 8163 | static void btrfs_submit_direct(int rw, struct bio *dio_bio, | 8162 | static void btrfs_submit_direct(int rw, struct bio *dio_bio, |
| 8164 | struct inode *inode, loff_t file_offset) | 8163 | struct inode *inode, loff_t file_offset) |
| 8165 | { | 8164 | { |
| 8166 | struct btrfs_root *root = BTRFS_I(inode)->root; | 8165 | struct btrfs_dio_private *dip = NULL; |
| 8167 | struct btrfs_dio_private *dip; | 8166 | struct bio *io_bio = NULL; |
| 8168 | struct bio *io_bio; | ||
| 8169 | struct btrfs_io_bio *btrfs_bio; | 8167 | struct btrfs_io_bio *btrfs_bio; |
| 8170 | int skip_sum; | 8168 | int skip_sum; |
| 8171 | int write = rw & REQ_WRITE; | 8169 | int write = rw & REQ_WRITE; |
| @@ -8182,7 +8180,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, | |||
| 8182 | dip = kzalloc(sizeof(*dip), GFP_NOFS); | 8180 | dip = kzalloc(sizeof(*dip), GFP_NOFS); |
| 8183 | if (!dip) { | 8181 | if (!dip) { |
| 8184 | ret = -ENOMEM; | 8182 | ret = -ENOMEM; |
| 8185 | goto free_io_bio; | 8183 | goto free_ordered; |
| 8186 | } | 8184 | } |
| 8187 | 8185 | ||
| 8188 | dip->private = dio_bio->bi_private; | 8186 | dip->private = dio_bio->bi_private; |
| @@ -8210,25 +8208,55 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, | |||
| 8210 | 8208 | ||
| 8211 | if (btrfs_bio->end_io) | 8209 | if (btrfs_bio->end_io) |
| 8212 | btrfs_bio->end_io(btrfs_bio, ret); | 8210 | btrfs_bio->end_io(btrfs_bio, ret); |
| 8213 | free_io_bio: | ||
| 8214 | bio_put(io_bio); | ||
| 8215 | 8211 | ||
| 8216 | free_ordered: | 8212 | free_ordered: |
| 8217 | /* | 8213 | /* |
| 8218 | * If this is a write, we need to clean up the reserved space and kill | 8214 | * If we arrived here it means either we failed to submit the dip |
| 8219 | * the ordered extent. | 8215 | * or we either failed to clone the dio_bio or failed to allocate the |
| 8216 | * dip. If we cloned the dio_bio and allocated the dip, we can just | ||
| 8217 | * call bio_endio against our io_bio so that we get proper resource | ||
| 8218 | * cleanup if we fail to submit the dip, otherwise, we must do the | ||
| 8219 | * same as btrfs_endio_direct_[write|read] because we can't call these | ||
| 8220 | * callbacks - they require an allocated dip and a clone of dio_bio. | ||
| 8220 | */ | 8221 | */ |
| 8221 | if (write) { | 8222 | if (io_bio && dip) { |
| 8222 | struct btrfs_ordered_extent *ordered; | 8223 | bio_endio(io_bio, ret); |
| 8223 | ordered = btrfs_lookup_ordered_extent(inode, file_offset); | 8224 | /* |
| 8224 | if (!test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags) && | 8225 | * The end io callbacks free our dip, do the final put on io_bio |
| 8225 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) | 8226 | * and all the cleanup and final put for dio_bio (through |
| 8226 | btrfs_free_reserved_extent(root, ordered->start, | 8227 | * dio_end_io()). |
| 8227 | ordered->disk_len, 1); | 8228 | */ |
| 8228 | btrfs_put_ordered_extent(ordered); | 8229 | dip = NULL; |
| 8229 | btrfs_put_ordered_extent(ordered); | 8230 | io_bio = NULL; |
| 8231 | } else { | ||
| 8232 | if (write) { | ||
| 8233 | struct btrfs_ordered_extent *ordered; | ||
| 8234 | |||
| 8235 | ordered = btrfs_lookup_ordered_extent(inode, | ||
| 8236 | file_offset); | ||
| 8237 | set_bit(BTRFS_ORDERED_IOERR, &ordered->flags); | ||
| 8238 | /* | ||
| 8239 | * Decrements our ref on the ordered extent and removes | ||
| 8240 | * the ordered extent from the inode's ordered tree, | ||
| 8241 | * doing all the proper resource cleanup such as for the | ||
| 8242 | * reserved space and waking up any waiters for this | ||
| 8243 | * ordered extent (through btrfs_remove_ordered_extent). | ||
| 8244 | */ | ||
| 8245 | btrfs_finish_ordered_io(ordered); | ||
| 8246 | } else { | ||
| 8247 | unlock_extent(&BTRFS_I(inode)->io_tree, file_offset, | ||
| 8248 | file_offset + dio_bio->bi_iter.bi_size - 1); | ||
| 8249 | } | ||
| 8250 | clear_bit(BIO_UPTODATE, &dio_bio->bi_flags); | ||
| 8251 | /* | ||
| 8252 | * Releases and cleans up our dio_bio, no need to bio_put() | ||
| 8253 | * nor bio_endio()/bio_io_error() against dio_bio. | ||
| 8254 | */ | ||
| 8255 | dio_end_io(dio_bio, ret); | ||
| 8230 | } | 8256 | } |
| 8231 | bio_endio(dio_bio, ret); | 8257 | if (io_bio) |
| 8258 | bio_put(io_bio); | ||
| 8259 | kfree(dip); | ||
| 8232 | } | 8260 | } |
| 8233 | 8261 | ||
| 8234 | static ssize_t check_direct_IO(struct btrfs_root *root, struct kiocb *iocb, | 8262 | static ssize_t check_direct_IO(struct btrfs_root *root, struct kiocb *iocb, |
| @@ -8330,9 +8358,18 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, | |||
| 8330 | btrfs_submit_direct, flags); | 8358 | btrfs_submit_direct, flags); |
| 8331 | if (iov_iter_rw(iter) == WRITE) { | 8359 | if (iov_iter_rw(iter) == WRITE) { |
| 8332 | current->journal_info = NULL; | 8360 | current->journal_info = NULL; |
| 8333 | if (ret < 0 && ret != -EIOCBQUEUED) | 8361 | if (ret < 0 && ret != -EIOCBQUEUED) { |
| 8334 | btrfs_delalloc_release_space(inode, count); | 8362 | /* |
| 8335 | else if (ret >= 0 && (size_t)ret < count) | 8363 | * If the error comes from submitting stage, |
| 8364 | * btrfs_get_blocsk_direct() has free'd data space, | ||
| 8365 | * and metadata space will be handled by | ||
| 8366 | * finish_ordered_fn, don't do that again to make | ||
| 8367 | * sure bytes_may_use is correct. | ||
| 8368 | */ | ||
| 8369 | if (!test_and_clear_bit(BTRFS_INODE_DIO_READY, | ||
| 8370 | &BTRFS_I(inode)->runtime_flags)) | ||
| 8371 | btrfs_delalloc_release_space(inode, count); | ||
| 8372 | } else if (ret >= 0 && (size_t)ret < count) | ||
| 8336 | btrfs_delalloc_release_space(inode, | 8373 | btrfs_delalloc_release_space(inode, |
| 8337 | count - (size_t)ret); | 8374 | count - (size_t)ret); |
| 8338 | } | 8375 | } |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c86b835da7a8..5d91776e12a2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -87,7 +87,8 @@ struct btrfs_ioctl_received_subvol_args_32 { | |||
| 87 | 87 | ||
| 88 | 88 | ||
| 89 | static int btrfs_clone(struct inode *src, struct inode *inode, | 89 | static int btrfs_clone(struct inode *src, struct inode *inode, |
| 90 | u64 off, u64 olen, u64 olen_aligned, u64 destoff); | 90 | u64 off, u64 olen, u64 olen_aligned, u64 destoff, |
| 91 | int no_time_update); | ||
| 91 | 92 | ||
| 92 | /* Mask out flags that are inappropriate for the given type of inode. */ | 93 | /* Mask out flags that are inappropriate for the given type of inode. */ |
| 93 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | 94 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) |
| @@ -2765,14 +2766,11 @@ out: | |||
| 2765 | return ret; | 2766 | return ret; |
| 2766 | } | 2767 | } |
| 2767 | 2768 | ||
| 2768 | static struct page *extent_same_get_page(struct inode *inode, u64 off) | 2769 | static struct page *extent_same_get_page(struct inode *inode, pgoff_t index) |
| 2769 | { | 2770 | { |
| 2770 | struct page *page; | 2771 | struct page *page; |
| 2771 | pgoff_t index; | ||
| 2772 | struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; | 2772 | struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree; |
| 2773 | 2773 | ||
| 2774 | index = off >> PAGE_CACHE_SHIFT; | ||
| 2775 | |||
| 2776 | page = grab_cache_page(inode->i_mapping, index); | 2774 | page = grab_cache_page(inode->i_mapping, index); |
| 2777 | if (!page) | 2775 | if (!page) |
| 2778 | return NULL; | 2776 | return NULL; |
| @@ -2793,6 +2791,20 @@ static struct page *extent_same_get_page(struct inode *inode, u64 off) | |||
| 2793 | return page; | 2791 | return page; |
| 2794 | } | 2792 | } |
| 2795 | 2793 | ||
| 2794 | static int gather_extent_pages(struct inode *inode, struct page **pages, | ||
| 2795 | int num_pages, u64 off) | ||
| 2796 | { | ||
| 2797 | int i; | ||
| 2798 | pgoff_t index = off >> PAGE_CACHE_SHIFT; | ||
| 2799 | |||
| 2800 | for (i = 0; i < num_pages; i++) { | ||
| 2801 | pages[i] = extent_same_get_page(inode, index + i); | ||
| 2802 | if (!pages[i]) | ||
| 2803 | return -ENOMEM; | ||
| 2804 | } | ||
| 2805 | return 0; | ||
| 2806 | } | ||
| 2807 | |||
| 2796 | static inline void lock_extent_range(struct inode *inode, u64 off, u64 len) | 2808 | static inline void lock_extent_range(struct inode *inode, u64 off, u64 len) |
| 2797 | { | 2809 | { |
| 2798 | /* do any pending delalloc/csum calc on src, one way or | 2810 | /* do any pending delalloc/csum calc on src, one way or |
| @@ -2818,52 +2830,120 @@ static inline void lock_extent_range(struct inode *inode, u64 off, u64 len) | |||
| 2818 | } | 2830 | } |
| 2819 | } | 2831 | } |
| 2820 | 2832 | ||
| 2821 | static void btrfs_double_unlock(struct inode *inode1, u64 loff1, | 2833 | static void btrfs_double_inode_unlock(struct inode *inode1, struct inode *inode2) |
| 2822 | struct inode *inode2, u64 loff2, u64 len) | ||
| 2823 | { | 2834 | { |
| 2824 | unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1); | ||
| 2825 | unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1); | ||
| 2826 | |||
| 2827 | mutex_unlock(&inode1->i_mutex); | 2835 | mutex_unlock(&inode1->i_mutex); |
| 2828 | mutex_unlock(&inode2->i_mutex); | 2836 | mutex_unlock(&inode2->i_mutex); |
| 2829 | } | 2837 | } |
| 2830 | 2838 | ||
| 2831 | static void btrfs_double_lock(struct inode *inode1, u64 loff1, | 2839 | static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2) |
| 2832 | struct inode *inode2, u64 loff2, u64 len) | 2840 | { |
| 2841 | if (inode1 < inode2) | ||
| 2842 | swap(inode1, inode2); | ||
| 2843 | |||
| 2844 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | ||
| 2845 | if (inode1 != inode2) | ||
| 2846 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); | ||
| 2847 | } | ||
| 2848 | |||
| 2849 | static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1, | ||
| 2850 | struct inode *inode2, u64 loff2, u64 len) | ||
| 2851 | { | ||
| 2852 | unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1); | ||
| 2853 | unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1); | ||
| 2854 | } | ||
| 2855 | |||
| 2856 | static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1, | ||
| 2857 | struct inode *inode2, u64 loff2, u64 len) | ||
| 2833 | { | 2858 | { |
| 2834 | if (inode1 < inode2) { | 2859 | if (inode1 < inode2) { |
| 2835 | swap(inode1, inode2); | 2860 | swap(inode1, inode2); |
| 2836 | swap(loff1, loff2); | 2861 | swap(loff1, loff2); |
| 2837 | } | 2862 | } |
| 2838 | |||
| 2839 | mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); | ||
| 2840 | lock_extent_range(inode1, loff1, len); | 2863 | lock_extent_range(inode1, loff1, len); |
| 2841 | if (inode1 != inode2) { | 2864 | if (inode1 != inode2) |
| 2842 | mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); | ||
| 2843 | lock_extent_range(inode2, loff2, len); | 2865 | lock_extent_range(inode2, loff2, len); |
| 2866 | } | ||
| 2867 | |||
| 2868 | struct cmp_pages { | ||
| 2869 | int num_pages; | ||
| 2870 | struct page **src_pages; | ||
| 2871 | struct page **dst_pages; | ||
| 2872 | }; | ||
| 2873 | |||
| 2874 | static void btrfs_cmp_data_free(struct cmp_pages *cmp) | ||
| 2875 | { | ||
| 2876 | int i; | ||
| 2877 | struct page *pg; | ||
| 2878 | |||
| 2879 | for (i = 0; i < cmp->num_pages; i++) { | ||
| 2880 | pg = cmp->src_pages[i]; | ||
| 2881 | if (pg) | ||
| 2882 | page_cache_release(pg); | ||
| 2883 | pg = cmp->dst_pages[i]; | ||
| 2884 | if (pg) | ||
| 2885 | page_cache_release(pg); | ||
| 2886 | } | ||
| 2887 | kfree(cmp->src_pages); | ||
| 2888 | kfree(cmp->dst_pages); | ||
| 2889 | } | ||
| 2890 | |||
| 2891 | static int btrfs_cmp_data_prepare(struct inode *src, u64 loff, | ||
| 2892 | struct inode *dst, u64 dst_loff, | ||
| 2893 | u64 len, struct cmp_pages *cmp) | ||
| 2894 | { | ||
| 2895 | int ret; | ||
| 2896 | int num_pages = PAGE_CACHE_ALIGN(len) >> PAGE_CACHE_SHIFT; | ||
| 2897 | struct page **src_pgarr, **dst_pgarr; | ||
| 2898 | |||
| 2899 | /* | ||
| 2900 | * We must gather up all the pages before we initiate our | ||
| 2901 | * extent locking. We use an array for the page pointers. Size | ||
| 2902 | * of the array is bounded by len, which is in turn bounded by | ||
| 2903 | * BTRFS_MAX_DEDUPE_LEN. | ||
| 2904 | */ | ||
| 2905 | src_pgarr = kzalloc(num_pages * sizeof(struct page *), GFP_NOFS); | ||
| 2906 | dst_pgarr = kzalloc(num_pages * sizeof(struct page *), GFP_NOFS); | ||
| 2907 | if (!src_pgarr || !dst_pgarr) { | ||
| 2908 | kfree(src_pgarr); | ||
| 2909 | kfree(dst_pgarr); | ||
| 2910 | return -ENOMEM; | ||
| 2844 | } | 2911 | } |
| 2912 | cmp->num_pages = num_pages; | ||
| 2913 | cmp->src_pages = src_pgarr; | ||
| 2914 | cmp->dst_pages = dst_pgarr; | ||
| 2915 | |||
| 2916 | ret = gather_extent_pages(src, cmp->src_pages, cmp->num_pages, loff); | ||
| 2917 | if (ret) | ||
| 2918 | goto out; | ||
| 2919 | |||
| 2920 | ret = gather_extent_pages(dst, cmp->dst_pages, cmp->num_pages, dst_loff); | ||
| 2921 | |||
| 2922 | out: | ||
| 2923 | if (ret) | ||
| 2924 | btrfs_cmp_data_free(cmp); | ||
| 2925 | return 0; | ||
| 2845 | } | 2926 | } |
| 2846 | 2927 | ||
| 2847 | static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst, | 2928 | static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst, |
| 2848 | u64 dst_loff, u64 len) | 2929 | u64 dst_loff, u64 len, struct cmp_pages *cmp) |
| 2849 | { | 2930 | { |
| 2850 | int ret = 0; | 2931 | int ret = 0; |
| 2932 | int i; | ||
| 2851 | struct page *src_page, *dst_page; | 2933 | struct page *src_page, *dst_page; |
| 2852 | unsigned int cmp_len = PAGE_CACHE_SIZE; | 2934 | unsigned int cmp_len = PAGE_CACHE_SIZE; |
| 2853 | void *addr, *dst_addr; | 2935 | void *addr, *dst_addr; |
| 2854 | 2936 | ||
| 2937 | i = 0; | ||
| 2855 | while (len) { | 2938 | while (len) { |
| 2856 | if (len < PAGE_CACHE_SIZE) | 2939 | if (len < PAGE_CACHE_SIZE) |
| 2857 | cmp_len = len; | 2940 | cmp_len = len; |
| 2858 | 2941 | ||
| 2859 | src_page = extent_same_get_page(src, loff); | 2942 | BUG_ON(i >= cmp->num_pages); |
| 2860 | if (!src_page) | 2943 | |
| 2861 | return -EINVAL; | 2944 | src_page = cmp->src_pages[i]; |
| 2862 | dst_page = extent_same_get_page(dst, dst_loff); | 2945 | dst_page = cmp->dst_pages[i]; |
| 2863 | if (!dst_page) { | 2946 | |
| 2864 | page_cache_release(src_page); | ||
| 2865 | return -EINVAL; | ||
| 2866 | } | ||
| 2867 | addr = kmap_atomic(src_page); | 2947 | addr = kmap_atomic(src_page); |
| 2868 | dst_addr = kmap_atomic(dst_page); | 2948 | dst_addr = kmap_atomic(dst_page); |
| 2869 | 2949 | ||
| @@ -2875,15 +2955,12 @@ static int btrfs_cmp_data(struct inode *src, u64 loff, struct inode *dst, | |||
| 2875 | 2955 | ||
| 2876 | kunmap_atomic(addr); | 2956 | kunmap_atomic(addr); |
| 2877 | kunmap_atomic(dst_addr); | 2957 | kunmap_atomic(dst_addr); |
| 2878 | page_cache_release(src_page); | ||
| 2879 | page_cache_release(dst_page); | ||
| 2880 | 2958 | ||
| 2881 | if (ret) | 2959 | if (ret) |
| 2882 | break; | 2960 | break; |
| 2883 | 2961 | ||
| 2884 | loff += cmp_len; | ||
| 2885 | dst_loff += cmp_len; | ||
| 2886 | len -= cmp_len; | 2962 | len -= cmp_len; |
| 2963 | i++; | ||
| 2887 | } | 2964 | } |
| 2888 | 2965 | ||
| 2889 | return ret; | 2966 | return ret; |
| @@ -2914,27 +2991,62 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, | |||
| 2914 | { | 2991 | { |
| 2915 | int ret; | 2992 | int ret; |
| 2916 | u64 len = olen; | 2993 | u64 len = olen; |
| 2994 | struct cmp_pages cmp; | ||
| 2995 | int same_inode = 0; | ||
| 2996 | u64 same_lock_start = 0; | ||
| 2997 | u64 same_lock_len = 0; | ||
| 2917 | 2998 | ||
| 2918 | /* | ||
| 2919 | * btrfs_clone() can't handle extents in the same file | ||
| 2920 | * yet. Once that works, we can drop this check and replace it | ||
| 2921 | * with a check for the same inode, but overlapping extents. | ||
| 2922 | */ | ||
| 2923 | if (src == dst) | 2999 | if (src == dst) |
| 2924 | return -EINVAL; | 3000 | same_inode = 1; |
| 2925 | 3001 | ||
| 2926 | if (len == 0) | 3002 | if (len == 0) |
| 2927 | return 0; | 3003 | return 0; |
| 2928 | 3004 | ||
| 2929 | btrfs_double_lock(src, loff, dst, dst_loff, len); | 3005 | if (same_inode) { |
| 3006 | mutex_lock(&src->i_mutex); | ||
| 2930 | 3007 | ||
| 2931 | ret = extent_same_check_offsets(src, loff, &len, olen); | 3008 | ret = extent_same_check_offsets(src, loff, &len, olen); |
| 2932 | if (ret) | 3009 | if (ret) |
| 2933 | goto out_unlock; | 3010 | goto out_unlock; |
| 2934 | 3011 | ||
| 2935 | ret = extent_same_check_offsets(dst, dst_loff, &len, olen); | 3012 | /* |
| 2936 | if (ret) | 3013 | * Single inode case wants the same checks, except we |
| 2937 | goto out_unlock; | 3014 | * don't want our length pushed out past i_size as |
| 3015 | * comparing that data range makes no sense. | ||
| 3016 | * | ||
| 3017 | * extent_same_check_offsets() will do this for an | ||
| 3018 | * unaligned length at i_size, so catch it here and | ||
| 3019 | * reject the request. | ||
| 3020 | * | ||
| 3021 | * This effectively means we require aligned extents | ||
| 3022 | * for the single-inode case, whereas the other cases | ||
| 3023 | * allow an unaligned length so long as it ends at | ||
| 3024 | * i_size. | ||
| 3025 | */ | ||
| 3026 | if (len != olen) { | ||
| 3027 | ret = -EINVAL; | ||
| 3028 | goto out_unlock; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | /* Check for overlapping ranges */ | ||
| 3032 | if (dst_loff + len > loff && dst_loff < loff + len) { | ||
| 3033 | ret = -EINVAL; | ||
| 3034 | goto out_unlock; | ||
| 3035 | } | ||
| 3036 | |||
| 3037 | same_lock_start = min_t(u64, loff, dst_loff); | ||
| 3038 | same_lock_len = max_t(u64, loff, dst_loff) + len - same_lock_start; | ||
| 3039 | } else { | ||
| 3040 | btrfs_double_inode_lock(src, dst); | ||
| 3041 | |||
| 3042 | ret = extent_same_check_offsets(src, loff, &len, olen); | ||
| 3043 | if (ret) | ||
| 3044 | goto out_unlock; | ||
| 3045 | |||
| 3046 | ret = extent_same_check_offsets(dst, dst_loff, &len, olen); | ||
| 3047 | if (ret) | ||
| 3048 | goto out_unlock; | ||
| 3049 | } | ||
| 2938 | 3050 | ||
| 2939 | /* don't make the dst file partly checksummed */ | 3051 | /* don't make the dst file partly checksummed */ |
| 2940 | if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != | 3052 | if ((BTRFS_I(src)->flags & BTRFS_INODE_NODATASUM) != |
| @@ -2943,12 +3055,32 @@ static int btrfs_extent_same(struct inode *src, u64 loff, u64 olen, | |||
| 2943 | goto out_unlock; | 3055 | goto out_unlock; |
| 2944 | } | 3056 | } |
| 2945 | 3057 | ||
| 2946 | ret = btrfs_cmp_data(src, loff, dst, dst_loff, len); | 3058 | ret = btrfs_cmp_data_prepare(src, loff, dst, dst_loff, olen, &cmp); |
| 3059 | if (ret) | ||
| 3060 | goto out_unlock; | ||
| 3061 | |||
| 3062 | if (same_inode) | ||
| 3063 | lock_extent_range(src, same_lock_start, same_lock_len); | ||
| 3064 | else | ||
| 3065 | btrfs_double_extent_lock(src, loff, dst, dst_loff, len); | ||
| 3066 | |||
| 3067 | /* pass original length for comparison so we stay within i_size */ | ||
| 3068 | ret = btrfs_cmp_data(src, loff, dst, dst_loff, olen, &cmp); | ||
| 2947 | if (ret == 0) | 3069 | if (ret == 0) |
| 2948 | ret = btrfs_clone(src, dst, loff, olen, len, dst_loff); | 3070 | ret = btrfs_clone(src, dst, loff, olen, len, dst_loff, 1); |
| 3071 | |||
| 3072 | if (same_inode) | ||
| 3073 | unlock_extent(&BTRFS_I(src)->io_tree, same_lock_start, | ||
| 3074 | same_lock_start + same_lock_len - 1); | ||
| 3075 | else | ||
| 3076 | btrfs_double_extent_unlock(src, loff, dst, dst_loff, len); | ||
| 2949 | 3077 | ||
| 3078 | btrfs_cmp_data_free(&cmp); | ||
| 2950 | out_unlock: | 3079 | out_unlock: |
| 2951 | btrfs_double_unlock(src, loff, dst, dst_loff, len); | 3080 | if (same_inode) |
| 3081 | mutex_unlock(&src->i_mutex); | ||
| 3082 | else | ||
| 3083 | btrfs_double_inode_unlock(src, dst); | ||
| 2952 | 3084 | ||
| 2953 | return ret; | 3085 | return ret; |
| 2954 | } | 3086 | } |
| @@ -3100,13 +3232,15 @@ static int clone_finish_inode_update(struct btrfs_trans_handle *trans, | |||
| 3100 | struct inode *inode, | 3232 | struct inode *inode, |
| 3101 | u64 endoff, | 3233 | u64 endoff, |
| 3102 | const u64 destoff, | 3234 | const u64 destoff, |
| 3103 | const u64 olen) | 3235 | const u64 olen, |
| 3236 | int no_time_update) | ||
| 3104 | { | 3237 | { |
| 3105 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3238 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 3106 | int ret; | 3239 | int ret; |
| 3107 | 3240 | ||
| 3108 | inode_inc_iversion(inode); | 3241 | inode_inc_iversion(inode); |
| 3109 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 3242 | if (!no_time_update) |
| 3243 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 3110 | /* | 3244 | /* |
| 3111 | * We round up to the block size at eof when determining which | 3245 | * We round up to the block size at eof when determining which |
| 3112 | * extents to clone above, but shouldn't round up the file size. | 3246 | * extents to clone above, but shouldn't round up the file size. |
| @@ -3191,13 +3325,13 @@ static void clone_update_extent_map(struct inode *inode, | |||
| 3191 | * @inode: Inode to clone to | 3325 | * @inode: Inode to clone to |
| 3192 | * @off: Offset within source to start clone from | 3326 | * @off: Offset within source to start clone from |
| 3193 | * @olen: Original length, passed by user, of range to clone | 3327 | * @olen: Original length, passed by user, of range to clone |
| 3194 | * @olen_aligned: Block-aligned value of olen, extent_same uses | 3328 | * @olen_aligned: Block-aligned value of olen |
| 3195 | * identical values here | ||
| 3196 | * @destoff: Offset within @inode to start clone | 3329 | * @destoff: Offset within @inode to start clone |
| 3330 | * @no_time_update: Whether to update mtime/ctime on the target inode | ||
| 3197 | */ | 3331 | */ |
| 3198 | static int btrfs_clone(struct inode *src, struct inode *inode, | 3332 | static int btrfs_clone(struct inode *src, struct inode *inode, |
| 3199 | const u64 off, const u64 olen, const u64 olen_aligned, | 3333 | const u64 off, const u64 olen, const u64 olen_aligned, |
| 3200 | const u64 destoff) | 3334 | const u64 destoff, int no_time_update) |
| 3201 | { | 3335 | { |
| 3202 | struct btrfs_root *root = BTRFS_I(inode)->root; | 3336 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 3203 | struct btrfs_path *path = NULL; | 3337 | struct btrfs_path *path = NULL; |
| @@ -3521,7 +3655,8 @@ process_slot: | |||
| 3521 | root->sectorsize); | 3655 | root->sectorsize); |
| 3522 | ret = clone_finish_inode_update(trans, inode, | 3656 | ret = clone_finish_inode_update(trans, inode, |
| 3523 | last_dest_end, | 3657 | last_dest_end, |
| 3524 | destoff, olen); | 3658 | destoff, olen, |
| 3659 | no_time_update); | ||
| 3525 | if (ret) | 3660 | if (ret) |
| 3526 | goto out; | 3661 | goto out; |
| 3527 | if (new_key.offset + datal >= destoff + len) | 3662 | if (new_key.offset + datal >= destoff + len) |
| @@ -3559,7 +3694,7 @@ process_slot: | |||
| 3559 | clone_update_extent_map(inode, trans, NULL, last_dest_end, | 3694 | clone_update_extent_map(inode, trans, NULL, last_dest_end, |
| 3560 | destoff + len - last_dest_end); | 3695 | destoff + len - last_dest_end); |
| 3561 | ret = clone_finish_inode_update(trans, inode, destoff + len, | 3696 | ret = clone_finish_inode_update(trans, inode, destoff + len, |
| 3562 | destoff, olen); | 3697 | destoff, olen, no_time_update); |
| 3563 | } | 3698 | } |
| 3564 | 3699 | ||
| 3565 | out: | 3700 | out: |
| @@ -3696,7 +3831,7 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 3696 | lock_extent_range(inode, destoff, len); | 3831 | lock_extent_range(inode, destoff, len); |
| 3697 | } | 3832 | } |
| 3698 | 3833 | ||
| 3699 | ret = btrfs_clone(src, inode, off, olen, len, destoff); | 3834 | ret = btrfs_clone(src, inode, off, olen, len, destoff, 0); |
| 3700 | 3835 | ||
| 3701 | if (same_inode) { | 3836 | if (same_inode) { |
| 3702 | u64 lock_start = min_t(u64, off, destoff); | 3837 | u64 lock_start = min_t(u64, off, destoff); |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 89656d799ff6..52170cf1757e 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -552,6 +552,10 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) | |||
| 552 | trace_btrfs_ordered_extent_put(entry->inode, entry); | 552 | trace_btrfs_ordered_extent_put(entry->inode, entry); |
| 553 | 553 | ||
| 554 | if (atomic_dec_and_test(&entry->refs)) { | 554 | if (atomic_dec_and_test(&entry->refs)) { |
| 555 | ASSERT(list_empty(&entry->log_list)); | ||
| 556 | ASSERT(list_empty(&entry->trans_list)); | ||
| 557 | ASSERT(list_empty(&entry->root_extent_list)); | ||
| 558 | ASSERT(RB_EMPTY_NODE(&entry->rb_node)); | ||
| 555 | if (entry->inode) | 559 | if (entry->inode) |
| 556 | btrfs_add_delayed_iput(entry->inode); | 560 | btrfs_add_delayed_iput(entry->inode); |
| 557 | while (!list_empty(&entry->list)) { | 561 | while (!list_empty(&entry->list)) { |
| @@ -579,6 +583,7 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
| 579 | spin_lock_irq(&tree->lock); | 583 | spin_lock_irq(&tree->lock); |
| 580 | node = &entry->rb_node; | 584 | node = &entry->rb_node; |
| 581 | rb_erase(node, &tree->tree); | 585 | rb_erase(node, &tree->tree); |
| 586 | RB_CLEAR_NODE(node); | ||
| 582 | if (tree->last == node) | 587 | if (tree->last == node) |
| 583 | tree->last = NULL; | 588 | tree->last = NULL; |
| 584 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); | 589 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index d5f1f033b7a0..e9ace099162c 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
| @@ -1349,6 +1349,11 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, | |||
| 1349 | struct btrfs_root *quota_root; | 1349 | struct btrfs_root *quota_root; |
| 1350 | struct btrfs_qgroup *qgroup; | 1350 | struct btrfs_qgroup *qgroup; |
| 1351 | int ret = 0; | 1351 | int ret = 0; |
| 1352 | /* Sometimes we would want to clear the limit on this qgroup. | ||
| 1353 | * To meet this requirement, we treat the -1 as a special value | ||
| 1354 | * which tell kernel to clear the limit on this qgroup. | ||
| 1355 | */ | ||
| 1356 | const u64 CLEAR_VALUE = -1; | ||
| 1352 | 1357 | ||
| 1353 | mutex_lock(&fs_info->qgroup_ioctl_lock); | 1358 | mutex_lock(&fs_info->qgroup_ioctl_lock); |
| 1354 | quota_root = fs_info->quota_root; | 1359 | quota_root = fs_info->quota_root; |
| @@ -1364,14 +1369,42 @@ int btrfs_limit_qgroup(struct btrfs_trans_handle *trans, | |||
| 1364 | } | 1369 | } |
| 1365 | 1370 | ||
| 1366 | spin_lock(&fs_info->qgroup_lock); | 1371 | spin_lock(&fs_info->qgroup_lock); |
| 1367 | if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER) | 1372 | if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_RFER) { |
| 1368 | qgroup->max_rfer = limit->max_rfer; | 1373 | if (limit->max_rfer == CLEAR_VALUE) { |
| 1369 | if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) | 1374 | qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER; |
| 1370 | qgroup->max_excl = limit->max_excl; | 1375 | limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_RFER; |
| 1371 | if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER) | 1376 | qgroup->max_rfer = 0; |
| 1372 | qgroup->rsv_rfer = limit->rsv_rfer; | 1377 | } else { |
| 1373 | if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL) | 1378 | qgroup->max_rfer = limit->max_rfer; |
| 1374 | qgroup->rsv_excl = limit->rsv_excl; | 1379 | } |
| 1380 | } | ||
| 1381 | if (limit->flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) { | ||
| 1382 | if (limit->max_excl == CLEAR_VALUE) { | ||
| 1383 | qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL; | ||
| 1384 | limit->flags &= ~BTRFS_QGROUP_LIMIT_MAX_EXCL; | ||
| 1385 | qgroup->max_excl = 0; | ||
| 1386 | } else { | ||
| 1387 | qgroup->max_excl = limit->max_excl; | ||
| 1388 | } | ||
| 1389 | } | ||
| 1390 | if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_RFER) { | ||
| 1391 | if (limit->rsv_rfer == CLEAR_VALUE) { | ||
| 1392 | qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER; | ||
| 1393 | limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_RFER; | ||
| 1394 | qgroup->rsv_rfer = 0; | ||
| 1395 | } else { | ||
| 1396 | qgroup->rsv_rfer = limit->rsv_rfer; | ||
| 1397 | } | ||
| 1398 | } | ||
| 1399 | if (limit->flags & BTRFS_QGROUP_LIMIT_RSV_EXCL) { | ||
| 1400 | if (limit->rsv_excl == CLEAR_VALUE) { | ||
| 1401 | qgroup->lim_flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL; | ||
| 1402 | limit->flags &= ~BTRFS_QGROUP_LIMIT_RSV_EXCL; | ||
| 1403 | qgroup->rsv_excl = 0; | ||
| 1404 | } else { | ||
| 1405 | qgroup->rsv_excl = limit->rsv_excl; | ||
| 1406 | } | ||
| 1407 | } | ||
| 1375 | qgroup->lim_flags |= limit->flags; | 1408 | qgroup->lim_flags |= limit->flags; |
| 1376 | 1409 | ||
| 1377 | spin_unlock(&fs_info->qgroup_lock); | 1410 | spin_unlock(&fs_info->qgroup_lock); |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 827951fbf7fc..88cbb5995667 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -4049,7 +4049,7 @@ restart: | |||
| 4049 | if (trans && progress && err == -ENOSPC) { | 4049 | if (trans && progress && err == -ENOSPC) { |
| 4050 | ret = btrfs_force_chunk_alloc(trans, rc->extent_root, | 4050 | ret = btrfs_force_chunk_alloc(trans, rc->extent_root, |
| 4051 | rc->block_group->flags); | 4051 | rc->block_group->flags); |
| 4052 | if (ret == 0) { | 4052 | if (ret == 1) { |
| 4053 | err = 0; | 4053 | err = 0; |
| 4054 | progress = 0; | 4054 | progress = 0; |
| 4055 | goto restart; | 4055 | goto restart; |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 9f2feabe99f2..94db0fa5225a 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
| @@ -3571,7 +3571,6 @@ static noinline_for_stack int scrub_supers(struct scrub_ctx *sctx, | |||
| 3571 | static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, | 3571 | static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, |
| 3572 | int is_dev_replace) | 3572 | int is_dev_replace) |
| 3573 | { | 3573 | { |
| 3574 | int ret = 0; | ||
| 3575 | unsigned int flags = WQ_FREEZABLE | WQ_UNBOUND; | 3574 | unsigned int flags = WQ_FREEZABLE | WQ_UNBOUND; |
| 3576 | int max_active = fs_info->thread_pool_size; | 3575 | int max_active = fs_info->thread_pool_size; |
| 3577 | 3576 | ||
| @@ -3584,34 +3583,36 @@ static noinline_for_stack int scrub_workers_get(struct btrfs_fs_info *fs_info, | |||
| 3584 | fs_info->scrub_workers = | 3583 | fs_info->scrub_workers = |
| 3585 | btrfs_alloc_workqueue("btrfs-scrub", flags, | 3584 | btrfs_alloc_workqueue("btrfs-scrub", flags, |
| 3586 | max_active, 4); | 3585 | max_active, 4); |
| 3587 | if (!fs_info->scrub_workers) { | 3586 | if (!fs_info->scrub_workers) |
| 3588 | ret = -ENOMEM; | 3587 | goto fail_scrub_workers; |
| 3589 | goto out; | 3588 | |
| 3590 | } | ||
| 3591 | fs_info->scrub_wr_completion_workers = | 3589 | fs_info->scrub_wr_completion_workers = |
| 3592 | btrfs_alloc_workqueue("btrfs-scrubwrc", flags, | 3590 | btrfs_alloc_workqueue("btrfs-scrubwrc", flags, |
| 3593 | max_active, 2); | 3591 | max_active, 2); |
| 3594 | if (!fs_info->scrub_wr_completion_workers) { | 3592 | if (!fs_info->scrub_wr_completion_workers) |
| 3595 | ret = -ENOMEM; | 3593 | goto fail_scrub_wr_completion_workers; |
| 3596 | goto out; | 3594 | |
| 3597 | } | ||
| 3598 | fs_info->scrub_nocow_workers = | 3595 | fs_info->scrub_nocow_workers = |
| 3599 | btrfs_alloc_workqueue("btrfs-scrubnc", flags, 1, 0); | 3596 | btrfs_alloc_workqueue("btrfs-scrubnc", flags, 1, 0); |
| 3600 | if (!fs_info->scrub_nocow_workers) { | 3597 | if (!fs_info->scrub_nocow_workers) |
| 3601 | ret = -ENOMEM; | 3598 | goto fail_scrub_nocow_workers; |
| 3602 | goto out; | ||
| 3603 | } | ||
| 3604 | fs_info->scrub_parity_workers = | 3599 | fs_info->scrub_parity_workers = |
| 3605 | btrfs_alloc_workqueue("btrfs-scrubparity", flags, | 3600 | btrfs_alloc_workqueue("btrfs-scrubparity", flags, |
| 3606 | max_active, 2); | 3601 | max_active, 2); |
| 3607 | if (!fs_info->scrub_parity_workers) { | 3602 | if (!fs_info->scrub_parity_workers) |
| 3608 | ret = -ENOMEM; | 3603 | goto fail_scrub_parity_workers; |
| 3609 | goto out; | ||
| 3610 | } | ||
| 3611 | } | 3604 | } |
| 3612 | ++fs_info->scrub_workers_refcnt; | 3605 | ++fs_info->scrub_workers_refcnt; |
| 3613 | out: | 3606 | return 0; |
| 3614 | return ret; | 3607 | |
| 3608 | fail_scrub_parity_workers: | ||
| 3609 | btrfs_destroy_workqueue(fs_info->scrub_nocow_workers); | ||
| 3610 | fail_scrub_nocow_workers: | ||
| 3611 | btrfs_destroy_workqueue(fs_info->scrub_wr_completion_workers); | ||
| 3612 | fail_scrub_wr_completion_workers: | ||
| 3613 | btrfs_destroy_workqueue(fs_info->scrub_workers); | ||
| 3614 | fail_scrub_workers: | ||
| 3615 | return -ENOMEM; | ||
| 3615 | } | 3616 | } |
| 3616 | 3617 | ||
| 3617 | static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info) | 3618 | static noinline_for_stack void scrub_workers_put(struct btrfs_fs_info *fs_info) |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1ce80c1c4eb6..9c45431e69ab 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -4117,6 +4117,187 @@ static int logged_inode_size(struct btrfs_root *log, struct inode *inode, | |||
| 4117 | return 0; | 4117 | return 0; |
| 4118 | } | 4118 | } |
| 4119 | 4119 | ||
| 4120 | /* | ||
| 4121 | * At the moment we always log all xattrs. This is to figure out at log replay | ||
| 4122 | * time which xattrs must have their deletion replayed. If a xattr is missing | ||
| 4123 | * in the log tree and exists in the fs/subvol tree, we delete it. This is | ||
| 4124 | * because if a xattr is deleted, the inode is fsynced and a power failure | ||
| 4125 | * happens, causing the log to be replayed the next time the fs is mounted, | ||
| 4126 | * we want the xattr to not exist anymore (same behaviour as other filesystems | ||
| 4127 | * with a journal, ext3/4, xfs, f2fs, etc). | ||
| 4128 | */ | ||
| 4129 | static int btrfs_log_all_xattrs(struct btrfs_trans_handle *trans, | ||
| 4130 | struct btrfs_root *root, | ||
| 4131 | struct inode *inode, | ||
| 4132 | struct btrfs_path *path, | ||
| 4133 | struct btrfs_path *dst_path) | ||
| 4134 | { | ||
| 4135 | int ret; | ||
| 4136 | struct btrfs_key key; | ||
| 4137 | const u64 ino = btrfs_ino(inode); | ||
| 4138 | int ins_nr = 0; | ||
| 4139 | int start_slot = 0; | ||
| 4140 | |||
| 4141 | key.objectid = ino; | ||
| 4142 | key.type = BTRFS_XATTR_ITEM_KEY; | ||
| 4143 | key.offset = 0; | ||
| 4144 | |||
| 4145 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
| 4146 | if (ret < 0) | ||
| 4147 | return ret; | ||
| 4148 | |||
| 4149 | while (true) { | ||
| 4150 | int slot = path->slots[0]; | ||
| 4151 | struct extent_buffer *leaf = path->nodes[0]; | ||
| 4152 | int nritems = btrfs_header_nritems(leaf); | ||
| 4153 | |||
| 4154 | if (slot >= nritems) { | ||
| 4155 | if (ins_nr > 0) { | ||
| 4156 | u64 last_extent = 0; | ||
| 4157 | |||
| 4158 | ret = copy_items(trans, inode, dst_path, path, | ||
| 4159 | &last_extent, start_slot, | ||
| 4160 | ins_nr, 1, 0); | ||
| 4161 | /* can't be 1, extent items aren't processed */ | ||
| 4162 | ASSERT(ret <= 0); | ||
| 4163 | if (ret < 0) | ||
| 4164 | return ret; | ||
| 4165 | ins_nr = 0; | ||
| 4166 | } | ||
| 4167 | ret = btrfs_next_leaf(root, path); | ||
| 4168 | if (ret < 0) | ||
| 4169 | return ret; | ||
| 4170 | else if (ret > 0) | ||
| 4171 | break; | ||
| 4172 | continue; | ||
| 4173 | } | ||
| 4174 | |||
| 4175 | btrfs_item_key_to_cpu(leaf, &key, slot); | ||
| 4176 | if (key.objectid != ino || key.type != BTRFS_XATTR_ITEM_KEY) | ||
| 4177 | break; | ||
| 4178 | |||
| 4179 | if (ins_nr == 0) | ||
| 4180 | start_slot = slot; | ||
| 4181 | ins_nr++; | ||
| 4182 | path->slots[0]++; | ||
| 4183 | cond_resched(); | ||
| 4184 | } | ||
| 4185 | if (ins_nr > 0) { | ||
| 4186 | u64 last_extent = 0; | ||
| 4187 | |||
| 4188 | ret = copy_items(trans, inode, dst_path, path, | ||
| 4189 | &last_extent, start_slot, | ||
| 4190 | ins_nr, 1, 0); | ||
| 4191 | /* can't be 1, extent items aren't processed */ | ||
| 4192 | ASSERT(ret <= 0); | ||
| 4193 | if (ret < 0) | ||
| 4194 | return ret; | ||
| 4195 | } | ||
| 4196 | |||
| 4197 | return 0; | ||
| 4198 | } | ||
| 4199 | |||
| 4200 | /* | ||
| 4201 | * If the no holes feature is enabled we need to make sure any hole between the | ||
| 4202 | * last extent and the i_size of our inode is explicitly marked in the log. This | ||
| 4203 | * is to make sure that doing something like: | ||
| 4204 | * | ||
| 4205 | * 1) create file with 128Kb of data | ||
| 4206 | * 2) truncate file to 64Kb | ||
| 4207 | * 3) truncate file to 256Kb | ||
| 4208 | * 4) fsync file | ||
| 4209 | * 5) <crash/power failure> | ||
| 4210 | * 6) mount fs and trigger log replay | ||
| 4211 | * | ||
| 4212 | * Will give us a file with a size of 256Kb, the first 64Kb of data match what | ||
| 4213 | * the file had in its first 64Kb of data at step 1 and the last 192Kb of the | ||
| 4214 | * file correspond to a hole. The presence of explicit holes in a log tree is | ||
| 4215 | * what guarantees that log replay will remove/adjust file extent items in the | ||
| 4216 | * fs/subvol tree. | ||
| 4217 | * | ||
| 4218 | * Here we do not need to care about holes between extents, that is already done | ||
| 4219 | * by copy_items(). We also only need to do this in the full sync path, where we | ||
| 4220 | * lookup for extents from the fs/subvol tree only. In the fast path case, we | ||
| 4221 | * lookup the list of modified extent maps and if any represents a hole, we | ||
| 4222 | * insert a corresponding extent representing a hole in the log tree. | ||
| 4223 | */ | ||
| 4224 | static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, | ||
| 4225 | struct btrfs_root *root, | ||
| 4226 | struct inode *inode, | ||
| 4227 | struct btrfs_path *path) | ||
| 4228 | { | ||
| 4229 | int ret; | ||
| 4230 | struct btrfs_key key; | ||
| 4231 | u64 hole_start; | ||
| 4232 | u64 hole_size; | ||
| 4233 | struct extent_buffer *leaf; | ||
| 4234 | struct btrfs_root *log = root->log_root; | ||
| 4235 | const u64 ino = btrfs_ino(inode); | ||
| 4236 | const u64 i_size = i_size_read(inode); | ||
| 4237 | |||
| 4238 | if (!btrfs_fs_incompat(root->fs_info, NO_HOLES)) | ||
| 4239 | return 0; | ||
| 4240 | |||
| 4241 | key.objectid = ino; | ||
| 4242 | key.type = BTRFS_EXTENT_DATA_KEY; | ||
| 4243 | key.offset = (u64)-1; | ||
| 4244 | |||
| 4245 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
| 4246 | ASSERT(ret != 0); | ||
| 4247 | if (ret < 0) | ||
| 4248 | return ret; | ||
| 4249 | |||
| 4250 | ASSERT(path->slots[0] > 0); | ||
| 4251 | path->slots[0]--; | ||
| 4252 | leaf = path->nodes[0]; | ||
| 4253 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
| 4254 | |||
| 4255 | if (key.objectid != ino || key.type != BTRFS_EXTENT_DATA_KEY) { | ||
| 4256 | /* inode does not have any extents */ | ||
| 4257 | hole_start = 0; | ||
| 4258 | hole_size = i_size; | ||
| 4259 | } else { | ||
| 4260 | struct btrfs_file_extent_item *extent; | ||
| 4261 | u64 len; | ||
| 4262 | |||
| 4263 | /* | ||
| 4264 | * If there's an extent beyond i_size, an explicit hole was | ||
| 4265 | * already inserted by copy_items(). | ||
| 4266 | */ | ||
| 4267 | if (key.offset >= i_size) | ||
| 4268 | return 0; | ||
| 4269 | |||
| 4270 | extent = btrfs_item_ptr(leaf, path->slots[0], | ||
| 4271 | struct btrfs_file_extent_item); | ||
| 4272 | |||
| 4273 | if (btrfs_file_extent_type(leaf, extent) == | ||
| 4274 | BTRFS_FILE_EXTENT_INLINE) { | ||
| 4275 | len = btrfs_file_extent_inline_len(leaf, | ||
| 4276 | path->slots[0], | ||
| 4277 | extent); | ||
| 4278 | ASSERT(len == i_size); | ||
| 4279 | return 0; | ||
| 4280 | } | ||
| 4281 | |||
| 4282 | len = btrfs_file_extent_num_bytes(leaf, extent); | ||
| 4283 | /* Last extent goes beyond i_size, no need to log a hole. */ | ||
| 4284 | if (key.offset + len > i_size) | ||
| 4285 | return 0; | ||
| 4286 | hole_start = key.offset + len; | ||
| 4287 | hole_size = i_size - hole_start; | ||
| 4288 | } | ||
| 4289 | btrfs_release_path(path); | ||
| 4290 | |||
| 4291 | /* Last extent ends at i_size. */ | ||
| 4292 | if (hole_size == 0) | ||
| 4293 | return 0; | ||
| 4294 | |||
| 4295 | hole_size = ALIGN(hole_size, root->sectorsize); | ||
| 4296 | ret = btrfs_insert_file_extent(trans, log, ino, hole_start, 0, 0, | ||
| 4297 | hole_size, 0, hole_size, 0, 0, 0); | ||
| 4298 | return ret; | ||
| 4299 | } | ||
| 4300 | |||
| 4120 | /* log a single inode in the tree log. | 4301 | /* log a single inode in the tree log. |
| 4121 | * At least one parent directory for this inode must exist in the tree | 4302 | * At least one parent directory for this inode must exist in the tree |
| 4122 | * or be logged already. | 4303 | * or be logged already. |
| @@ -4155,6 +4336,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
| 4155 | u64 ino = btrfs_ino(inode); | 4336 | u64 ino = btrfs_ino(inode); |
| 4156 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; | 4337 | struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree; |
| 4157 | u64 logged_isize = 0; | 4338 | u64 logged_isize = 0; |
| 4339 | bool need_log_inode_item = true; | ||
| 4158 | 4340 | ||
| 4159 | path = btrfs_alloc_path(); | 4341 | path = btrfs_alloc_path(); |
| 4160 | if (!path) | 4342 | if (!path) |
| @@ -4263,11 +4445,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans, | |||
| 4263 | } else { | 4445 | } else { |
| 4264 | if (inode_only == LOG_INODE_ALL) | 4446 | if (inode_only == LOG_INODE_ALL) |
| 4265 | fast_search = true; | 4447 | fast_search = true; |
| 4266 | ret = log_inode_item(trans, log, dst_path, inode); | ||
| 4267 | if (ret) { | ||
| 4268 | err = ret; | ||
| 4269 | goto out_unlock; | ||
| 4270 | } | ||
| 4271 | goto log_extents; | 4448 | goto log_extents; |
| 4272 | } | 4449 | } |
| 4273 | 4450 | ||
| @@ -4290,6 +4467,28 @@ again: | |||
| 4290 | if (min_key.type > max_key.type) | 4467 | if (min_key.type > max_key.type) |
| 4291 | break; | 4468 | break; |
| 4292 | 4469 | ||
| 4470 | if (min_key.type == BTRFS_INODE_ITEM_KEY) | ||
| 4471 | need_log_inode_item = false; | ||
| 4472 | |||
| 4473 | /* Skip xattrs, we log them later with btrfs_log_all_xattrs() */ | ||
| 4474 | if (min_key.type == BTRFS_XATTR_ITEM_KEY) { | ||
| 4475 | if (ins_nr == 0) | ||
| 4476 | goto next_slot; | ||
| 4477 | ret = copy_items(trans, inode, dst_path, path, | ||
| 4478 | &last_extent, ins_start_slot, | ||
| 4479 | ins_nr, inode_only, logged_isize); | ||
| 4480 | if (ret < 0) { | ||
| 4481 | err = ret; | ||
| 4482 | goto out_unlock; | ||
| 4483 | } | ||
| 4484 | ins_nr = 0; | ||
| 4485 | if (ret) { | ||
| 4486 | btrfs_release_path(path); | ||
| 4487 | continue; | ||
| 4488 | } | ||
| 4489 | goto next_slot; | ||
| 4490 | } | ||
| 4491 | |||
| 4293 | src = path->nodes[0]; | 4492 | src = path->nodes[0]; |
| 4294 | if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) { | 4493 | if (ins_nr && ins_start_slot + ins_nr == path->slots[0]) { |
| 4295 | ins_nr++; | 4494 | ins_nr++; |
| @@ -4357,9 +4556,26 @@ next_slot: | |||
| 4357 | ins_nr = 0; | 4556 | ins_nr = 0; |
| 4358 | } | 4557 | } |
| 4359 | 4558 | ||
| 4559 | btrfs_release_path(path); | ||
| 4560 | btrfs_release_path(dst_path); | ||
| 4561 | err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path); | ||
| 4562 | if (err) | ||
| 4563 | goto out_unlock; | ||
| 4564 | if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) { | ||
| 4565 | btrfs_release_path(path); | ||
| 4566 | btrfs_release_path(dst_path); | ||
| 4567 | err = btrfs_log_trailing_hole(trans, root, inode, path); | ||
| 4568 | if (err) | ||
| 4569 | goto out_unlock; | ||
| 4570 | } | ||
| 4360 | log_extents: | 4571 | log_extents: |
| 4361 | btrfs_release_path(path); | 4572 | btrfs_release_path(path); |
| 4362 | btrfs_release_path(dst_path); | 4573 | btrfs_release_path(dst_path); |
| 4574 | if (need_log_inode_item) { | ||
| 4575 | err = log_inode_item(trans, log, dst_path, inode); | ||
| 4576 | if (err) | ||
| 4577 | goto out_unlock; | ||
| 4578 | } | ||
| 4363 | if (fast_search) { | 4579 | if (fast_search) { |
| 4364 | /* | 4580 | /* |
| 4365 | * Some ordered extents started by fsync might have completed | 4581 | * Some ordered extents started by fsync might have completed |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 4b438b4c8c91..fbe7c104531c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -2766,6 +2766,20 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
| 2766 | root = root->fs_info->chunk_root; | 2766 | root = root->fs_info->chunk_root; |
| 2767 | extent_root = root->fs_info->extent_root; | 2767 | extent_root = root->fs_info->extent_root; |
| 2768 | 2768 | ||
| 2769 | /* | ||
| 2770 | * Prevent races with automatic removal of unused block groups. | ||
| 2771 | * After we relocate and before we remove the chunk with offset | ||
| 2772 | * chunk_offset, automatic removal of the block group can kick in, | ||
| 2773 | * resulting in a failure when calling btrfs_remove_chunk() below. | ||
| 2774 | * | ||
| 2775 | * Make sure to acquire this mutex before doing a tree search (dev | ||
| 2776 | * or chunk trees) to find chunks. Otherwise the cleaner kthread might | ||
| 2777 | * call btrfs_remove_chunk() (through btrfs_delete_unused_bgs()) after | ||
| 2778 | * we release the path used to search the chunk/dev tree and before | ||
| 2779 | * the current task acquires this mutex and calls us. | ||
| 2780 | */ | ||
| 2781 | ASSERT(mutex_is_locked(&root->fs_info->delete_unused_bgs_mutex)); | ||
| 2782 | |||
| 2769 | ret = btrfs_can_relocate(extent_root, chunk_offset); | 2783 | ret = btrfs_can_relocate(extent_root, chunk_offset); |
| 2770 | if (ret) | 2784 | if (ret) |
| 2771 | return -ENOSPC; | 2785 | return -ENOSPC; |
| @@ -2814,13 +2828,18 @@ again: | |||
| 2814 | key.type = BTRFS_CHUNK_ITEM_KEY; | 2828 | key.type = BTRFS_CHUNK_ITEM_KEY; |
| 2815 | 2829 | ||
| 2816 | while (1) { | 2830 | while (1) { |
| 2831 | mutex_lock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 2817 | ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); | 2832 | ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); |
| 2818 | if (ret < 0) | 2833 | if (ret < 0) { |
| 2834 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 2819 | goto error; | 2835 | goto error; |
| 2836 | } | ||
| 2820 | BUG_ON(ret == 0); /* Corruption */ | 2837 | BUG_ON(ret == 0); /* Corruption */ |
| 2821 | 2838 | ||
| 2822 | ret = btrfs_previous_item(chunk_root, path, key.objectid, | 2839 | ret = btrfs_previous_item(chunk_root, path, key.objectid, |
| 2823 | key.type); | 2840 | key.type); |
| 2841 | if (ret) | ||
| 2842 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 2824 | if (ret < 0) | 2843 | if (ret < 0) |
| 2825 | goto error; | 2844 | goto error; |
| 2826 | if (ret > 0) | 2845 | if (ret > 0) |
| @@ -2843,6 +2862,7 @@ again: | |||
| 2843 | else | 2862 | else |
| 2844 | BUG_ON(ret); | 2863 | BUG_ON(ret); |
| 2845 | } | 2864 | } |
| 2865 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 2846 | 2866 | ||
| 2847 | if (found_key.offset == 0) | 2867 | if (found_key.offset == 0) |
| 2848 | break; | 2868 | break; |
| @@ -3299,9 +3319,12 @@ again: | |||
| 3299 | goto error; | 3319 | goto error; |
| 3300 | } | 3320 | } |
| 3301 | 3321 | ||
| 3322 | mutex_lock(&fs_info->delete_unused_bgs_mutex); | ||
| 3302 | ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); | 3323 | ret = btrfs_search_slot(NULL, chunk_root, &key, path, 0, 0); |
| 3303 | if (ret < 0) | 3324 | if (ret < 0) { |
| 3325 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
| 3304 | goto error; | 3326 | goto error; |
| 3327 | } | ||
| 3305 | 3328 | ||
| 3306 | /* | 3329 | /* |
| 3307 | * this shouldn't happen, it means the last relocate | 3330 | * this shouldn't happen, it means the last relocate |
| @@ -3313,6 +3336,7 @@ again: | |||
| 3313 | ret = btrfs_previous_item(chunk_root, path, 0, | 3336 | ret = btrfs_previous_item(chunk_root, path, 0, |
| 3314 | BTRFS_CHUNK_ITEM_KEY); | 3337 | BTRFS_CHUNK_ITEM_KEY); |
| 3315 | if (ret) { | 3338 | if (ret) { |
| 3339 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
| 3316 | ret = 0; | 3340 | ret = 0; |
| 3317 | break; | 3341 | break; |
| 3318 | } | 3342 | } |
| @@ -3321,8 +3345,10 @@ again: | |||
| 3321 | slot = path->slots[0]; | 3345 | slot = path->slots[0]; |
| 3322 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 3346 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
| 3323 | 3347 | ||
| 3324 | if (found_key.objectid != key.objectid) | 3348 | if (found_key.objectid != key.objectid) { |
| 3349 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
| 3325 | break; | 3350 | break; |
| 3351 | } | ||
| 3326 | 3352 | ||
| 3327 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); | 3353 | chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); |
| 3328 | 3354 | ||
| @@ -3335,10 +3361,13 @@ again: | |||
| 3335 | ret = should_balance_chunk(chunk_root, leaf, chunk, | 3361 | ret = should_balance_chunk(chunk_root, leaf, chunk, |
| 3336 | found_key.offset); | 3362 | found_key.offset); |
| 3337 | btrfs_release_path(path); | 3363 | btrfs_release_path(path); |
| 3338 | if (!ret) | 3364 | if (!ret) { |
| 3365 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
| 3339 | goto loop; | 3366 | goto loop; |
| 3367 | } | ||
| 3340 | 3368 | ||
| 3341 | if (counting) { | 3369 | if (counting) { |
| 3370 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
| 3342 | spin_lock(&fs_info->balance_lock); | 3371 | spin_lock(&fs_info->balance_lock); |
| 3343 | bctl->stat.expected++; | 3372 | bctl->stat.expected++; |
| 3344 | spin_unlock(&fs_info->balance_lock); | 3373 | spin_unlock(&fs_info->balance_lock); |
| @@ -3348,6 +3377,7 @@ again: | |||
| 3348 | ret = btrfs_relocate_chunk(chunk_root, | 3377 | ret = btrfs_relocate_chunk(chunk_root, |
| 3349 | found_key.objectid, | 3378 | found_key.objectid, |
| 3350 | found_key.offset); | 3379 | found_key.offset); |
| 3380 | mutex_unlock(&fs_info->delete_unused_bgs_mutex); | ||
| 3351 | if (ret && ret != -ENOSPC) | 3381 | if (ret && ret != -ENOSPC) |
| 3352 | goto error; | 3382 | goto error; |
| 3353 | if (ret == -ENOSPC) { | 3383 | if (ret == -ENOSPC) { |
| @@ -4087,11 +4117,16 @@ again: | |||
| 4087 | key.type = BTRFS_DEV_EXTENT_KEY; | 4117 | key.type = BTRFS_DEV_EXTENT_KEY; |
| 4088 | 4118 | ||
| 4089 | do { | 4119 | do { |
| 4120 | mutex_lock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 4090 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 4121 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
| 4091 | if (ret < 0) | 4122 | if (ret < 0) { |
| 4123 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 4092 | goto done; | 4124 | goto done; |
| 4125 | } | ||
| 4093 | 4126 | ||
| 4094 | ret = btrfs_previous_item(root, path, 0, key.type); | 4127 | ret = btrfs_previous_item(root, path, 0, key.type); |
| 4128 | if (ret) | ||
| 4129 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 4095 | if (ret < 0) | 4130 | if (ret < 0) |
| 4096 | goto done; | 4131 | goto done; |
| 4097 | if (ret) { | 4132 | if (ret) { |
| @@ -4105,6 +4140,7 @@ again: | |||
| 4105 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 4140 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
| 4106 | 4141 | ||
| 4107 | if (key.objectid != device->devid) { | 4142 | if (key.objectid != device->devid) { |
| 4143 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 4108 | btrfs_release_path(path); | 4144 | btrfs_release_path(path); |
| 4109 | break; | 4145 | break; |
| 4110 | } | 4146 | } |
| @@ -4113,6 +4149,7 @@ again: | |||
| 4113 | length = btrfs_dev_extent_length(l, dev_extent); | 4149 | length = btrfs_dev_extent_length(l, dev_extent); |
| 4114 | 4150 | ||
| 4115 | if (key.offset + length <= new_size) { | 4151 | if (key.offset + length <= new_size) { |
| 4152 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 4116 | btrfs_release_path(path); | 4153 | btrfs_release_path(path); |
| 4117 | break; | 4154 | break; |
| 4118 | } | 4155 | } |
| @@ -4122,6 +4159,7 @@ again: | |||
| 4122 | btrfs_release_path(path); | 4159 | btrfs_release_path(path); |
| 4123 | 4160 | ||
| 4124 | ret = btrfs_relocate_chunk(root, chunk_objectid, chunk_offset); | 4161 | ret = btrfs_relocate_chunk(root, chunk_objectid, chunk_offset); |
| 4162 | mutex_unlock(&root->fs_info->delete_unused_bgs_mutex); | ||
| 4125 | if (ret && ret != -ENOSPC) | 4163 | if (ret && ret != -ENOSPC) |
| 4126 | goto done; | 4164 | goto done; |
| 4127 | if (ret == -ENOSPC) | 4165 | if (ret == -ENOSPC) |
| @@ -5715,7 +5753,6 @@ static inline void btrfs_end_bbio(struct btrfs_bio *bbio, struct bio *bio, int e | |||
| 5715 | static void btrfs_end_bio(struct bio *bio, int err) | 5753 | static void btrfs_end_bio(struct bio *bio, int err) |
| 5716 | { | 5754 | { |
| 5717 | struct btrfs_bio *bbio = bio->bi_private; | 5755 | struct btrfs_bio *bbio = bio->bi_private; |
| 5718 | struct btrfs_device *dev = bbio->stripes[0].dev; | ||
| 5719 | int is_orig_bio = 0; | 5756 | int is_orig_bio = 0; |
| 5720 | 5757 | ||
| 5721 | if (err) { | 5758 | if (err) { |
| @@ -5723,6 +5760,7 @@ static void btrfs_end_bio(struct bio *bio, int err) | |||
| 5723 | if (err == -EIO || err == -EREMOTEIO) { | 5760 | if (err == -EIO || err == -EREMOTEIO) { |
| 5724 | unsigned int stripe_index = | 5761 | unsigned int stripe_index = |
| 5725 | btrfs_io_bio(bio)->stripe_index; | 5762 | btrfs_io_bio(bio)->stripe_index; |
| 5763 | struct btrfs_device *dev; | ||
| 5726 | 5764 | ||
| 5727 | BUG_ON(stripe_index >= bbio->num_stripes); | 5765 | BUG_ON(stripe_index >= bbio->num_stripes); |
| 5728 | dev = bbio->stripes[stripe_index].dev; | 5766 | dev = bbio->stripes[stripe_index].dev; |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6b8e2f091f5b..48851f6ea6ec 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -896,6 +896,7 @@ COMPATIBLE_IOCTL(FIGETBSZ) | |||
| 896 | /* 'X' - originally XFS but some now in the VFS */ | 896 | /* 'X' - originally XFS but some now in the VFS */ |
| 897 | COMPATIBLE_IOCTL(FIFREEZE) | 897 | COMPATIBLE_IOCTL(FIFREEZE) |
| 898 | COMPATIBLE_IOCTL(FITHAW) | 898 | COMPATIBLE_IOCTL(FITHAW) |
| 899 | COMPATIBLE_IOCTL(FITRIM) | ||
| 899 | COMPATIBLE_IOCTL(KDGETKEYCODE) | 900 | COMPATIBLE_IOCTL(KDGETKEYCODE) |
| 900 | COMPATIBLE_IOCTL(KDSETKEYCODE) | 901 | COMPATIBLE_IOCTL(KDSETKEYCODE) |
| 901 | COMPATIBLE_IOCTL(KDGKBTYPE) | 902 | COMPATIBLE_IOCTL(KDGKBTYPE) |
diff --git a/fs/dcache.c b/fs/dcache.c index 7a3f3e5f9cea..5c8ea15e73a5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -642,7 +642,7 @@ static inline bool fast_dput(struct dentry *dentry) | |||
| 642 | 642 | ||
| 643 | /* | 643 | /* |
| 644 | * If we have a d_op->d_delete() operation, we sould not | 644 | * If we have a d_op->d_delete() operation, we sould not |
| 645 | * let the dentry count go to zero, so use "put__or_lock". | 645 | * let the dentry count go to zero, so use "put_or_lock". |
| 646 | */ | 646 | */ |
| 647 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) | 647 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) |
| 648 | return lockref_put_or_lock(&dentry->d_lockref); | 648 | return lockref_put_or_lock(&dentry->d_lockref); |
| @@ -697,7 +697,7 @@ static inline bool fast_dput(struct dentry *dentry) | |||
| 697 | */ | 697 | */ |
| 698 | smp_rmb(); | 698 | smp_rmb(); |
| 699 | d_flags = ACCESS_ONCE(dentry->d_flags); | 699 | d_flags = ACCESS_ONCE(dentry->d_flags); |
| 700 | d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST; | 700 | d_flags &= DCACHE_REFERENCED | DCACHE_LRU_LIST | DCACHE_DISCONNECTED; |
| 701 | 701 | ||
| 702 | /* Nothing to do? Dropping the reference was all we needed? */ | 702 | /* Nothing to do? Dropping the reference was all we needed? */ |
| 703 | if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) | 703 | if (d_flags == (DCACHE_REFERENCED | DCACHE_LRU_LIST) && !d_unhashed(dentry)) |
| @@ -776,6 +776,9 @@ repeat: | |||
| 776 | if (unlikely(d_unhashed(dentry))) | 776 | if (unlikely(d_unhashed(dentry))) |
| 777 | goto kill_it; | 777 | goto kill_it; |
| 778 | 778 | ||
| 779 | if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) | ||
| 780 | goto kill_it; | ||
| 781 | |||
| 779 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { | 782 | if (unlikely(dentry->d_flags & DCACHE_OP_DELETE)) { |
| 780 | if (dentry->d_op->d_delete(dentry)) | 783 | if (dentry->d_op->d_delete(dentry)) |
| 781 | goto kill_it; | 784 | goto kill_it; |
diff --git a/fs/ecryptfs/file.c b/fs/ecryptfs/file.c index 72afcc629d7b..feef8a9c4de7 100644 --- a/fs/ecryptfs/file.c +++ b/fs/ecryptfs/file.c | |||
| @@ -325,7 +325,6 @@ ecryptfs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 325 | return rc; | 325 | return rc; |
| 326 | 326 | ||
| 327 | switch (cmd) { | 327 | switch (cmd) { |
| 328 | case FITRIM: | ||
| 329 | case FS_IOC32_GETFLAGS: | 328 | case FS_IOC32_GETFLAGS: |
| 330 | case FS_IOC32_SETFLAGS: | 329 | case FS_IOC32_SETFLAGS: |
| 331 | case FS_IOC32_GETVERSION: | 330 | case FS_IOC32_GETVERSION: |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index aadb72828834..2553aa8b608d 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -504,7 +504,7 @@ __read_extent_tree_block(const char *function, unsigned int line, | |||
| 504 | struct buffer_head *bh; | 504 | struct buffer_head *bh; |
| 505 | int err; | 505 | int err; |
| 506 | 506 | ||
| 507 | bh = sb_getblk(inode->i_sb, pblk); | 507 | bh = sb_getblk_gfp(inode->i_sb, pblk, __GFP_MOVABLE | GFP_NOFS); |
| 508 | if (unlikely(!bh)) | 508 | if (unlikely(!bh)) |
| 509 | return ERR_PTR(-ENOMEM); | 509 | return ERR_PTR(-ENOMEM); |
| 510 | 510 | ||
| @@ -1089,7 +1089,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
| 1089 | err = -EIO; | 1089 | err = -EIO; |
| 1090 | goto cleanup; | 1090 | goto cleanup; |
| 1091 | } | 1091 | } |
| 1092 | bh = sb_getblk(inode->i_sb, newblock); | 1092 | bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); |
| 1093 | if (unlikely(!bh)) { | 1093 | if (unlikely(!bh)) { |
| 1094 | err = -ENOMEM; | 1094 | err = -ENOMEM; |
| 1095 | goto cleanup; | 1095 | goto cleanup; |
| @@ -1283,7 +1283,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
| 1283 | if (newblock == 0) | 1283 | if (newblock == 0) |
| 1284 | return err; | 1284 | return err; |
| 1285 | 1285 | ||
| 1286 | bh = sb_getblk(inode->i_sb, newblock); | 1286 | bh = sb_getblk_gfp(inode->i_sb, newblock, __GFP_MOVABLE | GFP_NOFS); |
| 1287 | if (unlikely(!bh)) | 1287 | if (unlikely(!bh)) |
| 1288 | return -ENOMEM; | 1288 | return -ENOMEM; |
| 1289 | lock_buffer(bh); | 1289 | lock_buffer(bh); |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 41f8e55afcd1..cecf9aa10811 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -1323,7 +1323,7 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
| 1323 | unsigned int offset, | 1323 | unsigned int offset, |
| 1324 | unsigned int length) | 1324 | unsigned int length) |
| 1325 | { | 1325 | { |
| 1326 | int to_release = 0; | 1326 | int to_release = 0, contiguous_blks = 0; |
| 1327 | struct buffer_head *head, *bh; | 1327 | struct buffer_head *head, *bh; |
| 1328 | unsigned int curr_off = 0; | 1328 | unsigned int curr_off = 0; |
| 1329 | struct inode *inode = page->mapping->host; | 1329 | struct inode *inode = page->mapping->host; |
| @@ -1344,14 +1344,23 @@ static void ext4_da_page_release_reservation(struct page *page, | |||
| 1344 | 1344 | ||
| 1345 | if ((offset <= curr_off) && (buffer_delay(bh))) { | 1345 | if ((offset <= curr_off) && (buffer_delay(bh))) { |
| 1346 | to_release++; | 1346 | to_release++; |
| 1347 | contiguous_blks++; | ||
| 1347 | clear_buffer_delay(bh); | 1348 | clear_buffer_delay(bh); |
| 1349 | } else if (contiguous_blks) { | ||
| 1350 | lblk = page->index << | ||
| 1351 | (PAGE_CACHE_SHIFT - inode->i_blkbits); | ||
| 1352 | lblk += (curr_off >> inode->i_blkbits) - | ||
| 1353 | contiguous_blks; | ||
| 1354 | ext4_es_remove_extent(inode, lblk, contiguous_blks); | ||
| 1355 | contiguous_blks = 0; | ||
| 1348 | } | 1356 | } |
| 1349 | curr_off = next_off; | 1357 | curr_off = next_off; |
| 1350 | } while ((bh = bh->b_this_page) != head); | 1358 | } while ((bh = bh->b_this_page) != head); |
| 1351 | 1359 | ||
| 1352 | if (to_release) { | 1360 | if (contiguous_blks) { |
| 1353 | lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); | 1361 | lblk = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); |
| 1354 | ext4_es_remove_extent(inode, lblk, to_release); | 1362 | lblk += (curr_off >> inode->i_blkbits) - contiguous_blks; |
| 1363 | ext4_es_remove_extent(inode, lblk, contiguous_blks); | ||
| 1355 | } | 1364 | } |
| 1356 | 1365 | ||
| 1357 | /* If we have released all the blocks belonging to a cluster, then we | 1366 | /* If we have released all the blocks belonging to a cluster, then we |
| @@ -4344,7 +4353,12 @@ static void ext4_update_other_inodes_time(struct super_block *sb, | |||
| 4344 | int inode_size = EXT4_INODE_SIZE(sb); | 4353 | int inode_size = EXT4_INODE_SIZE(sb); |
| 4345 | 4354 | ||
| 4346 | oi.orig_ino = orig_ino; | 4355 | oi.orig_ino = orig_ino; |
| 4347 | ino = (orig_ino & ~(inodes_per_block - 1)) + 1; | 4356 | /* |
| 4357 | * Calculate the first inode in the inode table block. Inode | ||
| 4358 | * numbers are one-based. That is, the first inode in a block | ||
| 4359 | * (assuming 4k blocks and 256 byte inodes) is (n*16 + 1). | ||
| 4360 | */ | ||
| 4361 | ino = ((orig_ino - 1) & ~(inodes_per_block - 1)) + 1; | ||
| 4348 | for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { | 4362 | for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) { |
| 4349 | if (ino == orig_ino) | 4363 | if (ino == orig_ino) |
| 4350 | continue; | 4364 | continue; |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index cb8451246b30..1346cfa355d0 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
| @@ -755,7 +755,6 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 755 | return err; | 755 | return err; |
| 756 | } | 756 | } |
| 757 | case EXT4_IOC_MOVE_EXT: | 757 | case EXT4_IOC_MOVE_EXT: |
| 758 | case FITRIM: | ||
| 759 | case EXT4_IOC_RESIZE_FS: | 758 | case EXT4_IOC_RESIZE_FS: |
| 760 | case EXT4_IOC_PRECACHE_EXTENTS: | 759 | case EXT4_IOC_PRECACHE_EXTENTS: |
| 761 | case EXT4_IOC_SET_ENCRYPTION_POLICY: | 760 | case EXT4_IOC_SET_ENCRYPTION_POLICY: |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index f6aedf88da43..34b610ea5030 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -4816,18 +4816,12 @@ do_more: | |||
| 4816 | /* | 4816 | /* |
| 4817 | * blocks being freed are metadata. these blocks shouldn't | 4817 | * blocks being freed are metadata. these blocks shouldn't |
| 4818 | * be used until this transaction is committed | 4818 | * be used until this transaction is committed |
| 4819 | * | ||
| 4820 | * We use __GFP_NOFAIL because ext4_free_blocks() is not allowed | ||
| 4821 | * to fail. | ||
| 4819 | */ | 4822 | */ |
| 4820 | retry: | 4823 | new_entry = kmem_cache_alloc(ext4_free_data_cachep, |
| 4821 | new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); | 4824 | GFP_NOFS|__GFP_NOFAIL); |
| 4822 | if (!new_entry) { | ||
| 4823 | /* | ||
| 4824 | * We use a retry loop because | ||
| 4825 | * ext4_free_blocks() is not allowed to fail. | ||
| 4826 | */ | ||
| 4827 | cond_resched(); | ||
| 4828 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
| 4829 | goto retry; | ||
| 4830 | } | ||
| 4831 | new_entry->efd_start_cluster = bit; | 4825 | new_entry->efd_start_cluster = bit; |
| 4832 | new_entry->efd_group = block_group; | 4826 | new_entry->efd_group = block_group; |
| 4833 | new_entry->efd_count = count_clusters; | 4827 | new_entry->efd_count = count_clusters; |
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index b52374e42102..6163ad21cb0e 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c | |||
| @@ -620,6 +620,7 @@ int ext4_ind_migrate(struct inode *inode) | |||
| 620 | struct ext4_inode_info *ei = EXT4_I(inode); | 620 | struct ext4_inode_info *ei = EXT4_I(inode); |
| 621 | struct ext4_extent *ex; | 621 | struct ext4_extent *ex; |
| 622 | unsigned int i, len; | 622 | unsigned int i, len; |
| 623 | ext4_lblk_t start, end; | ||
| 623 | ext4_fsblk_t blk; | 624 | ext4_fsblk_t blk; |
| 624 | handle_t *handle; | 625 | handle_t *handle; |
| 625 | int ret; | 626 | int ret; |
| @@ -633,6 +634,14 @@ int ext4_ind_migrate(struct inode *inode) | |||
| 633 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) | 634 | EXT4_FEATURE_RO_COMPAT_BIGALLOC)) |
| 634 | return -EOPNOTSUPP; | 635 | return -EOPNOTSUPP; |
| 635 | 636 | ||
| 637 | /* | ||
| 638 | * In order to get correct extent info, force all delayed allocation | ||
| 639 | * blocks to be allocated, otherwise delayed allocation blocks may not | ||
| 640 | * be reflected and bypass the checks on extent header. | ||
| 641 | */ | ||
| 642 | if (test_opt(inode->i_sb, DELALLOC)) | ||
| 643 | ext4_alloc_da_blocks(inode); | ||
| 644 | |||
| 636 | handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); | 645 | handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1); |
| 637 | if (IS_ERR(handle)) | 646 | if (IS_ERR(handle)) |
| 638 | return PTR_ERR(handle); | 647 | return PTR_ERR(handle); |
| @@ -650,11 +659,13 @@ int ext4_ind_migrate(struct inode *inode) | |||
| 650 | goto errout; | 659 | goto errout; |
| 651 | } | 660 | } |
| 652 | if (eh->eh_entries == 0) | 661 | if (eh->eh_entries == 0) |
| 653 | blk = len = 0; | 662 | blk = len = start = end = 0; |
| 654 | else { | 663 | else { |
| 655 | len = le16_to_cpu(ex->ee_len); | 664 | len = le16_to_cpu(ex->ee_len); |
| 656 | blk = ext4_ext_pblock(ex); | 665 | blk = ext4_ext_pblock(ex); |
| 657 | if (len > EXT4_NDIR_BLOCKS) { | 666 | start = le32_to_cpu(ex->ee_block); |
| 667 | end = start + len - 1; | ||
| 668 | if (end >= EXT4_NDIR_BLOCKS) { | ||
| 658 | ret = -EOPNOTSUPP; | 669 | ret = -EOPNOTSUPP; |
| 659 | goto errout; | 670 | goto errout; |
| 660 | } | 671 | } |
| @@ -662,7 +673,7 @@ int ext4_ind_migrate(struct inode *inode) | |||
| 662 | 673 | ||
| 663 | ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); | 674 | ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS); |
| 664 | memset(ei->i_data, 0, sizeof(ei->i_data)); | 675 | memset(ei->i_data, 0, sizeof(ei->i_data)); |
| 665 | for (i=0; i < len; i++) | 676 | for (i = start; i <= end; i++) |
| 666 | ei->i_data[i] = cpu_to_le32(blk++); | 677 | ei->i_data[i] = cpu_to_le32(blk++); |
| 667 | ext4_mark_inode_dirty(handle, inode); | 678 | ext4_mark_inode_dirty(handle, inode); |
| 668 | errout: | 679 | errout: |
diff --git a/fs/hpfs/alloc.c b/fs/hpfs/alloc.c index f005046e1591..d6a4b55d2ab0 100644 --- a/fs/hpfs/alloc.c +++ b/fs/hpfs/alloc.c | |||
| @@ -484,3 +484,98 @@ struct anode *hpfs_alloc_anode(struct super_block *s, secno near, anode_secno *a | |||
| 484 | a->btree.first_free = cpu_to_le16(8); | 484 | a->btree.first_free = cpu_to_le16(8); |
| 485 | return a; | 485 | return a; |
| 486 | } | 486 | } |
| 487 | |||
| 488 | static unsigned find_run(__le32 *bmp, unsigned *idx) | ||
| 489 | { | ||
| 490 | unsigned len; | ||
| 491 | while (tstbits(bmp, *idx, 1)) { | ||
| 492 | (*idx)++; | ||
| 493 | if (unlikely(*idx >= 0x4000)) | ||
| 494 | return 0; | ||
| 495 | } | ||
| 496 | len = 1; | ||
| 497 | while (!tstbits(bmp, *idx + len, 1)) | ||
| 498 | len++; | ||
| 499 | return len; | ||
| 500 | } | ||
| 501 | |||
| 502 | static int do_trim(struct super_block *s, secno start, unsigned len, secno limit_start, secno limit_end, unsigned minlen, unsigned *result) | ||
| 503 | { | ||
| 504 | int err; | ||
| 505 | secno end; | ||
| 506 | if (fatal_signal_pending(current)) | ||
| 507 | return -EINTR; | ||
| 508 | end = start + len; | ||
| 509 | if (start < limit_start) | ||
| 510 | start = limit_start; | ||
| 511 | if (end > limit_end) | ||
| 512 | end = limit_end; | ||
| 513 | if (start >= end) | ||
| 514 | return 0; | ||
| 515 | if (end - start < minlen) | ||
| 516 | return 0; | ||
| 517 | err = sb_issue_discard(s, start, end - start, GFP_NOFS, 0); | ||
| 518 | if (err) | ||
| 519 | return err; | ||
| 520 | *result += end - start; | ||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | int hpfs_trim_fs(struct super_block *s, u64 start, u64 end, u64 minlen, unsigned *result) | ||
| 525 | { | ||
| 526 | int err = 0; | ||
| 527 | struct hpfs_sb_info *sbi = hpfs_sb(s); | ||
| 528 | unsigned idx, len, start_bmp, end_bmp; | ||
| 529 | __le32 *bmp; | ||
| 530 | struct quad_buffer_head qbh; | ||
| 531 | |||
| 532 | *result = 0; | ||
| 533 | if (!end || end > sbi->sb_fs_size) | ||
| 534 | end = sbi->sb_fs_size; | ||
| 535 | if (start >= sbi->sb_fs_size) | ||
| 536 | return 0; | ||
| 537 | if (minlen > 0x4000) | ||
| 538 | return 0; | ||
| 539 | if (start < sbi->sb_dirband_start + sbi->sb_dirband_size && end > sbi->sb_dirband_start) { | ||
| 540 | hpfs_lock(s); | ||
| 541 | if (s->s_flags & MS_RDONLY) { | ||
| 542 | err = -EROFS; | ||
| 543 | goto unlock_1; | ||
| 544 | } | ||
| 545 | if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) { | ||
| 546 | err = -EIO; | ||
| 547 | goto unlock_1; | ||
| 548 | } | ||
| 549 | idx = 0; | ||
| 550 | while ((len = find_run(bmp, &idx)) && !err) { | ||
| 551 | err = do_trim(s, sbi->sb_dirband_start + idx * 4, len * 4, start, end, minlen, result); | ||
| 552 | idx += len; | ||
| 553 | } | ||
| 554 | hpfs_brelse4(&qbh); | ||
| 555 | unlock_1: | ||
| 556 | hpfs_unlock(s); | ||
| 557 | } | ||
| 558 | start_bmp = start >> 14; | ||
| 559 | end_bmp = (end + 0x3fff) >> 14; | ||
| 560 | while (start_bmp < end_bmp && !err) { | ||
| 561 | hpfs_lock(s); | ||
| 562 | if (s->s_flags & MS_RDONLY) { | ||
| 563 | err = -EROFS; | ||
| 564 | goto unlock_2; | ||
| 565 | } | ||
| 566 | if (!(bmp = hpfs_map_bitmap(s, start_bmp, &qbh, "trim"))) { | ||
| 567 | err = -EIO; | ||
| 568 | goto unlock_2; | ||
| 569 | } | ||
| 570 | idx = 0; | ||
| 571 | while ((len = find_run(bmp, &idx)) && !err) { | ||
| 572 | err = do_trim(s, (start_bmp << 14) + idx, len, start, end, minlen, result); | ||
| 573 | idx += len; | ||
| 574 | } | ||
| 575 | hpfs_brelse4(&qbh); | ||
| 576 | unlock_2: | ||
| 577 | hpfs_unlock(s); | ||
| 578 | start_bmp++; | ||
| 579 | } | ||
| 580 | return err; | ||
| 581 | } | ||
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c index 2a8e07425de0..dc540bfcee1d 100644 --- a/fs/hpfs/dir.c +++ b/fs/hpfs/dir.c | |||
| @@ -327,4 +327,5 @@ const struct file_operations hpfs_dir_ops = | |||
| 327 | .iterate = hpfs_readdir, | 327 | .iterate = hpfs_readdir, |
| 328 | .release = hpfs_dir_release, | 328 | .release = hpfs_dir_release, |
| 329 | .fsync = hpfs_file_fsync, | 329 | .fsync = hpfs_file_fsync, |
| 330 | .unlocked_ioctl = hpfs_ioctl, | ||
| 330 | }; | 331 | }; |
diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 6d8cfe9b52d6..7ca28d604bf7 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c | |||
| @@ -203,6 +203,7 @@ const struct file_operations hpfs_file_ops = | |||
| 203 | .release = hpfs_file_release, | 203 | .release = hpfs_file_release, |
| 204 | .fsync = hpfs_file_fsync, | 204 | .fsync = hpfs_file_fsync, |
| 205 | .splice_read = generic_file_splice_read, | 205 | .splice_read = generic_file_splice_read, |
| 206 | .unlocked_ioctl = hpfs_ioctl, | ||
| 206 | }; | 207 | }; |
| 207 | 208 | ||
| 208 | const struct inode_operations hpfs_file_iops = | 209 | const struct inode_operations hpfs_file_iops = |
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h index bb04b58d1d69..c4867b5116dd 100644 --- a/fs/hpfs/hpfs_fn.h +++ b/fs/hpfs/hpfs_fn.h | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 19 | #include <linux/buffer_head.h> | 19 | #include <linux/buffer_head.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/sched.h> | ||
| 22 | #include <linux/blkdev.h> | ||
| 21 | #include <asm/unaligned.h> | 23 | #include <asm/unaligned.h> |
| 22 | 24 | ||
| 23 | #include "hpfs.h" | 25 | #include "hpfs.h" |
| @@ -200,6 +202,7 @@ void hpfs_free_dnode(struct super_block *, secno); | |||
| 200 | struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *); | 202 | struct dnode *hpfs_alloc_dnode(struct super_block *, secno, dnode_secno *, struct quad_buffer_head *); |
| 201 | struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **); | 203 | struct fnode *hpfs_alloc_fnode(struct super_block *, secno, fnode_secno *, struct buffer_head **); |
| 202 | struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); | 204 | struct anode *hpfs_alloc_anode(struct super_block *, secno, anode_secno *, struct buffer_head **); |
| 205 | int hpfs_trim_fs(struct super_block *, u64, u64, u64, unsigned *); | ||
| 203 | 206 | ||
| 204 | /* anode.c */ | 207 | /* anode.c */ |
| 205 | 208 | ||
| @@ -318,6 +321,7 @@ __printf(2, 3) | |||
| 318 | void hpfs_error(struct super_block *, const char *, ...); | 321 | void hpfs_error(struct super_block *, const char *, ...); |
| 319 | int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *); | 322 | int hpfs_stop_cycles(struct super_block *, int, int *, int *, char *); |
| 320 | unsigned hpfs_get_free_dnodes(struct super_block *); | 323 | unsigned hpfs_get_free_dnodes(struct super_block *); |
| 324 | long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg); | ||
| 321 | 325 | ||
| 322 | /* | 326 | /* |
| 323 | * local time (HPFS) to GMT (Unix) | 327 | * local time (HPFS) to GMT (Unix) |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 7cd00d3a7c9b..68a9bed05628 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
| @@ -52,17 +52,20 @@ static void unmark_dirty(struct super_block *s) | |||
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | /* Filesystem error... */ | 54 | /* Filesystem error... */ |
| 55 | static char err_buf[1024]; | ||
| 56 | |||
| 57 | void hpfs_error(struct super_block *s, const char *fmt, ...) | 55 | void hpfs_error(struct super_block *s, const char *fmt, ...) |
| 58 | { | 56 | { |
| 57 | struct va_format vaf; | ||
| 59 | va_list args; | 58 | va_list args; |
| 60 | 59 | ||
| 61 | va_start(args, fmt); | 60 | va_start(args, fmt); |
| 62 | vsnprintf(err_buf, sizeof(err_buf), fmt, args); | 61 | |
| 62 | vaf.fmt = fmt; | ||
| 63 | vaf.va = &args; | ||
| 64 | |||
| 65 | pr_err("filesystem error: %pV", &vaf); | ||
| 66 | |||
| 63 | va_end(args); | 67 | va_end(args); |
| 64 | 68 | ||
| 65 | pr_err("filesystem error: %s", err_buf); | ||
| 66 | if (!hpfs_sb(s)->sb_was_error) { | 69 | if (!hpfs_sb(s)->sb_was_error) { |
| 67 | if (hpfs_sb(s)->sb_err == 2) { | 70 | if (hpfs_sb(s)->sb_err == 2) { |
| 68 | pr_cont("; crashing the system because you wanted it\n"); | 71 | pr_cont("; crashing the system because you wanted it\n"); |
| @@ -196,12 +199,39 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 196 | return 0; | 199 | return 0; |
| 197 | } | 200 | } |
| 198 | 201 | ||
| 202 | |||
| 203 | long hpfs_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||
| 204 | { | ||
| 205 | switch (cmd) { | ||
| 206 | case FITRIM: { | ||
| 207 | struct fstrim_range range; | ||
| 208 | secno n_trimmed; | ||
| 209 | int r; | ||
| 210 | if (!capable(CAP_SYS_ADMIN)) | ||
| 211 | return -EPERM; | ||
| 212 | if (copy_from_user(&range, (struct fstrim_range __user *)arg, sizeof(range))) | ||
| 213 | return -EFAULT; | ||
| 214 | r = hpfs_trim_fs(file_inode(file)->i_sb, range.start >> 9, (range.start + range.len) >> 9, (range.minlen + 511) >> 9, &n_trimmed); | ||
| 215 | if (r) | ||
| 216 | return r; | ||
| 217 | range.len = (u64)n_trimmed << 9; | ||
| 218 | if (copy_to_user((struct fstrim_range __user *)arg, &range, sizeof(range))) | ||
| 219 | return -EFAULT; | ||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | default: { | ||
| 223 | return -ENOIOCTLCMD; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 228 | |||
| 199 | static struct kmem_cache * hpfs_inode_cachep; | 229 | static struct kmem_cache * hpfs_inode_cachep; |
| 200 | 230 | ||
| 201 | static struct inode *hpfs_alloc_inode(struct super_block *sb) | 231 | static struct inode *hpfs_alloc_inode(struct super_block *sb) |
| 202 | { | 232 | { |
| 203 | struct hpfs_inode_info *ei; | 233 | struct hpfs_inode_info *ei; |
| 204 | ei = (struct hpfs_inode_info *)kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS); | 234 | ei = kmem_cache_alloc(hpfs_inode_cachep, GFP_NOFS); |
| 205 | if (!ei) | 235 | if (!ei) |
| 206 | return NULL; | 236 | return NULL; |
| 207 | ei->vfs_inode.i_version = 1; | 237 | ei->vfs_inode.i_version = 1; |
| @@ -424,11 +454,14 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data) | |||
| 424 | int o; | 454 | int o; |
| 425 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 455 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
| 426 | char *new_opts = kstrdup(data, GFP_KERNEL); | 456 | char *new_opts = kstrdup(data, GFP_KERNEL); |
| 427 | 457 | ||
| 458 | if (!new_opts) | ||
| 459 | return -ENOMEM; | ||
| 460 | |||
| 428 | sync_filesystem(s); | 461 | sync_filesystem(s); |
| 429 | 462 | ||
| 430 | *flags |= MS_NOATIME; | 463 | *flags |= MS_NOATIME; |
| 431 | 464 | ||
| 432 | hpfs_lock(s); | 465 | hpfs_lock(s); |
| 433 | uid = sbi->sb_uid; gid = sbi->sb_gid; | 466 | uid = sbi->sb_uid; gid = sbi->sb_gid; |
| 434 | umask = 0777 & ~sbi->sb_mode; | 467 | umask = 0777 & ~sbi->sb_mode; |
diff --git a/fs/jfs/ioctl.c b/fs/jfs/ioctl.c index 93a1232894f6..8db8b7d61e40 100644 --- a/fs/jfs/ioctl.c +++ b/fs/jfs/ioctl.c | |||
| @@ -180,9 +180,6 @@ long jfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 180 | case JFS_IOC_SETFLAGS32: | 180 | case JFS_IOC_SETFLAGS32: |
| 181 | cmd = JFS_IOC_SETFLAGS; | 181 | cmd = JFS_IOC_SETFLAGS; |
| 182 | break; | 182 | break; |
| 183 | case FITRIM: | ||
| 184 | cmd = FITRIM; | ||
| 185 | break; | ||
| 186 | } | 183 | } |
| 187 | return jfs_ioctl(filp, cmd, arg); | 184 | return jfs_ioctl(filp, cmd, arg); |
| 188 | } | 185 | } |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 9a20e513d7eb..aba43811d6ef 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -1369,7 +1369,6 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
| 1369 | case NILFS_IOCTL_SYNC: | 1369 | case NILFS_IOCTL_SYNC: |
| 1370 | case NILFS_IOCTL_RESIZE: | 1370 | case NILFS_IOCTL_RESIZE: |
| 1371 | case NILFS_IOCTL_SET_ALLOC_RANGE: | 1371 | case NILFS_IOCTL_SET_ALLOC_RANGE: |
| 1372 | case FITRIM: | ||
| 1373 | break; | 1372 | break; |
| 1374 | default: | 1373 | default: |
| 1375 | return -ENOIOCTLCMD; | 1374 | return -ENOIOCTLCMD; |
diff --git a/fs/ocfs2/ioctl.c b/fs/ocfs2/ioctl.c index 53e6c40ed4c6..3cb097ccce60 100644 --- a/fs/ocfs2/ioctl.c +++ b/fs/ocfs2/ioctl.c | |||
| @@ -980,7 +980,6 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
| 980 | case OCFS2_IOC_GROUP_EXTEND: | 980 | case OCFS2_IOC_GROUP_EXTEND: |
| 981 | case OCFS2_IOC_GROUP_ADD: | 981 | case OCFS2_IOC_GROUP_ADD: |
| 982 | case OCFS2_IOC_GROUP_ADD64: | 982 | case OCFS2_IOC_GROUP_ADD64: |
| 983 | case FITRIM: | ||
| 984 | break; | 983 | break; |
| 985 | case OCFS2_IOC_REFLINK: | 984 | case OCFS2_IOC_REFLINK: |
| 986 | if (copy_from_user(&args, argp, sizeof(args))) | 985 | if (copy_from_user(&args, argp, sizeof(args))) |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index f140e3dbfb7b..d9da5a4e9382 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
| @@ -343,6 +343,9 @@ struct inode *ovl_d_select_inode(struct dentry *dentry, unsigned file_flags) | |||
| 343 | struct path realpath; | 343 | struct path realpath; |
| 344 | enum ovl_path_type type; | 344 | enum ovl_path_type type; |
| 345 | 345 | ||
| 346 | if (d_is_dir(dentry)) | ||
| 347 | return d_backing_inode(dentry); | ||
| 348 | |||
| 346 | type = ovl_path_real(dentry, &realpath); | 349 | type = ovl_path_real(dentry, &realpath); |
| 347 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { | 350 | if (ovl_open_need_copy_up(file_flags, type, realpath.dentry)) { |
| 348 | err = ovl_want_write(dentry); | 351 | err = ovl_want_write(dentry); |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index c471dfc93b71..d2445fa9999f 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -58,6 +58,19 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) | |||
| 58 | acpi_fwnode_handle(adev) : NULL) | 58 | acpi_fwnode_handle(adev) : NULL) |
| 59 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) | 59 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) |
| 60 | 60 | ||
| 61 | /** | ||
| 62 | * ACPI_DEVICE_CLASS - macro used to describe an ACPI device with | ||
| 63 | * the PCI-defined class-code information | ||
| 64 | * | ||
| 65 | * @_cls : the class, subclass, prog-if triple for this device | ||
| 66 | * @_msk : the class mask for this device | ||
| 67 | * | ||
| 68 | * This macro is used to create a struct acpi_device_id that matches a | ||
| 69 | * specific PCI class. The .id and .driver_data fields will be left | ||
| 70 | * initialized with the default value. | ||
| 71 | */ | ||
| 72 | #define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (_cls), .cls_msk = (_msk), | ||
| 73 | |||
| 61 | static inline bool has_acpi_companion(struct device *dev) | 74 | static inline bool has_acpi_companion(struct device *dev) |
| 62 | { | 75 | { |
| 63 | return is_acpi_node(dev->fwnode); | 76 | return is_acpi_node(dev->fwnode); |
| @@ -309,9 +322,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n, | |||
| 309 | 322 | ||
| 310 | int acpi_resources_are_enforced(void); | 323 | int acpi_resources_are_enforced(void); |
| 311 | 324 | ||
| 312 | int acpi_reserve_region(u64 start, unsigned int length, u8 space_id, | ||
| 313 | unsigned long flags, char *desc); | ||
| 314 | |||
| 315 | #ifdef CONFIG_HIBERNATION | 325 | #ifdef CONFIG_HIBERNATION |
| 316 | void __init acpi_no_s4_hw_signature(void); | 326 | void __init acpi_no_s4_hw_signature(void); |
| 317 | #endif | 327 | #endif |
| @@ -446,6 +456,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *); | |||
| 446 | #define ACPI_COMPANION(dev) (NULL) | 456 | #define ACPI_COMPANION(dev) (NULL) |
| 447 | #define ACPI_COMPANION_SET(dev, adev) do { } while (0) | 457 | #define ACPI_COMPANION_SET(dev, adev) do { } while (0) |
| 448 | #define ACPI_HANDLE(dev) (NULL) | 458 | #define ACPI_HANDLE(dev) (NULL) |
| 459 | #define ACPI_DEVICE_CLASS(_cls, _msk) .cls = (0), .cls_msk = (0), | ||
| 449 | 460 | ||
| 450 | struct fwnode_handle; | 461 | struct fwnode_handle; |
| 451 | 462 | ||
| @@ -507,13 +518,6 @@ static inline int acpi_check_region(resource_size_t start, resource_size_t n, | |||
| 507 | return 0; | 518 | return 0; |
| 508 | } | 519 | } |
| 509 | 520 | ||
| 510 | static inline int acpi_reserve_region(u64 start, unsigned int length, | ||
| 511 | u8 space_id, unsigned long flags, | ||
| 512 | char *desc) | ||
| 513 | { | ||
| 514 | return -ENXIO; | ||
| 515 | } | ||
| 516 | |||
| 517 | struct acpi_table_header; | 521 | struct acpi_table_header; |
| 518 | static inline int acpi_table_parse(char *id, | 522 | static inline int acpi_table_parse(char *id, |
| 519 | int (*handler)(struct acpi_table_header *)) | 523 | int (*handler)(struct acpi_table_header *)) |
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 73b45225a7ca..e6797ded700e 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h | |||
| @@ -317,6 +317,13 @@ sb_getblk(struct super_block *sb, sector_t block) | |||
| 317 | return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE); | 317 | return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | |||
| 321 | static inline struct buffer_head * | ||
| 322 | sb_getblk_gfp(struct super_block *sb, sector_t block, gfp_t gfp) | ||
| 323 | { | ||
| 324 | return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, gfp); | ||
| 325 | } | ||
| 326 | |||
| 320 | static inline struct buffer_head * | 327 | static inline struct buffer_head * |
| 321 | sb_find_get_block(struct super_block *sb, sector_t block) | 328 | sb_find_get_block(struct super_block *sb, sector_t block) |
| 322 | { | 329 | { |
diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index e15499422fdc..37753278987a 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <linux/radix-tree.h> | 8 | #include <linux/radix-tree.h> |
| 9 | #include <linux/uio.h> | 9 | #include <linux/uio.h> |
| 10 | #include <linux/workqueue.h> | 10 | #include <linux/workqueue.h> |
| 11 | #include <net/net_namespace.h> | ||
| 11 | 12 | ||
| 12 | #include <linux/ceph/types.h> | 13 | #include <linux/ceph/types.h> |
| 13 | #include <linux/ceph/buffer.h> | 14 | #include <linux/ceph/buffer.h> |
| @@ -56,6 +57,7 @@ struct ceph_messenger { | |||
| 56 | struct ceph_entity_addr my_enc_addr; | 57 | struct ceph_entity_addr my_enc_addr; |
| 57 | 58 | ||
| 58 | atomic_t stopping; | 59 | atomic_t stopping; |
| 60 | possible_net_t net; | ||
| 59 | bool nocrc; | 61 | bool nocrc; |
| 60 | bool tcp_nodelay; | 62 | bool tcp_nodelay; |
| 61 | 63 | ||
| @@ -267,6 +269,7 @@ extern void ceph_messenger_init(struct ceph_messenger *msgr, | |||
| 267 | u64 required_features, | 269 | u64 required_features, |
| 268 | bool nocrc, | 270 | bool nocrc, |
| 269 | bool tcp_nodelay); | 271 | bool tcp_nodelay); |
| 272 | extern void ceph_messenger_fini(struct ceph_messenger *msgr); | ||
| 270 | 273 | ||
| 271 | extern void ceph_con_init(struct ceph_connection *con, void *private, | 274 | extern void ceph_con_init(struct ceph_connection *con, void *private, |
| 272 | const struct ceph_connection_operations *ops, | 275 | const struct ceph_connection_operations *ops, |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 7f8ad9593da7..e08a6ae7c0a4 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
| @@ -17,11 +17,11 @@ | |||
| 17 | # define __release(x) __context__(x,-1) | 17 | # define __release(x) __context__(x,-1) |
| 18 | # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) | 18 | # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) |
| 19 | # define __percpu __attribute__((noderef, address_space(3))) | 19 | # define __percpu __attribute__((noderef, address_space(3))) |
| 20 | # define __pmem __attribute__((noderef, address_space(5))) | ||
| 20 | #ifdef CONFIG_SPARSE_RCU_POINTER | 21 | #ifdef CONFIG_SPARSE_RCU_POINTER |
| 21 | # define __rcu __attribute__((noderef, address_space(4))) | 22 | # define __rcu __attribute__((noderef, address_space(4))) |
| 22 | #else | 23 | #else |
| 23 | # define __rcu | 24 | # define __rcu |
| 24 | # define __pmem __attribute__((noderef, address_space(5))) | ||
| 25 | #endif | 25 | #endif |
| 26 | extern void __chk_user_ptr(const volatile void __user *); | 26 | extern void __chk_user_ptr(const volatile void __user *); |
| 27 | extern void __chk_io_ptr(const volatile void __iomem *); | 27 | extern void __chk_io_ptr(const volatile void __iomem *); |
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 624a668e61f1..fcea4e48e21f 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h | |||
| @@ -87,7 +87,12 @@ struct irq_desc { | |||
| 87 | const char *name; | 87 | const char *name; |
| 88 | } ____cacheline_internodealigned_in_smp; | 88 | } ____cacheline_internodealigned_in_smp; |
| 89 | 89 | ||
| 90 | #ifndef CONFIG_SPARSE_IRQ | 90 | #ifdef CONFIG_SPARSE_IRQ |
| 91 | extern void irq_lock_sparse(void); | ||
| 92 | extern void irq_unlock_sparse(void); | ||
| 93 | #else | ||
| 94 | static inline void irq_lock_sparse(void) { } | ||
| 95 | static inline void irq_unlock_sparse(void) { } | ||
| 91 | extern struct irq_desc irq_desc[NR_IRQS]; | 96 | extern struct irq_desc irq_desc[NR_IRQS]; |
| 92 | #endif | 97 | #endif |
| 93 | 98 | ||
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 8183d6640ca7..34f25b7bf642 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
| @@ -189,6 +189,8 @@ struct css_device_id { | |||
| 189 | struct acpi_device_id { | 189 | struct acpi_device_id { |
| 190 | __u8 id[ACPI_ID_LEN]; | 190 | __u8 id[ACPI_ID_LEN]; |
| 191 | kernel_ulong_t driver_data; | 191 | kernel_ulong_t driver_data; |
| 192 | __u32 cls; | ||
| 193 | __u32 cls_msk; | ||
| 192 | }; | 194 | }; |
| 193 | 195 | ||
| 194 | #define PNP_ID_LEN 8 | 196 | #define PNP_ID_LEN 8 |
diff --git a/include/linux/tick.h b/include/linux/tick.h index 3741ba1a652c..edbfc9a5293e 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h | |||
| @@ -67,10 +67,13 @@ extern void tick_broadcast_control(enum tick_broadcast_mode mode); | |||
| 67 | static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { } | 67 | static inline void tick_broadcast_control(enum tick_broadcast_mode mode) { } |
| 68 | #endif /* BROADCAST */ | 68 | #endif /* BROADCAST */ |
| 69 | 69 | ||
| 70 | #if defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) && defined(CONFIG_TICK_ONESHOT) | 70 | #ifdef CONFIG_GENERIC_CLOCKEVENTS |
| 71 | extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state); | 71 | extern int tick_broadcast_oneshot_control(enum tick_broadcast_state state); |
| 72 | #else | 72 | #else |
| 73 | static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) { return 0; } | 73 | static inline int tick_broadcast_oneshot_control(enum tick_broadcast_state state) |
| 74 | { | ||
| 75 | return 0; | ||
| 76 | } | ||
| 74 | #endif | 77 | #endif |
| 75 | 78 | ||
| 76 | static inline void tick_broadcast_enable(void) | 79 | static inline void tick_broadcast_enable(void) |
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h index 3aa72e648650..6e191e4e6ab6 100644 --- a/include/linux/timekeeping.h +++ b/include/linux/timekeeping.h | |||
| @@ -145,7 +145,6 @@ static inline void getboottime(struct timespec *ts) | |||
| 145 | } | 145 | } |
| 146 | #endif | 146 | #endif |
| 147 | 147 | ||
| 148 | #define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) | ||
| 149 | #define ktime_get_real_ts64(ts) getnstimeofday64(ts) | 148 | #define ktime_get_real_ts64(ts) getnstimeofday64(ts) |
| 150 | 149 | ||
| 151 | /* | 150 | /* |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 09c65640cad6..e85bdfd15fed 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -1021,8 +1021,7 @@ static int audit_log_single_execve_arg(struct audit_context *context, | |||
| 1021 | * for strings that are too long, we should not have created | 1021 | * for strings that are too long, we should not have created |
| 1022 | * any. | 1022 | * any. |
| 1023 | */ | 1023 | */ |
| 1024 | if (unlikely((len == 0) || len > MAX_ARG_STRLEN - 1)) { | 1024 | if (WARN_ON_ONCE(len < 0 || len > MAX_ARG_STRLEN - 1)) { |
| 1025 | WARN_ON(1); | ||
| 1026 | send_sig(SIGKILL, current, 0); | 1025 | send_sig(SIGKILL, current, 0); |
| 1027 | return -1; | 1026 | return -1; |
| 1028 | } | 1027 | } |
diff --git a/kernel/cpu.c b/kernel/cpu.c index 9c9c9fab16cc..6a374544d495 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
| 22 | #include <linux/lockdep.h> | 22 | #include <linux/lockdep.h> |
| 23 | #include <linux/tick.h> | 23 | #include <linux/tick.h> |
| 24 | #include <linux/irq.h> | ||
| 24 | #include <trace/events/power.h> | 25 | #include <trace/events/power.h> |
| 25 | 26 | ||
| 26 | #include "smpboot.h" | 27 | #include "smpboot.h" |
| @@ -392,13 +393,19 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) | |||
| 392 | smpboot_park_threads(cpu); | 393 | smpboot_park_threads(cpu); |
| 393 | 394 | ||
| 394 | /* | 395 | /* |
| 395 | * So now all preempt/rcu users must observe !cpu_active(). | 396 | * Prevent irq alloc/free while the dying cpu reorganizes the |
| 397 | * interrupt affinities. | ||
| 396 | */ | 398 | */ |
| 399 | irq_lock_sparse(); | ||
| 397 | 400 | ||
| 401 | /* | ||
| 402 | * So now all preempt/rcu users must observe !cpu_active(). | ||
| 403 | */ | ||
| 398 | err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); | 404 | err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); |
| 399 | if (err) { | 405 | if (err) { |
| 400 | /* CPU didn't die: tell everyone. Can't complain. */ | 406 | /* CPU didn't die: tell everyone. Can't complain. */ |
| 401 | cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); | 407 | cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); |
| 408 | irq_unlock_sparse(); | ||
| 402 | goto out_release; | 409 | goto out_release; |
| 403 | } | 410 | } |
| 404 | BUG_ON(cpu_online(cpu)); | 411 | BUG_ON(cpu_online(cpu)); |
| @@ -415,6 +422,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) | |||
| 415 | smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */ | 422 | smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */ |
| 416 | per_cpu(cpu_dead_idle, cpu) = false; | 423 | per_cpu(cpu_dead_idle, cpu) = false; |
| 417 | 424 | ||
| 425 | /* Interrupts are moved away from the dying cpu, reenable alloc/free */ | ||
| 426 | irq_unlock_sparse(); | ||
| 427 | |||
| 418 | hotplug_cpu__broadcast_tick_pull(cpu); | 428 | hotplug_cpu__broadcast_tick_pull(cpu); |
| 419 | /* This actually kills the CPU. */ | 429 | /* This actually kills the CPU. */ |
| 420 | __cpu_die(cpu); | 430 | __cpu_die(cpu); |
| @@ -517,8 +527,18 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) | |||
| 517 | goto out_notify; | 527 | goto out_notify; |
| 518 | } | 528 | } |
| 519 | 529 | ||
| 530 | /* | ||
| 531 | * Some architectures have to walk the irq descriptors to | ||
| 532 | * setup the vector space for the cpu which comes online. | ||
| 533 | * Prevent irq alloc/free across the bringup. | ||
| 534 | */ | ||
| 535 | irq_lock_sparse(); | ||
| 536 | |||
| 520 | /* Arch-specific enabling code. */ | 537 | /* Arch-specific enabling code. */ |
| 521 | ret = __cpu_up(cpu, idle); | 538 | ret = __cpu_up(cpu, idle); |
| 539 | |||
| 540 | irq_unlock_sparse(); | ||
| 541 | |||
| 522 | if (ret != 0) | 542 | if (ret != 0) |
| 523 | goto out_notify; | 543 | goto out_notify; |
| 524 | BUG_ON(!cpu_online(cpu)); | 544 | BUG_ON(!cpu_online(cpu)); |
diff --git a/kernel/events/core.c b/kernel/events/core.c index e965cfae4207..d3dae3419b99 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -4358,14 +4358,6 @@ static void ring_buffer_wakeup(struct perf_event *event) | |||
| 4358 | rcu_read_unlock(); | 4358 | rcu_read_unlock(); |
| 4359 | } | 4359 | } |
| 4360 | 4360 | ||
| 4361 | static void rb_free_rcu(struct rcu_head *rcu_head) | ||
| 4362 | { | ||
| 4363 | struct ring_buffer *rb; | ||
| 4364 | |||
| 4365 | rb = container_of(rcu_head, struct ring_buffer, rcu_head); | ||
| 4366 | rb_free(rb); | ||
| 4367 | } | ||
| 4368 | |||
| 4369 | struct ring_buffer *ring_buffer_get(struct perf_event *event) | 4361 | struct ring_buffer *ring_buffer_get(struct perf_event *event) |
| 4370 | { | 4362 | { |
| 4371 | struct ring_buffer *rb; | 4363 | struct ring_buffer *rb; |
diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 2deb24c7a40d..2bbad9c1274c 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | struct ring_buffer { | 11 | struct ring_buffer { |
| 12 | atomic_t refcount; | 12 | atomic_t refcount; |
| 13 | struct rcu_head rcu_head; | 13 | struct rcu_head rcu_head; |
| 14 | struct irq_work irq_work; | ||
| 14 | #ifdef CONFIG_PERF_USE_VMALLOC | 15 | #ifdef CONFIG_PERF_USE_VMALLOC |
| 15 | struct work_struct work; | 16 | struct work_struct work; |
| 16 | int page_order; /* allocation order */ | 17 | int page_order; /* allocation order */ |
| @@ -55,6 +56,15 @@ struct ring_buffer { | |||
| 55 | }; | 56 | }; |
| 56 | 57 | ||
| 57 | extern void rb_free(struct ring_buffer *rb); | 58 | extern void rb_free(struct ring_buffer *rb); |
| 59 | |||
| 60 | static inline void rb_free_rcu(struct rcu_head *rcu_head) | ||
| 61 | { | ||
| 62 | struct ring_buffer *rb; | ||
| 63 | |||
| 64 | rb = container_of(rcu_head, struct ring_buffer, rcu_head); | ||
| 65 | rb_free(rb); | ||
| 66 | } | ||
| 67 | |||
| 58 | extern struct ring_buffer * | 68 | extern struct ring_buffer * |
| 59 | rb_alloc(int nr_pages, long watermark, int cpu, int flags); | 69 | rb_alloc(int nr_pages, long watermark, int cpu, int flags); |
| 60 | extern void perf_event_wakeup(struct perf_event *event); | 70 | extern void perf_event_wakeup(struct perf_event *event); |
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 96472824a752..b2be01b1aa9d 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
| @@ -221,6 +221,8 @@ void perf_output_end(struct perf_output_handle *handle) | |||
| 221 | rcu_read_unlock(); | 221 | rcu_read_unlock(); |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static void rb_irq_work(struct irq_work *work); | ||
| 225 | |||
| 224 | static void | 226 | static void |
| 225 | ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) | 227 | ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) |
| 226 | { | 228 | { |
| @@ -241,6 +243,16 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) | |||
| 241 | 243 | ||
| 242 | INIT_LIST_HEAD(&rb->event_list); | 244 | INIT_LIST_HEAD(&rb->event_list); |
| 243 | spin_lock_init(&rb->event_lock); | 245 | spin_lock_init(&rb->event_lock); |
| 246 | init_irq_work(&rb->irq_work, rb_irq_work); | ||
| 247 | } | ||
| 248 | |||
| 249 | static void ring_buffer_put_async(struct ring_buffer *rb) | ||
| 250 | { | ||
| 251 | if (!atomic_dec_and_test(&rb->refcount)) | ||
| 252 | return; | ||
| 253 | |||
| 254 | rb->rcu_head.next = (void *)rb; | ||
| 255 | irq_work_queue(&rb->irq_work); | ||
| 244 | } | 256 | } |
| 245 | 257 | ||
| 246 | /* | 258 | /* |
| @@ -319,7 +331,7 @@ err_put: | |||
| 319 | rb_free_aux(rb); | 331 | rb_free_aux(rb); |
| 320 | 332 | ||
| 321 | err: | 333 | err: |
| 322 | ring_buffer_put(rb); | 334 | ring_buffer_put_async(rb); |
| 323 | handle->event = NULL; | 335 | handle->event = NULL; |
| 324 | 336 | ||
| 325 | return NULL; | 337 | return NULL; |
| @@ -370,7 +382,7 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, | |||
| 370 | 382 | ||
| 371 | local_set(&rb->aux_nest, 0); | 383 | local_set(&rb->aux_nest, 0); |
| 372 | rb_free_aux(rb); | 384 | rb_free_aux(rb); |
| 373 | ring_buffer_put(rb); | 385 | ring_buffer_put_async(rb); |
| 374 | } | 386 | } |
| 375 | 387 | ||
| 376 | /* | 388 | /* |
| @@ -557,7 +569,18 @@ static void __rb_free_aux(struct ring_buffer *rb) | |||
| 557 | void rb_free_aux(struct ring_buffer *rb) | 569 | void rb_free_aux(struct ring_buffer *rb) |
| 558 | { | 570 | { |
| 559 | if (atomic_dec_and_test(&rb->aux_refcount)) | 571 | if (atomic_dec_and_test(&rb->aux_refcount)) |
| 572 | irq_work_queue(&rb->irq_work); | ||
| 573 | } | ||
| 574 | |||
| 575 | static void rb_irq_work(struct irq_work *work) | ||
| 576 | { | ||
| 577 | struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work); | ||
| 578 | |||
| 579 | if (!atomic_read(&rb->aux_refcount)) | ||
| 560 | __rb_free_aux(rb); | 580 | __rb_free_aux(rb); |
| 581 | |||
| 582 | if (rb->rcu_head.next == (void *)rb) | ||
| 583 | call_rcu(&rb->rcu_head, rb_free_rcu); | ||
| 561 | } | 584 | } |
| 562 | 585 | ||
| 563 | #ifndef CONFIG_PERF_USE_VMALLOC | 586 | #ifndef CONFIG_PERF_USE_VMALLOC |
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 4834ee828c41..61008b8433ab 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h | |||
| @@ -76,12 +76,8 @@ extern void unmask_threaded_irq(struct irq_desc *desc); | |||
| 76 | 76 | ||
| 77 | #ifdef CONFIG_SPARSE_IRQ | 77 | #ifdef CONFIG_SPARSE_IRQ |
| 78 | static inline void irq_mark_irq(unsigned int irq) { } | 78 | static inline void irq_mark_irq(unsigned int irq) { } |
| 79 | extern void irq_lock_sparse(void); | ||
| 80 | extern void irq_unlock_sparse(void); | ||
| 81 | #else | 79 | #else |
| 82 | extern void irq_mark_irq(unsigned int irq); | 80 | extern void irq_mark_irq(unsigned int irq); |
| 83 | static inline void irq_lock_sparse(void) { } | ||
| 84 | static inline void irq_unlock_sparse(void) { } | ||
| 85 | #endif | 81 | #endif |
| 86 | 82 | ||
| 87 | extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); | 83 | extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr); |
diff --git a/kernel/module.c b/kernel/module.c index 3e0e19763d24..4d2b82e610e2 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -3557,6 +3557,7 @@ static int load_module(struct load_info *info, const char __user *uargs, | |||
| 3557 | mutex_lock(&module_mutex); | 3557 | mutex_lock(&module_mutex); |
| 3558 | /* Unlink carefully: kallsyms could be walking list. */ | 3558 | /* Unlink carefully: kallsyms could be walking list. */ |
| 3559 | list_del_rcu(&mod->list); | 3559 | list_del_rcu(&mod->list); |
| 3560 | mod_tree_remove(mod); | ||
| 3560 | wake_up_all(&module_wq); | 3561 | wake_up_all(&module_wq); |
| 3561 | /* Wait for RCU-sched synchronizing before releasing mod->list. */ | 3562 | /* Wait for RCU-sched synchronizing before releasing mod->list. */ |
| 3562 | synchronize_sched(); | 3563 | synchronize_sched(); |
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 08ccc3da3ca0..50eb107f1198 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c | |||
| @@ -120,19 +120,25 @@ static int __clockevents_switch_state(struct clock_event_device *dev, | |||
| 120 | /* The clockevent device is getting replaced. Shut it down. */ | 120 | /* The clockevent device is getting replaced. Shut it down. */ |
| 121 | 121 | ||
| 122 | case CLOCK_EVT_STATE_SHUTDOWN: | 122 | case CLOCK_EVT_STATE_SHUTDOWN: |
| 123 | return dev->set_state_shutdown(dev); | 123 | if (dev->set_state_shutdown) |
| 124 | return dev->set_state_shutdown(dev); | ||
| 125 | return 0; | ||
| 124 | 126 | ||
| 125 | case CLOCK_EVT_STATE_PERIODIC: | 127 | case CLOCK_EVT_STATE_PERIODIC: |
| 126 | /* Core internal bug */ | 128 | /* Core internal bug */ |
| 127 | if (!(dev->features & CLOCK_EVT_FEAT_PERIODIC)) | 129 | if (!(dev->features & CLOCK_EVT_FEAT_PERIODIC)) |
| 128 | return -ENOSYS; | 130 | return -ENOSYS; |
| 129 | return dev->set_state_periodic(dev); | 131 | if (dev->set_state_periodic) |
| 132 | return dev->set_state_periodic(dev); | ||
| 133 | return 0; | ||
| 130 | 134 | ||
| 131 | case CLOCK_EVT_STATE_ONESHOT: | 135 | case CLOCK_EVT_STATE_ONESHOT: |
| 132 | /* Core internal bug */ | 136 | /* Core internal bug */ |
| 133 | if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) | 137 | if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT)) |
| 134 | return -ENOSYS; | 138 | return -ENOSYS; |
| 135 | return dev->set_state_oneshot(dev); | 139 | if (dev->set_state_oneshot) |
| 140 | return dev->set_state_oneshot(dev); | ||
| 141 | return 0; | ||
| 136 | 142 | ||
| 137 | case CLOCK_EVT_STATE_ONESHOT_STOPPED: | 143 | case CLOCK_EVT_STATE_ONESHOT_STOPPED: |
| 138 | /* Core internal bug */ | 144 | /* Core internal bug */ |
| @@ -471,18 +477,6 @@ static int clockevents_sanity_check(struct clock_event_device *dev) | |||
| 471 | if (dev->features & CLOCK_EVT_FEAT_DUMMY) | 477 | if (dev->features & CLOCK_EVT_FEAT_DUMMY) |
| 472 | return 0; | 478 | return 0; |
| 473 | 479 | ||
| 474 | /* New state-specific callbacks */ | ||
| 475 | if (!dev->set_state_shutdown) | ||
| 476 | return -EINVAL; | ||
| 477 | |||
| 478 | if ((dev->features & CLOCK_EVT_FEAT_PERIODIC) && | ||
| 479 | !dev->set_state_periodic) | ||
| 480 | return -EINVAL; | ||
| 481 | |||
| 482 | if ((dev->features & CLOCK_EVT_FEAT_ONESHOT) && | ||
| 483 | !dev->set_state_oneshot) | ||
| 484 | return -EINVAL; | ||
| 485 | |||
| 486 | return 0; | 480 | return 0; |
| 487 | } | 481 | } |
| 488 | 482 | ||
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index d39f32cdd1b5..52b9e199b5ac 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c | |||
| @@ -159,7 +159,7 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) | |||
| 159 | { | 159 | { |
| 160 | struct clock_event_device *bc = tick_broadcast_device.evtdev; | 160 | struct clock_event_device *bc = tick_broadcast_device.evtdev; |
| 161 | unsigned long flags; | 161 | unsigned long flags; |
| 162 | int ret; | 162 | int ret = 0; |
| 163 | 163 | ||
| 164 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); | 164 | raw_spin_lock_irqsave(&tick_broadcast_lock, flags); |
| 165 | 165 | ||
| @@ -221,13 +221,14 @@ int tick_device_uses_broadcast(struct clock_event_device *dev, int cpu) | |||
| 221 | * If we kept the cpu in the broadcast mask, | 221 | * If we kept the cpu in the broadcast mask, |
| 222 | * tell the caller to leave the per cpu device | 222 | * tell the caller to leave the per cpu device |
| 223 | * in shutdown state. The periodic interrupt | 223 | * in shutdown state. The periodic interrupt |
| 224 | * is delivered by the broadcast device. | 224 | * is delivered by the broadcast device, if |
| 225 | * the broadcast device exists and is not | ||
| 226 | * hrtimer based. | ||
| 225 | */ | 227 | */ |
| 226 | ret = cpumask_test_cpu(cpu, tick_broadcast_mask); | 228 | if (bc && !(bc->features & CLOCK_EVT_FEAT_HRTIMER)) |
| 229 | ret = cpumask_test_cpu(cpu, tick_broadcast_mask); | ||
| 227 | break; | 230 | break; |
| 228 | default: | 231 | default: |
| 229 | /* Nothing to do */ | ||
| 230 | ret = 0; | ||
| 231 | break; | 232 | break; |
| 232 | } | 233 | } |
| 233 | } | 234 | } |
| @@ -265,8 +266,22 @@ static bool tick_do_broadcast(struct cpumask *mask) | |||
| 265 | * Check, if the current cpu is in the mask | 266 | * Check, if the current cpu is in the mask |
| 266 | */ | 267 | */ |
| 267 | if (cpumask_test_cpu(cpu, mask)) { | 268 | if (cpumask_test_cpu(cpu, mask)) { |
| 269 | struct clock_event_device *bc = tick_broadcast_device.evtdev; | ||
| 270 | |||
| 268 | cpumask_clear_cpu(cpu, mask); | 271 | cpumask_clear_cpu(cpu, mask); |
| 269 | local = true; | 272 | /* |
| 273 | * We only run the local handler, if the broadcast | ||
| 274 | * device is not hrtimer based. Otherwise we run into | ||
| 275 | * a hrtimer recursion. | ||
| 276 | * | ||
| 277 | * local timer_interrupt() | ||
| 278 | * local_handler() | ||
| 279 | * expire_hrtimers() | ||
| 280 | * bc_handler() | ||
| 281 | * local_handler() | ||
| 282 | * expire_hrtimers() | ||
| 283 | */ | ||
| 284 | local = !(bc->features & CLOCK_EVT_FEAT_HRTIMER); | ||
| 270 | } | 285 | } |
| 271 | 286 | ||
| 272 | if (!cpumask_empty(mask)) { | 287 | if (!cpumask_empty(mask)) { |
| @@ -301,6 +316,13 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev) | |||
| 301 | bool bc_local; | 316 | bool bc_local; |
| 302 | 317 | ||
| 303 | raw_spin_lock(&tick_broadcast_lock); | 318 | raw_spin_lock(&tick_broadcast_lock); |
| 319 | |||
| 320 | /* Handle spurious interrupts gracefully */ | ||
| 321 | if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) { | ||
| 322 | raw_spin_unlock(&tick_broadcast_lock); | ||
| 323 | return; | ||
| 324 | } | ||
| 325 | |||
| 304 | bc_local = tick_do_periodic_broadcast(); | 326 | bc_local = tick_do_periodic_broadcast(); |
| 305 | 327 | ||
| 306 | if (clockevent_state_oneshot(dev)) { | 328 | if (clockevent_state_oneshot(dev)) { |
| @@ -359,8 +381,16 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) | |||
| 359 | case TICK_BROADCAST_ON: | 381 | case TICK_BROADCAST_ON: |
| 360 | cpumask_set_cpu(cpu, tick_broadcast_on); | 382 | cpumask_set_cpu(cpu, tick_broadcast_on); |
| 361 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { | 383 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { |
| 362 | if (tick_broadcast_device.mode == | 384 | /* |
| 363 | TICKDEV_MODE_PERIODIC) | 385 | * Only shutdown the cpu local device, if: |
| 386 | * | ||
| 387 | * - the broadcast device exists | ||
| 388 | * - the broadcast device is not a hrtimer based one | ||
| 389 | * - the broadcast device is in periodic mode to | ||
| 390 | * avoid a hickup during switch to oneshot mode | ||
| 391 | */ | ||
| 392 | if (bc && !(bc->features & CLOCK_EVT_FEAT_HRTIMER) && | ||
| 393 | tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) | ||
| 364 | clockevents_shutdown(dev); | 394 | clockevents_shutdown(dev); |
| 365 | } | 395 | } |
| 366 | break; | 396 | break; |
| @@ -379,14 +409,16 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) | |||
| 379 | break; | 409 | break; |
| 380 | } | 410 | } |
| 381 | 411 | ||
| 382 | if (cpumask_empty(tick_broadcast_mask)) { | 412 | if (bc) { |
| 383 | if (!bc_stopped) | 413 | if (cpumask_empty(tick_broadcast_mask)) { |
| 384 | clockevents_shutdown(bc); | 414 | if (!bc_stopped) |
| 385 | } else if (bc_stopped) { | 415 | clockevents_shutdown(bc); |
| 386 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) | 416 | } else if (bc_stopped) { |
| 387 | tick_broadcast_start_periodic(bc); | 417 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) |
| 388 | else | 418 | tick_broadcast_start_periodic(bc); |
| 389 | tick_broadcast_setup_oneshot(bc); | 419 | else |
| 420 | tick_broadcast_setup_oneshot(bc); | ||
| 421 | } | ||
| 390 | } | 422 | } |
| 391 | raw_spin_unlock(&tick_broadcast_lock); | 423 | raw_spin_unlock(&tick_broadcast_lock); |
| 392 | } | 424 | } |
| @@ -662,71 +694,82 @@ static void broadcast_shutdown_local(struct clock_event_device *bc, | |||
| 662 | clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); | 694 | clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN); |
| 663 | } | 695 | } |
| 664 | 696 | ||
| 665 | /** | 697 | int __tick_broadcast_oneshot_control(enum tick_broadcast_state state) |
| 666 | * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode | ||
| 667 | * @state: The target state (enter/exit) | ||
| 668 | * | ||
| 669 | * The system enters/leaves a state, where affected devices might stop | ||
| 670 | * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups. | ||
| 671 | * | ||
| 672 | * Called with interrupts disabled, so clockevents_lock is not | ||
| 673 | * required here because the local clock event device cannot go away | ||
| 674 | * under us. | ||
| 675 | */ | ||
| 676 | int tick_broadcast_oneshot_control(enum tick_broadcast_state state) | ||
| 677 | { | 698 | { |
| 678 | struct clock_event_device *bc, *dev; | 699 | struct clock_event_device *bc, *dev; |
| 679 | struct tick_device *td; | ||
| 680 | int cpu, ret = 0; | 700 | int cpu, ret = 0; |
| 681 | ktime_t now; | 701 | ktime_t now; |
| 682 | 702 | ||
| 683 | /* | 703 | /* |
| 684 | * Periodic mode does not care about the enter/exit of power | 704 | * If there is no broadcast device, tell the caller not to go |
| 685 | * states | 705 | * into deep idle. |
| 686 | */ | 706 | */ |
| 687 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) | 707 | if (!tick_broadcast_device.evtdev) |
| 688 | return 0; | 708 | return -EBUSY; |
| 689 | 709 | ||
| 690 | /* | 710 | dev = this_cpu_ptr(&tick_cpu_device)->evtdev; |
| 691 | * We are called with preemtion disabled from the depth of the | ||
| 692 | * idle code, so we can't be moved away. | ||
| 693 | */ | ||
| 694 | td = this_cpu_ptr(&tick_cpu_device); | ||
| 695 | dev = td->evtdev; | ||
| 696 | |||
| 697 | if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
| 698 | return 0; | ||
| 699 | 711 | ||
| 700 | raw_spin_lock(&tick_broadcast_lock); | 712 | raw_spin_lock(&tick_broadcast_lock); |
| 701 | bc = tick_broadcast_device.evtdev; | 713 | bc = tick_broadcast_device.evtdev; |
| 702 | cpu = smp_processor_id(); | 714 | cpu = smp_processor_id(); |
| 703 | 715 | ||
| 704 | if (state == TICK_BROADCAST_ENTER) { | 716 | if (state == TICK_BROADCAST_ENTER) { |
| 717 | /* | ||
| 718 | * If the current CPU owns the hrtimer broadcast | ||
| 719 | * mechanism, it cannot go deep idle and we do not add | ||
| 720 | * the CPU to the broadcast mask. We don't have to go | ||
| 721 | * through the EXIT path as the local timer is not | ||
| 722 | * shutdown. | ||
| 723 | */ | ||
| 724 | ret = broadcast_needs_cpu(bc, cpu); | ||
| 725 | if (ret) | ||
| 726 | goto out; | ||
| 727 | |||
| 728 | /* | ||
| 729 | * If the broadcast device is in periodic mode, we | ||
| 730 | * return. | ||
| 731 | */ | ||
| 732 | if (tick_broadcast_device.mode == TICKDEV_MODE_PERIODIC) { | ||
| 733 | /* If it is a hrtimer based broadcast, return busy */ | ||
| 734 | if (bc->features & CLOCK_EVT_FEAT_HRTIMER) | ||
| 735 | ret = -EBUSY; | ||
| 736 | goto out; | ||
| 737 | } | ||
| 738 | |||
| 705 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) { | 739 | if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_oneshot_mask)) { |
| 706 | WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask)); | 740 | WARN_ON_ONCE(cpumask_test_cpu(cpu, tick_broadcast_pending_mask)); |
| 741 | |||
| 742 | /* Conditionally shut down the local timer. */ | ||
| 707 | broadcast_shutdown_local(bc, dev); | 743 | broadcast_shutdown_local(bc, dev); |
| 744 | |||
| 708 | /* | 745 | /* |
| 709 | * We only reprogram the broadcast timer if we | 746 | * We only reprogram the broadcast timer if we |
| 710 | * did not mark ourself in the force mask and | 747 | * did not mark ourself in the force mask and |
| 711 | * if the cpu local event is earlier than the | 748 | * if the cpu local event is earlier than the |
| 712 | * broadcast event. If the current CPU is in | 749 | * broadcast event. If the current CPU is in |
| 713 | * the force mask, then we are going to be | 750 | * the force mask, then we are going to be |
| 714 | * woken by the IPI right away. | 751 | * woken by the IPI right away; we return |
| 752 | * busy, so the CPU does not try to go deep | ||
| 753 | * idle. | ||
| 715 | */ | 754 | */ |
| 716 | if (!cpumask_test_cpu(cpu, tick_broadcast_force_mask) && | 755 | if (cpumask_test_cpu(cpu, tick_broadcast_force_mask)) { |
| 717 | dev->next_event.tv64 < bc->next_event.tv64) | 756 | ret = -EBUSY; |
| 757 | } else if (dev->next_event.tv64 < bc->next_event.tv64) { | ||
| 718 | tick_broadcast_set_event(bc, cpu, dev->next_event); | 758 | tick_broadcast_set_event(bc, cpu, dev->next_event); |
| 759 | /* | ||
| 760 | * In case of hrtimer broadcasts the | ||
| 761 | * programming might have moved the | ||
| 762 | * timer to this cpu. If yes, remove | ||
| 763 | * us from the broadcast mask and | ||
| 764 | * return busy. | ||
| 765 | */ | ||
| 766 | ret = broadcast_needs_cpu(bc, cpu); | ||
| 767 | if (ret) { | ||
| 768 | cpumask_clear_cpu(cpu, | ||
| 769 | tick_broadcast_oneshot_mask); | ||
| 770 | } | ||
| 771 | } | ||
| 719 | } | 772 | } |
| 720 | /* | ||
| 721 | * If the current CPU owns the hrtimer broadcast | ||
| 722 | * mechanism, it cannot go deep idle and we remove the | ||
| 723 | * CPU from the broadcast mask. We don't have to go | ||
| 724 | * through the EXIT path as the local timer is not | ||
| 725 | * shutdown. | ||
| 726 | */ | ||
| 727 | ret = broadcast_needs_cpu(bc, cpu); | ||
| 728 | if (ret) | ||
| 729 | cpumask_clear_cpu(cpu, tick_broadcast_oneshot_mask); | ||
| 730 | } else { | 773 | } else { |
| 731 | if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) { | 774 | if (cpumask_test_and_clear_cpu(cpu, tick_broadcast_oneshot_mask)) { |
| 732 | clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT); | 775 | clockevents_switch_state(dev, CLOCK_EVT_STATE_ONESHOT); |
| @@ -938,6 +981,16 @@ bool tick_broadcast_oneshot_available(void) | |||
| 938 | return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false; | 981 | return bc ? bc->features & CLOCK_EVT_FEAT_ONESHOT : false; |
| 939 | } | 982 | } |
| 940 | 983 | ||
| 984 | #else | ||
| 985 | int __tick_broadcast_oneshot_control(enum tick_broadcast_state state) | ||
| 986 | { | ||
| 987 | struct clock_event_device *bc = tick_broadcast_device.evtdev; | ||
| 988 | |||
| 989 | if (!bc || (bc->features & CLOCK_EVT_FEAT_HRTIMER)) | ||
| 990 | return -EBUSY; | ||
| 991 | |||
| 992 | return 0; | ||
| 993 | } | ||
| 941 | #endif | 994 | #endif |
| 942 | 995 | ||
| 943 | void __init tick_broadcast_init(void) | 996 | void __init tick_broadcast_init(void) |
diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 76446cb5dfe1..55e13efff1ab 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c | |||
| @@ -343,6 +343,27 @@ out_bc: | |||
| 343 | tick_install_broadcast_device(newdev); | 343 | tick_install_broadcast_device(newdev); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | /** | ||
| 347 | * tick_broadcast_oneshot_control - Enter/exit broadcast oneshot mode | ||
| 348 | * @state: The target state (enter/exit) | ||
| 349 | * | ||
| 350 | * The system enters/leaves a state, where affected devices might stop | ||
| 351 | * Returns 0 on success, -EBUSY if the cpu is used to broadcast wakeups. | ||
| 352 | * | ||
| 353 | * Called with interrupts disabled, so clockevents_lock is not | ||
| 354 | * required here because the local clock event device cannot go away | ||
| 355 | * under us. | ||
| 356 | */ | ||
| 357 | int tick_broadcast_oneshot_control(enum tick_broadcast_state state) | ||
| 358 | { | ||
| 359 | struct tick_device *td = this_cpu_ptr(&tick_cpu_device); | ||
| 360 | |||
| 361 | if (!(td->evtdev->features & CLOCK_EVT_FEAT_C3STOP)) | ||
| 362 | return 0; | ||
| 363 | |||
| 364 | return __tick_broadcast_oneshot_control(state); | ||
| 365 | } | ||
| 366 | |||
| 346 | #ifdef CONFIG_HOTPLUG_CPU | 367 | #ifdef CONFIG_HOTPLUG_CPU |
| 347 | /* | 368 | /* |
| 348 | * Transfer the do_timer job away from a dying cpu. | 369 | * Transfer the do_timer job away from a dying cpu. |
diff --git a/kernel/time/tick-sched.h b/kernel/time/tick-sched.h index 42fdf4958bcc..a4a8d4e9baa1 100644 --- a/kernel/time/tick-sched.h +++ b/kernel/time/tick-sched.h | |||
| @@ -71,4 +71,14 @@ extern void tick_cancel_sched_timer(int cpu); | |||
| 71 | static inline void tick_cancel_sched_timer(int cpu) { } | 71 | static inline void tick_cancel_sched_timer(int cpu) { } |
| 72 | #endif | 72 | #endif |
| 73 | 73 | ||
| 74 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
| 75 | extern int __tick_broadcast_oneshot_control(enum tick_broadcast_state state); | ||
| 76 | #else | ||
| 77 | static inline int | ||
| 78 | __tick_broadcast_oneshot_control(enum tick_broadcast_state state) | ||
| 79 | { | ||
| 80 | return -EBUSY; | ||
| 81 | } | ||
| 82 | #endif | ||
| 83 | |||
| 74 | #endif | 84 | #endif |
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index 777eda7d1ab4..39f24d6721e5 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan | |||
| @@ -18,10 +18,6 @@ config KASAN | |||
| 18 | For better error detection enable CONFIG_STACKTRACE, | 18 | For better error detection enable CONFIG_STACKTRACE, |
| 19 | and add slub_debug=U to boot cmdline. | 19 | and add slub_debug=U to boot cmdline. |
| 20 | 20 | ||
| 21 | config KASAN_SHADOW_OFFSET | ||
| 22 | hex | ||
| 23 | default 0xdffffc0000000000 if X86_64 | ||
| 24 | |||
| 25 | choice | 21 | choice |
| 26 | prompt "Instrumentation type" | 22 | prompt "Instrumentation type" |
| 27 | depends on KASAN | 23 | depends on KASAN |
diff --git a/mm/memory.c b/mm/memory.c index a84fbb772034..388dcf9aa283 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -2670,6 +2670,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 2670 | 2670 | ||
| 2671 | pte_unmap(page_table); | 2671 | pte_unmap(page_table); |
| 2672 | 2672 | ||
| 2673 | /* File mapping without ->vm_ops ? */ | ||
| 2674 | if (vma->vm_flags & VM_SHARED) | ||
| 2675 | return VM_FAULT_SIGBUS; | ||
| 2676 | |||
| 2673 | /* Check if we need to add a guard page to the stack */ | 2677 | /* Check if we need to add a guard page to the stack */ |
| 2674 | if (check_stack_guard_page(vma, address) < 0) | 2678 | if (check_stack_guard_page(vma, address) < 0) |
| 2675 | return VM_FAULT_SIGSEGV; | 2679 | return VM_FAULT_SIGSEGV; |
| @@ -3099,6 +3103,9 @@ static int do_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
| 3099 | - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; | 3103 | - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; |
| 3100 | 3104 | ||
| 3101 | pte_unmap(page_table); | 3105 | pte_unmap(page_table); |
| 3106 | /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */ | ||
| 3107 | if (!vma->vm_ops->fault) | ||
| 3108 | return VM_FAULT_SIGBUS; | ||
| 3102 | if (!(flags & FAULT_FLAG_WRITE)) | 3109 | if (!(flags & FAULT_FLAG_WRITE)) |
| 3103 | return do_read_fault(mm, vma, address, pmd, pgoff, flags, | 3110 | return do_read_fault(mm, vma, address, pmd, pgoff, flags, |
| 3104 | orig_pte); | 3111 | orig_pte); |
| @@ -3244,13 +3251,12 @@ static int handle_pte_fault(struct mm_struct *mm, | |||
| 3244 | barrier(); | 3251 | barrier(); |
| 3245 | if (!pte_present(entry)) { | 3252 | if (!pte_present(entry)) { |
| 3246 | if (pte_none(entry)) { | 3253 | if (pte_none(entry)) { |
| 3247 | if (vma->vm_ops) { | 3254 | if (vma->vm_ops) |
| 3248 | if (likely(vma->vm_ops->fault)) | 3255 | return do_fault(mm, vma, address, pte, pmd, |
| 3249 | return do_fault(mm, vma, address, pte, | 3256 | flags, entry); |
| 3250 | pmd, flags, entry); | 3257 | |
| 3251 | } | 3258 | return do_anonymous_page(mm, vma, address, pte, pmd, |
| 3252 | return do_anonymous_page(mm, vma, address, | 3259 | flags); |
| 3253 | pte, pmd, flags); | ||
| 3254 | } | 3260 | } |
| 3255 | return do_swap_page(mm, vma, address, | 3261 | return do_swap_page(mm, vma, address, |
| 3256 | pte, pmd, flags, entry); | 3262 | pte, pmd, flags, entry); |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index cb7db320dd27..f30329f72641 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <keys/ceph-type.h> | 9 | #include <keys/ceph-type.h> |
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
| 12 | #include <linux/nsproxy.h> | ||
| 12 | #include <linux/parser.h> | 13 | #include <linux/parser.h> |
| 13 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
| 14 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
| @@ -16,8 +17,6 @@ | |||
| 16 | #include <linux/statfs.h> | 17 | #include <linux/statfs.h> |
| 17 | #include <linux/string.h> | 18 | #include <linux/string.h> |
| 18 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
| 19 | #include <linux/nsproxy.h> | ||
| 20 | #include <net/net_namespace.h> | ||
| 21 | 20 | ||
| 22 | 21 | ||
| 23 | #include <linux/ceph/ceph_features.h> | 22 | #include <linux/ceph/ceph_features.h> |
| @@ -131,6 +130,13 @@ int ceph_compare_options(struct ceph_options *new_opt, | |||
| 131 | int i; | 130 | int i; |
| 132 | int ret; | 131 | int ret; |
| 133 | 132 | ||
| 133 | /* | ||
| 134 | * Don't bother comparing options if network namespaces don't | ||
| 135 | * match. | ||
| 136 | */ | ||
| 137 | if (!net_eq(current->nsproxy->net_ns, read_pnet(&client->msgr.net))) | ||
| 138 | return -1; | ||
| 139 | |||
| 134 | ret = memcmp(opt1, opt2, ofs); | 140 | ret = memcmp(opt1, opt2, ofs); |
| 135 | if (ret) | 141 | if (ret) |
| 136 | return ret; | 142 | return ret; |
| @@ -335,9 +341,6 @@ ceph_parse_options(char *options, const char *dev_name, | |||
| 335 | int err = -ENOMEM; | 341 | int err = -ENOMEM; |
| 336 | substring_t argstr[MAX_OPT_ARGS]; | 342 | substring_t argstr[MAX_OPT_ARGS]; |
| 337 | 343 | ||
| 338 | if (current->nsproxy->net_ns != &init_net) | ||
| 339 | return ERR_PTR(-EINVAL); | ||
| 340 | |||
| 341 | opt = kzalloc(sizeof(*opt), GFP_KERNEL); | 344 | opt = kzalloc(sizeof(*opt), GFP_KERNEL); |
| 342 | if (!opt) | 345 | if (!opt) |
| 343 | return ERR_PTR(-ENOMEM); | 346 | return ERR_PTR(-ENOMEM); |
| @@ -608,6 +611,7 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, | |||
| 608 | fail_monc: | 611 | fail_monc: |
| 609 | ceph_monc_stop(&client->monc); | 612 | ceph_monc_stop(&client->monc); |
| 610 | fail: | 613 | fail: |
| 614 | ceph_messenger_fini(&client->msgr); | ||
| 611 | kfree(client); | 615 | kfree(client); |
| 612 | return ERR_PTR(err); | 616 | return ERR_PTR(err); |
| 613 | } | 617 | } |
| @@ -621,8 +625,8 @@ void ceph_destroy_client(struct ceph_client *client) | |||
| 621 | 625 | ||
| 622 | /* unmount */ | 626 | /* unmount */ |
| 623 | ceph_osdc_stop(&client->osdc); | 627 | ceph_osdc_stop(&client->osdc); |
| 624 | |||
| 625 | ceph_monc_stop(&client->monc); | 628 | ceph_monc_stop(&client->monc); |
| 629 | ceph_messenger_fini(&client->msgr); | ||
| 626 | 630 | ||
| 627 | ceph_debugfs_client_cleanup(client); | 631 | ceph_debugfs_client_cleanup(client); |
| 628 | 632 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1679f47280e2..e3be1d22a247 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <linux/inet.h> | 6 | #include <linux/inet.h> |
| 7 | #include <linux/kthread.h> | 7 | #include <linux/kthread.h> |
| 8 | #include <linux/net.h> | 8 | #include <linux/net.h> |
| 9 | #include <linux/nsproxy.h> | ||
| 9 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 10 | #include <linux/socket.h> | 11 | #include <linux/socket.h> |
| 11 | #include <linux/string.h> | 12 | #include <linux/string.h> |
| @@ -479,7 +480,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) | |||
| 479 | int ret; | 480 | int ret; |
| 480 | 481 | ||
| 481 | BUG_ON(con->sock); | 482 | BUG_ON(con->sock); |
| 482 | ret = sock_create_kern(&init_net, con->peer_addr.in_addr.ss_family, | 483 | ret = sock_create_kern(read_pnet(&con->msgr->net), paddr->ss_family, |
| 483 | SOCK_STREAM, IPPROTO_TCP, &sock); | 484 | SOCK_STREAM, IPPROTO_TCP, &sock); |
| 484 | if (ret) | 485 | if (ret) |
| 485 | return ret; | 486 | return ret; |
| @@ -1731,17 +1732,17 @@ static int verify_hello(struct ceph_connection *con) | |||
| 1731 | 1732 | ||
| 1732 | static bool addr_is_blank(struct sockaddr_storage *ss) | 1733 | static bool addr_is_blank(struct sockaddr_storage *ss) |
| 1733 | { | 1734 | { |
| 1735 | struct in_addr *addr = &((struct sockaddr_in *)ss)->sin_addr; | ||
| 1736 | struct in6_addr *addr6 = &((struct sockaddr_in6 *)ss)->sin6_addr; | ||
| 1737 | |||
| 1734 | switch (ss->ss_family) { | 1738 | switch (ss->ss_family) { |
| 1735 | case AF_INET: | 1739 | case AF_INET: |
| 1736 | return ((struct sockaddr_in *)ss)->sin_addr.s_addr == 0; | 1740 | return addr->s_addr == htonl(INADDR_ANY); |
| 1737 | case AF_INET6: | 1741 | case AF_INET6: |
| 1738 | return | 1742 | return ipv6_addr_any(addr6); |
| 1739 | ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[0] == 0 && | 1743 | default: |
| 1740 | ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[1] == 0 && | 1744 | return true; |
| 1741 | ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[2] == 0 && | ||
| 1742 | ((struct sockaddr_in6 *)ss)->sin6_addr.s6_addr32[3] == 0; | ||
| 1743 | } | 1745 | } |
| 1744 | return false; | ||
| 1745 | } | 1746 | } |
| 1746 | 1747 | ||
| 1747 | static int addr_port(struct sockaddr_storage *ss) | 1748 | static int addr_port(struct sockaddr_storage *ss) |
| @@ -2944,11 +2945,18 @@ void ceph_messenger_init(struct ceph_messenger *msgr, | |||
| 2944 | msgr->tcp_nodelay = tcp_nodelay; | 2945 | msgr->tcp_nodelay = tcp_nodelay; |
| 2945 | 2946 | ||
| 2946 | atomic_set(&msgr->stopping, 0); | 2947 | atomic_set(&msgr->stopping, 0); |
| 2948 | write_pnet(&msgr->net, get_net(current->nsproxy->net_ns)); | ||
| 2947 | 2949 | ||
| 2948 | dout("%s %p\n", __func__, msgr); | 2950 | dout("%s %p\n", __func__, msgr); |
| 2949 | } | 2951 | } |
| 2950 | EXPORT_SYMBOL(ceph_messenger_init); | 2952 | EXPORT_SYMBOL(ceph_messenger_init); |
| 2951 | 2953 | ||
| 2954 | void ceph_messenger_fini(struct ceph_messenger *msgr) | ||
| 2955 | { | ||
| 2956 | put_net(read_pnet(&msgr->net)); | ||
| 2957 | } | ||
| 2958 | EXPORT_SYMBOL(ceph_messenger_fini); | ||
| 2959 | |||
| 2952 | static void clear_standby(struct ceph_connection *con) | 2960 | static void clear_standby(struct ceph_connection *con) |
| 2953 | { | 2961 | { |
| 2954 | /* come back from STANDBY? */ | 2962 | /* come back from STANDBY? */ |
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index eff7de1fc82e..e70fcd12eeeb 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c | |||
| @@ -63,6 +63,8 @@ int main(void) | |||
| 63 | 63 | ||
| 64 | DEVID(acpi_device_id); | 64 | DEVID(acpi_device_id); |
| 65 | DEVID_FIELD(acpi_device_id, id); | 65 | DEVID_FIELD(acpi_device_id, id); |
| 66 | DEVID_FIELD(acpi_device_id, cls); | ||
| 67 | DEVID_FIELD(acpi_device_id, cls_msk); | ||
| 66 | 68 | ||
| 67 | DEVID(pnp_device_id); | 69 | DEVID(pnp_device_id); |
| 68 | DEVID_FIELD(pnp_device_id, id); | 70 | DEVID_FIELD(pnp_device_id, id); |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 84c86f3cd6cd..5f2088209132 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
| @@ -523,12 +523,40 @@ static int do_serio_entry(const char *filename, | |||
| 523 | } | 523 | } |
| 524 | ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry); | 524 | ADD_TO_DEVTABLE("serio", serio_device_id, do_serio_entry); |
| 525 | 525 | ||
| 526 | /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */ | 526 | /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or |
| 527 | * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) | ||
| 528 | * | ||
| 529 | * NOTE: Each driver should use one of the following : _HID, _CIDs | ||
| 530 | * or _CLS. Also, bb, ss, and pp can be substituted with ?? | ||
| 531 | * as don't care byte. | ||
| 532 | */ | ||
| 527 | static int do_acpi_entry(const char *filename, | 533 | static int do_acpi_entry(const char *filename, |
| 528 | void *symval, char *alias) | 534 | void *symval, char *alias) |
| 529 | { | 535 | { |
| 530 | DEF_FIELD_ADDR(symval, acpi_device_id, id); | 536 | DEF_FIELD_ADDR(symval, acpi_device_id, id); |
| 531 | sprintf(alias, "acpi*:%s:*", *id); | 537 | DEF_FIELD_ADDR(symval, acpi_device_id, cls); |
| 538 | DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk); | ||
| 539 | |||
| 540 | if (id && strlen((const char *)*id)) | ||
| 541 | sprintf(alias, "acpi*:%s:*", *id); | ||
| 542 | else if (cls) { | ||
| 543 | int i, byte_shift, cnt = 0; | ||
| 544 | unsigned int msk; | ||
| 545 | |||
| 546 | sprintf(&alias[cnt], "acpi*:"); | ||
| 547 | cnt = 6; | ||
| 548 | for (i = 1; i <= 3; i++) { | ||
| 549 | byte_shift = 8 * (3-i); | ||
| 550 | msk = (*cls_msk >> byte_shift) & 0xFF; | ||
| 551 | if (msk) | ||
| 552 | sprintf(&alias[cnt], "%02x", | ||
| 553 | (*cls >> byte_shift) & 0xFF); | ||
| 554 | else | ||
| 555 | sprintf(&alias[cnt], "??"); | ||
| 556 | cnt += 2; | ||
| 557 | } | ||
| 558 | sprintf(&alias[cnt], ":*"); | ||
| 559 | } | ||
| 532 | return 1; | 560 | return 1; |
| 533 | } | 561 | } |
| 534 | ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry); | 562 | ADD_TO_DEVTABLE("acpi", acpi_device_id, do_acpi_entry); |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 91ee1b2e0f9a..12d3db3bd46b 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -886,7 +886,8 @@ static void check_section(const char *modname, struct elf_info *elf, | |||
| 886 | #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ | 886 | #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ |
| 887 | ".kprobes.text" | 887 | ".kprobes.text" |
| 888 | #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ | 888 | #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ |
| 889 | ".fixup", ".entry.text", ".exception.text", ".text.*" | 889 | ".fixup", ".entry.text", ".exception.text", ".text.*", \ |
| 890 | ".coldtext" | ||
| 890 | 891 | ||
| 891 | #define INIT_SECTIONS ".init.*" | 892 | #define INIT_SECTIONS ".init.*" |
| 892 | #define MEM_INIT_SECTIONS ".meminit.*" | 893 | #define MEM_INIT_SECTIONS ".meminit.*" |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 623108199641..564079c5c49d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -3283,7 +3283,8 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
| 3283 | int rc = 0; | 3283 | int rc = 0; |
| 3284 | 3284 | ||
| 3285 | if (default_noexec && | 3285 | if (default_noexec && |
| 3286 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 3286 | (prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) || |
| 3287 | (!shared && (prot & PROT_WRITE)))) { | ||
| 3287 | /* | 3288 | /* |
| 3288 | * We are making executable an anonymous mapping or a | 3289 | * We are making executable an anonymous mapping or a |
| 3289 | * private file mapping that will also be writable. | 3290 | * private file mapping that will also be writable. |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index afe6a269ec17..57644b1dc42e 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
| @@ -153,6 +153,12 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap, | |||
| 153 | if (offset == (u32)-1) | 153 | if (offset == (u32)-1) |
| 154 | return 0; | 154 | return 0; |
| 155 | 155 | ||
| 156 | /* don't waste ebitmap space if the netlabel bitmap is empty */ | ||
| 157 | if (bitmap == 0) { | ||
| 158 | offset += EBITMAP_UNIT_SIZE; | ||
| 159 | continue; | ||
| 160 | } | ||
| 161 | |||
| 156 | if (e_iter == NULL || | 162 | if (e_iter == NULL || |
| 157 | offset >= e_iter->startbit + EBITMAP_SIZE) { | 163 | offset >= e_iter->startbit + EBITMAP_SIZE) { |
| 158 | e_prev = e_iter; | 164 | e_prev = e_iter; |
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h index f0e72674c52d..9098083869c8 100644 --- a/tools/include/linux/compiler.h +++ b/tools/include/linux/compiler.h | |||
| @@ -41,4 +41,62 @@ | |||
| 41 | 41 | ||
| 42 | #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) | 42 | #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) |
| 43 | 43 | ||
| 44 | #include <linux/types.h> | ||
| 45 | |||
| 46 | static __always_inline void __read_once_size(const volatile void *p, void *res, int size) | ||
| 47 | { | ||
| 48 | switch (size) { | ||
| 49 | case 1: *(__u8 *)res = *(volatile __u8 *)p; break; | ||
| 50 | case 2: *(__u16 *)res = *(volatile __u16 *)p; break; | ||
| 51 | case 4: *(__u32 *)res = *(volatile __u32 *)p; break; | ||
| 52 | case 8: *(__u64 *)res = *(volatile __u64 *)p; break; | ||
| 53 | default: | ||
| 54 | barrier(); | ||
| 55 | __builtin_memcpy((void *)res, (const void *)p, size); | ||
| 56 | barrier(); | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | static __always_inline void __write_once_size(volatile void *p, void *res, int size) | ||
| 61 | { | ||
| 62 | switch (size) { | ||
| 63 | case 1: *(volatile __u8 *)p = *(__u8 *)res; break; | ||
| 64 | case 2: *(volatile __u16 *)p = *(__u16 *)res; break; | ||
| 65 | case 4: *(volatile __u32 *)p = *(__u32 *)res; break; | ||
| 66 | case 8: *(volatile __u64 *)p = *(__u64 *)res; break; | ||
| 67 | default: | ||
| 68 | barrier(); | ||
| 69 | __builtin_memcpy((void *)p, (const void *)res, size); | ||
| 70 | barrier(); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | /* | ||
| 75 | * Prevent the compiler from merging or refetching reads or writes. The | ||
| 76 | * compiler is also forbidden from reordering successive instances of | ||
| 77 | * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the | ||
| 78 | * compiler is aware of some particular ordering. One way to make the | ||
| 79 | * compiler aware of ordering is to put the two invocations of READ_ONCE, | ||
| 80 | * WRITE_ONCE or ACCESS_ONCE() in different C statements. | ||
| 81 | * | ||
| 82 | * In contrast to ACCESS_ONCE these two macros will also work on aggregate | ||
| 83 | * data types like structs or unions. If the size of the accessed data | ||
| 84 | * type exceeds the word size of the machine (e.g., 32 bits or 64 bits) | ||
| 85 | * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a | ||
| 86 | * compile-time warning. | ||
| 87 | * | ||
| 88 | * Their two major use cases are: (1) Mediating communication between | ||
| 89 | * process-level code and irq/NMI handlers, all running on the same CPU, | ||
| 90 | * and (2) Ensuring that the compiler does not fold, spindle, or otherwise | ||
| 91 | * mutilate accesses that either do not require ordering or that interact | ||
| 92 | * with an explicit memory barrier or atomic instruction that provides the | ||
| 93 | * required ordering. | ||
| 94 | */ | ||
| 95 | |||
| 96 | #define READ_ONCE(x) \ | ||
| 97 | ({ union { typeof(x) __val; char __c[1]; } __u; __read_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) | ||
| 98 | |||
| 99 | #define WRITE_ONCE(x, val) \ | ||
| 100 | ({ union { typeof(x) __val; char __c[1]; } __u = { .__val = (val) }; __write_once_size(&(x), __u.__c, sizeof(x)); __u.__val; }) | ||
| 101 | |||
| 44 | #endif /* _TOOLS_LINUX_COMPILER_H */ | 102 | #endif /* _TOOLS_LINUX_COMPILER_H */ |
diff --git a/tools/include/linux/export.h b/tools/include/linux/export.h deleted file mode 100644 index d07e586b9ba0..000000000000 --- a/tools/include/linux/export.h +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | #ifndef _TOOLS_LINUX_EXPORT_H_ | ||
| 2 | #define _TOOLS_LINUX_EXPORT_H_ | ||
| 3 | |||
| 4 | #define EXPORT_SYMBOL(sym) | ||
| 5 | #define EXPORT_SYMBOL_GPL(sym) | ||
| 6 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) | ||
| 7 | #define EXPORT_UNUSED_SYMBOL(sym) | ||
| 8 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) | ||
| 9 | |||
| 10 | #endif | ||
diff --git a/tools/include/linux/rbtree.h b/tools/include/linux/rbtree.h new file mode 100644 index 000000000000..112582253dd0 --- /dev/null +++ b/tools/include/linux/rbtree.h | |||
| @@ -0,0 +1,104 @@ | |||
| 1 | /* | ||
| 2 | Red Black Trees | ||
| 3 | (C) 1999 Andrea Arcangeli <andrea@suse.de> | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 2 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, write to the Free Software | ||
| 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | |||
| 19 | linux/include/linux/rbtree.h | ||
| 20 | |||
| 21 | To use rbtrees you'll have to implement your own insert and search cores. | ||
| 22 | This will avoid us to use callbacks and to drop drammatically performances. | ||
| 23 | I know it's not the cleaner way, but in C (not in C++) to get | ||
| 24 | performances and genericity... | ||
| 25 | |||
| 26 | See Documentation/rbtree.txt for documentation and samples. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #ifndef __TOOLS_LINUX_PERF_RBTREE_H | ||
| 30 | #define __TOOLS_LINUX_PERF_RBTREE_H | ||
| 31 | |||
| 32 | #include <linux/kernel.h> | ||
| 33 | #include <linux/stddef.h> | ||
| 34 | |||
| 35 | struct rb_node { | ||
| 36 | unsigned long __rb_parent_color; | ||
| 37 | struct rb_node *rb_right; | ||
| 38 | struct rb_node *rb_left; | ||
| 39 | } __attribute__((aligned(sizeof(long)))); | ||
| 40 | /* The alignment might seem pointless, but allegedly CRIS needs it */ | ||
| 41 | |||
| 42 | struct rb_root { | ||
| 43 | struct rb_node *rb_node; | ||
| 44 | }; | ||
| 45 | |||
| 46 | |||
| 47 | #define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3)) | ||
| 48 | |||
| 49 | #define RB_ROOT (struct rb_root) { NULL, } | ||
| 50 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) | ||
| 51 | |||
| 52 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) | ||
| 53 | |||
| 54 | /* 'empty' nodes are nodes that are known not to be inserted in an rbtree */ | ||
| 55 | #define RB_EMPTY_NODE(node) \ | ||
| 56 | ((node)->__rb_parent_color == (unsigned long)(node)) | ||
| 57 | #define RB_CLEAR_NODE(node) \ | ||
| 58 | ((node)->__rb_parent_color = (unsigned long)(node)) | ||
| 59 | |||
| 60 | |||
| 61 | extern void rb_insert_color(struct rb_node *, struct rb_root *); | ||
| 62 | extern void rb_erase(struct rb_node *, struct rb_root *); | ||
| 63 | |||
| 64 | |||
| 65 | /* Find logical next and previous nodes in a tree */ | ||
| 66 | extern struct rb_node *rb_next(const struct rb_node *); | ||
| 67 | extern struct rb_node *rb_prev(const struct rb_node *); | ||
| 68 | extern struct rb_node *rb_first(const struct rb_root *); | ||
| 69 | extern struct rb_node *rb_last(const struct rb_root *); | ||
| 70 | |||
| 71 | /* Postorder iteration - always visit the parent after its children */ | ||
| 72 | extern struct rb_node *rb_first_postorder(const struct rb_root *); | ||
| 73 | extern struct rb_node *rb_next_postorder(const struct rb_node *); | ||
| 74 | |||
| 75 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ | ||
| 76 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, | ||
| 77 | struct rb_root *root); | ||
| 78 | |||
| 79 | static inline void rb_link_node(struct rb_node *node, struct rb_node *parent, | ||
| 80 | struct rb_node **rb_link) | ||
| 81 | { | ||
| 82 | node->__rb_parent_color = (unsigned long)parent; | ||
| 83 | node->rb_left = node->rb_right = NULL; | ||
| 84 | |||
| 85 | *rb_link = node; | ||
| 86 | } | ||
| 87 | |||
| 88 | #define rb_entry_safe(ptr, type, member) \ | ||
| 89 | ({ typeof(ptr) ____ptr = (ptr); \ | ||
| 90 | ____ptr ? rb_entry(____ptr, type, member) : NULL; \ | ||
| 91 | }) | ||
| 92 | |||
| 93 | |||
| 94 | /* | ||
| 95 | * Handy for checking that we are not deleting an entry that is | ||
| 96 | * already in a list, found in block/{blk-throttle,cfq-iosched}.c, | ||
| 97 | * probably should be moved to lib/rbtree.c... | ||
| 98 | */ | ||
| 99 | static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) | ||
| 100 | { | ||
| 101 | rb_erase(n, root); | ||
| 102 | RB_CLEAR_NODE(n); | ||
| 103 | } | ||
| 104 | #endif /* __TOOLS_LINUX_PERF_RBTREE_H */ | ||
diff --git a/tools/include/linux/rbtree_augmented.h b/tools/include/linux/rbtree_augmented.h new file mode 100644 index 000000000000..43be941db695 --- /dev/null +++ b/tools/include/linux/rbtree_augmented.h | |||
| @@ -0,0 +1,245 @@ | |||
| 1 | /* | ||
| 2 | Red Black Trees | ||
| 3 | (C) 1999 Andrea Arcangeli <andrea@suse.de> | ||
| 4 | (C) 2002 David Woodhouse <dwmw2@infradead.org> | ||
| 5 | (C) 2012 Michel Lespinasse <walken@google.com> | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | |||
| 21 | tools/linux/include/linux/rbtree_augmented.h | ||
| 22 | |||
| 23 | Copied from: | ||
| 24 | linux/include/linux/rbtree_augmented.h | ||
| 25 | */ | ||
| 26 | |||
| 27 | #ifndef _TOOLS_LINUX_RBTREE_AUGMENTED_H | ||
| 28 | #define _TOOLS_LINUX_RBTREE_AUGMENTED_H | ||
| 29 | |||
| 30 | #include <linux/compiler.h> | ||
| 31 | #include <linux/rbtree.h> | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Please note - only struct rb_augment_callbacks and the prototypes for | ||
| 35 | * rb_insert_augmented() and rb_erase_augmented() are intended to be public. | ||
| 36 | * The rest are implementation details you are not expected to depend on. | ||
| 37 | * | ||
| 38 | * See Documentation/rbtree.txt for documentation and samples. | ||
| 39 | */ | ||
| 40 | |||
| 41 | struct rb_augment_callbacks { | ||
| 42 | void (*propagate)(struct rb_node *node, struct rb_node *stop); | ||
| 43 | void (*copy)(struct rb_node *old, struct rb_node *new); | ||
| 44 | void (*rotate)(struct rb_node *old, struct rb_node *new); | ||
| 45 | }; | ||
| 46 | |||
| 47 | extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, | ||
| 48 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); | ||
| 49 | /* | ||
| 50 | * Fixup the rbtree and update the augmented information when rebalancing. | ||
| 51 | * | ||
| 52 | * On insertion, the user must update the augmented information on the path | ||
| 53 | * leading to the inserted node, then call rb_link_node() as usual and | ||
| 54 | * rb_augment_inserted() instead of the usual rb_insert_color() call. | ||
| 55 | * If rb_augment_inserted() rebalances the rbtree, it will callback into | ||
| 56 | * a user provided function to update the augmented information on the | ||
| 57 | * affected subtrees. | ||
| 58 | */ | ||
| 59 | static inline void | ||
| 60 | rb_insert_augmented(struct rb_node *node, struct rb_root *root, | ||
| 61 | const struct rb_augment_callbacks *augment) | ||
| 62 | { | ||
| 63 | __rb_insert_augmented(node, root, augment->rotate); | ||
| 64 | } | ||
| 65 | |||
| 66 | #define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \ | ||
| 67 | rbtype, rbaugmented, rbcompute) \ | ||
| 68 | static inline void \ | ||
| 69 | rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \ | ||
| 70 | { \ | ||
| 71 | while (rb != stop) { \ | ||
| 72 | rbstruct *node = rb_entry(rb, rbstruct, rbfield); \ | ||
| 73 | rbtype augmented = rbcompute(node); \ | ||
| 74 | if (node->rbaugmented == augmented) \ | ||
| 75 | break; \ | ||
| 76 | node->rbaugmented = augmented; \ | ||
| 77 | rb = rb_parent(&node->rbfield); \ | ||
| 78 | } \ | ||
| 79 | } \ | ||
| 80 | static inline void \ | ||
| 81 | rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \ | ||
| 82 | { \ | ||
| 83 | rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ | ||
| 84 | rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ | ||
| 85 | new->rbaugmented = old->rbaugmented; \ | ||
| 86 | } \ | ||
| 87 | static void \ | ||
| 88 | rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \ | ||
| 89 | { \ | ||
| 90 | rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \ | ||
| 91 | rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \ | ||
| 92 | new->rbaugmented = old->rbaugmented; \ | ||
| 93 | old->rbaugmented = rbcompute(old); \ | ||
| 94 | } \ | ||
| 95 | rbstatic const struct rb_augment_callbacks rbname = { \ | ||
| 96 | rbname ## _propagate, rbname ## _copy, rbname ## _rotate \ | ||
| 97 | }; | ||
| 98 | |||
| 99 | |||
| 100 | #define RB_RED 0 | ||
| 101 | #define RB_BLACK 1 | ||
| 102 | |||
| 103 | #define __rb_parent(pc) ((struct rb_node *)(pc & ~3)) | ||
| 104 | |||
| 105 | #define __rb_color(pc) ((pc) & 1) | ||
| 106 | #define __rb_is_black(pc) __rb_color(pc) | ||
| 107 | #define __rb_is_red(pc) (!__rb_color(pc)) | ||
| 108 | #define rb_color(rb) __rb_color((rb)->__rb_parent_color) | ||
| 109 | #define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color) | ||
| 110 | #define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color) | ||
| 111 | |||
| 112 | static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) | ||
| 113 | { | ||
| 114 | rb->__rb_parent_color = rb_color(rb) | (unsigned long)p; | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline void rb_set_parent_color(struct rb_node *rb, | ||
| 118 | struct rb_node *p, int color) | ||
| 119 | { | ||
| 120 | rb->__rb_parent_color = (unsigned long)p | color; | ||
| 121 | } | ||
| 122 | |||
| 123 | static inline void | ||
| 124 | __rb_change_child(struct rb_node *old, struct rb_node *new, | ||
| 125 | struct rb_node *parent, struct rb_root *root) | ||
| 126 | { | ||
| 127 | if (parent) { | ||
| 128 | if (parent->rb_left == old) | ||
| 129 | parent->rb_left = new; | ||
| 130 | else | ||
| 131 | parent->rb_right = new; | ||
| 132 | } else | ||
| 133 | root->rb_node = new; | ||
| 134 | } | ||
| 135 | |||
| 136 | extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | ||
| 137 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)); | ||
| 138 | |||
| 139 | static __always_inline struct rb_node * | ||
| 140 | __rb_erase_augmented(struct rb_node *node, struct rb_root *root, | ||
| 141 | const struct rb_augment_callbacks *augment) | ||
| 142 | { | ||
| 143 | struct rb_node *child = node->rb_right, *tmp = node->rb_left; | ||
| 144 | struct rb_node *parent, *rebalance; | ||
| 145 | unsigned long pc; | ||
| 146 | |||
| 147 | if (!tmp) { | ||
| 148 | /* | ||
| 149 | * Case 1: node to erase has no more than 1 child (easy!) | ||
| 150 | * | ||
| 151 | * Note that if there is one child it must be red due to 5) | ||
| 152 | * and node must be black due to 4). We adjust colors locally | ||
| 153 | * so as to bypass __rb_erase_color() later on. | ||
| 154 | */ | ||
| 155 | pc = node->__rb_parent_color; | ||
| 156 | parent = __rb_parent(pc); | ||
| 157 | __rb_change_child(node, child, parent, root); | ||
| 158 | if (child) { | ||
| 159 | child->__rb_parent_color = pc; | ||
| 160 | rebalance = NULL; | ||
| 161 | } else | ||
| 162 | rebalance = __rb_is_black(pc) ? parent : NULL; | ||
| 163 | tmp = parent; | ||
| 164 | } else if (!child) { | ||
| 165 | /* Still case 1, but this time the child is node->rb_left */ | ||
| 166 | tmp->__rb_parent_color = pc = node->__rb_parent_color; | ||
| 167 | parent = __rb_parent(pc); | ||
| 168 | __rb_change_child(node, tmp, parent, root); | ||
| 169 | rebalance = NULL; | ||
| 170 | tmp = parent; | ||
| 171 | } else { | ||
| 172 | struct rb_node *successor = child, *child2; | ||
| 173 | tmp = child->rb_left; | ||
| 174 | if (!tmp) { | ||
| 175 | /* | ||
| 176 | * Case 2: node's successor is its right child | ||
| 177 | * | ||
| 178 | * (n) (s) | ||
| 179 | * / \ / \ | ||
| 180 | * (x) (s) -> (x) (c) | ||
| 181 | * \ | ||
| 182 | * (c) | ||
| 183 | */ | ||
| 184 | parent = successor; | ||
| 185 | child2 = successor->rb_right; | ||
| 186 | augment->copy(node, successor); | ||
| 187 | } else { | ||
| 188 | /* | ||
| 189 | * Case 3: node's successor is leftmost under | ||
| 190 | * node's right child subtree | ||
| 191 | * | ||
| 192 | * (n) (s) | ||
| 193 | * / \ / \ | ||
| 194 | * (x) (y) -> (x) (y) | ||
| 195 | * / / | ||
| 196 | * (p) (p) | ||
| 197 | * / / | ||
| 198 | * (s) (c) | ||
| 199 | * \ | ||
| 200 | * (c) | ||
| 201 | */ | ||
| 202 | do { | ||
| 203 | parent = successor; | ||
| 204 | successor = tmp; | ||
| 205 | tmp = tmp->rb_left; | ||
| 206 | } while (tmp); | ||
| 207 | parent->rb_left = child2 = successor->rb_right; | ||
| 208 | successor->rb_right = child; | ||
| 209 | rb_set_parent(child, successor); | ||
| 210 | augment->copy(node, successor); | ||
| 211 | augment->propagate(parent, successor); | ||
| 212 | } | ||
| 213 | |||
| 214 | successor->rb_left = tmp = node->rb_left; | ||
| 215 | rb_set_parent(tmp, successor); | ||
| 216 | |||
| 217 | pc = node->__rb_parent_color; | ||
| 218 | tmp = __rb_parent(pc); | ||
| 219 | __rb_change_child(node, successor, tmp, root); | ||
| 220 | if (child2) { | ||
| 221 | successor->__rb_parent_color = pc; | ||
| 222 | rb_set_parent_color(child2, parent, RB_BLACK); | ||
| 223 | rebalance = NULL; | ||
| 224 | } else { | ||
| 225 | unsigned long pc2 = successor->__rb_parent_color; | ||
| 226 | successor->__rb_parent_color = pc; | ||
| 227 | rebalance = __rb_is_black(pc2) ? parent : NULL; | ||
| 228 | } | ||
| 229 | tmp = successor; | ||
| 230 | } | ||
| 231 | |||
| 232 | augment->propagate(tmp, NULL); | ||
| 233 | return rebalance; | ||
| 234 | } | ||
| 235 | |||
| 236 | static __always_inline void | ||
| 237 | rb_erase_augmented(struct rb_node *node, struct rb_root *root, | ||
| 238 | const struct rb_augment_callbacks *augment) | ||
| 239 | { | ||
| 240 | struct rb_node *rebalance = __rb_erase_augmented(node, root, augment); | ||
| 241 | if (rebalance) | ||
| 242 | __rb_erase_color(rebalance, root, augment->rotate); | ||
| 243 | } | ||
| 244 | |||
| 245 | #endif /* _TOOLS_LINUX_RBTREE_AUGMENTED_H */ | ||
diff --git a/tools/lib/rbtree.c b/tools/lib/rbtree.c new file mode 100644 index 000000000000..17c2b596f043 --- /dev/null +++ b/tools/lib/rbtree.c | |||
| @@ -0,0 +1,548 @@ | |||
| 1 | /* | ||
| 2 | Red Black Trees | ||
| 3 | (C) 1999 Andrea Arcangeli <andrea@suse.de> | ||
| 4 | (C) 2002 David Woodhouse <dwmw2@infradead.org> | ||
| 5 | (C) 2012 Michel Lespinasse <walken@google.com> | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software | ||
| 19 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 20 | |||
| 21 | linux/lib/rbtree.c | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/rbtree_augmented.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * red-black trees properties: http://en.wikipedia.org/wiki/Rbtree | ||
| 28 | * | ||
| 29 | * 1) A node is either red or black | ||
| 30 | * 2) The root is black | ||
| 31 | * 3) All leaves (NULL) are black | ||
| 32 | * 4) Both children of every red node are black | ||
| 33 | * 5) Every simple path from root to leaves contains the same number | ||
| 34 | * of black nodes. | ||
| 35 | * | ||
| 36 | * 4 and 5 give the O(log n) guarantee, since 4 implies you cannot have two | ||
| 37 | * consecutive red nodes in a path and every red node is therefore followed by | ||
| 38 | * a black. So if B is the number of black nodes on every simple path (as per | ||
| 39 | * 5), then the longest possible path due to 4 is 2B. | ||
| 40 | * | ||
| 41 | * We shall indicate color with case, where black nodes are uppercase and red | ||
| 42 | * nodes will be lowercase. Unknown color nodes shall be drawn as red within | ||
| 43 | * parentheses and have some accompanying text comment. | ||
| 44 | */ | ||
| 45 | |||
| 46 | static inline void rb_set_black(struct rb_node *rb) | ||
| 47 | { | ||
| 48 | rb->__rb_parent_color |= RB_BLACK; | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline struct rb_node *rb_red_parent(struct rb_node *red) | ||
| 52 | { | ||
| 53 | return (struct rb_node *)red->__rb_parent_color; | ||
| 54 | } | ||
| 55 | |||
| 56 | /* | ||
| 57 | * Helper function for rotations: | ||
| 58 | * - old's parent and color get assigned to new | ||
| 59 | * - old gets assigned new as a parent and 'color' as a color. | ||
| 60 | */ | ||
| 61 | static inline void | ||
| 62 | __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new, | ||
| 63 | struct rb_root *root, int color) | ||
| 64 | { | ||
| 65 | struct rb_node *parent = rb_parent(old); | ||
| 66 | new->__rb_parent_color = old->__rb_parent_color; | ||
| 67 | rb_set_parent_color(old, new, color); | ||
| 68 | __rb_change_child(old, new, parent, root); | ||
| 69 | } | ||
| 70 | |||
| 71 | static __always_inline void | ||
| 72 | __rb_insert(struct rb_node *node, struct rb_root *root, | ||
| 73 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | ||
| 74 | { | ||
| 75 | struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; | ||
| 76 | |||
| 77 | while (true) { | ||
| 78 | /* | ||
| 79 | * Loop invariant: node is red | ||
| 80 | * | ||
| 81 | * If there is a black parent, we are done. | ||
| 82 | * Otherwise, take some corrective action as we don't | ||
| 83 | * want a red root or two consecutive red nodes. | ||
| 84 | */ | ||
| 85 | if (!parent) { | ||
| 86 | rb_set_parent_color(node, NULL, RB_BLACK); | ||
| 87 | break; | ||
| 88 | } else if (rb_is_black(parent)) | ||
| 89 | break; | ||
| 90 | |||
| 91 | gparent = rb_red_parent(parent); | ||
| 92 | |||
| 93 | tmp = gparent->rb_right; | ||
| 94 | if (parent != tmp) { /* parent == gparent->rb_left */ | ||
| 95 | if (tmp && rb_is_red(tmp)) { | ||
| 96 | /* | ||
| 97 | * Case 1 - color flips | ||
| 98 | * | ||
| 99 | * G g | ||
| 100 | * / \ / \ | ||
| 101 | * p u --> P U | ||
| 102 | * / / | ||
| 103 | * n n | ||
| 104 | * | ||
| 105 | * However, since g's parent might be red, and | ||
| 106 | * 4) does not allow this, we need to recurse | ||
| 107 | * at g. | ||
| 108 | */ | ||
| 109 | rb_set_parent_color(tmp, gparent, RB_BLACK); | ||
| 110 | rb_set_parent_color(parent, gparent, RB_BLACK); | ||
| 111 | node = gparent; | ||
| 112 | parent = rb_parent(node); | ||
| 113 | rb_set_parent_color(node, parent, RB_RED); | ||
| 114 | continue; | ||
| 115 | } | ||
| 116 | |||
| 117 | tmp = parent->rb_right; | ||
| 118 | if (node == tmp) { | ||
| 119 | /* | ||
| 120 | * Case 2 - left rotate at parent | ||
| 121 | * | ||
| 122 | * G G | ||
| 123 | * / \ / \ | ||
| 124 | * p U --> n U | ||
| 125 | * \ / | ||
| 126 | * n p | ||
| 127 | * | ||
| 128 | * This still leaves us in violation of 4), the | ||
| 129 | * continuation into Case 3 will fix that. | ||
| 130 | */ | ||
| 131 | parent->rb_right = tmp = node->rb_left; | ||
| 132 | node->rb_left = parent; | ||
| 133 | if (tmp) | ||
| 134 | rb_set_parent_color(tmp, parent, | ||
| 135 | RB_BLACK); | ||
| 136 | rb_set_parent_color(parent, node, RB_RED); | ||
| 137 | augment_rotate(parent, node); | ||
| 138 | parent = node; | ||
| 139 | tmp = node->rb_right; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Case 3 - right rotate at gparent | ||
| 144 | * | ||
| 145 | * G P | ||
| 146 | * / \ / \ | ||
| 147 | * p U --> n g | ||
| 148 | * / \ | ||
| 149 | * n U | ||
| 150 | */ | ||
| 151 | gparent->rb_left = tmp; /* == parent->rb_right */ | ||
| 152 | parent->rb_right = gparent; | ||
| 153 | if (tmp) | ||
| 154 | rb_set_parent_color(tmp, gparent, RB_BLACK); | ||
| 155 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); | ||
| 156 | augment_rotate(gparent, parent); | ||
| 157 | break; | ||
| 158 | } else { | ||
| 159 | tmp = gparent->rb_left; | ||
| 160 | if (tmp && rb_is_red(tmp)) { | ||
| 161 | /* Case 1 - color flips */ | ||
| 162 | rb_set_parent_color(tmp, gparent, RB_BLACK); | ||
| 163 | rb_set_parent_color(parent, gparent, RB_BLACK); | ||
| 164 | node = gparent; | ||
| 165 | parent = rb_parent(node); | ||
| 166 | rb_set_parent_color(node, parent, RB_RED); | ||
| 167 | continue; | ||
| 168 | } | ||
| 169 | |||
| 170 | tmp = parent->rb_left; | ||
| 171 | if (node == tmp) { | ||
| 172 | /* Case 2 - right rotate at parent */ | ||
| 173 | parent->rb_left = tmp = node->rb_right; | ||
| 174 | node->rb_right = parent; | ||
| 175 | if (tmp) | ||
| 176 | rb_set_parent_color(tmp, parent, | ||
| 177 | RB_BLACK); | ||
| 178 | rb_set_parent_color(parent, node, RB_RED); | ||
| 179 | augment_rotate(parent, node); | ||
| 180 | parent = node; | ||
| 181 | tmp = node->rb_left; | ||
| 182 | } | ||
| 183 | |||
| 184 | /* Case 3 - left rotate at gparent */ | ||
| 185 | gparent->rb_right = tmp; /* == parent->rb_left */ | ||
| 186 | parent->rb_left = gparent; | ||
| 187 | if (tmp) | ||
| 188 | rb_set_parent_color(tmp, gparent, RB_BLACK); | ||
| 189 | __rb_rotate_set_parents(gparent, parent, root, RB_RED); | ||
| 190 | augment_rotate(gparent, parent); | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | /* | ||
| 197 | * Inline version for rb_erase() use - we want to be able to inline | ||
| 198 | * and eliminate the dummy_rotate callback there | ||
| 199 | */ | ||
| 200 | static __always_inline void | ||
| 201 | ____rb_erase_color(struct rb_node *parent, struct rb_root *root, | ||
| 202 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | ||
| 203 | { | ||
| 204 | struct rb_node *node = NULL, *sibling, *tmp1, *tmp2; | ||
| 205 | |||
| 206 | while (true) { | ||
| 207 | /* | ||
| 208 | * Loop invariants: | ||
| 209 | * - node is black (or NULL on first iteration) | ||
| 210 | * - node is not the root (parent is not NULL) | ||
| 211 | * - All leaf paths going through parent and node have a | ||
| 212 | * black node count that is 1 lower than other leaf paths. | ||
| 213 | */ | ||
| 214 | sibling = parent->rb_right; | ||
| 215 | if (node != sibling) { /* node == parent->rb_left */ | ||
| 216 | if (rb_is_red(sibling)) { | ||
| 217 | /* | ||
| 218 | * Case 1 - left rotate at parent | ||
| 219 | * | ||
| 220 | * P S | ||
| 221 | * / \ / \ | ||
| 222 | * N s --> p Sr | ||
| 223 | * / \ / \ | ||
| 224 | * Sl Sr N Sl | ||
| 225 | */ | ||
| 226 | parent->rb_right = tmp1 = sibling->rb_left; | ||
| 227 | sibling->rb_left = parent; | ||
| 228 | rb_set_parent_color(tmp1, parent, RB_BLACK); | ||
| 229 | __rb_rotate_set_parents(parent, sibling, root, | ||
| 230 | RB_RED); | ||
| 231 | augment_rotate(parent, sibling); | ||
| 232 | sibling = tmp1; | ||
| 233 | } | ||
| 234 | tmp1 = sibling->rb_right; | ||
| 235 | if (!tmp1 || rb_is_black(tmp1)) { | ||
| 236 | tmp2 = sibling->rb_left; | ||
| 237 | if (!tmp2 || rb_is_black(tmp2)) { | ||
| 238 | /* | ||
| 239 | * Case 2 - sibling color flip | ||
| 240 | * (p could be either color here) | ||
| 241 | * | ||
| 242 | * (p) (p) | ||
| 243 | * / \ / \ | ||
| 244 | * N S --> N s | ||
| 245 | * / \ / \ | ||
| 246 | * Sl Sr Sl Sr | ||
| 247 | * | ||
| 248 | * This leaves us violating 5) which | ||
| 249 | * can be fixed by flipping p to black | ||
| 250 | * if it was red, or by recursing at p. | ||
| 251 | * p is red when coming from Case 1. | ||
| 252 | */ | ||
| 253 | rb_set_parent_color(sibling, parent, | ||
| 254 | RB_RED); | ||
| 255 | if (rb_is_red(parent)) | ||
| 256 | rb_set_black(parent); | ||
| 257 | else { | ||
| 258 | node = parent; | ||
| 259 | parent = rb_parent(node); | ||
| 260 | if (parent) | ||
| 261 | continue; | ||
| 262 | } | ||
| 263 | break; | ||
| 264 | } | ||
| 265 | /* | ||
| 266 | * Case 3 - right rotate at sibling | ||
| 267 | * (p could be either color here) | ||
| 268 | * | ||
| 269 | * (p) (p) | ||
| 270 | * / \ / \ | ||
| 271 | * N S --> N Sl | ||
| 272 | * / \ \ | ||
| 273 | * sl Sr s | ||
| 274 | * \ | ||
| 275 | * Sr | ||
| 276 | */ | ||
| 277 | sibling->rb_left = tmp1 = tmp2->rb_right; | ||
| 278 | tmp2->rb_right = sibling; | ||
| 279 | parent->rb_right = tmp2; | ||
| 280 | if (tmp1) | ||
| 281 | rb_set_parent_color(tmp1, sibling, | ||
| 282 | RB_BLACK); | ||
| 283 | augment_rotate(sibling, tmp2); | ||
| 284 | tmp1 = sibling; | ||
| 285 | sibling = tmp2; | ||
| 286 | } | ||
| 287 | /* | ||
| 288 | * Case 4 - left rotate at parent + color flips | ||
| 289 | * (p and sl could be either color here. | ||
| 290 | * After rotation, p becomes black, s acquires | ||
| 291 | * p's color, and sl keeps its color) | ||
| 292 | * | ||
| 293 | * (p) (s) | ||
| 294 | * / \ / \ | ||
| 295 | * N S --> P Sr | ||
| 296 | * / \ / \ | ||
| 297 | * (sl) sr N (sl) | ||
| 298 | */ | ||
| 299 | parent->rb_right = tmp2 = sibling->rb_left; | ||
| 300 | sibling->rb_left = parent; | ||
| 301 | rb_set_parent_color(tmp1, sibling, RB_BLACK); | ||
| 302 | if (tmp2) | ||
| 303 | rb_set_parent(tmp2, parent); | ||
| 304 | __rb_rotate_set_parents(parent, sibling, root, | ||
| 305 | RB_BLACK); | ||
| 306 | augment_rotate(parent, sibling); | ||
| 307 | break; | ||
| 308 | } else { | ||
| 309 | sibling = parent->rb_left; | ||
| 310 | if (rb_is_red(sibling)) { | ||
| 311 | /* Case 1 - right rotate at parent */ | ||
| 312 | parent->rb_left = tmp1 = sibling->rb_right; | ||
| 313 | sibling->rb_right = parent; | ||
| 314 | rb_set_parent_color(tmp1, parent, RB_BLACK); | ||
| 315 | __rb_rotate_set_parents(parent, sibling, root, | ||
| 316 | RB_RED); | ||
| 317 | augment_rotate(parent, sibling); | ||
| 318 | sibling = tmp1; | ||
| 319 | } | ||
| 320 | tmp1 = sibling->rb_left; | ||
| 321 | if (!tmp1 || rb_is_black(tmp1)) { | ||
| 322 | tmp2 = sibling->rb_right; | ||
| 323 | if (!tmp2 || rb_is_black(tmp2)) { | ||
| 324 | /* Case 2 - sibling color flip */ | ||
| 325 | rb_set_parent_color(sibling, parent, | ||
| 326 | RB_RED); | ||
| 327 | if (rb_is_red(parent)) | ||
| 328 | rb_set_black(parent); | ||
| 329 | else { | ||
| 330 | node = parent; | ||
| 331 | parent = rb_parent(node); | ||
| 332 | if (parent) | ||
| 333 | continue; | ||
| 334 | } | ||
| 335 | break; | ||
| 336 | } | ||
| 337 | /* Case 3 - right rotate at sibling */ | ||
| 338 | sibling->rb_right = tmp1 = tmp2->rb_left; | ||
| 339 | tmp2->rb_left = sibling; | ||
| 340 | parent->rb_left = tmp2; | ||
| 341 | if (tmp1) | ||
| 342 | rb_set_parent_color(tmp1, sibling, | ||
| 343 | RB_BLACK); | ||
| 344 | augment_rotate(sibling, tmp2); | ||
| 345 | tmp1 = sibling; | ||
| 346 | sibling = tmp2; | ||
| 347 | } | ||
| 348 | /* Case 4 - left rotate at parent + color flips */ | ||
| 349 | parent->rb_left = tmp2 = sibling->rb_right; | ||
| 350 | sibling->rb_right = parent; | ||
| 351 | rb_set_parent_color(tmp1, sibling, RB_BLACK); | ||
| 352 | if (tmp2) | ||
| 353 | rb_set_parent(tmp2, parent); | ||
| 354 | __rb_rotate_set_parents(parent, sibling, root, | ||
| 355 | RB_BLACK); | ||
| 356 | augment_rotate(parent, sibling); | ||
| 357 | break; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | /* Non-inline version for rb_erase_augmented() use */ | ||
| 363 | void __rb_erase_color(struct rb_node *parent, struct rb_root *root, | ||
| 364 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | ||
| 365 | { | ||
| 366 | ____rb_erase_color(parent, root, augment_rotate); | ||
| 367 | } | ||
| 368 | |||
| 369 | /* | ||
| 370 | * Non-augmented rbtree manipulation functions. | ||
| 371 | * | ||
| 372 | * We use dummy augmented callbacks here, and have the compiler optimize them | ||
| 373 | * out of the rb_insert_color() and rb_erase() function definitions. | ||
| 374 | */ | ||
| 375 | |||
| 376 | static inline void dummy_propagate(struct rb_node *node, struct rb_node *stop) {} | ||
| 377 | static inline void dummy_copy(struct rb_node *old, struct rb_node *new) {} | ||
| 378 | static inline void dummy_rotate(struct rb_node *old, struct rb_node *new) {} | ||
| 379 | |||
| 380 | static const struct rb_augment_callbacks dummy_callbacks = { | ||
| 381 | dummy_propagate, dummy_copy, dummy_rotate | ||
| 382 | }; | ||
| 383 | |||
| 384 | void rb_insert_color(struct rb_node *node, struct rb_root *root) | ||
| 385 | { | ||
| 386 | __rb_insert(node, root, dummy_rotate); | ||
| 387 | } | ||
| 388 | |||
| 389 | void rb_erase(struct rb_node *node, struct rb_root *root) | ||
| 390 | { | ||
| 391 | struct rb_node *rebalance; | ||
| 392 | rebalance = __rb_erase_augmented(node, root, &dummy_callbacks); | ||
| 393 | if (rebalance) | ||
| 394 | ____rb_erase_color(rebalance, root, dummy_rotate); | ||
| 395 | } | ||
| 396 | |||
| 397 | /* | ||
| 398 | * Augmented rbtree manipulation functions. | ||
| 399 | * | ||
| 400 | * This instantiates the same __always_inline functions as in the non-augmented | ||
| 401 | * case, but this time with user-defined callbacks. | ||
| 402 | */ | ||
| 403 | |||
| 404 | void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, | ||
| 405 | void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) | ||
| 406 | { | ||
| 407 | __rb_insert(node, root, augment_rotate); | ||
| 408 | } | ||
| 409 | |||
| 410 | /* | ||
| 411 | * This function returns the first node (in sort order) of the tree. | ||
| 412 | */ | ||
| 413 | struct rb_node *rb_first(const struct rb_root *root) | ||
| 414 | { | ||
| 415 | struct rb_node *n; | ||
| 416 | |||
| 417 | n = root->rb_node; | ||
| 418 | if (!n) | ||
| 419 | return NULL; | ||
| 420 | while (n->rb_left) | ||
| 421 | n = n->rb_left; | ||
| 422 | return n; | ||
| 423 | } | ||
| 424 | |||
| 425 | struct rb_node *rb_last(const struct rb_root *root) | ||
| 426 | { | ||
| 427 | struct rb_node *n; | ||
| 428 | |||
| 429 | n = root->rb_node; | ||
| 430 | if (!n) | ||
| 431 | return NULL; | ||
| 432 | while (n->rb_right) | ||
| 433 | n = n->rb_right; | ||
| 434 | return n; | ||
| 435 | } | ||
| 436 | |||
| 437 | struct rb_node *rb_next(const struct rb_node *node) | ||
| 438 | { | ||
| 439 | struct rb_node *parent; | ||
| 440 | |||
| 441 | if (RB_EMPTY_NODE(node)) | ||
| 442 | return NULL; | ||
| 443 | |||
| 444 | /* | ||
| 445 | * If we have a right-hand child, go down and then left as far | ||
| 446 | * as we can. | ||
| 447 | */ | ||
| 448 | if (node->rb_right) { | ||
| 449 | node = node->rb_right; | ||
| 450 | while (node->rb_left) | ||
| 451 | node=node->rb_left; | ||
| 452 | return (struct rb_node *)node; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* | ||
| 456 | * No right-hand children. Everything down and left is smaller than us, | ||
| 457 | * so any 'next' node must be in the general direction of our parent. | ||
| 458 | * Go up the tree; any time the ancestor is a right-hand child of its | ||
| 459 | * parent, keep going up. First time it's a left-hand child of its | ||
| 460 | * parent, said parent is our 'next' node. | ||
| 461 | */ | ||
| 462 | while ((parent = rb_parent(node)) && node == parent->rb_right) | ||
| 463 | node = parent; | ||
| 464 | |||
| 465 | return parent; | ||
| 466 | } | ||
| 467 | |||
| 468 | struct rb_node *rb_prev(const struct rb_node *node) | ||
| 469 | { | ||
| 470 | struct rb_node *parent; | ||
| 471 | |||
| 472 | if (RB_EMPTY_NODE(node)) | ||
| 473 | return NULL; | ||
| 474 | |||
| 475 | /* | ||
| 476 | * If we have a left-hand child, go down and then right as far | ||
| 477 | * as we can. | ||
| 478 | */ | ||
| 479 | if (node->rb_left) { | ||
| 480 | node = node->rb_left; | ||
| 481 | while (node->rb_right) | ||
| 482 | node=node->rb_right; | ||
| 483 | return (struct rb_node *)node; | ||
| 484 | } | ||
| 485 | |||
| 486 | /* | ||
| 487 | * No left-hand children. Go up till we find an ancestor which | ||
| 488 | * is a right-hand child of its parent. | ||
| 489 | */ | ||
| 490 | while ((parent = rb_parent(node)) && node == parent->rb_left) | ||
| 491 | node = parent; | ||
| 492 | |||
| 493 | return parent; | ||
| 494 | } | ||
| 495 | |||
| 496 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, | ||
| 497 | struct rb_root *root) | ||
| 498 | { | ||
| 499 | struct rb_node *parent = rb_parent(victim); | ||
| 500 | |||
| 501 | /* Set the surrounding nodes to point to the replacement */ | ||
| 502 | __rb_change_child(victim, new, parent, root); | ||
| 503 | if (victim->rb_left) | ||
| 504 | rb_set_parent(victim->rb_left, new); | ||
| 505 | if (victim->rb_right) | ||
| 506 | rb_set_parent(victim->rb_right, new); | ||
| 507 | |||
| 508 | /* Copy the pointers/colour from the victim to the replacement */ | ||
| 509 | *new = *victim; | ||
| 510 | } | ||
| 511 | |||
| 512 | static struct rb_node *rb_left_deepest_node(const struct rb_node *node) | ||
| 513 | { | ||
| 514 | for (;;) { | ||
| 515 | if (node->rb_left) | ||
| 516 | node = node->rb_left; | ||
| 517 | else if (node->rb_right) | ||
| 518 | node = node->rb_right; | ||
| 519 | else | ||
| 520 | return (struct rb_node *)node; | ||
| 521 | } | ||
| 522 | } | ||
| 523 | |||
| 524 | struct rb_node *rb_next_postorder(const struct rb_node *node) | ||
| 525 | { | ||
| 526 | const struct rb_node *parent; | ||
| 527 | if (!node) | ||
| 528 | return NULL; | ||
| 529 | parent = rb_parent(node); | ||
| 530 | |||
| 531 | /* If we're sitting on node, we've already seen our children */ | ||
| 532 | if (parent && node == parent->rb_left && parent->rb_right) { | ||
| 533 | /* If we are the parent's left node, go to the parent's right | ||
| 534 | * node then all the way down to the left */ | ||
| 535 | return rb_left_deepest_node(parent->rb_right); | ||
| 536 | } else | ||
| 537 | /* Otherwise we are the parent's right node, and the parent | ||
| 538 | * should be next */ | ||
| 539 | return (struct rb_node *)parent; | ||
| 540 | } | ||
| 541 | |||
| 542 | struct rb_node *rb_first_postorder(const struct rb_root *root) | ||
| 543 | { | ||
| 544 | if (!root->rb_node) | ||
| 545 | return NULL; | ||
| 546 | |||
| 547 | return rb_left_deepest_node(root->rb_node); | ||
| 548 | } | ||
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index fe50a1b34aa0..09dc0aabb515 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST | |||
| @@ -18,6 +18,7 @@ tools/arch/x86/include/asm/atomic.h | |||
| 18 | tools/arch/x86/include/asm/rmwcc.h | 18 | tools/arch/x86/include/asm/rmwcc.h |
| 19 | tools/lib/traceevent | 19 | tools/lib/traceevent |
| 20 | tools/lib/api | 20 | tools/lib/api |
| 21 | tools/lib/rbtree.c | ||
| 21 | tools/lib/symbol/kallsyms.c | 22 | tools/lib/symbol/kallsyms.c |
| 22 | tools/lib/symbol/kallsyms.h | 23 | tools/lib/symbol/kallsyms.h |
| 23 | tools/lib/util/find_next_bit.c | 24 | tools/lib/util/find_next_bit.c |
| @@ -44,6 +45,8 @@ tools/include/linux/kernel.h | |||
| 44 | tools/include/linux/list.h | 45 | tools/include/linux/list.h |
| 45 | tools/include/linux/log2.h | 46 | tools/include/linux/log2.h |
| 46 | tools/include/linux/poison.h | 47 | tools/include/linux/poison.h |
| 48 | tools/include/linux/rbtree.h | ||
| 49 | tools/include/linux/rbtree_augmented.h | ||
| 47 | tools/include/linux/types.h | 50 | tools/include/linux/types.h |
| 48 | include/asm-generic/bitops/arch_hweight.h | 51 | include/asm-generic/bitops/arch_hweight.h |
| 49 | include/asm-generic/bitops/const_hweight.h | 52 | include/asm-generic/bitops/const_hweight.h |
| @@ -51,12 +54,10 @@ include/asm-generic/bitops/fls64.h | |||
| 51 | include/asm-generic/bitops/__fls.h | 54 | include/asm-generic/bitops/__fls.h |
| 52 | include/asm-generic/bitops/fls.h | 55 | include/asm-generic/bitops/fls.h |
| 53 | include/linux/perf_event.h | 56 | include/linux/perf_event.h |
| 54 | include/linux/rbtree.h | ||
| 55 | include/linux/list.h | 57 | include/linux/list.h |
| 56 | include/linux/hash.h | 58 | include/linux/hash.h |
| 57 | include/linux/stringify.h | 59 | include/linux/stringify.h |
| 58 | lib/hweight.c | 60 | lib/hweight.c |
| 59 | lib/rbtree.c | ||
| 60 | include/linux/swab.h | 61 | include/linux/swab.h |
| 61 | arch/*/include/asm/unistd*.h | 62 | arch/*/include/asm/unistd*.h |
| 62 | arch/*/include/uapi/asm/unistd*.h | 63 | arch/*/include/uapi/asm/unistd*.h |
| @@ -65,7 +66,6 @@ arch/*/lib/memcpy*.S | |||
| 65 | arch/*/lib/memset*.S | 66 | arch/*/lib/memset*.S |
| 66 | include/linux/poison.h | 67 | include/linux/poison.h |
| 67 | include/linux/hw_breakpoint.h | 68 | include/linux/hw_breakpoint.h |
| 68 | include/linux/rbtree_augmented.h | ||
| 69 | include/uapi/linux/perf_event.h | 69 | include/uapi/linux/perf_event.h |
| 70 | include/uapi/linux/const.h | 70 | include/uapi/linux/const.h |
| 71 | include/uapi/linux/swab.h | 71 | include/uapi/linux/swab.h |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 586a59d46022..601d11440596 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
| @@ -139,7 +139,7 @@ $(OUTPUT)util/find_next_bit.o: ../lib/util/find_next_bit.c FORCE | |||
| 139 | $(call rule_mkdir) | 139 | $(call rule_mkdir) |
| 140 | $(call if_changed_dep,cc_o_c) | 140 | $(call if_changed_dep,cc_o_c) |
| 141 | 141 | ||
| 142 | $(OUTPUT)util/rbtree.o: ../../lib/rbtree.c FORCE | 142 | $(OUTPUT)util/rbtree.o: ../lib/rbtree.c FORCE |
| 143 | $(call rule_mkdir) | 143 | $(call rule_mkdir) |
| 144 | $(call if_changed_dep,cc_o_c) | 144 | $(call if_changed_dep,cc_o_c) |
| 145 | 145 | ||
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h deleted file mode 100644 index f06d89f0b867..000000000000 --- a/tools/perf/util/include/linux/rbtree.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | #ifndef __TOOLS_LINUX_PERF_RBTREE_H | ||
| 2 | #define __TOOLS_LINUX_PERF_RBTREE_H | ||
| 3 | #include <stdbool.h> | ||
| 4 | #include "../../../../include/linux/rbtree.h" | ||
| 5 | |||
| 6 | /* | ||
| 7 | * Handy for checking that we are not deleting an entry that is | ||
| 8 | * already in a list, found in block/{blk-throttle,cfq-iosched}.c, | ||
| 9 | * probably should be moved to lib/rbtree.c... | ||
| 10 | */ | ||
| 11 | static inline void rb_erase_init(struct rb_node *n, struct rb_root *root) | ||
| 12 | { | ||
| 13 | rb_erase(n, root); | ||
| 14 | RB_CLEAR_NODE(n); | ||
| 15 | } | ||
| 16 | #endif /* __TOOLS_LINUX_PERF_RBTREE_H */ | ||
diff --git a/tools/perf/util/include/linux/rbtree_augmented.h b/tools/perf/util/include/linux/rbtree_augmented.h deleted file mode 100644 index 9d6fcdf1788b..000000000000 --- a/tools/perf/util/include/linux/rbtree_augmented.h +++ /dev/null | |||
| @@ -1,2 +0,0 @@ | |||
| 1 | #include <stdbool.h> | ||
| 2 | #include "../../../../include/linux/rbtree_augmented.h" | ||
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index 8e9b64520ec1..f56914c7929b 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild | |||
| @@ -1,3 +1,6 @@ | |||
| 1 | ldflags-y += --wrap=ioremap_wt | ||
| 2 | ldflags-y += --wrap=ioremap_wc | ||
| 3 | ldflags-y += --wrap=devm_ioremap_nocache | ||
| 1 | ldflags-y += --wrap=ioremap_cache | 4 | ldflags-y += --wrap=ioremap_cache |
| 2 | ldflags-y += --wrap=ioremap_nocache | 5 | ldflags-y += --wrap=ioremap_nocache |
| 3 | ldflags-y += --wrap=iounmap | 6 | ldflags-y += --wrap=iounmap |
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index c85a6f6ba559..64bfaa50831c 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c | |||
| @@ -65,6 +65,21 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, | |||
| 65 | return fallback_fn(offset, size); | 65 | return fallback_fn(offset, size); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | void __iomem *__wrap_devm_ioremap_nocache(struct device *dev, | ||
| 69 | resource_size_t offset, unsigned long size) | ||
| 70 | { | ||
| 71 | struct nfit_test_resource *nfit_res; | ||
| 72 | |||
| 73 | rcu_read_lock(); | ||
| 74 | nfit_res = get_nfit_res(offset); | ||
| 75 | rcu_read_unlock(); | ||
| 76 | if (nfit_res) | ||
| 77 | return (void __iomem *) nfit_res->buf + offset | ||
| 78 | - nfit_res->res->start; | ||
| 79 | return devm_ioremap_nocache(dev, offset, size); | ||
| 80 | } | ||
| 81 | EXPORT_SYMBOL(__wrap_devm_ioremap_nocache); | ||
| 82 | |||
| 68 | void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size) | 83 | void __iomem *__wrap_ioremap_cache(resource_size_t offset, unsigned long size) |
| 69 | { | 84 | { |
| 70 | return __nfit_test_ioremap(offset, size, ioremap_cache); | 85 | return __nfit_test_ioremap(offset, size, ioremap_cache); |
| @@ -77,6 +92,18 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size) | |||
| 77 | } | 92 | } |
| 78 | EXPORT_SYMBOL(__wrap_ioremap_nocache); | 93 | EXPORT_SYMBOL(__wrap_ioremap_nocache); |
| 79 | 94 | ||
| 95 | void __iomem *__wrap_ioremap_wt(resource_size_t offset, unsigned long size) | ||
| 96 | { | ||
| 97 | return __nfit_test_ioremap(offset, size, ioremap_wt); | ||
| 98 | } | ||
| 99 | EXPORT_SYMBOL(__wrap_ioremap_wt); | ||
| 100 | |||
| 101 | void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size) | ||
| 102 | { | ||
| 103 | return __nfit_test_ioremap(offset, size, ioremap_wc); | ||
| 104 | } | ||
| 105 | EXPORT_SYMBOL(__wrap_ioremap_wc); | ||
| 106 | |||
| 80 | void __wrap_iounmap(volatile void __iomem *addr) | 107 | void __wrap_iounmap(volatile void __iomem *addr) |
| 81 | { | 108 | { |
| 82 | struct nfit_test_resource *nfit_res; | 109 | struct nfit_test_resource *nfit_res; |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 4b69b8368de0..d0bdae40ccc9 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
| @@ -128,6 +128,8 @@ struct nfit_test { | |||
| 128 | int num_pm; | 128 | int num_pm; |
| 129 | void **dimm; | 129 | void **dimm; |
| 130 | dma_addr_t *dimm_dma; | 130 | dma_addr_t *dimm_dma; |
| 131 | void **flush; | ||
| 132 | dma_addr_t *flush_dma; | ||
| 131 | void **label; | 133 | void **label; |
| 132 | dma_addr_t *label_dma; | 134 | dma_addr_t *label_dma; |
| 133 | void **spa_set; | 135 | void **spa_set; |
| @@ -155,7 +157,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
| 155 | int i, rc; | 157 | int i, rc; |
| 156 | 158 | ||
| 157 | if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) | 159 | if (!nfit_mem || !test_bit(cmd, &nfit_mem->dsm_mask)) |
| 158 | return -ENXIO; | 160 | return -ENOTTY; |
| 159 | 161 | ||
| 160 | /* lookup label space for the given dimm */ | 162 | /* lookup label space for the given dimm */ |
| 161 | for (i = 0; i < ARRAY_SIZE(handle); i++) | 163 | for (i = 0; i < ARRAY_SIZE(handle); i++) |
| @@ -331,7 +333,8 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
| 331 | + sizeof(struct acpi_nfit_system_address) * NUM_SPA | 333 | + sizeof(struct acpi_nfit_system_address) * NUM_SPA |
| 332 | + sizeof(struct acpi_nfit_memory_map) * NUM_MEM | 334 | + sizeof(struct acpi_nfit_memory_map) * NUM_MEM |
| 333 | + sizeof(struct acpi_nfit_control_region) * NUM_DCR | 335 | + sizeof(struct acpi_nfit_control_region) * NUM_DCR |
| 334 | + sizeof(struct acpi_nfit_data_region) * NUM_BDW; | 336 | + sizeof(struct acpi_nfit_data_region) * NUM_BDW |
| 337 | + sizeof(struct acpi_nfit_flush_address) * NUM_DCR; | ||
| 335 | int i; | 338 | int i; |
| 336 | 339 | ||
| 337 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); | 340 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); |
| @@ -356,6 +359,10 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
| 356 | if (!t->label[i]) | 359 | if (!t->label[i]) |
| 357 | return -ENOMEM; | 360 | return -ENOMEM; |
| 358 | sprintf(t->label[i], "label%d", i); | 361 | sprintf(t->label[i], "label%d", i); |
| 362 | |||
| 363 | t->flush[i] = test_alloc(t, 8, &t->flush_dma[i]); | ||
| 364 | if (!t->flush[i]) | ||
| 365 | return -ENOMEM; | ||
| 359 | } | 366 | } |
| 360 | 367 | ||
| 361 | for (i = 0; i < NUM_DCR; i++) { | 368 | for (i = 0; i < NUM_DCR; i++) { |
| @@ -408,6 +415,7 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
| 408 | struct acpi_nfit_system_address *spa; | 415 | struct acpi_nfit_system_address *spa; |
| 409 | struct acpi_nfit_control_region *dcr; | 416 | struct acpi_nfit_control_region *dcr; |
| 410 | struct acpi_nfit_data_region *bdw; | 417 | struct acpi_nfit_data_region *bdw; |
| 418 | struct acpi_nfit_flush_address *flush; | ||
| 411 | unsigned int offset; | 419 | unsigned int offset; |
| 412 | 420 | ||
| 413 | nfit_test_init_header(nfit_buf, size); | 421 | nfit_test_init_header(nfit_buf, size); |
| @@ -831,6 +839,39 @@ static void nfit_test0_setup(struct nfit_test *t) | |||
| 831 | bdw->capacity = DIMM_SIZE; | 839 | bdw->capacity = DIMM_SIZE; |
| 832 | bdw->start_address = 0; | 840 | bdw->start_address = 0; |
| 833 | 841 | ||
| 842 | offset = offset + sizeof(struct acpi_nfit_data_region) * 4; | ||
| 843 | /* flush0 (dimm0) */ | ||
| 844 | flush = nfit_buf + offset; | ||
| 845 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | ||
| 846 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | ||
| 847 | flush->device_handle = handle[0]; | ||
| 848 | flush->hint_count = 1; | ||
| 849 | flush->hint_address[0] = t->flush_dma[0]; | ||
| 850 | |||
| 851 | /* flush1 (dimm1) */ | ||
| 852 | flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 1; | ||
| 853 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | ||
| 854 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | ||
| 855 | flush->device_handle = handle[1]; | ||
| 856 | flush->hint_count = 1; | ||
| 857 | flush->hint_address[0] = t->flush_dma[1]; | ||
| 858 | |||
| 859 | /* flush2 (dimm2) */ | ||
| 860 | flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 2; | ||
| 861 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | ||
| 862 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | ||
| 863 | flush->device_handle = handle[2]; | ||
| 864 | flush->hint_count = 1; | ||
| 865 | flush->hint_address[0] = t->flush_dma[2]; | ||
| 866 | |||
| 867 | /* flush3 (dimm3) */ | ||
| 868 | flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 3; | ||
| 869 | flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; | ||
| 870 | flush->header.length = sizeof(struct acpi_nfit_flush_address); | ||
| 871 | flush->device_handle = handle[3]; | ||
| 872 | flush->hint_count = 1; | ||
| 873 | flush->hint_address[0] = t->flush_dma[3]; | ||
| 874 | |||
| 834 | acpi_desc = &t->acpi_desc; | 875 | acpi_desc = &t->acpi_desc; |
| 835 | set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); | 876 | set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_dsm_force_en); |
| 836 | set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); | 877 | set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_dsm_force_en); |
| @@ -933,6 +974,10 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
| 933 | GFP_KERNEL); | 974 | GFP_KERNEL); |
| 934 | nfit_test->dimm_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t), | 975 | nfit_test->dimm_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t), |
| 935 | GFP_KERNEL); | 976 | GFP_KERNEL); |
| 977 | nfit_test->flush = devm_kcalloc(dev, num, sizeof(void *), | ||
| 978 | GFP_KERNEL); | ||
| 979 | nfit_test->flush_dma = devm_kcalloc(dev, num, sizeof(dma_addr_t), | ||
| 980 | GFP_KERNEL); | ||
| 936 | nfit_test->label = devm_kcalloc(dev, num, sizeof(void *), | 981 | nfit_test->label = devm_kcalloc(dev, num, sizeof(void *), |
| 937 | GFP_KERNEL); | 982 | GFP_KERNEL); |
| 938 | nfit_test->label_dma = devm_kcalloc(dev, num, | 983 | nfit_test->label_dma = devm_kcalloc(dev, num, |
| @@ -943,7 +988,8 @@ static int nfit_test_probe(struct platform_device *pdev) | |||
| 943 | sizeof(dma_addr_t), GFP_KERNEL); | 988 | sizeof(dma_addr_t), GFP_KERNEL); |
| 944 | if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label | 989 | if (nfit_test->dimm && nfit_test->dimm_dma && nfit_test->label |
| 945 | && nfit_test->label_dma && nfit_test->dcr | 990 | && nfit_test->label_dma && nfit_test->dcr |
| 946 | && nfit_test->dcr_dma) | 991 | && nfit_test->dcr_dma && nfit_test->flush |
| 992 | && nfit_test->flush_dma) | ||
| 947 | /* pass */; | 993 | /* pass */; |
| 948 | else | 994 | else |
| 949 | return -ENOMEM; | 995 | return -ENOMEM; |
