diff options
196 files changed, 2923 insertions, 1820 deletions
diff --git a/Documentation/admin-guide/cgroup-v2.rst b/Documentation/admin-guide/cgroup-v2.rst index 8384c681a4b2..476722b7b636 100644 --- a/Documentation/admin-guide/cgroup-v2.rst +++ b/Documentation/admin-guide/cgroup-v2.rst | |||
| @@ -1879,10 +1879,8 @@ following two functions. | |||
| 1879 | 1879 | ||
| 1880 | wbc_init_bio(@wbc, @bio) | 1880 | wbc_init_bio(@wbc, @bio) |
| 1881 | Should be called for each bio carrying writeback data and | 1881 | Should be called for each bio carrying writeback data and |
| 1882 | associates the bio with the inode's owner cgroup and the | 1882 | associates the bio with the inode's owner cgroup. Can be |
| 1883 | corresponding request queue. This must be called after | 1883 | called anytime between bio allocation and submission. |
| 1884 | a queue (device) has been associated with the bio and | ||
| 1885 | before submission. | ||
| 1886 | 1884 | ||
| 1887 | wbc_account_io(@wbc, @page, @bytes) | 1885 | wbc_account_io(@wbc, @page, @bytes) |
| 1888 | Should be called for each data segment being written out. | 1886 | Should be called for each data segment being written out. |
| @@ -1901,7 +1899,7 @@ the configuration, the bio may be executed at a lower priority and if | |||
| 1901 | the writeback session is holding shared resources, e.g. a journal | 1899 | the writeback session is holding shared resources, e.g. a journal |
| 1902 | entry, may lead to priority inversion. There is no one easy solution | 1900 | entry, may lead to priority inversion. There is no one easy solution |
| 1903 | for the problem. Filesystems can try to work around specific problem | 1901 | for the problem. Filesystems can try to work around specific problem |
| 1904 | cases by skipping wbc_init_bio() or using bio_associate_create_blkg() | 1902 | cases by skipping wbc_init_bio() or using bio_associate_blkcg() |
| 1905 | directly. | 1903 | directly. |
| 1906 | 1904 | ||
| 1907 | 1905 | ||
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt b/Documentation/devicetree/bindings/display/panel/innolux,p120zdg-bf1.txt index a9b35265fa13..513f03466aba 100644 --- a/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt +++ b/Documentation/devicetree/bindings/display/panel/innolux,p120zdg-bf1.txt | |||
| @@ -1,20 +1,22 @@ | |||
| 1 | Innolux TV123WAM 12.3 inch eDP 2K display panel | 1 | Innolux P120ZDG-BF1 12.02 inch eDP 2K display panel |
| 2 | 2 | ||
| 3 | This binding is compatible with the simple-panel binding, which is specified | 3 | This binding is compatible with the simple-panel binding, which is specified |
| 4 | in simple-panel.txt in this directory. | 4 | in simple-panel.txt in this directory. |
| 5 | 5 | ||
| 6 | Required properties: | 6 | Required properties: |
| 7 | - compatible: should be "innolux,tv123wam" | 7 | - compatible: should be "innolux,p120zdg-bf1" |
| 8 | - power-supply: regulator to provide the supply voltage | 8 | - power-supply: regulator to provide the supply voltage |
| 9 | 9 | ||
| 10 | Optional properties: | 10 | Optional properties: |
| 11 | - enable-gpios: GPIO pin to enable or disable the panel | 11 | - enable-gpios: GPIO pin to enable or disable the panel |
| 12 | - backlight: phandle of the backlight device attached to the panel | 12 | - backlight: phandle of the backlight device attached to the panel |
| 13 | - no-hpd: If HPD isn't hooked up; add this property. | ||
| 13 | 14 | ||
| 14 | Example: | 15 | Example: |
| 15 | panel_edp: panel-edp { | 16 | panel_edp: panel-edp { |
| 16 | compatible = "innolux,tv123wam"; | 17 | compatible = "innolux,p120zdg-bf1"; |
| 17 | enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>; | 18 | enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>; |
| 18 | power-supply = <&pm8916_l2>; | 19 | power-supply = <&pm8916_l2>; |
| 19 | backlight = <&backlight>; | 20 | backlight = <&backlight>; |
| 21 | no-hpd; | ||
| 20 | }; | 22 | }; |
diff --git a/Documentation/devicetree/bindings/display/panel/simple-panel.txt b/Documentation/devicetree/bindings/display/panel/simple-panel.txt index 45a457ad38f0..b2b872c710f2 100644 --- a/Documentation/devicetree/bindings/display/panel/simple-panel.txt +++ b/Documentation/devicetree/bindings/display/panel/simple-panel.txt | |||
| @@ -11,6 +11,9 @@ Optional properties: | |||
| 11 | - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing | 11 | - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing |
| 12 | - enable-gpios: GPIO pin to enable or disable the panel | 12 | - enable-gpios: GPIO pin to enable or disable the panel |
| 13 | - backlight: phandle of the backlight device attached to the panel | 13 | - backlight: phandle of the backlight device attached to the panel |
| 14 | - no-hpd: This panel is supposed to communicate that it's ready via HPD | ||
| 15 | (hot plug detect) signal, but the signal isn't hooked up so we should | ||
| 16 | hardcode the max delay from the panel spec when powering up the panel. | ||
| 14 | 17 | ||
| 15 | Example: | 18 | Example: |
| 16 | 19 | ||
diff --git a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt index 06a363d9ccef..b9a1d7402128 100644 --- a/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt +++ b/Documentation/devicetree/bindings/pwm/pwm-tiecap.txt | |||
| @@ -7,6 +7,7 @@ Required properties: | |||
| 7 | for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap"; | 7 | for da850 - compatible = "ti,da850-ecap", "ti,am3352-ecap", "ti,am33xx-ecap"; |
| 8 | for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap"; | 8 | for dra746 - compatible = "ti,dra746-ecap", "ti,am3352-ecap"; |
| 9 | for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap"; | 9 | for 66ak2g - compatible = "ti,k2g-ecap", "ti,am3352-ecap"; |
| 10 | for am654 - compatible = "ti,am654-ecap", "ti,am3352-ecap"; | ||
| 10 | - #pwm-cells: should be 3. See pwm.txt in this directory for a description of | 11 | - #pwm-cells: should be 3. See pwm.txt in this directory for a description of |
| 11 | the cells format. The PWM channel index ranges from 0 to 4. The only third | 12 | the cells format. The PWM channel index ranges from 0 to 4. The only third |
| 12 | cell flag supported by this binding is PWM_POLARITY_INVERTED. | 13 | cell flag supported by this binding is PWM_POLARITY_INVERTED. |
diff --git a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt index e1ef6afbe3a7..7f31fe7e2093 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,pwm-rcar.txt | |||
| @@ -3,7 +3,9 @@ | |||
| 3 | Required Properties: | 3 | Required Properties: |
| 4 | - compatible: should be "renesas,pwm-rcar" and one of the following. | 4 | - compatible: should be "renesas,pwm-rcar" and one of the following. |
| 5 | - "renesas,pwm-r8a7743": for RZ/G1M | 5 | - "renesas,pwm-r8a7743": for RZ/G1M |
| 6 | - "renesas,pwm-r8a7744": for RZ/G1N | ||
| 6 | - "renesas,pwm-r8a7745": for RZ/G1E | 7 | - "renesas,pwm-r8a7745": for RZ/G1E |
| 8 | - "renesas,pwm-r8a774a1": for RZ/G2M | ||
| 7 | - "renesas,pwm-r8a7778": for R-Car M1A | 9 | - "renesas,pwm-r8a7778": for R-Car M1A |
| 8 | - "renesas,pwm-r8a7779": for R-Car H1 | 10 | - "renesas,pwm-r8a7779": for R-Car H1 |
| 9 | - "renesas,pwm-r8a7790": for R-Car H2 | 11 | - "renesas,pwm-r8a7790": for R-Car H2 |
| @@ -12,6 +14,8 @@ Required Properties: | |||
| 12 | - "renesas,pwm-r8a7795": for R-Car H3 | 14 | - "renesas,pwm-r8a7795": for R-Car H3 |
| 13 | - "renesas,pwm-r8a7796": for R-Car M3-W | 15 | - "renesas,pwm-r8a7796": for R-Car M3-W |
| 14 | - "renesas,pwm-r8a77965": for R-Car M3-N | 16 | - "renesas,pwm-r8a77965": for R-Car M3-N |
| 17 | - "renesas,pwm-r8a77970": for R-Car V3M | ||
| 18 | - "renesas,pwm-r8a77980": for R-Car V3H | ||
| 15 | - "renesas,pwm-r8a77990": for R-Car E3 | 19 | - "renesas,pwm-r8a77990": for R-Car E3 |
| 16 | - "renesas,pwm-r8a77995": for R-Car D3 | 20 | - "renesas,pwm-r8a77995": for R-Car D3 |
| 17 | - reg: base address and length of the registers block for the PWM. | 21 | - reg: base address and length of the registers block for the PWM. |
diff --git a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt index d53a16715da6..848a92b53d81 100644 --- a/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt +++ b/Documentation/devicetree/bindings/pwm/renesas,tpu-pwm.txt | |||
| @@ -2,13 +2,19 @@ | |||
| 2 | 2 | ||
| 3 | Required Properties: | 3 | Required Properties: |
| 4 | 4 | ||
| 5 | - compatible: should be one of the following. | 5 | - compatible: must contain one or more of the following: |
| 6 | - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. | 6 | - "renesas,tpu-r8a73a4": for R8A73A4 (R-Mobile APE6) compatible PWM controller. |
| 7 | - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. | 7 | - "renesas,tpu-r8a7740": for R8A7740 (R-Mobile A1) compatible PWM controller. |
| 8 | - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. | 8 | - "renesas,tpu-r8a7743": for R8A7743 (RZ/G1M) compatible PWM controller. |
| 9 | - "renesas,tpu-r8a7744": for R8A7744 (RZ/G1N) compatible PWM controller. | ||
| 9 | - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. | 10 | - "renesas,tpu-r8a7745": for R8A7745 (RZ/G1E) compatible PWM controller. |
| 10 | - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. | 11 | - "renesas,tpu-r8a7790": for R8A7790 (R-Car H2) compatible PWM controller. |
| 11 | - "renesas,tpu": for generic R-Car and RZ/G1 TPU PWM controller. | 12 | - "renesas,tpu-r8a77970": for R8A77970 (R-Car V3M) compatible PWM |
| 13 | controller. | ||
| 14 | - "renesas,tpu-r8a77980": for R8A77980 (R-Car V3H) compatible PWM | ||
| 15 | controller. | ||
| 16 | - "renesas,tpu": for the generic TPU PWM controller; this is a fallback for | ||
| 17 | the entries listed above. | ||
| 12 | 18 | ||
| 13 | - reg: Base address and length of each memory resource used by the PWM | 19 | - reg: Base address and length of each memory resource used by the PWM |
| 14 | controller hardware module. | 20 | controller hardware module. |
diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 321d74b73937..cf43bc4dbf31 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting | |||
| @@ -623,6 +623,11 @@ in your dentry operations instead. | |||
| 623 | On success you get a new struct file sharing the mount/dentry with the | 623 | On success you get a new struct file sharing the mount/dentry with the |
| 624 | original, on failure - ERR_PTR(). | 624 | original, on failure - ERR_PTR(). |
| 625 | -- | 625 | -- |
| 626 | [mandatory] | ||
| 627 | ->clone_file_range() and ->dedupe_file_range have been replaced with | ||
| 628 | ->remap_file_range(). See Documentation/filesystems/vfs.txt for more | ||
| 629 | information. | ||
| 630 | -- | ||
| 626 | [recommended] | 631 | [recommended] |
| 627 | ->lookup() instances doing an equivalent of | 632 | ->lookup() instances doing an equivalent of |
| 628 | if (IS_ERR(inode)) | 633 | if (IS_ERR(inode)) |
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index a6c6a8af48a2..5f71a252e2e0 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -883,8 +883,9 @@ struct file_operations { | |||
| 883 | unsigned (*mmap_capabilities)(struct file *); | 883 | unsigned (*mmap_capabilities)(struct file *); |
| 884 | #endif | 884 | #endif |
| 885 | ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int); | 885 | ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int); |
| 886 | int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t, u64); | 886 | loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in, |
| 887 | int (*dedupe_file_range)(struct file *, loff_t, struct file *, loff_t, u64); | 887 | struct file *file_out, loff_t pos_out, |
| 888 | loff_t len, unsigned int remap_flags); | ||
| 888 | int (*fadvise)(struct file *, loff_t, loff_t, int); | 889 | int (*fadvise)(struct file *, loff_t, loff_t, int); |
| 889 | }; | 890 | }; |
| 890 | 891 | ||
| @@ -960,11 +961,18 @@ otherwise noted. | |||
| 960 | 961 | ||
| 961 | copy_file_range: called by the copy_file_range(2) system call. | 962 | copy_file_range: called by the copy_file_range(2) system call. |
| 962 | 963 | ||
| 963 | clone_file_range: called by the ioctl(2) system call for FICLONERANGE and | 964 | remap_file_range: called by the ioctl(2) system call for FICLONERANGE and |
| 964 | FICLONE commands. | 965 | FICLONE and FIDEDUPERANGE commands to remap file ranges. An |
| 965 | 966 | implementation should remap len bytes at pos_in of the source file into | |
| 966 | dedupe_file_range: called by the ioctl(2) system call for FIDEDUPERANGE | 967 | the dest file at pos_out. Implementations must handle callers passing |
| 967 | command. | 968 | in len == 0; this means "remap to the end of the source file". The |
| 969 | return value should the number of bytes remapped, or the usual | ||
| 970 | negative error code if errors occurred before any bytes were remapped. | ||
| 971 | The remap_flags parameter accepts REMAP_FILE_* flags. If | ||
| 972 | REMAP_FILE_DEDUP is set then the implementation must only remap if the | ||
| 973 | requested file ranges have identical contents. If REMAP_CAN_SHORTEN is | ||
| 974 | set, the caller is ok with the implementation shortening the request | ||
| 975 | length to satisfy alignment or EOF requirements (or any other reason). | ||
| 968 | 976 | ||
| 969 | fadvise: possibly called by the fadvise64() system call. | 977 | fadvise: possibly called by the fadvise64() system call. |
| 970 | 978 | ||
diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 7b6a2b2bdc98..8da26c6dd886 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt | |||
| @@ -537,21 +537,6 @@ more details, with real examples. | |||
| 537 | The third parameter may be a text as in this example, but it may also | 537 | The third parameter may be a text as in this example, but it may also |
| 538 | be an expanded variable or a macro. | 538 | be an expanded variable or a macro. |
| 539 | 539 | ||
| 540 | cc-fullversion | ||
| 541 | cc-fullversion is useful when the exact version of gcc is needed. | ||
| 542 | One typical use-case is when a specific GCC version is broken. | ||
| 543 | cc-fullversion points out a more specific version than cc-version does. | ||
| 544 | |||
| 545 | Example: | ||
| 546 | #arch/powerpc/Makefile | ||
| 547 | $(Q)if test "$(cc-fullversion)" = "040200" ; then \ | ||
| 548 | echo -n '*** GCC-4.2.0 cannot compile the 64-bit powerpc ' ; \ | ||
| 549 | false ; \ | ||
| 550 | fi | ||
| 551 | |||
| 552 | In this example for a specific GCC version the build will error out | ||
| 553 | explaining to the user why it stops. | ||
| 554 | |||
| 555 | cc-cross-prefix | 540 | cc-cross-prefix |
| 556 | cc-cross-prefix is used to check if there exists a $(CC) in path with | 541 | cc-cross-prefix is used to check if there exists a $(CC) in path with |
| 557 | one of the listed prefixes. The first prefix where there exist a | 542 | one of the listed prefixes. The first prefix where there exist a |
diff --git a/Documentation/networking/ice.rst b/Documentation/networking/ice.rst index 1e4948c9e989..4d118b827bbb 100644 --- a/Documentation/networking/ice.rst +++ b/Documentation/networking/ice.rst | |||
| @@ -20,7 +20,7 @@ Enabling the driver | |||
| 20 | The driver is enabled via the standard kernel configuration system, | 20 | The driver is enabled via the standard kernel configuration system, |
| 21 | using the make command:: | 21 | using the make command:: |
| 22 | 22 | ||
| 23 | make oldconfig/silentoldconfig/menuconfig/etc. | 23 | make oldconfig/menuconfig/etc. |
| 24 | 24 | ||
| 25 | The driver is located in the menu structure at: | 25 | The driver is located in the menu structure at: |
| 26 | 26 | ||
| @@ -485,7 +485,7 @@ ifneq ($(KBUILD_SRC),) | |||
| 485 | $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) | 485 | $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile $(srctree) |
| 486 | endif | 486 | endif |
| 487 | 487 | ||
| 488 | ifeq ($(cc-name),clang) | 488 | ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),) |
| 489 | ifneq ($(CROSS_COMPILE),) | 489 | ifneq ($(CROSS_COMPILE),) |
| 490 | CLANG_TARGET := --target=$(notdir $(CROSS_COMPILE:%-=%)) | 490 | CLANG_TARGET := --target=$(notdir $(CROSS_COMPILE:%-=%)) |
| 491 | GCC_TOOLCHAIN_DIR := $(dir $(shell which $(LD))) | 491 | GCC_TOOLCHAIN_DIR := $(dir $(shell which $(LD))) |
| @@ -702,7 +702,7 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong | |||
| 702 | 702 | ||
| 703 | KBUILD_CFLAGS += $(stackp-flags-y) | 703 | KBUILD_CFLAGS += $(stackp-flags-y) |
| 704 | 704 | ||
| 705 | ifeq ($(cc-name),clang) | 705 | ifdef CONFIG_CC_IS_CLANG |
| 706 | KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) | 706 | KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) |
| 707 | KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) | 707 | KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) |
| 708 | KBUILD_CFLAGS += $(call cc-disable-warning, gnu) | 708 | KBUILD_CFLAGS += $(call cc-disable-warning, gnu) |
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 15a84cfd0719..68410490e12f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
| @@ -128,7 +128,7 @@ cflags-y += -ffreestanding | |||
| 128 | # clang's output will be based upon the build machine. So for clang we simply | 128 | # clang's output will be based upon the build machine. So for clang we simply |
| 129 | # unconditionally specify -EB or -EL as appropriate. | 129 | # unconditionally specify -EB or -EL as appropriate. |
| 130 | # | 130 | # |
| 131 | ifeq ($(cc-name),clang) | 131 | ifdef CONFIG_CC_IS_CLANG |
| 132 | cflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB | 132 | cflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB |
| 133 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -EL | 133 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -EL |
| 134 | else | 134 | else |
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile index 34605ca21498..58a0315ad743 100644 --- a/arch/mips/vdso/Makefile +++ b/arch/mips/vdso/Makefile | |||
| @@ -10,7 +10,7 @@ ccflags-vdso := \ | |||
| 10 | $(filter -march=%,$(KBUILD_CFLAGS)) \ | 10 | $(filter -march=%,$(KBUILD_CFLAGS)) \ |
| 11 | -D__VDSO__ | 11 | -D__VDSO__ |
| 12 | 12 | ||
| 13 | ifeq ($(cc-name),clang) | 13 | ifdef CONFIG_CC_IS_CLANG |
| 14 | ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) | 14 | ccflags-vdso += $(filter --target=%,$(KBUILD_CFLAGS)) |
| 15 | endif | 15 | endif |
| 16 | 16 | ||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 2d51b2bd4aa1..8be31261aec8 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -930,10 +930,6 @@ config FSL_GTM | |||
| 930 | help | 930 | help |
| 931 | Freescale General-purpose Timers support | 931 | Freescale General-purpose Timers support |
| 932 | 932 | ||
| 933 | # Yes MCA RS/6000s exist but Linux-PPC does not currently support any | ||
| 934 | config MCA | ||
| 935 | bool | ||
| 936 | |||
| 937 | # Platforms that what PCI turned unconditionally just do select PCI | 933 | # Platforms that what PCI turned unconditionally just do select PCI |
| 938 | # in their config node. Platforms that want to choose at config | 934 | # in their config node. Platforms that want to choose at config |
| 939 | # time should select PPC_PCI_CHOICE | 935 | # time should select PPC_PCI_CHOICE |
| @@ -944,7 +940,6 @@ config PCI | |||
| 944 | bool "PCI support" if PPC_PCI_CHOICE | 940 | bool "PCI support" if PPC_PCI_CHOICE |
| 945 | default y if !40x && !CPM2 && !PPC_8xx && !PPC_83xx \ | 941 | default y if !40x && !CPM2 && !PPC_8xx && !PPC_83xx \ |
| 946 | && !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON | 942 | && !PPC_85xx && !PPC_86xx && !GAMECUBE_COMMON |
| 947 | default PCI_QSPAN if PPC_8xx | ||
| 948 | select GENERIC_PCI_IOMAP | 943 | select GENERIC_PCI_IOMAP |
| 949 | help | 944 | help |
| 950 | Find out whether your system includes a PCI bus. PCI is the name of | 945 | Find out whether your system includes a PCI bus. PCI is the name of |
| @@ -958,14 +953,6 @@ config PCI_DOMAINS | |||
| 958 | config PCI_SYSCALL | 953 | config PCI_SYSCALL |
| 959 | def_bool PCI | 954 | def_bool PCI |
| 960 | 955 | ||
| 961 | config PCI_QSPAN | ||
| 962 | bool "QSpan PCI" | ||
| 963 | depends on PPC_8xx | ||
| 964 | select PPC_I8259 | ||
| 965 | help | ||
| 966 | Say Y here if you have a system based on a Motorola 8xx-series | ||
| 967 | embedded processor with a QSPAN PCI interface, otherwise say N. | ||
| 968 | |||
| 969 | config PCI_8260 | 956 | config PCI_8260 |
| 970 | bool | 957 | bool |
| 971 | depends on PCI && 8260 | 958 | depends on PCI && 8260 |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 17be664dafa2..8a2ce14d68d0 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
| @@ -96,7 +96,7 @@ aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1) | |||
| 96 | aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2 | 96 | aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2 |
| 97 | endif | 97 | endif |
| 98 | 98 | ||
| 99 | ifneq ($(cc-name),clang) | 99 | ifndef CONFIG_CC_IS_CLANG |
| 100 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mno-strict-align | 100 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mno-strict-align |
| 101 | endif | 101 | endif |
| 102 | 102 | ||
| @@ -175,7 +175,7 @@ endif | |||
| 175 | # Work around gcc code-gen bugs with -pg / -fno-omit-frame-pointer in gcc <= 4.8 | 175 | # Work around gcc code-gen bugs with -pg / -fno-omit-frame-pointer in gcc <= 4.8 |
| 176 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44199 | 176 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44199 |
| 177 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52828 | 177 | # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52828 |
| 178 | ifneq ($(cc-name),clang) | 178 | ifndef CONFIG_CC_IS_CLANG |
| 179 | CC_FLAGS_FTRACE += $(call cc-ifversion, -lt, 0409, -mno-sched-epilog) | 179 | CC_FLAGS_FTRACE += $(call cc-ifversion, -lt, 0409, -mno-sched-epilog) |
| 180 | endif | 180 | endif |
| 181 | endif | 181 | endif |
diff --git a/arch/powerpc/boot/dts/fsl/t2080rdb.dts b/arch/powerpc/boot/dts/fsl/t2080rdb.dts index 55c0210a771d..092a400740f8 100644 --- a/arch/powerpc/boot/dts/fsl/t2080rdb.dts +++ b/arch/powerpc/boot/dts/fsl/t2080rdb.dts | |||
| @@ -77,12 +77,12 @@ | |||
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | ethernet@f0000 { | 79 | ethernet@f0000 { |
| 80 | phy-handle = <&xg_cs4315_phy1>; | 80 | phy-handle = <&xg_cs4315_phy2>; |
| 81 | phy-connection-type = "xgmii"; | 81 | phy-connection-type = "xgmii"; |
| 82 | }; | 82 | }; |
| 83 | 83 | ||
| 84 | ethernet@f2000 { | 84 | ethernet@f2000 { |
| 85 | phy-handle = <&xg_cs4315_phy2>; | 85 | phy-handle = <&xg_cs4315_phy1>; |
| 86 | phy-connection-type = "xgmii"; | 86 | phy-connection-type = "xgmii"; |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
diff --git a/arch/powerpc/boot/dts/mpc885ads.dts b/arch/powerpc/boot/dts/mpc885ads.dts index 5b037f51741d..3aa300afbbca 100644 --- a/arch/powerpc/boot/dts/mpc885ads.dts +++ b/arch/powerpc/boot/dts/mpc885ads.dts | |||
| @@ -72,7 +72,7 @@ | |||
| 72 | #address-cells = <1>; | 72 | #address-cells = <1>; |
| 73 | #size-cells = <1>; | 73 | #size-cells = <1>; |
| 74 | device_type = "soc"; | 74 | device_type = "soc"; |
| 75 | ranges = <0x0 0xff000000 0x4000>; | 75 | ranges = <0x0 0xff000000 0x28000>; |
| 76 | bus-frequency = <0>; | 76 | bus-frequency = <0>; |
| 77 | 77 | ||
| 78 | // Temporary -- will go away once kernel uses ranges for get_immrbase(). | 78 | // Temporary -- will go away once kernel uses ranges for get_immrbase(). |
| @@ -224,6 +224,17 @@ | |||
| 224 | #size-cells = <0>; | 224 | #size-cells = <0>; |
| 225 | }; | 225 | }; |
| 226 | }; | 226 | }; |
| 227 | |||
| 228 | crypto@20000 { | ||
| 229 | compatible = "fsl,sec1.2", "fsl,sec1.0"; | ||
| 230 | reg = <0x20000 0x8000>; | ||
| 231 | interrupts = <1 1>; | ||
| 232 | interrupt-parent = <&PIC>; | ||
| 233 | fsl,num-channels = <1>; | ||
| 234 | fsl,channel-fifo-len = <24>; | ||
| 235 | fsl,exec-units-mask = <0x4c>; | ||
| 236 | fsl,descriptor-types-mask = <0x05000154>; | ||
| 237 | }; | ||
| 227 | }; | 238 | }; |
| 228 | 239 | ||
| 229 | chosen { | 240 | chosen { |
diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h index 31733a95bbd0..3d5acd2b113a 100644 --- a/arch/powerpc/include/asm/code-patching.h +++ b/arch/powerpc/include/asm/code-patching.h | |||
| @@ -36,6 +36,11 @@ int raw_patch_instruction(unsigned int *addr, unsigned int instr); | |||
| 36 | int patch_instruction_site(s32 *addr, unsigned int instr); | 36 | int patch_instruction_site(s32 *addr, unsigned int instr); |
| 37 | int patch_branch_site(s32 *site, unsigned long target, int flags); | 37 | int patch_branch_site(s32 *site, unsigned long target, int flags); |
| 38 | 38 | ||
| 39 | static inline unsigned long patch_site_addr(s32 *site) | ||
| 40 | { | ||
| 41 | return (unsigned long)site + *site; | ||
| 42 | } | ||
| 43 | |||
| 39 | int instr_is_relative_branch(unsigned int instr); | 44 | int instr_is_relative_branch(unsigned int instr); |
| 40 | int instr_is_relative_link_branch(unsigned int instr); | 45 | int instr_is_relative_link_branch(unsigned int instr); |
| 41 | int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr); | 46 | int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr); |
diff --git a/arch/powerpc/include/asm/mmu-8xx.h b/arch/powerpc/include/asm/mmu-8xx.h index 4f547752ae79..fa05aa566ece 100644 --- a/arch/powerpc/include/asm/mmu-8xx.h +++ b/arch/powerpc/include/asm/mmu-8xx.h | |||
| @@ -34,20 +34,12 @@ | |||
| 34 | * respectively NA for All or X for Supervisor and no access for User. | 34 | * respectively NA for All or X for Supervisor and no access for User. |
| 35 | * Then we use the APG to say whether accesses are according to Page rules or | 35 | * Then we use the APG to say whether accesses are according to Page rules or |
| 36 | * "all Supervisor" rules (Access to all) | 36 | * "all Supervisor" rules (Access to all) |
| 37 | * We also use the 2nd APG bit for _PAGE_ACCESSED when having SWAP: | 37 | * Therefore, we define 2 APG groups. lsb is _PMD_USER |
| 38 | * When that bit is not set access is done iaw "all user" | 38 | * 0 => No user => 01 (all accesses performed according to page definition) |
| 39 | * which means no access iaw page rules. | 39 | * 1 => User => 00 (all accesses performed as supervisor iaw page definition) |
| 40 | * Therefore, we define 4 APG groups. lsb is _PMD_USER, 2nd is _PAGE_ACCESSED | ||
| 41 | * 0x => No access => 11 (all accesses performed as user iaw page definition) | ||
| 42 | * 10 => No user => 01 (all accesses performed according to page definition) | ||
| 43 | * 11 => User => 00 (all accesses performed as supervisor iaw page definition) | ||
| 44 | * We define all 16 groups so that all other bits of APG can take any value | 40 | * We define all 16 groups so that all other bits of APG can take any value |
| 45 | */ | 41 | */ |
| 46 | #ifdef CONFIG_SWAP | ||
| 47 | #define MI_APG_INIT 0xf4f4f4f4 | ||
| 48 | #else | ||
| 49 | #define MI_APG_INIT 0x44444444 | 42 | #define MI_APG_INIT 0x44444444 |
| 50 | #endif | ||
| 51 | 43 | ||
| 52 | /* The effective page number register. When read, contains the information | 44 | /* The effective page number register. When read, contains the information |
| 53 | * about the last instruction TLB miss. When MI_RPN is written, bits in | 45 | * about the last instruction TLB miss. When MI_RPN is written, bits in |
| @@ -115,20 +107,12 @@ | |||
| 115 | * Supervisor and no access for user and NA for ALL. | 107 | * Supervisor and no access for user and NA for ALL. |
| 116 | * Then we use the APG to say whether accesses are according to Page rules or | 108 | * Then we use the APG to say whether accesses are according to Page rules or |
| 117 | * "all Supervisor" rules (Access to all) | 109 | * "all Supervisor" rules (Access to all) |
| 118 | * We also use the 2nd APG bit for _PAGE_ACCESSED when having SWAP: | 110 | * Therefore, we define 2 APG groups. lsb is _PMD_USER |
| 119 | * When that bit is not set access is done iaw "all user" | 111 | * 0 => No user => 01 (all accesses performed according to page definition) |
| 120 | * which means no access iaw page rules. | 112 | * 1 => User => 00 (all accesses performed as supervisor iaw page definition) |
| 121 | * Therefore, we define 4 APG groups. lsb is _PMD_USER, 2nd is _PAGE_ACCESSED | ||
| 122 | * 0x => No access => 11 (all accesses performed as user iaw page definition) | ||
| 123 | * 10 => No user => 01 (all accesses performed according to page definition) | ||
| 124 | * 11 => User => 00 (all accesses performed as supervisor iaw page definition) | ||
| 125 | * We define all 16 groups so that all other bits of APG can take any value | 113 | * We define all 16 groups so that all other bits of APG can take any value |
| 126 | */ | 114 | */ |
| 127 | #ifdef CONFIG_SWAP | ||
| 128 | #define MD_APG_INIT 0xf4f4f4f4 | ||
| 129 | #else | ||
| 130 | #define MD_APG_INIT 0x44444444 | 115 | #define MD_APG_INIT 0x44444444 |
| 131 | #endif | ||
| 132 | 116 | ||
| 133 | /* The effective page number register. When read, contains the information | 117 | /* The effective page number register. When read, contains the information |
| 134 | * about the last instruction TLB miss. When MD_RPN is written, bits in | 118 | * about the last instruction TLB miss. When MD_RPN is written, bits in |
| @@ -180,12 +164,6 @@ | |||
| 180 | */ | 164 | */ |
| 181 | #define SPRN_M_TW 799 | 165 | #define SPRN_M_TW 799 |
| 182 | 166 | ||
| 183 | /* APGs */ | ||
| 184 | #define M_APG0 0x00000000 | ||
| 185 | #define M_APG1 0x00000020 | ||
| 186 | #define M_APG2 0x00000040 | ||
| 187 | #define M_APG3 0x00000060 | ||
| 188 | |||
| 189 | #ifdef CONFIG_PPC_MM_SLICES | 167 | #ifdef CONFIG_PPC_MM_SLICES |
| 190 | #include <asm/nohash/32/slice.h> | 168 | #include <asm/nohash/32/slice.h> |
| 191 | #define SLICE_ARRAY_SIZE (1 << (32 - SLICE_LOW_SHIFT - 1)) | 169 | #define SLICE_ARRAY_SIZE (1 << (32 - SLICE_LOW_SHIFT - 1)) |
| @@ -251,6 +229,15 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) | |||
| 251 | BUG(); | 229 | BUG(); |
| 252 | } | 230 | } |
| 253 | 231 | ||
| 232 | /* patch sites */ | ||
| 233 | extern s32 patch__itlbmiss_linmem_top; | ||
| 234 | extern s32 patch__dtlbmiss_linmem_top, patch__dtlbmiss_immr_jmp; | ||
| 235 | extern s32 patch__fixupdar_linmem_top; | ||
| 236 | |||
| 237 | extern s32 patch__itlbmiss_exit_1, patch__itlbmiss_exit_2; | ||
| 238 | extern s32 patch__dtlbmiss_exit_1, patch__dtlbmiss_exit_2, patch__dtlbmiss_exit_3; | ||
| 239 | extern s32 patch__itlbmiss_perf, patch__dtlbmiss_perf; | ||
| 240 | |||
| 254 | #endif /* !__ASSEMBLY__ */ | 241 | #endif /* !__ASSEMBLY__ */ |
| 255 | 242 | ||
| 256 | #if defined(CONFIG_PPC_4K_PAGES) | 243 | #if defined(CONFIG_PPC_4K_PAGES) |
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index bb38dd67d47d..1b06add4f092 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
| 6 | #include <asm/page.h> | 6 | #include <asm/page.h> |
| 7 | #include <linux/time.h> | 7 | #include <linux/time.h> |
| 8 | #include <linux/cpumask.h> | ||
| 8 | 9 | ||
| 9 | /* | 10 | /* |
| 10 | * Definitions for talking to the RTAS on CHRP machines. | 11 | * Definitions for talking to the RTAS on CHRP machines. |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 134a573a9f2d..3b67b9533c82 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <asm/asm-offsets.h> | 31 | #include <asm/asm-offsets.h> |
| 32 | #include <asm/ptrace.h> | 32 | #include <asm/ptrace.h> |
| 33 | #include <asm/export.h> | 33 | #include <asm/export.h> |
| 34 | #include <asm/code-patching-asm.h> | ||
| 34 | 35 | ||
| 35 | #if CONFIG_TASK_SIZE <= 0x80000000 && CONFIG_PAGE_OFFSET >= 0x80000000 | 36 | #if CONFIG_TASK_SIZE <= 0x80000000 && CONFIG_PAGE_OFFSET >= 0x80000000 |
| 36 | /* By simply checking Address >= 0x80000000, we know if its a kernel address */ | 37 | /* By simply checking Address >= 0x80000000, we know if its a kernel address */ |
| @@ -318,8 +319,8 @@ InstructionTLBMiss: | |||
| 318 | cmpli cr0, r11, PAGE_OFFSET@h | 319 | cmpli cr0, r11, PAGE_OFFSET@h |
| 319 | #ifndef CONFIG_PIN_TLB_TEXT | 320 | #ifndef CONFIG_PIN_TLB_TEXT |
| 320 | /* It is assumed that kernel code fits into the first 8M page */ | 321 | /* It is assumed that kernel code fits into the first 8M page */ |
| 321 | _ENTRY(ITLBMiss_cmp) | 322 | 0: cmpli cr7, r11, (PAGE_OFFSET + 0x0800000)@h |
| 322 | cmpli cr7, r11, (PAGE_OFFSET + 0x0800000)@h | 323 | patch_site 0b, patch__itlbmiss_linmem_top |
| 323 | #endif | 324 | #endif |
| 324 | #endif | 325 | #endif |
| 325 | #endif | 326 | #endif |
| @@ -353,13 +354,14 @@ _ENTRY(ITLBMiss_cmp) | |||
| 353 | #if defined(ITLB_MISS_KERNEL) || defined(CONFIG_HUGETLB_PAGE) | 354 | #if defined(ITLB_MISS_KERNEL) || defined(CONFIG_HUGETLB_PAGE) |
| 354 | mtcr r12 | 355 | mtcr r12 |
| 355 | #endif | 356 | #endif |
| 356 | |||
| 357 | #ifdef CONFIG_SWAP | ||
| 358 | rlwinm r11, r10, 31, _PAGE_ACCESSED >> 1 | ||
| 359 | #endif | ||
| 360 | /* Load the MI_TWC with the attributes for this "segment." */ | 357 | /* Load the MI_TWC with the attributes for this "segment." */ |
| 361 | mtspr SPRN_MI_TWC, r11 /* Set segment attributes */ | 358 | mtspr SPRN_MI_TWC, r11 /* Set segment attributes */ |
| 362 | 359 | ||
| 360 | #ifdef CONFIG_SWAP | ||
| 361 | rlwinm r11, r10, 32-5, _PAGE_PRESENT | ||
| 362 | and r11, r11, r10 | ||
| 363 | rlwimi r10, r11, 0, _PAGE_PRESENT | ||
| 364 | #endif | ||
| 363 | li r11, RPN_PATTERN | 0x200 | 365 | li r11, RPN_PATTERN | 0x200 |
| 364 | /* The Linux PTE won't go exactly into the MMU TLB. | 366 | /* The Linux PTE won't go exactly into the MMU TLB. |
| 365 | * Software indicator bits 20 and 23 must be clear. | 367 | * Software indicator bits 20 and 23 must be clear. |
| @@ -372,16 +374,17 @@ _ENTRY(ITLBMiss_cmp) | |||
| 372 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | 374 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ |
| 373 | 375 | ||
| 374 | /* Restore registers */ | 376 | /* Restore registers */ |
| 375 | _ENTRY(itlb_miss_exit_1) | 377 | 0: mfspr r10, SPRN_SPRG_SCRATCH0 |
| 376 | mfspr r10, SPRN_SPRG_SCRATCH0 | ||
| 377 | mfspr r11, SPRN_SPRG_SCRATCH1 | 378 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 378 | #if defined(ITLB_MISS_KERNEL) || defined(CONFIG_HUGETLB_PAGE) | 379 | #if defined(ITLB_MISS_KERNEL) || defined(CONFIG_HUGETLB_PAGE) |
| 379 | mfspr r12, SPRN_SPRG_SCRATCH2 | 380 | mfspr r12, SPRN_SPRG_SCRATCH2 |
| 380 | #endif | 381 | #endif |
| 381 | rfi | 382 | rfi |
| 383 | patch_site 0b, patch__itlbmiss_exit_1 | ||
| 384 | |||
| 382 | #ifdef CONFIG_PERF_EVENTS | 385 | #ifdef CONFIG_PERF_EVENTS |
| 383 | _ENTRY(itlb_miss_perf) | 386 | patch_site 0f, patch__itlbmiss_perf |
| 384 | lis r10, (itlb_miss_counter - PAGE_OFFSET)@ha | 387 | 0: lis r10, (itlb_miss_counter - PAGE_OFFSET)@ha |
| 385 | lwz r11, (itlb_miss_counter - PAGE_OFFSET)@l(r10) | 388 | lwz r11, (itlb_miss_counter - PAGE_OFFSET)@l(r10) |
| 386 | addi r11, r11, 1 | 389 | addi r11, r11, 1 |
| 387 | stw r11, (itlb_miss_counter - PAGE_OFFSET)@l(r10) | 390 | stw r11, (itlb_miss_counter - PAGE_OFFSET)@l(r10) |
| @@ -435,11 +438,11 @@ DataStoreTLBMiss: | |||
| 435 | #ifndef CONFIG_PIN_TLB_IMMR | 438 | #ifndef CONFIG_PIN_TLB_IMMR |
| 436 | cmpli cr0, r11, VIRT_IMMR_BASE@h | 439 | cmpli cr0, r11, VIRT_IMMR_BASE@h |
| 437 | #endif | 440 | #endif |
| 438 | _ENTRY(DTLBMiss_cmp) | 441 | 0: cmpli cr7, r11, (PAGE_OFFSET + 0x1800000)@h |
| 439 | cmpli cr7, r11, (PAGE_OFFSET + 0x1800000)@h | 442 | patch_site 0b, patch__dtlbmiss_linmem_top |
| 440 | #ifndef CONFIG_PIN_TLB_IMMR | 443 | #ifndef CONFIG_PIN_TLB_IMMR |
| 441 | _ENTRY(DTLBMiss_jmp) | 444 | 0: beq- DTLBMissIMMR |
| 442 | beq- DTLBMissIMMR | 445 | patch_site 0b, patch__dtlbmiss_immr_jmp |
| 443 | #endif | 446 | #endif |
| 444 | blt cr7, DTLBMissLinear | 447 | blt cr7, DTLBMissLinear |
| 445 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha | 448 | lis r11, (swapper_pg_dir-PAGE_OFFSET)@ha |
| @@ -470,14 +473,22 @@ _ENTRY(DTLBMiss_jmp) | |||
| 470 | * above. | 473 | * above. |
| 471 | */ | 474 | */ |
| 472 | rlwimi r11, r10, 0, _PAGE_GUARDED | 475 | rlwimi r11, r10, 0, _PAGE_GUARDED |
| 473 | #ifdef CONFIG_SWAP | ||
| 474 | /* _PAGE_ACCESSED has to be set. We use second APG bit for that, 0 | ||
| 475 | * on that bit will represent a Non Access group | ||
| 476 | */ | ||
| 477 | rlwinm r11, r10, 31, _PAGE_ACCESSED >> 1 | ||
| 478 | #endif | ||
| 479 | mtspr SPRN_MD_TWC, r11 | 476 | mtspr SPRN_MD_TWC, r11 |
| 480 | 477 | ||
| 478 | /* Both _PAGE_ACCESSED and _PAGE_PRESENT has to be set. | ||
| 479 | * We also need to know if the insn is a load/store, so: | ||
| 480 | * Clear _PAGE_PRESENT and load that which will | ||
| 481 | * trap into DTLB Error with store bit set accordinly. | ||
| 482 | */ | ||
| 483 | /* PRESENT=0x1, ACCESSED=0x20 | ||
| 484 | * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); | ||
| 485 | * r10 = (r10 & ~PRESENT) | r11; | ||
| 486 | */ | ||
| 487 | #ifdef CONFIG_SWAP | ||
| 488 | rlwinm r11, r10, 32-5, _PAGE_PRESENT | ||
| 489 | and r11, r11, r10 | ||
| 490 | rlwimi r10, r11, 0, _PAGE_PRESENT | ||
| 491 | #endif | ||
| 481 | /* The Linux PTE won't go exactly into the MMU TLB. | 492 | /* The Linux PTE won't go exactly into the MMU TLB. |
| 482 | * Software indicator bits 24, 25, 26, and 27 must be | 493 | * Software indicator bits 24, 25, 26, and 27 must be |
| 483 | * set. All other Linux PTE bits control the behavior | 494 | * set. All other Linux PTE bits control the behavior |
| @@ -489,14 +500,16 @@ _ENTRY(DTLBMiss_jmp) | |||
| 489 | 500 | ||
| 490 | /* Restore registers */ | 501 | /* Restore registers */ |
| 491 | mtspr SPRN_DAR, r11 /* Tag DAR */ | 502 | mtspr SPRN_DAR, r11 /* Tag DAR */ |
| 492 | _ENTRY(dtlb_miss_exit_1) | 503 | |
| 493 | mfspr r10, SPRN_SPRG_SCRATCH0 | 504 | 0: mfspr r10, SPRN_SPRG_SCRATCH0 |
| 494 | mfspr r11, SPRN_SPRG_SCRATCH1 | 505 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 495 | mfspr r12, SPRN_SPRG_SCRATCH2 | 506 | mfspr r12, SPRN_SPRG_SCRATCH2 |
| 496 | rfi | 507 | rfi |
| 508 | patch_site 0b, patch__dtlbmiss_exit_1 | ||
| 509 | |||
| 497 | #ifdef CONFIG_PERF_EVENTS | 510 | #ifdef CONFIG_PERF_EVENTS |
| 498 | _ENTRY(dtlb_miss_perf) | 511 | patch_site 0f, patch__dtlbmiss_perf |
| 499 | lis r10, (dtlb_miss_counter - PAGE_OFFSET)@ha | 512 | 0: lis r10, (dtlb_miss_counter - PAGE_OFFSET)@ha |
| 500 | lwz r11, (dtlb_miss_counter - PAGE_OFFSET)@l(r10) | 513 | lwz r11, (dtlb_miss_counter - PAGE_OFFSET)@l(r10) |
| 501 | addi r11, r11, 1 | 514 | addi r11, r11, 1 |
| 502 | stw r11, (dtlb_miss_counter - PAGE_OFFSET)@l(r10) | 515 | stw r11, (dtlb_miss_counter - PAGE_OFFSET)@l(r10) |
| @@ -637,8 +650,8 @@ InstructionBreakpoint: | |||
| 637 | */ | 650 | */ |
| 638 | DTLBMissIMMR: | 651 | DTLBMissIMMR: |
| 639 | mtcr r12 | 652 | mtcr r12 |
| 640 | /* Set 512k byte guarded page and mark it valid and accessed */ | 653 | /* Set 512k byte guarded page and mark it valid */ |
| 641 | li r10, MD_PS512K | MD_GUARDED | MD_SVALID | M_APG2 | 654 | li r10, MD_PS512K | MD_GUARDED | MD_SVALID |
| 642 | mtspr SPRN_MD_TWC, r10 | 655 | mtspr SPRN_MD_TWC, r10 |
| 643 | mfspr r10, SPRN_IMMR /* Get current IMMR */ | 656 | mfspr r10, SPRN_IMMR /* Get current IMMR */ |
| 644 | rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */ | 657 | rlwinm r10, r10, 0, 0xfff80000 /* Get 512 kbytes boundary */ |
| @@ -648,16 +661,17 @@ DTLBMissIMMR: | |||
| 648 | 661 | ||
| 649 | li r11, RPN_PATTERN | 662 | li r11, RPN_PATTERN |
| 650 | mtspr SPRN_DAR, r11 /* Tag DAR */ | 663 | mtspr SPRN_DAR, r11 /* Tag DAR */ |
| 651 | _ENTRY(dtlb_miss_exit_2) | 664 | |
| 652 | mfspr r10, SPRN_SPRG_SCRATCH0 | 665 | 0: mfspr r10, SPRN_SPRG_SCRATCH0 |
| 653 | mfspr r11, SPRN_SPRG_SCRATCH1 | 666 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 654 | mfspr r12, SPRN_SPRG_SCRATCH2 | 667 | mfspr r12, SPRN_SPRG_SCRATCH2 |
| 655 | rfi | 668 | rfi |
| 669 | patch_site 0b, patch__dtlbmiss_exit_2 | ||
| 656 | 670 | ||
| 657 | DTLBMissLinear: | 671 | DTLBMissLinear: |
| 658 | mtcr r12 | 672 | mtcr r12 |
| 659 | /* Set 8M byte page and mark it valid and accessed */ | 673 | /* Set 8M byte page and mark it valid */ |
| 660 | li r11, MD_PS8MEG | MD_SVALID | M_APG2 | 674 | li r11, MD_PS8MEG | MD_SVALID |
| 661 | mtspr SPRN_MD_TWC, r11 | 675 | mtspr SPRN_MD_TWC, r11 |
| 662 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ | 676 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ |
| 663 | ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ | 677 | ori r10, r10, 0xf0 | MD_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ |
| @@ -666,28 +680,29 @@ DTLBMissLinear: | |||
| 666 | 680 | ||
| 667 | li r11, RPN_PATTERN | 681 | li r11, RPN_PATTERN |
| 668 | mtspr SPRN_DAR, r11 /* Tag DAR */ | 682 | mtspr SPRN_DAR, r11 /* Tag DAR */ |
| 669 | _ENTRY(dtlb_miss_exit_3) | 683 | |
| 670 | mfspr r10, SPRN_SPRG_SCRATCH0 | 684 | 0: mfspr r10, SPRN_SPRG_SCRATCH0 |
| 671 | mfspr r11, SPRN_SPRG_SCRATCH1 | 685 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 672 | mfspr r12, SPRN_SPRG_SCRATCH2 | 686 | mfspr r12, SPRN_SPRG_SCRATCH2 |
| 673 | rfi | 687 | rfi |
| 688 | patch_site 0b, patch__dtlbmiss_exit_3 | ||
| 674 | 689 | ||
| 675 | #ifndef CONFIG_PIN_TLB_TEXT | 690 | #ifndef CONFIG_PIN_TLB_TEXT |
| 676 | ITLBMissLinear: | 691 | ITLBMissLinear: |
| 677 | mtcr r12 | 692 | mtcr r12 |
| 678 | /* Set 8M byte page and mark it valid,accessed */ | 693 | /* Set 8M byte page and mark it valid */ |
| 679 | li r11, MI_PS8MEG | MI_SVALID | M_APG2 | 694 | li r11, MI_PS8MEG | MI_SVALID |
| 680 | mtspr SPRN_MI_TWC, r11 | 695 | mtspr SPRN_MI_TWC, r11 |
| 681 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ | 696 | rlwinm r10, r10, 0, 0x0f800000 /* 8xx supports max 256Mb RAM */ |
| 682 | ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ | 697 | ori r10, r10, 0xf0 | MI_SPS16K | _PAGE_SH | _PAGE_DIRTY | \ |
| 683 | _PAGE_PRESENT | 698 | _PAGE_PRESENT |
| 684 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ | 699 | mtspr SPRN_MI_RPN, r10 /* Update TLB entry */ |
| 685 | 700 | ||
| 686 | _ENTRY(itlb_miss_exit_2) | 701 | 0: mfspr r10, SPRN_SPRG_SCRATCH0 |
| 687 | mfspr r10, SPRN_SPRG_SCRATCH0 | ||
| 688 | mfspr r11, SPRN_SPRG_SCRATCH1 | 702 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 689 | mfspr r12, SPRN_SPRG_SCRATCH2 | 703 | mfspr r12, SPRN_SPRG_SCRATCH2 |
| 690 | rfi | 704 | rfi |
| 705 | patch_site 0b, patch__itlbmiss_exit_2 | ||
| 691 | #endif | 706 | #endif |
| 692 | 707 | ||
| 693 | /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions | 708 | /* This is the procedure to calculate the data EA for buggy dcbx,dcbi instructions |
| @@ -705,8 +720,10 @@ FixupDAR:/* Entry point for dcbx workaround. */ | |||
| 705 | mfspr r11, SPRN_M_TW /* Get level 1 table */ | 720 | mfspr r11, SPRN_M_TW /* Get level 1 table */ |
| 706 | blt+ 3f | 721 | blt+ 3f |
| 707 | rlwinm r11, r10, 16, 0xfff8 | 722 | rlwinm r11, r10, 16, 0xfff8 |
| 708 | _ENTRY(FixupDAR_cmp) | 723 | |
| 709 | cmpli cr7, r11, (PAGE_OFFSET + 0x1800000)@h | 724 | 0: cmpli cr7, r11, (PAGE_OFFSET + 0x1800000)@h |
| 725 | patch_site 0b, patch__fixupdar_linmem_top | ||
| 726 | |||
| 710 | /* create physical page address from effective address */ | 727 | /* create physical page address from effective address */ |
| 711 | tophys(r11, r10) | 728 | tophys(r11, r10) |
| 712 | blt- cr7, 201f | 729 | blt- cr7, 201f |
| @@ -960,7 +977,7 @@ initial_mmu: | |||
| 960 | ori r8, r8, MI_EVALID /* Mark it valid */ | 977 | ori r8, r8, MI_EVALID /* Mark it valid */ |
| 961 | mtspr SPRN_MI_EPN, r8 | 978 | mtspr SPRN_MI_EPN, r8 |
| 962 | li r8, MI_PS8MEG /* Set 8M byte page */ | 979 | li r8, MI_PS8MEG /* Set 8M byte page */ |
| 963 | ori r8, r8, MI_SVALID | M_APG2 /* Make it valid, APG 2 */ | 980 | ori r8, r8, MI_SVALID /* Make it valid */ |
| 964 | mtspr SPRN_MI_TWC, r8 | 981 | mtspr SPRN_MI_TWC, r8 |
| 965 | li r8, MI_BOOTINIT /* Create RPN for address 0 */ | 982 | li r8, MI_BOOTINIT /* Create RPN for address 0 */ |
| 966 | mtspr SPRN_MI_RPN, r8 /* Store TLB entry */ | 983 | mtspr SPRN_MI_RPN, r8 /* Store TLB entry */ |
| @@ -987,7 +1004,7 @@ initial_mmu: | |||
| 987 | ori r8, r8, MD_EVALID /* Mark it valid */ | 1004 | ori r8, r8, MD_EVALID /* Mark it valid */ |
| 988 | mtspr SPRN_MD_EPN, r8 | 1005 | mtspr SPRN_MD_EPN, r8 |
| 989 | li r8, MD_PS512K | MD_GUARDED /* Set 512k byte page */ | 1006 | li r8, MD_PS512K | MD_GUARDED /* Set 512k byte page */ |
| 990 | ori r8, r8, MD_SVALID | M_APG2 /* Make it valid and accessed */ | 1007 | ori r8, r8, MD_SVALID /* Make it valid */ |
| 991 | mtspr SPRN_MD_TWC, r8 | 1008 | mtspr SPRN_MD_TWC, r8 |
| 992 | mr r8, r9 /* Create paddr for TLB */ | 1009 | mr r8, r9 /* Create paddr for TLB */ |
| 993 | ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ | 1010 | ori r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */ |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 4d5322cfad25..96f34730010f 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -590,12 +590,11 @@ void flush_all_to_thread(struct task_struct *tsk) | |||
| 590 | if (tsk->thread.regs) { | 590 | if (tsk->thread.regs) { |
| 591 | preempt_disable(); | 591 | preempt_disable(); |
| 592 | BUG_ON(tsk != current); | 592 | BUG_ON(tsk != current); |
| 593 | save_all(tsk); | ||
| 594 | |||
| 595 | #ifdef CONFIG_SPE | 593 | #ifdef CONFIG_SPE |
| 596 | if (tsk->thread.regs->msr & MSR_SPE) | 594 | if (tsk->thread.regs->msr & MSR_SPE) |
| 597 | tsk->thread.spefscr = mfspr(SPRN_SPEFSCR); | 595 | tsk->thread.spefscr = mfspr(SPRN_SPEFSCR); |
| 598 | #endif | 596 | #endif |
| 597 | save_all(tsk); | ||
| 599 | 598 | ||
| 600 | preempt_enable(); | 599 | preempt_enable(); |
| 601 | } | 600 | } |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index bf8def2159c3..d65b961661fb 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
| @@ -2337,8 +2337,7 @@ static void kvmppc_set_timer(struct kvm_vcpu *vcpu) | |||
| 2337 | kvmppc_core_prepare_to_enter(vcpu); | 2337 | kvmppc_core_prepare_to_enter(vcpu); |
| 2338 | return; | 2338 | return; |
| 2339 | } | 2339 | } |
| 2340 | dec_nsec = (vcpu->arch.dec_expires - now) * NSEC_PER_SEC | 2340 | dec_nsec = tb_to_ns(vcpu->arch.dec_expires - now); |
| 2341 | / tb_ticks_per_sec; | ||
| 2342 | hrtimer_start(&vcpu->arch.dec_timer, dec_nsec, HRTIMER_MODE_REL); | 2341 | hrtimer_start(&vcpu->arch.dec_timer, dec_nsec, HRTIMER_MODE_REL); |
| 2343 | vcpu->arch.timer_running = 1; | 2342 | vcpu->arch.timer_running = 1; |
| 2344 | } | 2343 | } |
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index fa888bfc347e..9f5b8c01c4e1 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
| @@ -61,11 +61,10 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) | |||
| 61 | 61 | ||
| 62 | dec_time = vcpu->arch.dec; | 62 | dec_time = vcpu->arch.dec; |
| 63 | /* | 63 | /* |
| 64 | * Guest timebase ticks at the same frequency as host decrementer. | 64 | * Guest timebase ticks at the same frequency as host timebase. |
| 65 | * So use the host decrementer calculations for decrementer emulation. | 65 | * So use the host timebase calculations for decrementer emulation. |
| 66 | */ | 66 | */ |
| 67 | dec_time = dec_time << decrementer_clockevent.shift; | 67 | dec_time = tb_to_ns(dec_time); |
| 68 | do_div(dec_time, decrementer_clockevent.mult); | ||
| 69 | dec_nsec = do_div(dec_time, NSEC_PER_SEC); | 68 | dec_nsec = do_div(dec_time, NSEC_PER_SEC); |
| 70 | hrtimer_start(&vcpu->arch.dec_timer, | 69 | hrtimer_start(&vcpu->arch.dec_timer, |
| 71 | ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL); | 70 | ktime_set(dec_time, dec_nsec), HRTIMER_MODE_REL); |
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c index 36484a2ef915..01b7f5107c3a 100644 --- a/arch/powerpc/mm/8xx_mmu.c +++ b/arch/powerpc/mm/8xx_mmu.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <linux/memblock.h> | 15 | #include <linux/memblock.h> |
| 16 | #include <linux/mmu_context.h> | ||
| 16 | #include <asm/fixmap.h> | 17 | #include <asm/fixmap.h> |
| 17 | #include <asm/code-patching.h> | 18 | #include <asm/code-patching.h> |
| 18 | 19 | ||
| @@ -79,7 +80,7 @@ void __init MMU_init_hw(void) | |||
| 79 | for (; i < 32 && mem >= LARGE_PAGE_SIZE_8M; i++) { | 80 | for (; i < 32 && mem >= LARGE_PAGE_SIZE_8M; i++) { |
| 80 | mtspr(SPRN_MD_CTR, ctr | (i << 8)); | 81 | mtspr(SPRN_MD_CTR, ctr | (i << 8)); |
| 81 | mtspr(SPRN_MD_EPN, (unsigned long)__va(addr) | MD_EVALID); | 82 | mtspr(SPRN_MD_EPN, (unsigned long)__va(addr) | MD_EVALID); |
| 82 | mtspr(SPRN_MD_TWC, MD_PS8MEG | MD_SVALID | M_APG2); | 83 | mtspr(SPRN_MD_TWC, MD_PS8MEG | MD_SVALID); |
| 83 | mtspr(SPRN_MD_RPN, addr | flags | _PAGE_PRESENT); | 84 | mtspr(SPRN_MD_RPN, addr | flags | _PAGE_PRESENT); |
| 84 | addr += LARGE_PAGE_SIZE_8M; | 85 | addr += LARGE_PAGE_SIZE_8M; |
| 85 | mem -= LARGE_PAGE_SIZE_8M; | 86 | mem -= LARGE_PAGE_SIZE_8M; |
| @@ -97,22 +98,13 @@ static void __init mmu_mapin_immr(void) | |||
| 97 | map_kernel_page(v + offset, p + offset, PAGE_KERNEL_NCG); | 98 | map_kernel_page(v + offset, p + offset, PAGE_KERNEL_NCG); |
| 98 | } | 99 | } |
| 99 | 100 | ||
| 100 | /* Address of instructions to patch */ | 101 | static void __init mmu_patch_cmp_limit(s32 *site, unsigned long mapped) |
| 101 | #ifndef CONFIG_PIN_TLB_IMMR | ||
| 102 | extern unsigned int DTLBMiss_jmp; | ||
| 103 | #endif | ||
| 104 | extern unsigned int DTLBMiss_cmp, FixupDAR_cmp; | ||
| 105 | #ifndef CONFIG_PIN_TLB_TEXT | ||
| 106 | extern unsigned int ITLBMiss_cmp; | ||
| 107 | #endif | ||
| 108 | |||
| 109 | static void __init mmu_patch_cmp_limit(unsigned int *addr, unsigned long mapped) | ||
| 110 | { | 102 | { |
| 111 | unsigned int instr = *addr; | 103 | unsigned int instr = *(unsigned int *)patch_site_addr(site); |
| 112 | 104 | ||
| 113 | instr &= 0xffff0000; | 105 | instr &= 0xffff0000; |
| 114 | instr |= (unsigned long)__va(mapped) >> 16; | 106 | instr |= (unsigned long)__va(mapped) >> 16; |
| 115 | patch_instruction(addr, instr); | 107 | patch_instruction_site(site, instr); |
| 116 | } | 108 | } |
| 117 | 109 | ||
| 118 | unsigned long __init mmu_mapin_ram(unsigned long top) | 110 | unsigned long __init mmu_mapin_ram(unsigned long top) |
| @@ -123,17 +115,17 @@ unsigned long __init mmu_mapin_ram(unsigned long top) | |||
| 123 | mapped = 0; | 115 | mapped = 0; |
| 124 | mmu_mapin_immr(); | 116 | mmu_mapin_immr(); |
| 125 | #ifndef CONFIG_PIN_TLB_IMMR | 117 | #ifndef CONFIG_PIN_TLB_IMMR |
| 126 | patch_instruction(&DTLBMiss_jmp, PPC_INST_NOP); | 118 | patch_instruction_site(&patch__dtlbmiss_immr_jmp, PPC_INST_NOP); |
| 127 | #endif | 119 | #endif |
| 128 | #ifndef CONFIG_PIN_TLB_TEXT | 120 | #ifndef CONFIG_PIN_TLB_TEXT |
| 129 | mmu_patch_cmp_limit(&ITLBMiss_cmp, 0); | 121 | mmu_patch_cmp_limit(&patch__itlbmiss_linmem_top, 0); |
| 130 | #endif | 122 | #endif |
| 131 | } else { | 123 | } else { |
| 132 | mapped = top & ~(LARGE_PAGE_SIZE_8M - 1); | 124 | mapped = top & ~(LARGE_PAGE_SIZE_8M - 1); |
| 133 | } | 125 | } |
| 134 | 126 | ||
| 135 | mmu_patch_cmp_limit(&DTLBMiss_cmp, mapped); | 127 | mmu_patch_cmp_limit(&patch__dtlbmiss_linmem_top, mapped); |
| 136 | mmu_patch_cmp_limit(&FixupDAR_cmp, mapped); | 128 | mmu_patch_cmp_limit(&patch__fixupdar_linmem_top, mapped); |
| 137 | 129 | ||
| 138 | /* If the size of RAM is not an exact power of two, we may not | 130 | /* If the size of RAM is not an exact power of two, we may not |
| 139 | * have covered RAM in its entirety with 8 MiB | 131 | * have covered RAM in its entirety with 8 MiB |
diff --git a/arch/powerpc/perf/8xx-pmu.c b/arch/powerpc/perf/8xx-pmu.c index 6c0020d1c561..e38f74e9e7a4 100644 --- a/arch/powerpc/perf/8xx-pmu.c +++ b/arch/powerpc/perf/8xx-pmu.c | |||
| @@ -31,9 +31,6 @@ | |||
| 31 | 31 | ||
| 32 | extern unsigned long itlb_miss_counter, dtlb_miss_counter; | 32 | extern unsigned long itlb_miss_counter, dtlb_miss_counter; |
| 33 | extern atomic_t instruction_counter; | 33 | extern atomic_t instruction_counter; |
| 34 | extern unsigned int itlb_miss_perf, dtlb_miss_perf; | ||
| 35 | extern unsigned int itlb_miss_exit_1, itlb_miss_exit_2; | ||
| 36 | extern unsigned int dtlb_miss_exit_1, dtlb_miss_exit_2, dtlb_miss_exit_3; | ||
| 37 | 34 | ||
| 38 | static atomic_t insn_ctr_ref; | 35 | static atomic_t insn_ctr_ref; |
| 39 | static atomic_t itlb_miss_ref; | 36 | static atomic_t itlb_miss_ref; |
| @@ -103,22 +100,22 @@ static int mpc8xx_pmu_add(struct perf_event *event, int flags) | |||
| 103 | break; | 100 | break; |
| 104 | case PERF_8xx_ID_ITLB_LOAD_MISS: | 101 | case PERF_8xx_ID_ITLB_LOAD_MISS: |
| 105 | if (atomic_inc_return(&itlb_miss_ref) == 1) { | 102 | if (atomic_inc_return(&itlb_miss_ref) == 1) { |
| 106 | unsigned long target = (unsigned long)&itlb_miss_perf; | 103 | unsigned long target = patch_site_addr(&patch__itlbmiss_perf); |
| 107 | 104 | ||
| 108 | patch_branch(&itlb_miss_exit_1, target, 0); | 105 | patch_branch_site(&patch__itlbmiss_exit_1, target, 0); |
| 109 | #ifndef CONFIG_PIN_TLB_TEXT | 106 | #ifndef CONFIG_PIN_TLB_TEXT |
| 110 | patch_branch(&itlb_miss_exit_2, target, 0); | 107 | patch_branch_site(&patch__itlbmiss_exit_2, target, 0); |
| 111 | #endif | 108 | #endif |
| 112 | } | 109 | } |
| 113 | val = itlb_miss_counter; | 110 | val = itlb_miss_counter; |
| 114 | break; | 111 | break; |
| 115 | case PERF_8xx_ID_DTLB_LOAD_MISS: | 112 | case PERF_8xx_ID_DTLB_LOAD_MISS: |
| 116 | if (atomic_inc_return(&dtlb_miss_ref) == 1) { | 113 | if (atomic_inc_return(&dtlb_miss_ref) == 1) { |
| 117 | unsigned long target = (unsigned long)&dtlb_miss_perf; | 114 | unsigned long target = patch_site_addr(&patch__dtlbmiss_perf); |
| 118 | 115 | ||
| 119 | patch_branch(&dtlb_miss_exit_1, target, 0); | 116 | patch_branch_site(&patch__dtlbmiss_exit_1, target, 0); |
| 120 | patch_branch(&dtlb_miss_exit_2, target, 0); | 117 | patch_branch_site(&patch__dtlbmiss_exit_2, target, 0); |
| 121 | patch_branch(&dtlb_miss_exit_3, target, 0); | 118 | patch_branch_site(&patch__dtlbmiss_exit_3, target, 0); |
| 122 | } | 119 | } |
| 123 | val = dtlb_miss_counter; | 120 | val = dtlb_miss_counter; |
| 124 | break; | 121 | break; |
| @@ -180,17 +177,17 @@ static void mpc8xx_pmu_del(struct perf_event *event, int flags) | |||
| 180 | break; | 177 | break; |
| 181 | case PERF_8xx_ID_ITLB_LOAD_MISS: | 178 | case PERF_8xx_ID_ITLB_LOAD_MISS: |
| 182 | if (atomic_dec_return(&itlb_miss_ref) == 0) { | 179 | if (atomic_dec_return(&itlb_miss_ref) == 0) { |
| 183 | patch_instruction(&itlb_miss_exit_1, insn); | 180 | patch_instruction_site(&patch__itlbmiss_exit_1, insn); |
| 184 | #ifndef CONFIG_PIN_TLB_TEXT | 181 | #ifndef CONFIG_PIN_TLB_TEXT |
| 185 | patch_instruction(&itlb_miss_exit_2, insn); | 182 | patch_instruction_site(&patch__itlbmiss_exit_2, insn); |
| 186 | #endif | 183 | #endif |
| 187 | } | 184 | } |
| 188 | break; | 185 | break; |
| 189 | case PERF_8xx_ID_DTLB_LOAD_MISS: | 186 | case PERF_8xx_ID_DTLB_LOAD_MISS: |
| 190 | if (atomic_dec_return(&dtlb_miss_ref) == 0) { | 187 | if (atomic_dec_return(&dtlb_miss_ref) == 0) { |
| 191 | patch_instruction(&dtlb_miss_exit_1, insn); | 188 | patch_instruction_site(&patch__dtlbmiss_exit_1, insn); |
| 192 | patch_instruction(&dtlb_miss_exit_2, insn); | 189 | patch_instruction_site(&patch__dtlbmiss_exit_2, insn); |
| 193 | patch_instruction(&dtlb_miss_exit_3, insn); | 190 | patch_instruction_site(&patch__dtlbmiss_exit_3, insn); |
| 194 | } | 191 | } |
| 195 | break; | 192 | break; |
| 196 | } | 193 | } |
diff --git a/arch/powerpc/platforms/40x/Kconfig b/arch/powerpc/platforms/40x/Kconfig index 2a9d66254ffc..5326ece36120 100644 --- a/arch/powerpc/platforms/40x/Kconfig +++ b/arch/powerpc/platforms/40x/Kconfig | |||
| @@ -29,6 +29,7 @@ config KILAUEA | |||
| 29 | select 405EX | 29 | select 405EX |
| 30 | select PPC40x_SIMPLE | 30 | select PPC40x_SIMPLE |
| 31 | select PPC4xx_PCI_EXPRESS | 31 | select PPC4xx_PCI_EXPRESS |
| 32 | select PCI | ||
| 32 | select PCI_MSI | 33 | select PCI_MSI |
| 33 | select PPC4xx_MSI | 34 | select PPC4xx_MSI |
| 34 | help | 35 | help |
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index f024efd5a4c2..9a85d350b1b6 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
| @@ -21,6 +21,7 @@ config BLUESTONE | |||
| 21 | depends on 44x | 21 | depends on 44x |
| 22 | select PPC44x_SIMPLE | 22 | select PPC44x_SIMPLE |
| 23 | select APM821xx | 23 | select APM821xx |
| 24 | select PCI | ||
| 24 | select PCI_MSI | 25 | select PCI_MSI |
| 25 | select PPC4xx_MSI | 26 | select PPC4xx_MSI |
| 26 | select PPC4xx_PCI_EXPRESS | 27 | select PPC4xx_PCI_EXPRESS |
| @@ -200,6 +201,7 @@ config AKEBONO | |||
| 200 | select SWIOTLB | 201 | select SWIOTLB |
| 201 | select 476FPE | 202 | select 476FPE |
| 202 | select PPC4xx_PCI_EXPRESS | 203 | select PPC4xx_PCI_EXPRESS |
| 204 | select PCI | ||
| 203 | select PCI_MSI | 205 | select PCI_MSI |
| 204 | select PPC4xx_HSTA_MSI | 206 | select PPC4xx_HSTA_MSI |
| 205 | select I2C | 207 | select I2C |
diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index 8bd590af488a..794487313cc8 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
| 29 | #include <linux/hugetlb.h> | ||
| 29 | #include <asm/lppaca.h> | 30 | #include <asm/lppaca.h> |
| 30 | #include <asm/hvcall.h> | 31 | #include <asm/hvcall.h> |
| 31 | #include <asm/firmware.h> | 32 | #include <asm/firmware.h> |
| @@ -36,6 +37,7 @@ | |||
| 36 | #include <asm/vio.h> | 37 | #include <asm/vio.h> |
| 37 | #include <asm/mmu.h> | 38 | #include <asm/mmu.h> |
| 38 | #include <asm/machdep.h> | 39 | #include <asm/machdep.h> |
| 40 | #include <asm/drmem.h> | ||
| 39 | 41 | ||
| 40 | #include "pseries.h" | 42 | #include "pseries.h" |
| 41 | 43 | ||
| @@ -433,6 +435,16 @@ static void parse_em_data(struct seq_file *m) | |||
| 433 | seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]); | 435 | seq_printf(m, "power_mode_data=%016lx\n", retbuf[0]); |
| 434 | } | 436 | } |
| 435 | 437 | ||
| 438 | static void maxmem_data(struct seq_file *m) | ||
| 439 | { | ||
| 440 | unsigned long maxmem = 0; | ||
| 441 | |||
| 442 | maxmem += drmem_info->n_lmbs * drmem_info->lmb_size; | ||
| 443 | maxmem += hugetlb_total_pages() * PAGE_SIZE; | ||
| 444 | |||
| 445 | seq_printf(m, "MaxMem=%ld\n", maxmem); | ||
| 446 | } | ||
| 447 | |||
| 436 | static int pseries_lparcfg_data(struct seq_file *m, void *v) | 448 | static int pseries_lparcfg_data(struct seq_file *m, void *v) |
| 437 | { | 449 | { |
| 438 | int partition_potential_processors; | 450 | int partition_potential_processors; |
| @@ -491,6 +503,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 491 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); | 503 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); |
| 492 | #endif | 504 | #endif |
| 493 | parse_em_data(m); | 505 | parse_em_data(m); |
| 506 | maxmem_data(m); | ||
| 494 | 507 | ||
| 495 | return 0; | 508 | return 0; |
| 496 | } | 509 | } |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index 69e7fb47bcaa..878f9c1d3615 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
| @@ -11,6 +11,12 @@ UBSAN_SANITIZE := n | |||
| 11 | ORIG_CFLAGS := $(KBUILD_CFLAGS) | 11 | ORIG_CFLAGS := $(KBUILD_CFLAGS) |
| 12 | KBUILD_CFLAGS = $(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS)) | 12 | KBUILD_CFLAGS = $(subst $(CC_FLAGS_FTRACE),,$(ORIG_CFLAGS)) |
| 13 | 13 | ||
| 14 | ifdef CONFIG_CC_IS_CLANG | ||
| 15 | # clang stores addresses on the stack causing the frame size to blow | ||
| 16 | # out. See https://github.com/ClangBuiltLinux/linux/issues/252 | ||
| 17 | KBUILD_CFLAGS += -Wframe-larger-than=4096 | ||
| 18 | endif | ||
| 19 | |||
| 14 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) | 20 | ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) |
| 15 | 21 | ||
| 16 | obj-y += xmon.o nonstdio.o spr_access.o | 22 | obj-y += xmon.o nonstdio.o spr_access.o |
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index 36473d7dbaac..07fa9ea75fea 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig | |||
| @@ -1,6 +1,3 @@ | |||
| 1 | CONFIG_SMP=y | ||
| 2 | CONFIG_PCI=y | ||
| 3 | CONFIG_PCIE_XILINX=y | ||
| 4 | CONFIG_SYSVIPC=y | 1 | CONFIG_SYSVIPC=y |
| 5 | CONFIG_POSIX_MQUEUE=y | 2 | CONFIG_POSIX_MQUEUE=y |
| 6 | CONFIG_IKCONFIG=y | 3 | CONFIG_IKCONFIG=y |
| @@ -11,10 +8,15 @@ CONFIG_CFS_BANDWIDTH=y | |||
| 11 | CONFIG_CGROUP_BPF=y | 8 | CONFIG_CGROUP_BPF=y |
| 12 | CONFIG_NAMESPACES=y | 9 | CONFIG_NAMESPACES=y |
| 13 | CONFIG_USER_NS=y | 10 | CONFIG_USER_NS=y |
| 11 | CONFIG_CHECKPOINT_RESTORE=y | ||
| 14 | CONFIG_BLK_DEV_INITRD=y | 12 | CONFIG_BLK_DEV_INITRD=y |
| 15 | CONFIG_EXPERT=y | 13 | CONFIG_EXPERT=y |
| 16 | CONFIG_CHECKPOINT_RESTORE=y | ||
| 17 | CONFIG_BPF_SYSCALL=y | 14 | CONFIG_BPF_SYSCALL=y |
| 15 | CONFIG_SMP=y | ||
| 16 | CONFIG_PCI=y | ||
| 17 | CONFIG_PCIE_XILINX=y | ||
| 18 | CONFIG_MODULES=y | ||
| 19 | CONFIG_MODULE_UNLOAD=y | ||
| 18 | CONFIG_NET=y | 20 | CONFIG_NET=y |
| 19 | CONFIG_PACKET=y | 21 | CONFIG_PACKET=y |
| 20 | CONFIG_UNIX=y | 22 | CONFIG_UNIX=y |
| @@ -59,6 +61,7 @@ CONFIG_USB_OHCI_HCD_PLATFORM=y | |||
| 59 | CONFIG_USB_STORAGE=y | 61 | CONFIG_USB_STORAGE=y |
| 60 | CONFIG_USB_UAS=y | 62 | CONFIG_USB_UAS=y |
| 61 | CONFIG_VIRTIO_MMIO=y | 63 | CONFIG_VIRTIO_MMIO=y |
| 64 | CONFIG_SIFIVE_PLIC=y | ||
| 62 | CONFIG_RAS=y | 65 | CONFIG_RAS=y |
| 63 | CONFIG_EXT4_FS=y | 66 | CONFIG_EXT4_FS=y |
| 64 | CONFIG_EXT4_FS_POSIX_ACL=y | 67 | CONFIG_EXT4_FS_POSIX_ACL=y |
| @@ -72,8 +75,5 @@ CONFIG_NFS_V4=y | |||
| 72 | CONFIG_NFS_V4_1=y | 75 | CONFIG_NFS_V4_1=y |
| 73 | CONFIG_NFS_V4_2=y | 76 | CONFIG_NFS_V4_2=y |
| 74 | CONFIG_ROOT_NFS=y | 77 | CONFIG_ROOT_NFS=y |
| 75 | # CONFIG_RCU_TRACE is not set | ||
| 76 | CONFIG_CRYPTO_USER_API_HASH=y | 78 | CONFIG_CRYPTO_USER_API_HASH=y |
| 77 | CONFIG_MODULES=y | 79 | # CONFIG_RCU_TRACE is not set |
| 78 | CONFIG_MODULE_UNLOAD=y | ||
| 79 | CONFIG_SIFIVE_PLIC=y | ||
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c index d9a7916ff0ab..9fe5952d117d 100644 --- a/block/bfq-cgroup.c +++ b/block/bfq-cgroup.c | |||
| @@ -642,7 +642,7 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) | |||
| 642 | uint64_t serial_nr; | 642 | uint64_t serial_nr; |
| 643 | 643 | ||
| 644 | rcu_read_lock(); | 644 | rcu_read_lock(); |
| 645 | serial_nr = __bio_blkcg(bio)->css.serial_nr; | 645 | serial_nr = bio_blkcg(bio)->css.serial_nr; |
| 646 | 646 | ||
| 647 | /* | 647 | /* |
| 648 | * Check whether blkcg has changed. The condition may trigger | 648 | * Check whether blkcg has changed. The condition may trigger |
| @@ -651,7 +651,7 @@ void bfq_bic_update_cgroup(struct bfq_io_cq *bic, struct bio *bio) | |||
| 651 | if (unlikely(!bfqd) || likely(bic->blkcg_serial_nr == serial_nr)) | 651 | if (unlikely(!bfqd) || likely(bic->blkcg_serial_nr == serial_nr)) |
| 652 | goto out; | 652 | goto out; |
| 653 | 653 | ||
| 654 | bfqg = __bfq_bic_change_cgroup(bfqd, bic, __bio_blkcg(bio)); | 654 | bfqg = __bfq_bic_change_cgroup(bfqd, bic, bio_blkcg(bio)); |
| 655 | /* | 655 | /* |
| 656 | * Update blkg_path for bfq_log_* functions. We cache this | 656 | * Update blkg_path for bfq_log_* functions. We cache this |
| 657 | * path, and update it here, for the following | 657 | * path, and update it here, for the following |
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index 6075100f03a5..3a27d31fcda6 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c | |||
| @@ -4384,7 +4384,7 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd, | |||
| 4384 | 4384 | ||
| 4385 | rcu_read_lock(); | 4385 | rcu_read_lock(); |
| 4386 | 4386 | ||
| 4387 | bfqg = bfq_find_set_group(bfqd, __bio_blkcg(bio)); | 4387 | bfqg = bfq_find_set_group(bfqd, bio_blkcg(bio)); |
| 4388 | if (!bfqg) { | 4388 | if (!bfqg) { |
| 4389 | bfqq = &bfqd->oom_bfqq; | 4389 | bfqq = &bfqd->oom_bfqq; |
| 4390 | goto out; | 4390 | goto out; |
diff --git a/block/bio.c b/block/bio.c index c27f77befbac..d5368a445561 100644 --- a/block/bio.c +++ b/block/bio.c | |||
| @@ -609,9 +609,7 @@ void __bio_clone_fast(struct bio *bio, struct bio *bio_src) | |||
| 609 | bio->bi_iter = bio_src->bi_iter; | 609 | bio->bi_iter = bio_src->bi_iter; |
| 610 | bio->bi_io_vec = bio_src->bi_io_vec; | 610 | bio->bi_io_vec = bio_src->bi_io_vec; |
| 611 | 611 | ||
| 612 | bio_clone_blkg_association(bio, bio_src); | 612 | bio_clone_blkcg_association(bio, bio_src); |
| 613 | |||
| 614 | blkcg_bio_issue_init(bio); | ||
| 615 | } | 613 | } |
| 616 | EXPORT_SYMBOL(__bio_clone_fast); | 614 | EXPORT_SYMBOL(__bio_clone_fast); |
| 617 | 615 | ||
| @@ -1956,151 +1954,69 @@ EXPORT_SYMBOL(bioset_init_from_src); | |||
| 1956 | 1954 | ||
| 1957 | #ifdef CONFIG_BLK_CGROUP | 1955 | #ifdef CONFIG_BLK_CGROUP |
| 1958 | 1956 | ||
| 1959 | /** | ||
| 1960 | * bio_associate_blkg - associate a bio with the a blkg | ||
| 1961 | * @bio: target bio | ||
| 1962 | * @blkg: the blkg to associate | ||
| 1963 | * | ||
| 1964 | * This tries to associate @bio with the specified blkg. Association failure | ||
| 1965 | * is handled by walking up the blkg tree. Therefore, the blkg associated can | ||
| 1966 | * be anything between @blkg and the root_blkg. This situation only happens | ||
| 1967 | * when a cgroup is dying and then the remaining bios will spill to the closest | ||
| 1968 | * alive blkg. | ||
| 1969 | * | ||
| 1970 | * A reference will be taken on the @blkg and will be released when @bio is | ||
| 1971 | * freed. | ||
| 1972 | */ | ||
| 1973 | int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg) | ||
| 1974 | { | ||
| 1975 | if (unlikely(bio->bi_blkg)) | ||
| 1976 | return -EBUSY; | ||
| 1977 | bio->bi_blkg = blkg_tryget_closest(blkg); | ||
| 1978 | return 0; | ||
| 1979 | } | ||
| 1980 | |||
| 1981 | /** | ||
| 1982 | * __bio_associate_blkg_from_css - internal blkg association function | ||
| 1983 | * | ||
| 1984 | * This in the core association function that all association paths rely on. | ||
| 1985 | * A blkg reference is taken which is released upon freeing of the bio. | ||
| 1986 | */ | ||
| 1987 | static int __bio_associate_blkg_from_css(struct bio *bio, | ||
| 1988 | struct cgroup_subsys_state *css) | ||
| 1989 | { | ||
| 1990 | struct request_queue *q = bio->bi_disk->queue; | ||
| 1991 | struct blkcg_gq *blkg; | ||
| 1992 | int ret; | ||
| 1993 | |||
| 1994 | rcu_read_lock(); | ||
| 1995 | |||
| 1996 | if (!css || !css->parent) | ||
| 1997 | blkg = q->root_blkg; | ||
| 1998 | else | ||
| 1999 | blkg = blkg_lookup_create(css_to_blkcg(css), q); | ||
| 2000 | |||
| 2001 | ret = bio_associate_blkg(bio, blkg); | ||
| 2002 | |||
| 2003 | rcu_read_unlock(); | ||
| 2004 | return ret; | ||
| 2005 | } | ||
| 2006 | |||
| 2007 | /** | ||
| 2008 | * bio_associate_blkg_from_css - associate a bio with a specified css | ||
| 2009 | * @bio: target bio | ||
| 2010 | * @css: target css | ||
| 2011 | * | ||
| 2012 | * Associate @bio with the blkg found by combining the css's blkg and the | ||
| 2013 | * request_queue of the @bio. This falls back to the queue's root_blkg if | ||
| 2014 | * the association fails with the css. | ||
| 2015 | */ | ||
| 2016 | int bio_associate_blkg_from_css(struct bio *bio, | ||
| 2017 | struct cgroup_subsys_state *css) | ||
| 2018 | { | ||
| 2019 | if (unlikely(bio->bi_blkg)) | ||
| 2020 | return -EBUSY; | ||
| 2021 | return __bio_associate_blkg_from_css(bio, css); | ||
| 2022 | } | ||
| 2023 | EXPORT_SYMBOL_GPL(bio_associate_blkg_from_css); | ||
| 2024 | |||
| 2025 | #ifdef CONFIG_MEMCG | 1957 | #ifdef CONFIG_MEMCG |
| 2026 | /** | 1958 | /** |
| 2027 | * bio_associate_blkg_from_page - associate a bio with the page's blkg | 1959 | * bio_associate_blkcg_from_page - associate a bio with the page's blkcg |
| 2028 | * @bio: target bio | 1960 | * @bio: target bio |
| 2029 | * @page: the page to lookup the blkcg from | 1961 | * @page: the page to lookup the blkcg from |
| 2030 | * | 1962 | * |
| 2031 | * Associate @bio with the blkg from @page's owning memcg and the respective | 1963 | * Associate @bio with the blkcg from @page's owning memcg. This works like |
| 2032 | * request_queue. If cgroup_e_css returns NULL, fall back to the queue's | 1964 | * every other associate function wrt references. |
| 2033 | * root_blkg. | ||
| 2034 | * | ||
| 2035 | * Note: this must be called after bio has an associated device. | ||
| 2036 | */ | 1965 | */ |
| 2037 | int bio_associate_blkg_from_page(struct bio *bio, struct page *page) | 1966 | int bio_associate_blkcg_from_page(struct bio *bio, struct page *page) |
| 2038 | { | 1967 | { |
| 2039 | struct cgroup_subsys_state *css; | 1968 | struct cgroup_subsys_state *blkcg_css; |
| 2040 | int ret; | ||
| 2041 | 1969 | ||
| 2042 | if (unlikely(bio->bi_blkg)) | 1970 | if (unlikely(bio->bi_css)) |
| 2043 | return -EBUSY; | 1971 | return -EBUSY; |
| 2044 | if (!page->mem_cgroup) | 1972 | if (!page->mem_cgroup) |
| 2045 | return 0; | 1973 | return 0; |
| 2046 | 1974 | blkcg_css = cgroup_get_e_css(page->mem_cgroup->css.cgroup, | |
| 2047 | rcu_read_lock(); | 1975 | &io_cgrp_subsys); |
| 2048 | 1976 | bio->bi_css = blkcg_css; | |
| 2049 | css = cgroup_e_css(page->mem_cgroup->css.cgroup, &io_cgrp_subsys); | 1977 | return 0; |
| 2050 | |||
| 2051 | ret = __bio_associate_blkg_from_css(bio, css); | ||
| 2052 | |||
| 2053 | rcu_read_unlock(); | ||
| 2054 | return ret; | ||
| 2055 | } | 1978 | } |
| 2056 | #endif /* CONFIG_MEMCG */ | 1979 | #endif /* CONFIG_MEMCG */ |
| 2057 | 1980 | ||
| 2058 | /** | 1981 | /** |
| 2059 | * bio_associate_create_blkg - associate a bio with a blkg from q | 1982 | * bio_associate_blkcg - associate a bio with the specified blkcg |
| 2060 | * @q: request_queue where bio is going | ||
| 2061 | * @bio: target bio | 1983 | * @bio: target bio |
| 1984 | * @blkcg_css: css of the blkcg to associate | ||
| 1985 | * | ||
| 1986 | * Associate @bio with the blkcg specified by @blkcg_css. Block layer will | ||
| 1987 | * treat @bio as if it were issued by a task which belongs to the blkcg. | ||
| 2062 | * | 1988 | * |
| 2063 | * Associate @bio with the blkg found from the bio's css and the request_queue. | 1989 | * This function takes an extra reference of @blkcg_css which will be put |
| 2064 | * If one is not found, bio_lookup_blkg creates the blkg. This falls back to | 1990 | * when @bio is released. The caller must own @bio and is responsible for |
| 2065 | * the queue's root_blkg if association fails. | 1991 | * synchronizing calls to this function. |
| 2066 | */ | 1992 | */ |
| 2067 | int bio_associate_create_blkg(struct request_queue *q, struct bio *bio) | 1993 | int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css) |
| 2068 | { | 1994 | { |
| 2069 | struct cgroup_subsys_state *css; | 1995 | if (unlikely(bio->bi_css)) |
| 2070 | int ret = 0; | 1996 | return -EBUSY; |
| 2071 | 1997 | css_get(blkcg_css); | |
| 2072 | /* someone has already associated this bio with a blkg */ | 1998 | bio->bi_css = blkcg_css; |
| 2073 | if (bio->bi_blkg) | 1999 | return 0; |
| 2074 | return ret; | ||
| 2075 | |||
| 2076 | rcu_read_lock(); | ||
| 2077 | |||
| 2078 | css = blkcg_css(); | ||
| 2079 | |||
| 2080 | ret = __bio_associate_blkg_from_css(bio, css); | ||
| 2081 | |||
| 2082 | rcu_read_unlock(); | ||
| 2083 | return ret; | ||
| 2084 | } | 2000 | } |
| 2001 | EXPORT_SYMBOL_GPL(bio_associate_blkcg); | ||
| 2085 | 2002 | ||
| 2086 | /** | 2003 | /** |
| 2087 | * bio_reassociate_blkg - reassociate a bio with a blkg from q | 2004 | * bio_associate_blkg - associate a bio with the specified blkg |
| 2088 | * @q: request_queue where bio is going | ||
| 2089 | * @bio: target bio | 2005 | * @bio: target bio |
| 2006 | * @blkg: the blkg to associate | ||
| 2090 | * | 2007 | * |
| 2091 | * When submitting a bio, multiple recursive calls to make_request() may occur. | 2008 | * Associate @bio with the blkg specified by @blkg. This is the queue specific |
| 2092 | * This causes the initial associate done in blkcg_bio_issue_check() to be | 2009 | * blkcg information associated with the @bio, a reference will be taken on the |
| 2093 | * incorrect and reference the prior request_queue. This performs reassociation | 2010 | * @blkg and will be freed when the bio is freed. |
| 2094 | * when this situation happens. | ||
| 2095 | */ | 2011 | */ |
| 2096 | int bio_reassociate_blkg(struct request_queue *q, struct bio *bio) | 2012 | int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg) |
| 2097 | { | 2013 | { |
| 2098 | if (bio->bi_blkg) { | 2014 | if (unlikely(bio->bi_blkg)) |
| 2099 | blkg_put(bio->bi_blkg); | 2015 | return -EBUSY; |
| 2100 | bio->bi_blkg = NULL; | 2016 | if (!blkg_try_get(blkg)) |
| 2101 | } | 2017 | return -ENODEV; |
| 2102 | 2018 | bio->bi_blkg = blkg; | |
| 2103 | return bio_associate_create_blkg(q, bio); | 2019 | return 0; |
| 2104 | } | 2020 | } |
| 2105 | 2021 | ||
| 2106 | /** | 2022 | /** |
| @@ -2113,6 +2029,10 @@ void bio_disassociate_task(struct bio *bio) | |||
| 2113 | put_io_context(bio->bi_ioc); | 2029 | put_io_context(bio->bi_ioc); |
| 2114 | bio->bi_ioc = NULL; | 2030 | bio->bi_ioc = NULL; |
| 2115 | } | 2031 | } |
| 2032 | if (bio->bi_css) { | ||
| 2033 | css_put(bio->bi_css); | ||
| 2034 | bio->bi_css = NULL; | ||
| 2035 | } | ||
| 2116 | if (bio->bi_blkg) { | 2036 | if (bio->bi_blkg) { |
| 2117 | blkg_put(bio->bi_blkg); | 2037 | blkg_put(bio->bi_blkg); |
| 2118 | bio->bi_blkg = NULL; | 2038 | bio->bi_blkg = NULL; |
| @@ -2120,16 +2040,16 @@ void bio_disassociate_task(struct bio *bio) | |||
| 2120 | } | 2040 | } |
| 2121 | 2041 | ||
| 2122 | /** | 2042 | /** |
| 2123 | * bio_clone_blkg_association - clone blkg association from src to dst bio | 2043 | * bio_clone_blkcg_association - clone blkcg association from src to dst bio |
| 2124 | * @dst: destination bio | 2044 | * @dst: destination bio |
| 2125 | * @src: source bio | 2045 | * @src: source bio |
| 2126 | */ | 2046 | */ |
| 2127 | void bio_clone_blkg_association(struct bio *dst, struct bio *src) | 2047 | void bio_clone_blkcg_association(struct bio *dst, struct bio *src) |
| 2128 | { | 2048 | { |
| 2129 | if (src->bi_blkg) | 2049 | if (src->bi_css) |
| 2130 | bio_associate_blkg(dst, src->bi_blkg); | 2050 | WARN_ON(bio_associate_blkcg(dst, src->bi_css)); |
| 2131 | } | 2051 | } |
| 2132 | EXPORT_SYMBOL_GPL(bio_clone_blkg_association); | 2052 | EXPORT_SYMBOL_GPL(bio_clone_blkcg_association); |
| 2133 | #endif /* CONFIG_BLK_CGROUP */ | 2053 | #endif /* CONFIG_BLK_CGROUP */ |
| 2134 | 2054 | ||
| 2135 | static void __init biovec_init_slabs(void) | 2055 | static void __init biovec_init_slabs(void) |
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 992da5592c6e..c630e02836a8 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c | |||
| @@ -84,37 +84,6 @@ static void blkg_free(struct blkcg_gq *blkg) | |||
| 84 | kfree(blkg); | 84 | kfree(blkg); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static void __blkg_release(struct rcu_head *rcu) | ||
| 88 | { | ||
| 89 | struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head); | ||
| 90 | |||
| 91 | percpu_ref_exit(&blkg->refcnt); | ||
| 92 | |||
| 93 | /* release the blkcg and parent blkg refs this blkg has been holding */ | ||
| 94 | css_put(&blkg->blkcg->css); | ||
| 95 | if (blkg->parent) | ||
| 96 | blkg_put(blkg->parent); | ||
| 97 | |||
| 98 | wb_congested_put(blkg->wb_congested); | ||
| 99 | |||
| 100 | blkg_free(blkg); | ||
| 101 | } | ||
| 102 | |||
| 103 | /* | ||
| 104 | * A group is RCU protected, but having an rcu lock does not mean that one | ||
| 105 | * can access all the fields of blkg and assume these are valid. For | ||
| 106 | * example, don't try to follow throtl_data and request queue links. | ||
| 107 | * | ||
| 108 | * Having a reference to blkg under an rcu allows accesses to only values | ||
| 109 | * local to groups like group stats and group rate limits. | ||
| 110 | */ | ||
| 111 | static void blkg_release(struct percpu_ref *ref) | ||
| 112 | { | ||
| 113 | struct blkcg_gq *blkg = container_of(ref, struct blkcg_gq, refcnt); | ||
| 114 | |||
| 115 | call_rcu(&blkg->rcu_head, __blkg_release); | ||
| 116 | } | ||
| 117 | |||
| 118 | /** | 87 | /** |
| 119 | * blkg_alloc - allocate a blkg | 88 | * blkg_alloc - allocate a blkg |
| 120 | * @blkcg: block cgroup the new blkg is associated with | 89 | * @blkcg: block cgroup the new blkg is associated with |
| @@ -141,6 +110,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q, | |||
| 141 | blkg->q = q; | 110 | blkg->q = q; |
| 142 | INIT_LIST_HEAD(&blkg->q_node); | 111 | INIT_LIST_HEAD(&blkg->q_node); |
| 143 | blkg->blkcg = blkcg; | 112 | blkg->blkcg = blkcg; |
| 113 | atomic_set(&blkg->refcnt, 1); | ||
| 144 | 114 | ||
| 145 | /* root blkg uses @q->root_rl, init rl only for !root blkgs */ | 115 | /* root blkg uses @q->root_rl, init rl only for !root blkgs */ |
| 146 | if (blkcg != &blkcg_root) { | 116 | if (blkcg != &blkcg_root) { |
| @@ -247,11 +217,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
| 247 | blkg_get(blkg->parent); | 217 | blkg_get(blkg->parent); |
| 248 | } | 218 | } |
| 249 | 219 | ||
| 250 | ret = percpu_ref_init(&blkg->refcnt, blkg_release, 0, | ||
| 251 | GFP_NOWAIT | __GFP_NOWARN); | ||
| 252 | if (ret) | ||
| 253 | goto err_cancel_ref; | ||
| 254 | |||
| 255 | /* invoke per-policy init */ | 220 | /* invoke per-policy init */ |
| 256 | for (i = 0; i < BLKCG_MAX_POLS; i++) { | 221 | for (i = 0; i < BLKCG_MAX_POLS; i++) { |
| 257 | struct blkcg_policy *pol = blkcg_policy[i]; | 222 | struct blkcg_policy *pol = blkcg_policy[i]; |
| @@ -284,8 +249,6 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg, | |||
| 284 | blkg_put(blkg); | 249 | blkg_put(blkg); |
| 285 | return ERR_PTR(ret); | 250 | return ERR_PTR(ret); |
| 286 | 251 | ||
| 287 | err_cancel_ref: | ||
| 288 | percpu_ref_exit(&blkg->refcnt); | ||
| 289 | err_put_congested: | 252 | err_put_congested: |
| 290 | wb_congested_put(wb_congested); | 253 | wb_congested_put(wb_congested); |
| 291 | err_put_css: | 254 | err_put_css: |
| @@ -296,7 +259,7 @@ err_free_blkg: | |||
| 296 | } | 259 | } |
| 297 | 260 | ||
| 298 | /** | 261 | /** |
| 299 | * __blkg_lookup_create - lookup blkg, try to create one if not there | 262 | * blkg_lookup_create - lookup blkg, try to create one if not there |
| 300 | * @blkcg: blkcg of interest | 263 | * @blkcg: blkcg of interest |
| 301 | * @q: request_queue of interest | 264 | * @q: request_queue of interest |
| 302 | * | 265 | * |
| @@ -305,11 +268,12 @@ err_free_blkg: | |||
| 305 | * that all non-root blkg's have access to the parent blkg. This function | 268 | * that all non-root blkg's have access to the parent blkg. This function |
| 306 | * should be called under RCU read lock and @q->queue_lock. | 269 | * should be called under RCU read lock and @q->queue_lock. |
| 307 | * | 270 | * |
| 308 | * Returns the blkg or the closest blkg if blkg_create fails as it walks | 271 | * Returns pointer to the looked up or created blkg on success, ERR_PTR() |
| 309 | * down from root. | 272 | * value on error. If @q is dead, returns ERR_PTR(-EINVAL). If @q is not |
| 273 | * dead and bypassing, returns ERR_PTR(-EBUSY). | ||
| 310 | */ | 274 | */ |
| 311 | struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg, | 275 | struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, |
| 312 | struct request_queue *q) | 276 | struct request_queue *q) |
| 313 | { | 277 | { |
| 314 | struct blkcg_gq *blkg; | 278 | struct blkcg_gq *blkg; |
| 315 | 279 | ||
| @@ -321,7 +285,7 @@ struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg, | |||
| 321 | * we shouldn't allow anything to go through for a bypassing queue. | 285 | * we shouldn't allow anything to go through for a bypassing queue. |
| 322 | */ | 286 | */ |
| 323 | if (unlikely(blk_queue_bypass(q))) | 287 | if (unlikely(blk_queue_bypass(q))) |
| 324 | return q->root_blkg; | 288 | return ERR_PTR(blk_queue_dying(q) ? -ENODEV : -EBUSY); |
| 325 | 289 | ||
| 326 | blkg = __blkg_lookup(blkcg, q, true); | 290 | blkg = __blkg_lookup(blkcg, q, true); |
| 327 | if (blkg) | 291 | if (blkg) |
| @@ -329,58 +293,23 @@ struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg, | |||
| 329 | 293 | ||
| 330 | /* | 294 | /* |
| 331 | * Create blkgs walking down from blkcg_root to @blkcg, so that all | 295 | * Create blkgs walking down from blkcg_root to @blkcg, so that all |
| 332 | * non-root blkgs have access to their parents. Returns the closest | 296 | * non-root blkgs have access to their parents. |
| 333 | * blkg to the intended blkg should blkg_create() fail. | ||
| 334 | */ | 297 | */ |
| 335 | while (true) { | 298 | while (true) { |
| 336 | struct blkcg *pos = blkcg; | 299 | struct blkcg *pos = blkcg; |
| 337 | struct blkcg *parent = blkcg_parent(blkcg); | 300 | struct blkcg *parent = blkcg_parent(blkcg); |
| 338 | struct blkcg_gq *ret_blkg = q->root_blkg; | 301 | |
| 339 | 302 | while (parent && !__blkg_lookup(parent, q, false)) { | |
| 340 | while (parent) { | ||
| 341 | blkg = __blkg_lookup(parent, q, false); | ||
| 342 | if (blkg) { | ||
| 343 | /* remember closest blkg */ | ||
| 344 | ret_blkg = blkg; | ||
| 345 | break; | ||
| 346 | } | ||
| 347 | pos = parent; | 303 | pos = parent; |
| 348 | parent = blkcg_parent(parent); | 304 | parent = blkcg_parent(parent); |
| 349 | } | 305 | } |
| 350 | 306 | ||
| 351 | blkg = blkg_create(pos, q, NULL); | 307 | blkg = blkg_create(pos, q, NULL); |
| 352 | if (IS_ERR(blkg)) | 308 | if (pos == blkcg || IS_ERR(blkg)) |
| 353 | return ret_blkg; | ||
| 354 | if (pos == blkcg) | ||
| 355 | return blkg; | 309 | return blkg; |
| 356 | } | 310 | } |
| 357 | } | 311 | } |
| 358 | 312 | ||
| 359 | /** | ||
| 360 | * blkg_lookup_create - find or create a blkg | ||
| 361 | * @blkcg: target block cgroup | ||
| 362 | * @q: target request_queue | ||
| 363 | * | ||
| 364 | * This looks up or creates the blkg representing the unique pair | ||
| 365 | * of the blkcg and the request_queue. | ||
| 366 | */ | ||
| 367 | struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, | ||
| 368 | struct request_queue *q) | ||
| 369 | { | ||
| 370 | struct blkcg_gq *blkg = blkg_lookup(blkcg, q); | ||
| 371 | unsigned long flags; | ||
| 372 | |||
| 373 | if (unlikely(!blkg)) { | ||
| 374 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 375 | |||
| 376 | blkg = __blkg_lookup_create(blkcg, q); | ||
| 377 | |||
| 378 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 379 | } | ||
| 380 | |||
| 381 | return blkg; | ||
| 382 | } | ||
| 383 | |||
| 384 | static void blkg_destroy(struct blkcg_gq *blkg) | 313 | static void blkg_destroy(struct blkcg_gq *blkg) |
| 385 | { | 314 | { |
| 386 | struct blkcg *blkcg = blkg->blkcg; | 315 | struct blkcg *blkcg = blkg->blkcg; |
| @@ -424,7 +353,7 @@ static void blkg_destroy(struct blkcg_gq *blkg) | |||
| 424 | * Put the reference taken at the time of creation so that when all | 353 | * Put the reference taken at the time of creation so that when all |
| 425 | * queues are gone, group can be destroyed. | 354 | * queues are gone, group can be destroyed. |
| 426 | */ | 355 | */ |
| 427 | percpu_ref_kill(&blkg->refcnt); | 356 | blkg_put(blkg); |
| 428 | } | 357 | } |
| 429 | 358 | ||
| 430 | /** | 359 | /** |
| @@ -452,6 +381,29 @@ static void blkg_destroy_all(struct request_queue *q) | |||
| 452 | } | 381 | } |
| 453 | 382 | ||
| 454 | /* | 383 | /* |
| 384 | * A group is RCU protected, but having an rcu lock does not mean that one | ||
| 385 | * can access all the fields of blkg and assume these are valid. For | ||
| 386 | * example, don't try to follow throtl_data and request queue links. | ||
| 387 | * | ||
| 388 | * Having a reference to blkg under an rcu allows accesses to only values | ||
| 389 | * local to groups like group stats and group rate limits. | ||
| 390 | */ | ||
| 391 | void __blkg_release_rcu(struct rcu_head *rcu_head) | ||
| 392 | { | ||
| 393 | struct blkcg_gq *blkg = container_of(rcu_head, struct blkcg_gq, rcu_head); | ||
| 394 | |||
| 395 | /* release the blkcg and parent blkg refs this blkg has been holding */ | ||
| 396 | css_put(&blkg->blkcg->css); | ||
| 397 | if (blkg->parent) | ||
| 398 | blkg_put(blkg->parent); | ||
| 399 | |||
| 400 | wb_congested_put(blkg->wb_congested); | ||
| 401 | |||
| 402 | blkg_free(blkg); | ||
| 403 | } | ||
| 404 | EXPORT_SYMBOL_GPL(__blkg_release_rcu); | ||
| 405 | |||
| 406 | /* | ||
| 455 | * The next function used by blk_queue_for_each_rl(). It's a bit tricky | 407 | * The next function used by blk_queue_for_each_rl(). It's a bit tricky |
| 456 | * because the root blkg uses @q->root_rl instead of its own rl. | 408 | * because the root blkg uses @q->root_rl instead of its own rl. |
| 457 | */ | 409 | */ |
| @@ -1796,7 +1748,8 @@ void blkcg_maybe_throttle_current(void) | |||
| 1796 | blkg = blkg_lookup(blkcg, q); | 1748 | blkg = blkg_lookup(blkcg, q); |
| 1797 | if (!blkg) | 1749 | if (!blkg) |
| 1798 | goto out; | 1750 | goto out; |
| 1799 | if (!blkg_tryget(blkg)) | 1751 | blkg = blkg_try_get(blkg); |
| 1752 | if (!blkg) | ||
| 1800 | goto out; | 1753 | goto out; |
| 1801 | rcu_read_unlock(); | 1754 | rcu_read_unlock(); |
| 1802 | 1755 | ||
diff --git a/block/blk-core.c b/block/blk-core.c index bc6ea87d10e0..ce12515f9b9b 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -785,6 +785,9 @@ void blk_cleanup_queue(struct request_queue *q) | |||
| 785 | * prevent that q->request_fn() gets invoked after draining finished. | 785 | * prevent that q->request_fn() gets invoked after draining finished. |
| 786 | */ | 786 | */ |
| 787 | blk_freeze_queue(q); | 787 | blk_freeze_queue(q); |
| 788 | |||
| 789 | rq_qos_exit(q); | ||
| 790 | |||
| 788 | spin_lock_irq(lock); | 791 | spin_lock_irq(lock); |
| 789 | queue_flag_set(QUEUE_FLAG_DEAD, q); | 792 | queue_flag_set(QUEUE_FLAG_DEAD, q); |
| 790 | spin_unlock_irq(lock); | 793 | spin_unlock_irq(lock); |
| @@ -2432,7 +2435,6 @@ blk_qc_t generic_make_request(struct bio *bio) | |||
| 2432 | if (q) | 2435 | if (q) |
| 2433 | blk_queue_exit(q); | 2436 | blk_queue_exit(q); |
| 2434 | q = bio->bi_disk->queue; | 2437 | q = bio->bi_disk->queue; |
| 2435 | bio_reassociate_blkg(q, bio); | ||
| 2436 | flags = 0; | 2438 | flags = 0; |
| 2437 | if (bio->bi_opf & REQ_NOWAIT) | 2439 | if (bio->bi_opf & REQ_NOWAIT) |
| 2438 | flags = BLK_MQ_REQ_NOWAIT; | 2440 | flags = BLK_MQ_REQ_NOWAIT; |
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c index 28f80d227528..38c35c32aff2 100644 --- a/block/blk-iolatency.c +++ b/block/blk-iolatency.c | |||
| @@ -482,12 +482,34 @@ static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio, | |||
| 482 | spinlock_t *lock) | 482 | spinlock_t *lock) |
| 483 | { | 483 | { |
| 484 | struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos); | 484 | struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos); |
| 485 | struct blkcg_gq *blkg = bio->bi_blkg; | 485 | struct blkcg *blkcg; |
| 486 | struct blkcg_gq *blkg; | ||
| 487 | struct request_queue *q = rqos->q; | ||
| 486 | bool issue_as_root = bio_issue_as_root_blkg(bio); | 488 | bool issue_as_root = bio_issue_as_root_blkg(bio); |
| 487 | 489 | ||
| 488 | if (!blk_iolatency_enabled(blkiolat)) | 490 | if (!blk_iolatency_enabled(blkiolat)) |
| 489 | return; | 491 | return; |
| 490 | 492 | ||
| 493 | rcu_read_lock(); | ||
| 494 | blkcg = bio_blkcg(bio); | ||
| 495 | bio_associate_blkcg(bio, &blkcg->css); | ||
| 496 | blkg = blkg_lookup(blkcg, q); | ||
| 497 | if (unlikely(!blkg)) { | ||
| 498 | if (!lock) | ||
| 499 | spin_lock_irq(q->queue_lock); | ||
| 500 | blkg = blkg_lookup_create(blkcg, q); | ||
| 501 | if (IS_ERR(blkg)) | ||
| 502 | blkg = NULL; | ||
| 503 | if (!lock) | ||
| 504 | spin_unlock_irq(q->queue_lock); | ||
| 505 | } | ||
| 506 | if (!blkg) | ||
| 507 | goto out; | ||
| 508 | |||
| 509 | bio_issue_init(&bio->bi_issue, bio_sectors(bio)); | ||
| 510 | bio_associate_blkg(bio, blkg); | ||
| 511 | out: | ||
| 512 | rcu_read_unlock(); | ||
| 491 | while (blkg && blkg->parent) { | 513 | while (blkg && blkg->parent) { |
| 492 | struct iolatency_grp *iolat = blkg_to_lat(blkg); | 514 | struct iolatency_grp *iolat = blkg_to_lat(blkg); |
| 493 | if (!iolat) { | 515 | if (!iolat) { |
| @@ -708,7 +730,7 @@ static void blkiolatency_timer_fn(struct timer_list *t) | |||
| 708 | * We could be exiting, don't access the pd unless we have a | 730 | * We could be exiting, don't access the pd unless we have a |
| 709 | * ref on the blkg. | 731 | * ref on the blkg. |
| 710 | */ | 732 | */ |
| 711 | if (!blkg_tryget(blkg)) | 733 | if (!blkg_try_get(blkg)) |
| 712 | continue; | 734 | continue; |
| 713 | 735 | ||
| 714 | iolat = blkg_to_lat(blkg); | 736 | iolat = blkg_to_lat(blkg); |
diff --git a/block/blk-merge.c b/block/blk-merge.c index 42a46744c11b..6b5ad275ed56 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
| @@ -714,6 +714,31 @@ static void blk_account_io_merge(struct request *req) | |||
| 714 | part_stat_unlock(); | 714 | part_stat_unlock(); |
| 715 | } | 715 | } |
| 716 | } | 716 | } |
| 717 | /* | ||
| 718 | * Two cases of handling DISCARD merge: | ||
| 719 | * If max_discard_segments > 1, the driver takes every bio | ||
| 720 | * as a range and send them to controller together. The ranges | ||
| 721 | * needn't to be contiguous. | ||
| 722 | * Otherwise, the bios/requests will be handled as same as | ||
| 723 | * others which should be contiguous. | ||
| 724 | */ | ||
| 725 | static inline bool blk_discard_mergable(struct request *req) | ||
| 726 | { | ||
| 727 | if (req_op(req) == REQ_OP_DISCARD && | ||
| 728 | queue_max_discard_segments(req->q) > 1) | ||
| 729 | return true; | ||
| 730 | return false; | ||
| 731 | } | ||
| 732 | |||
| 733 | enum elv_merge blk_try_req_merge(struct request *req, struct request *next) | ||
| 734 | { | ||
| 735 | if (blk_discard_mergable(req)) | ||
| 736 | return ELEVATOR_DISCARD_MERGE; | ||
| 737 | else if (blk_rq_pos(req) + blk_rq_sectors(req) == blk_rq_pos(next)) | ||
| 738 | return ELEVATOR_BACK_MERGE; | ||
| 739 | |||
| 740 | return ELEVATOR_NO_MERGE; | ||
| 741 | } | ||
| 717 | 742 | ||
| 718 | /* | 743 | /* |
| 719 | * For non-mq, this has to be called with the request spinlock acquired. | 744 | * For non-mq, this has to be called with the request spinlock acquired. |
| @@ -731,12 +756,6 @@ static struct request *attempt_merge(struct request_queue *q, | |||
| 731 | if (req_op(req) != req_op(next)) | 756 | if (req_op(req) != req_op(next)) |
| 732 | return NULL; | 757 | return NULL; |
| 733 | 758 | ||
| 734 | /* | ||
| 735 | * not contiguous | ||
| 736 | */ | ||
| 737 | if (blk_rq_pos(req) + blk_rq_sectors(req) != blk_rq_pos(next)) | ||
| 738 | return NULL; | ||
| 739 | |||
| 740 | if (rq_data_dir(req) != rq_data_dir(next) | 759 | if (rq_data_dir(req) != rq_data_dir(next) |
| 741 | || req->rq_disk != next->rq_disk | 760 | || req->rq_disk != next->rq_disk |
| 742 | || req_no_special_merge(next)) | 761 | || req_no_special_merge(next)) |
| @@ -760,11 +779,19 @@ static struct request *attempt_merge(struct request_queue *q, | |||
| 760 | * counts here. Handle DISCARDs separately, as they | 779 | * counts here. Handle DISCARDs separately, as they |
| 761 | * have separate settings. | 780 | * have separate settings. |
| 762 | */ | 781 | */ |
| 763 | if (req_op(req) == REQ_OP_DISCARD) { | 782 | |
| 783 | switch (blk_try_req_merge(req, next)) { | ||
| 784 | case ELEVATOR_DISCARD_MERGE: | ||
| 764 | if (!req_attempt_discard_merge(q, req, next)) | 785 | if (!req_attempt_discard_merge(q, req, next)) |
| 765 | return NULL; | 786 | return NULL; |
| 766 | } else if (!ll_merge_requests_fn(q, req, next)) | 787 | break; |
| 788 | case ELEVATOR_BACK_MERGE: | ||
| 789 | if (!ll_merge_requests_fn(q, req, next)) | ||
| 790 | return NULL; | ||
| 791 | break; | ||
| 792 | default: | ||
| 767 | return NULL; | 793 | return NULL; |
| 794 | } | ||
| 768 | 795 | ||
| 769 | /* | 796 | /* |
| 770 | * If failfast settings disagree or any of the two is already | 797 | * If failfast settings disagree or any of the two is already |
| @@ -888,8 +915,7 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) | |||
| 888 | 915 | ||
| 889 | enum elv_merge blk_try_merge(struct request *rq, struct bio *bio) | 916 | enum elv_merge blk_try_merge(struct request *rq, struct bio *bio) |
| 890 | { | 917 | { |
| 891 | if (req_op(rq) == REQ_OP_DISCARD && | 918 | if (blk_discard_mergable(rq)) |
| 892 | queue_max_discard_segments(rq->q) > 1) | ||
| 893 | return ELEVATOR_DISCARD_MERGE; | 919 | return ELEVATOR_DISCARD_MERGE; |
| 894 | else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector) | 920 | else if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector) |
| 895 | return ELEVATOR_BACK_MERGE; | 921 | return ELEVATOR_BACK_MERGE; |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 0641533597f1..844a454a7b3a 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
| @@ -1007,8 +1007,6 @@ void blk_unregister_queue(struct gendisk *disk) | |||
| 1007 | kobject_del(&q->kobj); | 1007 | kobject_del(&q->kobj); |
| 1008 | blk_trace_remove_sysfs(disk_to_dev(disk)); | 1008 | blk_trace_remove_sysfs(disk_to_dev(disk)); |
| 1009 | 1009 | ||
| 1010 | rq_qos_exit(q); | ||
| 1011 | |||
| 1012 | mutex_lock(&q->sysfs_lock); | 1010 | mutex_lock(&q->sysfs_lock); |
| 1013 | if (q->request_fn || (q->mq_ops && q->elevator)) | 1011 | if (q->request_fn || (q->mq_ops && q->elevator)) |
| 1014 | elv_unregister_queue(q); | 1012 | elv_unregister_queue(q); |
diff --git a/block/blk-throttle.c b/block/blk-throttle.c index 4bda70e8db48..db1a3a2ae006 100644 --- a/block/blk-throttle.c +++ b/block/blk-throttle.c | |||
| @@ -2115,11 +2115,21 @@ static inline void throtl_update_latency_buckets(struct throtl_data *td) | |||
| 2115 | } | 2115 | } |
| 2116 | #endif | 2116 | #endif |
| 2117 | 2117 | ||
| 2118 | static void blk_throtl_assoc_bio(struct throtl_grp *tg, struct bio *bio) | ||
| 2119 | { | ||
| 2120 | #ifdef CONFIG_BLK_DEV_THROTTLING_LOW | ||
| 2121 | /* fallback to root_blkg if we fail to get a blkg ref */ | ||
| 2122 | if (bio->bi_css && (bio_associate_blkg(bio, tg_to_blkg(tg)) == -ENODEV)) | ||
| 2123 | bio_associate_blkg(bio, bio->bi_disk->queue->root_blkg); | ||
| 2124 | bio_issue_init(&bio->bi_issue, bio_sectors(bio)); | ||
| 2125 | #endif | ||
| 2126 | } | ||
| 2127 | |||
| 2118 | bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, | 2128 | bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, |
| 2119 | struct bio *bio) | 2129 | struct bio *bio) |
| 2120 | { | 2130 | { |
| 2121 | struct throtl_qnode *qn = NULL; | 2131 | struct throtl_qnode *qn = NULL; |
| 2122 | struct throtl_grp *tg = blkg_to_tg(blkg); | 2132 | struct throtl_grp *tg = blkg_to_tg(blkg ?: q->root_blkg); |
| 2123 | struct throtl_service_queue *sq; | 2133 | struct throtl_service_queue *sq; |
| 2124 | bool rw = bio_data_dir(bio); | 2134 | bool rw = bio_data_dir(bio); |
| 2125 | bool throttled = false; | 2135 | bool throttled = false; |
| @@ -2138,6 +2148,7 @@ bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg, | |||
| 2138 | if (unlikely(blk_queue_bypass(q))) | 2148 | if (unlikely(blk_queue_bypass(q))) |
| 2139 | goto out_unlock; | 2149 | goto out_unlock; |
| 2140 | 2150 | ||
| 2151 | blk_throtl_assoc_bio(tg, bio); | ||
| 2141 | blk_throtl_update_idletime(tg); | 2152 | blk_throtl_update_idletime(tg); |
| 2142 | 2153 | ||
| 2143 | sq = &tg->service_queue; | 2154 | sq = &tg->service_queue; |
diff --git a/block/bounce.c b/block/bounce.c index cf49fe02f65c..36869afc258c 100644 --- a/block/bounce.c +++ b/block/bounce.c | |||
| @@ -276,9 +276,7 @@ static struct bio *bounce_clone_bio(struct bio *bio_src, gfp_t gfp_mask, | |||
| 276 | } | 276 | } |
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | bio_clone_blkg_association(bio, bio_src); | 279 | bio_clone_blkcg_association(bio, bio_src); |
| 280 | |||
| 281 | blkcg_bio_issue_init(bio); | ||
| 282 | 280 | ||
| 283 | return bio; | 281 | return bio; |
| 284 | } | 282 | } |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 6a3d87dd3c1a..ed41aa978c4a 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -3759,7 +3759,7 @@ static void check_blkcg_changed(struct cfq_io_cq *cic, struct bio *bio) | |||
| 3759 | uint64_t serial_nr; | 3759 | uint64_t serial_nr; |
| 3760 | 3760 | ||
| 3761 | rcu_read_lock(); | 3761 | rcu_read_lock(); |
| 3762 | serial_nr = __bio_blkcg(bio)->css.serial_nr; | 3762 | serial_nr = bio_blkcg(bio)->css.serial_nr; |
| 3763 | rcu_read_unlock(); | 3763 | rcu_read_unlock(); |
| 3764 | 3764 | ||
| 3765 | /* | 3765 | /* |
| @@ -3824,7 +3824,7 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic, | |||
| 3824 | struct cfq_group *cfqg; | 3824 | struct cfq_group *cfqg; |
| 3825 | 3825 | ||
| 3826 | rcu_read_lock(); | 3826 | rcu_read_lock(); |
| 3827 | cfqg = cfq_lookup_cfqg(cfqd, __bio_blkcg(bio)); | 3827 | cfqg = cfq_lookup_cfqg(cfqd, bio_blkcg(bio)); |
| 3828 | if (!cfqg) { | 3828 | if (!cfqg) { |
| 3829 | cfqq = &cfqd->oom_cfqq; | 3829 | cfqq = &cfqd->oom_cfqq; |
| 3830 | goto out; | 3830 | goto out; |
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index a7c2673ffd36..824ae985ad93 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c | |||
| @@ -126,6 +126,7 @@ int acpi_device_get_power(struct acpi_device *device, int *state) | |||
| 126 | 126 | ||
| 127 | return 0; | 127 | return 0; |
| 128 | } | 128 | } |
| 129 | EXPORT_SYMBOL(acpi_device_get_power); | ||
| 129 | 130 | ||
| 130 | static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) | 131 | static int acpi_dev_pm_explicit_set(struct acpi_device *adev, int state) |
| 131 | { | 132 | { |
diff --git a/drivers/block/brd.c b/drivers/block/brd.c index df8103dd40ac..c18586fccb6f 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c | |||
| @@ -396,15 +396,14 @@ static struct brd_device *brd_alloc(int i) | |||
| 396 | disk->first_minor = i * max_part; | 396 | disk->first_minor = i * max_part; |
| 397 | disk->fops = &brd_fops; | 397 | disk->fops = &brd_fops; |
| 398 | disk->private_data = brd; | 398 | disk->private_data = brd; |
| 399 | disk->queue = brd->brd_queue; | ||
| 400 | disk->flags = GENHD_FL_EXT_DEVT; | 399 | disk->flags = GENHD_FL_EXT_DEVT; |
| 401 | sprintf(disk->disk_name, "ram%d", i); | 400 | sprintf(disk->disk_name, "ram%d", i); |
| 402 | set_capacity(disk, rd_size * 2); | 401 | set_capacity(disk, rd_size * 2); |
| 403 | disk->queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; | 402 | brd->brd_queue->backing_dev_info->capabilities |= BDI_CAP_SYNCHRONOUS_IO; |
| 404 | 403 | ||
| 405 | /* Tell the block layer that this is not a rotational device */ | 404 | /* Tell the block layer that this is not a rotational device */ |
| 406 | blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); | 405 | blk_queue_flag_set(QUEUE_FLAG_NONROT, brd->brd_queue); |
| 407 | blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue); | 406 | blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, brd->brd_queue); |
| 408 | 407 | ||
| 409 | return brd; | 408 | return brd; |
| 410 | 409 | ||
| @@ -436,6 +435,7 @@ static struct brd_device *brd_init_one(int i, bool *new) | |||
| 436 | 435 | ||
| 437 | brd = brd_alloc(i); | 436 | brd = brd_alloc(i); |
| 438 | if (brd) { | 437 | if (brd) { |
| 438 | brd->brd_disk->queue = brd->brd_queue; | ||
| 439 | add_disk(brd->brd_disk); | 439 | add_disk(brd->brd_disk); |
| 440 | list_add_tail(&brd->brd_list, &brd_devices); | 440 | list_add_tail(&brd->brd_list, &brd_devices); |
| 441 | } | 441 | } |
| @@ -503,8 +503,14 @@ static int __init brd_init(void) | |||
| 503 | 503 | ||
| 504 | /* point of no return */ | 504 | /* point of no return */ |
| 505 | 505 | ||
| 506 | list_for_each_entry(brd, &brd_devices, brd_list) | 506 | list_for_each_entry(brd, &brd_devices, brd_list) { |
| 507 | /* | ||
| 508 | * associate with queue just before adding disk for | ||
| 509 | * avoiding to mess up failure path | ||
| 510 | */ | ||
| 511 | brd->brd_disk->queue = brd->brd_queue; | ||
| 507 | add_disk(brd->brd_disk); | 512 | add_disk(brd->brd_disk); |
| 513 | } | ||
| 508 | 514 | ||
| 509 | blk_register_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS, | 515 | blk_register_region(MKDEV(RAMDISK_MAJOR, 0), 1UL << MINORBITS, |
| 510 | THIS_MODULE, brd_probe, NULL, NULL); | 516 | THIS_MODULE, brd_probe, NULL, NULL); |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e6273ae85246..cb0cc8685076 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -77,7 +77,6 @@ | |||
| 77 | #include <linux/falloc.h> | 77 | #include <linux/falloc.h> |
| 78 | #include <linux/uio.h> | 78 | #include <linux/uio.h> |
| 79 | #include <linux/ioprio.h> | 79 | #include <linux/ioprio.h> |
| 80 | #include <linux/blk-cgroup.h> | ||
| 81 | 80 | ||
| 82 | #include "loop.h" | 81 | #include "loop.h" |
| 83 | 82 | ||
| @@ -1760,8 +1759,8 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx, | |||
| 1760 | 1759 | ||
| 1761 | /* always use the first bio's css */ | 1760 | /* always use the first bio's css */ |
| 1762 | #ifdef CONFIG_BLK_CGROUP | 1761 | #ifdef CONFIG_BLK_CGROUP |
| 1763 | if (cmd->use_aio && rq->bio && rq->bio->bi_blkg) { | 1762 | if (cmd->use_aio && rq->bio && rq->bio->bi_css) { |
| 1764 | cmd->css = &bio_blkcg(rq->bio)->css; | 1763 | cmd->css = rq->bio->bi_css; |
| 1765 | css_get(cmd->css); | 1764 | css_get(cmd->css); |
| 1766 | } else | 1765 | } else |
| 1767 | #endif | 1766 | #endif |
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index dfc8de6ce525..a7daa8acbab3 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
| @@ -1942,8 +1942,8 @@ static int exec_drive_taskfile(struct driver_data *dd, | |||
| 1942 | dev_warn(&dd->pdev->dev, | 1942 | dev_warn(&dd->pdev->dev, |
| 1943 | "data movement but " | 1943 | "data movement but " |
| 1944 | "sect_count is 0\n"); | 1944 | "sect_count is 0\n"); |
| 1945 | err = -EINVAL; | 1945 | err = -EINVAL; |
| 1946 | goto abort; | 1946 | goto abort; |
| 1947 | } | 1947 | } |
| 1948 | } | 1948 | } |
| 1949 | } | 1949 | } |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index df9467eef32a..41c9ccdd20d6 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -234,6 +234,7 @@ config EDAC_SKX | |||
| 234 | depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG | 234 | depends on PCI && X86_64 && X86_MCE_INTEL && PCI_MMCONFIG |
| 235 | depends on ACPI_NFIT || !ACPI_NFIT # if ACPI_NFIT=m, EDAC_SKX can't be y | 235 | depends on ACPI_NFIT || !ACPI_NFIT # if ACPI_NFIT=m, EDAC_SKX can't be y |
| 236 | select DMI | 236 | select DMI |
| 237 | select ACPI_ADXL if ACPI | ||
| 237 | help | 238 | help |
| 238 | Support for error detection and correction the Intel | 239 | Support for error detection and correction the Intel |
| 239 | Skylake server Integrated Memory Controllers. If your | 240 | Skylake server Integrated Memory Controllers. If your |
diff --git a/drivers/edac/skx_edac.c b/drivers/edac/skx_edac.c index dd209e0dd9ab..a99ea61dad32 100644 --- a/drivers/edac/skx_edac.c +++ b/drivers/edac/skx_edac.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/bitmap.h> | 26 | #include <linux/bitmap.h> |
| 27 | #include <linux/math64.h> | 27 | #include <linux/math64.h> |
| 28 | #include <linux/mod_devicetable.h> | 28 | #include <linux/mod_devicetable.h> |
| 29 | #include <linux/adxl.h> | ||
| 29 | #include <acpi/nfit.h> | 30 | #include <acpi/nfit.h> |
| 30 | #include <asm/cpu_device_id.h> | 31 | #include <asm/cpu_device_id.h> |
| 31 | #include <asm/intel-family.h> | 32 | #include <asm/intel-family.h> |
| @@ -35,6 +36,7 @@ | |||
| 35 | #include "edac_module.h" | 36 | #include "edac_module.h" |
| 36 | 37 | ||
| 37 | #define EDAC_MOD_STR "skx_edac" | 38 | #define EDAC_MOD_STR "skx_edac" |
| 39 | #define MSG_SIZE 1024 | ||
| 38 | 40 | ||
| 39 | /* | 41 | /* |
| 40 | * Debug macros | 42 | * Debug macros |
| @@ -54,6 +56,29 @@ | |||
| 54 | static LIST_HEAD(skx_edac_list); | 56 | static LIST_HEAD(skx_edac_list); |
| 55 | 57 | ||
| 56 | static u64 skx_tolm, skx_tohm; | 58 | static u64 skx_tolm, skx_tohm; |
| 59 | static char *skx_msg; | ||
| 60 | static unsigned int nvdimm_count; | ||
| 61 | |||
| 62 | enum { | ||
| 63 | INDEX_SOCKET, | ||
| 64 | INDEX_MEMCTRL, | ||
| 65 | INDEX_CHANNEL, | ||
| 66 | INDEX_DIMM, | ||
| 67 | INDEX_MAX | ||
| 68 | }; | ||
| 69 | |||
| 70 | static const char * const component_names[] = { | ||
| 71 | [INDEX_SOCKET] = "ProcessorSocketId", | ||
| 72 | [INDEX_MEMCTRL] = "MemoryControllerId", | ||
| 73 | [INDEX_CHANNEL] = "ChannelId", | ||
| 74 | [INDEX_DIMM] = "DimmSlotId", | ||
| 75 | }; | ||
| 76 | |||
| 77 | static int component_indices[ARRAY_SIZE(component_names)]; | ||
| 78 | static int adxl_component_count; | ||
| 79 | static const char * const *adxl_component_names; | ||
| 80 | static u64 *adxl_values; | ||
| 81 | static char *adxl_msg; | ||
| 57 | 82 | ||
| 58 | #define NUM_IMC 2 /* memory controllers per socket */ | 83 | #define NUM_IMC 2 /* memory controllers per socket */ |
| 59 | #define NUM_CHANNELS 3 /* channels per memory controller */ | 84 | #define NUM_CHANNELS 3 /* channels per memory controller */ |
| @@ -393,6 +418,8 @@ static int get_nvdimm_info(struct dimm_info *dimm, struct skx_imc *imc, | |||
| 393 | u16 flags; | 418 | u16 flags; |
| 394 | u64 size = 0; | 419 | u64 size = 0; |
| 395 | 420 | ||
| 421 | nvdimm_count++; | ||
| 422 | |||
| 396 | dev_handle = ACPI_NFIT_BUILD_DEVICE_HANDLE(dimmno, chan, imc->lmc, | 423 | dev_handle = ACPI_NFIT_BUILD_DEVICE_HANDLE(dimmno, chan, imc->lmc, |
| 397 | imc->src_id, 0); | 424 | imc->src_id, 0); |
| 398 | 425 | ||
| @@ -941,12 +968,46 @@ static void teardown_skx_debug(void) | |||
| 941 | } | 968 | } |
| 942 | #endif /*CONFIG_EDAC_DEBUG*/ | 969 | #endif /*CONFIG_EDAC_DEBUG*/ |
| 943 | 970 | ||
| 971 | static bool skx_adxl_decode(struct decoded_addr *res) | ||
| 972 | |||
| 973 | { | ||
| 974 | int i, len = 0; | ||
| 975 | |||
| 976 | if (res->addr >= skx_tohm || (res->addr >= skx_tolm && | ||
| 977 | res->addr < BIT_ULL(32))) { | ||
| 978 | edac_dbg(0, "Address 0x%llx out of range\n", res->addr); | ||
| 979 | return false; | ||
| 980 | } | ||
| 981 | |||
| 982 | if (adxl_decode(res->addr, adxl_values)) { | ||
| 983 | edac_dbg(0, "Failed to decode 0x%llx\n", res->addr); | ||
| 984 | return false; | ||
| 985 | } | ||
| 986 | |||
| 987 | res->socket = (int)adxl_values[component_indices[INDEX_SOCKET]]; | ||
| 988 | res->imc = (int)adxl_values[component_indices[INDEX_MEMCTRL]]; | ||
| 989 | res->channel = (int)adxl_values[component_indices[INDEX_CHANNEL]]; | ||
| 990 | res->dimm = (int)adxl_values[component_indices[INDEX_DIMM]]; | ||
| 991 | |||
| 992 | for (i = 0; i < adxl_component_count; i++) { | ||
| 993 | if (adxl_values[i] == ~0x0ull) | ||
| 994 | continue; | ||
| 995 | |||
| 996 | len += snprintf(adxl_msg + len, MSG_SIZE - len, " %s:0x%llx", | ||
| 997 | adxl_component_names[i], adxl_values[i]); | ||
| 998 | if (MSG_SIZE - len <= 0) | ||
| 999 | break; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | return true; | ||
| 1003 | } | ||
| 1004 | |||
| 944 | static void skx_mce_output_error(struct mem_ctl_info *mci, | 1005 | static void skx_mce_output_error(struct mem_ctl_info *mci, |
| 945 | const struct mce *m, | 1006 | const struct mce *m, |
| 946 | struct decoded_addr *res) | 1007 | struct decoded_addr *res) |
| 947 | { | 1008 | { |
| 948 | enum hw_event_mc_err_type tp_event; | 1009 | enum hw_event_mc_err_type tp_event; |
| 949 | char *type, *optype, msg[256]; | 1010 | char *type, *optype; |
| 950 | bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); | 1011 | bool ripv = GET_BITFIELD(m->mcgstatus, 0, 0); |
| 951 | bool overflow = GET_BITFIELD(m->status, 62, 62); | 1012 | bool overflow = GET_BITFIELD(m->status, 62, 62); |
| 952 | bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); | 1013 | bool uncorrected_error = GET_BITFIELD(m->status, 61, 61); |
| @@ -1007,22 +1068,47 @@ static void skx_mce_output_error(struct mem_ctl_info *mci, | |||
| 1007 | break; | 1068 | break; |
| 1008 | } | 1069 | } |
| 1009 | } | 1070 | } |
| 1071 | if (adxl_component_count) { | ||
| 1072 | snprintf(skx_msg, MSG_SIZE, "%s%s err_code:%04x:%04x %s", | ||
| 1073 | overflow ? " OVERFLOW" : "", | ||
| 1074 | (uncorrected_error && recoverable) ? " recoverable" : "", | ||
| 1075 | mscod, errcode, adxl_msg); | ||
| 1076 | } else { | ||
| 1077 | snprintf(skx_msg, MSG_SIZE, | ||
| 1078 | "%s%s err_code:%04x:%04x socket:%d imc:%d rank:%d bg:%d ba:%d row:%x col:%x", | ||
| 1079 | overflow ? " OVERFLOW" : "", | ||
| 1080 | (uncorrected_error && recoverable) ? " recoverable" : "", | ||
| 1081 | mscod, errcode, | ||
| 1082 | res->socket, res->imc, res->rank, | ||
| 1083 | res->bank_group, res->bank_address, res->row, res->column); | ||
| 1084 | } | ||
| 1010 | 1085 | ||
| 1011 | snprintf(msg, sizeof(msg), | 1086 | edac_dbg(0, "%s\n", skx_msg); |
| 1012 | "%s%s err_code:%04x:%04x socket:%d imc:%d rank:%d bg:%d ba:%d row:%x col:%x", | ||
| 1013 | overflow ? " OVERFLOW" : "", | ||
| 1014 | (uncorrected_error && recoverable) ? " recoverable" : "", | ||
| 1015 | mscod, errcode, | ||
| 1016 | res->socket, res->imc, res->rank, | ||
| 1017 | res->bank_group, res->bank_address, res->row, res->column); | ||
| 1018 | |||
| 1019 | edac_dbg(0, "%s\n", msg); | ||
| 1020 | 1087 | ||
| 1021 | /* Call the helper to output message */ | 1088 | /* Call the helper to output message */ |
| 1022 | edac_mc_handle_error(tp_event, mci, core_err_cnt, | 1089 | edac_mc_handle_error(tp_event, mci, core_err_cnt, |
| 1023 | m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, | 1090 | m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0, |
| 1024 | res->channel, res->dimm, -1, | 1091 | res->channel, res->dimm, -1, |
| 1025 | optype, msg); | 1092 | optype, skx_msg); |
| 1093 | } | ||
| 1094 | |||
| 1095 | static struct mem_ctl_info *get_mci(int src_id, int lmc) | ||
| 1096 | { | ||
| 1097 | struct skx_dev *d; | ||
| 1098 | |||
| 1099 | if (lmc > NUM_IMC - 1) { | ||
| 1100 | skx_printk(KERN_ERR, "Bad lmc %d\n", lmc); | ||
| 1101 | return NULL; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | list_for_each_entry(d, &skx_edac_list, list) { | ||
| 1105 | if (d->imc[0].src_id == src_id) | ||
| 1106 | return d->imc[lmc].mci; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | skx_printk(KERN_ERR, "No mci for src_id %d lmc %d\n", src_id, lmc); | ||
| 1110 | |||
| 1111 | return NULL; | ||
| 1026 | } | 1112 | } |
| 1027 | 1113 | ||
| 1028 | static int skx_mce_check_error(struct notifier_block *nb, unsigned long val, | 1114 | static int skx_mce_check_error(struct notifier_block *nb, unsigned long val, |
| @@ -1040,10 +1126,23 @@ static int skx_mce_check_error(struct notifier_block *nb, unsigned long val, | |||
| 1040 | if ((mce->status & 0xefff) >> 7 != 1 || !(mce->status & MCI_STATUS_ADDRV)) | 1126 | if ((mce->status & 0xefff) >> 7 != 1 || !(mce->status & MCI_STATUS_ADDRV)) |
| 1041 | return NOTIFY_DONE; | 1127 | return NOTIFY_DONE; |
| 1042 | 1128 | ||
| 1129 | memset(&res, 0, sizeof(res)); | ||
| 1043 | res.addr = mce->addr; | 1130 | res.addr = mce->addr; |
| 1044 | if (!skx_decode(&res)) | 1131 | |
| 1132 | if (adxl_component_count) { | ||
| 1133 | if (!skx_adxl_decode(&res)) | ||
| 1134 | return NOTIFY_DONE; | ||
| 1135 | |||
| 1136 | mci = get_mci(res.socket, res.imc); | ||
| 1137 | } else { | ||
| 1138 | if (!skx_decode(&res)) | ||
| 1139 | return NOTIFY_DONE; | ||
| 1140 | |||
| 1141 | mci = res.dev->imc[res.imc].mci; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | if (!mci) | ||
| 1045 | return NOTIFY_DONE; | 1145 | return NOTIFY_DONE; |
| 1046 | mci = res.dev->imc[res.imc].mci; | ||
| 1047 | 1146 | ||
| 1048 | if (mce->mcgstatus & MCG_STATUS_MCIP) | 1147 | if (mce->mcgstatus & MCG_STATUS_MCIP) |
| 1049 | type = "Exception"; | 1148 | type = "Exception"; |
| @@ -1094,6 +1193,62 @@ static void skx_remove(void) | |||
| 1094 | } | 1193 | } |
| 1095 | } | 1194 | } |
| 1096 | 1195 | ||
| 1196 | static void __init skx_adxl_get(void) | ||
| 1197 | { | ||
| 1198 | const char * const *names; | ||
| 1199 | int i, j; | ||
| 1200 | |||
| 1201 | names = adxl_get_component_names(); | ||
| 1202 | if (!names) { | ||
| 1203 | skx_printk(KERN_NOTICE, "No firmware support for address translation."); | ||
| 1204 | skx_printk(KERN_CONT, " Only decoding DDR4 address!\n"); | ||
| 1205 | return; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | for (i = 0; i < INDEX_MAX; i++) { | ||
| 1209 | for (j = 0; names[j]; j++) { | ||
| 1210 | if (!strcmp(component_names[i], names[j])) { | ||
| 1211 | component_indices[i] = j; | ||
| 1212 | break; | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | if (!names[j]) | ||
| 1217 | goto err; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | adxl_component_names = names; | ||
| 1221 | while (*names++) | ||
| 1222 | adxl_component_count++; | ||
| 1223 | |||
| 1224 | adxl_values = kcalloc(adxl_component_count, sizeof(*adxl_values), | ||
| 1225 | GFP_KERNEL); | ||
| 1226 | if (!adxl_values) { | ||
| 1227 | adxl_component_count = 0; | ||
| 1228 | return; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | adxl_msg = kzalloc(MSG_SIZE, GFP_KERNEL); | ||
| 1232 | if (!adxl_msg) { | ||
| 1233 | adxl_component_count = 0; | ||
| 1234 | kfree(adxl_values); | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | return; | ||
| 1238 | err: | ||
| 1239 | skx_printk(KERN_ERR, "'%s' is not matched from DSM parameters: ", | ||
| 1240 | component_names[i]); | ||
| 1241 | for (j = 0; names[j]; j++) | ||
| 1242 | skx_printk(KERN_CONT, "%s ", names[j]); | ||
| 1243 | skx_printk(KERN_CONT, "\n"); | ||
| 1244 | } | ||
| 1245 | |||
| 1246 | static void __exit skx_adxl_put(void) | ||
| 1247 | { | ||
| 1248 | kfree(adxl_values); | ||
| 1249 | kfree(adxl_msg); | ||
| 1250 | } | ||
| 1251 | |||
| 1097 | /* | 1252 | /* |
| 1098 | * skx_init: | 1253 | * skx_init: |
| 1099 | * make sure we are running on the correct cpu model | 1254 | * make sure we are running on the correct cpu model |
| @@ -1158,6 +1313,15 @@ static int __init skx_init(void) | |||
| 1158 | } | 1313 | } |
| 1159 | } | 1314 | } |
| 1160 | 1315 | ||
| 1316 | skx_msg = kzalloc(MSG_SIZE, GFP_KERNEL); | ||
| 1317 | if (!skx_msg) { | ||
| 1318 | rc = -ENOMEM; | ||
| 1319 | goto fail; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | if (nvdimm_count) | ||
| 1323 | skx_adxl_get(); | ||
| 1324 | |||
| 1161 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ | 1325 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ |
| 1162 | opstate_init(); | 1326 | opstate_init(); |
| 1163 | 1327 | ||
| @@ -1176,6 +1340,9 @@ static void __exit skx_exit(void) | |||
| 1176 | edac_dbg(2, "\n"); | 1340 | edac_dbg(2, "\n"); |
| 1177 | mce_unregister_decode_chain(&skx_mce_dec); | 1341 | mce_unregister_decode_chain(&skx_mce_dec); |
| 1178 | skx_remove(); | 1342 | skx_remove(); |
| 1343 | if (nvdimm_count) | ||
| 1344 | skx_adxl_put(); | ||
| 1345 | kfree(skx_msg); | ||
| 1179 | teardown_skx_debug(); | 1346 | teardown_skx_debug(); |
| 1180 | } | 1347 | } |
| 1181 | 1348 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index 297a5490ad8c..0a4fba196b84 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | |||
| @@ -135,7 +135,8 @@ static int acp_poweroff(struct generic_pm_domain *genpd) | |||
| 135 | * 2. power off the acp tiles | 135 | * 2. power off the acp tiles |
| 136 | * 3. check and enter ulv state | 136 | * 3. check and enter ulv state |
| 137 | */ | 137 | */ |
| 138 | if (adev->powerplay.pp_funcs->set_powergating_by_smu) | 138 | if (adev->powerplay.pp_funcs && |
| 139 | adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 139 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); | 140 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); |
| 140 | } | 141 | } |
| 141 | return 0; | 142 | return 0; |
| @@ -517,7 +518,8 @@ static int acp_set_powergating_state(void *handle, | |||
| 517 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 518 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 518 | bool enable = state == AMD_PG_STATE_GATE ? true : false; | 519 | bool enable = state == AMD_PG_STATE_GATE ? true : false; |
| 519 | 520 | ||
| 520 | if (adev->powerplay.pp_funcs->set_powergating_by_smu) | 521 | if (adev->powerplay.pp_funcs && |
| 522 | adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 521 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); | 523 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); |
| 522 | 524 | ||
| 523 | return 0; | 525 | return 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1e4dd09a5072..30bc345d6fdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
| @@ -1493,8 +1493,6 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) | |||
| 1493 | } | 1493 | } |
| 1494 | 1494 | ||
| 1495 | adev->powerplay.pp_feature = amdgpu_pp_feature_mask; | 1495 | adev->powerplay.pp_feature = amdgpu_pp_feature_mask; |
| 1496 | if (amdgpu_sriov_vf(adev)) | ||
| 1497 | adev->powerplay.pp_feature &= ~PP_GFXOFF_MASK; | ||
| 1498 | 1496 | ||
| 1499 | for (i = 0; i < adev->num_ip_blocks; i++) { | 1497 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1500 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { | 1498 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { |
| @@ -1600,7 +1598,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) | |||
| 1600 | } | 1598 | } |
| 1601 | } | 1599 | } |
| 1602 | 1600 | ||
| 1603 | if (adev->powerplay.pp_funcs->load_firmware) { | 1601 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { |
| 1604 | r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); | 1602 | r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); |
| 1605 | if (r) { | 1603 | if (r) { |
| 1606 | pr_err("firmware loading failed\n"); | 1604 | pr_err("firmware loading failed\n"); |
| @@ -3341,7 +3339,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, | |||
| 3341 | 3339 | ||
| 3342 | kthread_park(ring->sched.thread); | 3340 | kthread_park(ring->sched.thread); |
| 3343 | 3341 | ||
| 3344 | if (job && job->base.sched == &ring->sched) | 3342 | if (job && job->base.sched != &ring->sched) |
| 3345 | continue; | 3343 | continue; |
| 3346 | 3344 | ||
| 3347 | drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL); | 3345 | drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 28781414d71c..943dbf3c5da1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | |||
| @@ -114,8 +114,8 @@ uint amdgpu_pg_mask = 0xffffffff; | |||
| 114 | uint amdgpu_sdma_phase_quantum = 32; | 114 | uint amdgpu_sdma_phase_quantum = 32; |
| 115 | char *amdgpu_disable_cu = NULL; | 115 | char *amdgpu_disable_cu = NULL; |
| 116 | char *amdgpu_virtual_display = NULL; | 116 | char *amdgpu_virtual_display = NULL; |
| 117 | /* OverDrive(bit 14) disabled by default*/ | 117 | /* OverDrive(bit 14),gfxoff(bit 15),stutter mode(bit 17) disabled by default*/ |
| 118 | uint amdgpu_pp_feature_mask = 0xffffbfff; | 118 | uint amdgpu_pp_feature_mask = 0xfffd3fff; |
| 119 | int amdgpu_ngg = 0; | 119 | int amdgpu_ngg = 0; |
| 120 | int amdgpu_prim_buf_per_se = 0; | 120 | int amdgpu_prim_buf_per_se = 0; |
| 121 | int amdgpu_pos_buf_per_se = 0; | 121 | int amdgpu_pos_buf_per_se = 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 790fd5408ddf..1a656b8657f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | |||
| @@ -392,7 +392,7 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable) | |||
| 392 | if (!(adev->powerplay.pp_feature & PP_GFXOFF_MASK)) | 392 | if (!(adev->powerplay.pp_feature & PP_GFXOFF_MASK)) |
| 393 | return; | 393 | return; |
| 394 | 394 | ||
| 395 | if (!adev->powerplay.pp_funcs->set_powergating_by_smu) | 395 | if (!adev->powerplay.pp_funcs || !adev->powerplay.pp_funcs->set_powergating_by_smu) |
| 396 | return; | 396 | return; |
| 397 | 397 | ||
| 398 | 398 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 94055a485e01..59cc678de8c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
| @@ -704,7 +704,10 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, | |||
| 704 | return ret; | 704 | return ret; |
| 705 | 705 | ||
| 706 | if (adev->powerplay.pp_funcs->force_clock_level) | 706 | if (adev->powerplay.pp_funcs->force_clock_level) |
| 707 | amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); | 707 | ret = amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); |
| 708 | |||
| 709 | if (ret) | ||
| 710 | return -EINVAL; | ||
| 708 | 711 | ||
| 709 | return count; | 712 | return count; |
| 710 | } | 713 | } |
| @@ -737,7 +740,10 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, | |||
| 737 | return ret; | 740 | return ret; |
| 738 | 741 | ||
| 739 | if (adev->powerplay.pp_funcs->force_clock_level) | 742 | if (adev->powerplay.pp_funcs->force_clock_level) |
| 740 | amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); | 743 | ret = amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); |
| 744 | |||
| 745 | if (ret) | ||
| 746 | return -EINVAL; | ||
| 741 | 747 | ||
| 742 | return count; | 748 | return count; |
| 743 | } | 749 | } |
| @@ -770,7 +776,10 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, | |||
| 770 | return ret; | 776 | return ret; |
| 771 | 777 | ||
| 772 | if (adev->powerplay.pp_funcs->force_clock_level) | 778 | if (adev->powerplay.pp_funcs->force_clock_level) |
| 773 | amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); | 779 | ret = amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); |
| 780 | |||
| 781 | if (ret) | ||
| 782 | return -EINVAL; | ||
| 774 | 783 | ||
| 775 | return count; | 784 | return count; |
| 776 | } | 785 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6904d794d60a..352b30409060 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
| @@ -542,7 +542,8 @@ static void amdgpu_vm_pt_next_leaf(struct amdgpu_device *adev, | |||
| 542 | struct amdgpu_vm_pt_cursor *cursor) | 542 | struct amdgpu_vm_pt_cursor *cursor) |
| 543 | { | 543 | { |
| 544 | amdgpu_vm_pt_next(adev, cursor); | 544 | amdgpu_vm_pt_next(adev, cursor); |
| 545 | while (amdgpu_vm_pt_descendant(adev, cursor)); | 545 | if (cursor->pfn != ~0ll) |
| 546 | while (amdgpu_vm_pt_descendant(adev, cursor)); | ||
| 546 | } | 547 | } |
| 547 | 548 | ||
| 548 | /** | 549 | /** |
| @@ -3234,8 +3235,10 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
| 3234 | } | 3235 | } |
| 3235 | rbtree_postorder_for_each_entry_safe(mapping, tmp, | 3236 | rbtree_postorder_for_each_entry_safe(mapping, tmp, |
| 3236 | &vm->va.rb_root, rb) { | 3237 | &vm->va.rb_root, rb) { |
| 3238 | /* Don't remove the mapping here, we don't want to trigger a | ||
| 3239 | * rebalance and the tree is about to be destroyed anyway. | ||
| 3240 | */ | ||
| 3237 | list_del(&mapping->list); | 3241 | list_del(&mapping->list); |
| 3238 | amdgpu_vm_it_remove(mapping, &vm->va); | ||
| 3239 | kfree(mapping); | 3242 | kfree(mapping); |
| 3240 | } | 3243 | } |
| 3241 | list_for_each_entry_safe(mapping, tmp, &vm->freed, list) { | 3244 | list_for_each_entry_safe(mapping, tmp, &vm->freed, list) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 3d0f277a6523..617b0c8908a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | |||
| @@ -4815,8 +4815,10 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev) | |||
| 4815 | if (r) | 4815 | if (r) |
| 4816 | goto done; | 4816 | goto done; |
| 4817 | 4817 | ||
| 4818 | /* Test KCQs */ | 4818 | /* Test KCQs - reversing the order of rings seems to fix ring test failure |
| 4819 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { | 4819 | * after GPU reset |
| 4820 | */ | ||
| 4821 | for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) { | ||
| 4820 | ring = &adev->gfx.compute_ring[i]; | 4822 | ring = &adev->gfx.compute_ring[i]; |
| 4821 | ring->ready = true; | 4823 | ring->ready = true; |
| 4822 | r = amdgpu_ring_test_ring(ring); | 4824 | r = amdgpu_ring_test_ring(ring); |
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 14649f8475f3..fd23ba1226a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | |||
| @@ -280,7 +280,7 @@ void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, | |||
| 280 | return; | 280 | return; |
| 281 | 281 | ||
| 282 | if (enable && adev->pg_flags & AMD_PG_SUPPORT_MMHUB) { | 282 | if (enable && adev->pg_flags & AMD_PG_SUPPORT_MMHUB) { |
| 283 | if (adev->powerplay.pp_funcs->set_powergating_by_smu) | 283 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_powergating_by_smu) |
| 284 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); | 284 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); |
| 285 | 285 | ||
| 286 | } | 286 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 04fa3d972636..7a8c9172d30a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | |||
| @@ -1366,7 +1366,8 @@ static int sdma_v4_0_hw_init(void *handle) | |||
| 1366 | int r; | 1366 | int r; |
| 1367 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1367 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1368 | 1368 | ||
| 1369 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs->set_powergating_by_smu) | 1369 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs && |
| 1370 | adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 1370 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false); | 1371 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false); |
| 1371 | 1372 | ||
| 1372 | sdma_v4_0_init_golden_registers(adev); | 1373 | sdma_v4_0_init_golden_registers(adev); |
| @@ -1386,7 +1387,8 @@ static int sdma_v4_0_hw_fini(void *handle) | |||
| 1386 | sdma_v4_0_ctx_switch_enable(adev, false); | 1387 | sdma_v4_0_ctx_switch_enable(adev, false); |
| 1387 | sdma_v4_0_enable(adev, false); | 1388 | sdma_v4_0_enable(adev, false); |
| 1388 | 1389 | ||
| 1389 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs->set_powergating_by_smu) | 1390 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs |
| 1391 | && adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 1390 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true); | 1392 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true); |
| 1391 | 1393 | ||
| 1392 | return 0; | 1394 | return 0; |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index e224f23e2215..b0df6dc9a775 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
| @@ -1524,6 +1524,13 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) | |||
| 1524 | { | 1524 | { |
| 1525 | struct amdgpu_display_manager *dm = bl_get_data(bd); | 1525 | struct amdgpu_display_manager *dm = bl_get_data(bd); |
| 1526 | 1526 | ||
| 1527 | /* | ||
| 1528 | * PWM interperts 0 as 100% rather than 0% because of HW | ||
| 1529 | * limitation for level 0.So limiting minimum brightness level | ||
| 1530 | * to 1. | ||
| 1531 | */ | ||
| 1532 | if (bd->props.brightness < 1) | ||
| 1533 | return 1; | ||
| 1527 | if (dc_link_set_backlight_level(dm->backlight_link, | 1534 | if (dc_link_set_backlight_level(dm->backlight_link, |
| 1528 | bd->props.brightness, 0, 0)) | 1535 | bd->props.brightness, 0, 0)) |
| 1529 | return 0; | 1536 | return 0; |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 0fab64a2a915..12001a006b2d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | |||
| @@ -101,7 +101,7 @@ bool dm_pp_apply_display_requirements( | |||
| 101 | adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1; | 101 | adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | if (adev->powerplay.pp_funcs->display_configuration_change) | 104 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_configuration_change) |
| 105 | adev->powerplay.pp_funcs->display_configuration_change( | 105 | adev->powerplay.pp_funcs->display_configuration_change( |
| 106 | adev->powerplay.pp_handle, | 106 | adev->powerplay.pp_handle, |
| 107 | &adev->pm.pm_display_cfg); | 107 | &adev->pm.pm_display_cfg); |
| @@ -304,7 +304,7 @@ bool dm_pp_get_clock_levels_by_type( | |||
| 304 | struct amd_pp_simple_clock_info validation_clks = { 0 }; | 304 | struct amd_pp_simple_clock_info validation_clks = { 0 }; |
| 305 | uint32_t i; | 305 | uint32_t i; |
| 306 | 306 | ||
| 307 | if (adev->powerplay.pp_funcs->get_clock_by_type) { | 307 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) { |
| 308 | if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, | 308 | if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, |
| 309 | dc_to_pp_clock_type(clk_type), &pp_clks)) { | 309 | dc_to_pp_clock_type(clk_type), &pp_clks)) { |
| 310 | /* Error in pplib. Provide default values. */ | 310 | /* Error in pplib. Provide default values. */ |
| @@ -315,7 +315,7 @@ bool dm_pp_get_clock_levels_by_type( | |||
| 315 | 315 | ||
| 316 | pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); | 316 | pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); |
| 317 | 317 | ||
| 318 | if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks) { | 318 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_display_mode_validation_clocks) { |
| 319 | if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks( | 319 | if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks( |
| 320 | pp_handle, &validation_clks)) { | 320 | pp_handle, &validation_clks)) { |
| 321 | /* Error in pplib. Provide default values. */ | 321 | /* Error in pplib. Provide default values. */ |
| @@ -398,6 +398,9 @@ bool dm_pp_get_clock_levels_by_type_with_voltage( | |||
| 398 | struct pp_clock_levels_with_voltage pp_clk_info = {0}; | 398 | struct pp_clock_levels_with_voltage pp_clk_info = {0}; |
| 399 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; | 399 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; |
| 400 | 400 | ||
| 401 | if (!pp_funcs || !pp_funcs->get_clock_by_type_with_voltage) | ||
| 402 | return false; | ||
| 403 | |||
| 401 | if (pp_funcs->get_clock_by_type_with_voltage(pp_handle, | 404 | if (pp_funcs->get_clock_by_type_with_voltage(pp_handle, |
| 402 | dc_to_pp_clock_type(clk_type), | 405 | dc_to_pp_clock_type(clk_type), |
| 403 | &pp_clk_info)) | 406 | &pp_clk_info)) |
| @@ -438,7 +441,7 @@ bool dm_pp_apply_clock_for_voltage_request( | |||
| 438 | if (!pp_clock_request.clock_type) | 441 | if (!pp_clock_request.clock_type) |
| 439 | return false; | 442 | return false; |
| 440 | 443 | ||
| 441 | if (adev->powerplay.pp_funcs->display_clock_voltage_request) | 444 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_clock_voltage_request) |
| 442 | ret = adev->powerplay.pp_funcs->display_clock_voltage_request( | 445 | ret = adev->powerplay.pp_funcs->display_clock_voltage_request( |
| 443 | adev->powerplay.pp_handle, | 446 | adev->powerplay.pp_handle, |
| 444 | &pp_clock_request); | 447 | &pp_clock_request); |
| @@ -455,7 +458,7 @@ bool dm_pp_get_static_clocks( | |||
| 455 | struct amd_pp_clock_info pp_clk_info = {0}; | 458 | struct amd_pp_clock_info pp_clk_info = {0}; |
| 456 | int ret = 0; | 459 | int ret = 0; |
| 457 | 460 | ||
| 458 | if (adev->powerplay.pp_funcs->get_current_clocks) | 461 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_current_clocks) |
| 459 | ret = adev->powerplay.pp_funcs->get_current_clocks( | 462 | ret = adev->powerplay.pp_funcs->get_current_clocks( |
| 460 | adev->powerplay.pp_handle, | 463 | adev->powerplay.pp_handle, |
| 461 | &pp_clk_info); | 464 | &pp_clk_info); |
| @@ -505,6 +508,9 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp, | |||
| 505 | wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets; | 508 | wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets; |
| 506 | wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets; | 509 | wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets; |
| 507 | 510 | ||
| 511 | if (!pp_funcs || !pp_funcs->set_watermarks_for_clocks_ranges) | ||
| 512 | return; | ||
| 513 | |||
| 508 | for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) { | 514 | for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) { |
| 509 | if (ranges->reader_wm_sets[i].wm_inst > 3) | 515 | if (ranges->reader_wm_sets[i].wm_inst > 3) |
| 510 | wm_dce_clocks[i].wm_set_id = WM_SET_A; | 516 | wm_dce_clocks[i].wm_set_id = WM_SET_A; |
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index de190935f0a4..e3624ca24574 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | |||
| @@ -568,7 +568,7 @@ static struct input_pixel_processor *dce110_ipp_create( | |||
| 568 | 568 | ||
| 569 | static const struct encoder_feature_support link_enc_feature = { | 569 | static const struct encoder_feature_support link_enc_feature = { |
| 570 | .max_hdmi_deep_color = COLOR_DEPTH_121212, | 570 | .max_hdmi_deep_color = COLOR_DEPTH_121212, |
| 571 | .max_hdmi_pixel_clock = 594000, | 571 | .max_hdmi_pixel_clock = 300000, |
| 572 | .flags.bits.IS_HBR2_CAPABLE = true, | 572 | .flags.bits.IS_HBR2_CAPABLE = true, |
| 573 | .flags.bits.IS_TPS3_CAPABLE = true | 573 | .flags.bits.IS_TPS3_CAPABLE = true |
| 574 | }; | 574 | }; |
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index e8964cae6b93..d6aa1d414320 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
| @@ -723,11 +723,14 @@ static int pp_dpm_force_clock_level(void *handle, | |||
| 723 | pr_info("%s was not implemented.\n", __func__); | 723 | pr_info("%s was not implemented.\n", __func__); |
| 724 | return 0; | 724 | return 0; |
| 725 | } | 725 | } |
| 726 | |||
| 727 | if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { | ||
| 728 | pr_info("force clock level is for dpm manual mode only.\n"); | ||
| 729 | return -EINVAL; | ||
| 730 | } | ||
| 731 | |||
| 726 | mutex_lock(&hwmgr->smu_lock); | 732 | mutex_lock(&hwmgr->smu_lock); |
| 727 | if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) | 733 | ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); |
| 728 | ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); | ||
| 729 | else | ||
| 730 | ret = -EINVAL; | ||
| 731 | mutex_unlock(&hwmgr->smu_lock); | 734 | mutex_unlock(&hwmgr->smu_lock); |
| 732 | return ret; | 735 | return ret; |
| 733 | } | 736 | } |
| @@ -963,6 +966,7 @@ static int pp_dpm_switch_power_profile(void *handle, | |||
| 963 | static int pp_set_power_limit(void *handle, uint32_t limit) | 966 | static int pp_set_power_limit(void *handle, uint32_t limit) |
| 964 | { | 967 | { |
| 965 | struct pp_hwmgr *hwmgr = handle; | 968 | struct pp_hwmgr *hwmgr = handle; |
| 969 | uint32_t max_power_limit; | ||
| 966 | 970 | ||
| 967 | if (!hwmgr || !hwmgr->pm_en) | 971 | if (!hwmgr || !hwmgr->pm_en) |
| 968 | return -EINVAL; | 972 | return -EINVAL; |
| @@ -975,7 +979,13 @@ static int pp_set_power_limit(void *handle, uint32_t limit) | |||
| 975 | if (limit == 0) | 979 | if (limit == 0) |
| 976 | limit = hwmgr->default_power_limit; | 980 | limit = hwmgr->default_power_limit; |
| 977 | 981 | ||
| 978 | if (limit > hwmgr->default_power_limit) | 982 | max_power_limit = hwmgr->default_power_limit; |
| 983 | if (hwmgr->od_enabled) { | ||
| 984 | max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); | ||
| 985 | max_power_limit /= 100; | ||
| 986 | } | ||
| 987 | |||
| 988 | if (limit > max_power_limit) | ||
| 979 | return -EINVAL; | 989 | return -EINVAL; |
| 980 | 990 | ||
| 981 | mutex_lock(&hwmgr->smu_lock); | 991 | mutex_lock(&hwmgr->smu_lock); |
| @@ -994,8 +1004,13 @@ static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) | |||
| 994 | 1004 | ||
| 995 | mutex_lock(&hwmgr->smu_lock); | 1005 | mutex_lock(&hwmgr->smu_lock); |
| 996 | 1006 | ||
| 997 | if (default_limit) | 1007 | if (default_limit) { |
| 998 | *limit = hwmgr->default_power_limit; | 1008 | *limit = hwmgr->default_power_limit; |
| 1009 | if (hwmgr->od_enabled) { | ||
| 1010 | *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); | ||
| 1011 | *limit /= 100; | ||
| 1012 | } | ||
| 1013 | } | ||
| 999 | else | 1014 | else |
| 1000 | *limit = hwmgr->power_limit; | 1015 | *limit = hwmgr->power_limit; |
| 1001 | 1016 | ||
| @@ -1303,12 +1318,12 @@ static int pp_enable_mgpu_fan_boost(void *handle) | |||
| 1303 | { | 1318 | { |
| 1304 | struct pp_hwmgr *hwmgr = handle; | 1319 | struct pp_hwmgr *hwmgr = handle; |
| 1305 | 1320 | ||
| 1306 | if (!hwmgr || !hwmgr->pm_en) | 1321 | if (!hwmgr) |
| 1307 | return -EINVAL; | 1322 | return -EINVAL; |
| 1308 | 1323 | ||
| 1309 | if (hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) { | 1324 | if (!hwmgr->pm_en || |
| 1325 | hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) | ||
| 1310 | return 0; | 1326 | return 0; |
| 1311 | } | ||
| 1312 | 1327 | ||
| 1313 | mutex_lock(&hwmgr->smu_lock); | 1328 | mutex_lock(&hwmgr->smu_lock); |
| 1314 | hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); | 1329 | hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 6c99cbf51c08..ed35ec0341e6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | |||
| @@ -3588,9 +3588,10 @@ static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, cons | |||
| 3588 | break; | 3588 | break; |
| 3589 | } | 3589 | } |
| 3590 | 3590 | ||
| 3591 | if (i >= sclk_table->count) | 3591 | if (i >= sclk_table->count) { |
| 3592 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; | 3592 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; |
| 3593 | else { | 3593 | sclk_table->dpm_levels[i-1].value = sclk; |
| 3594 | } else { | ||
| 3594 | /* TODO: Check SCLK in DAL's minimum clocks | 3595 | /* TODO: Check SCLK in DAL's minimum clocks |
| 3595 | * in case DeepSleep divider update is required. | 3596 | * in case DeepSleep divider update is required. |
| 3596 | */ | 3597 | */ |
| @@ -3605,9 +3606,10 @@ static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, cons | |||
| 3605 | break; | 3606 | break; |
| 3606 | } | 3607 | } |
| 3607 | 3608 | ||
| 3608 | if (i >= mclk_table->count) | 3609 | if (i >= mclk_table->count) { |
| 3609 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; | 3610 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; |
| 3610 | 3611 | mclk_table->dpm_levels[i-1].value = mclk; | |
| 3612 | } | ||
| 3611 | 3613 | ||
| 3612 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) | 3614 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) |
| 3613 | data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; | 3615 | data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c index 4714b5b59825..99a33c33a32c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c | |||
| @@ -718,7 +718,7 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table, | |||
| 718 | table->WatermarkRow[1][i].MaxClock = | 718 | table->WatermarkRow[1][i].MaxClock = |
| 719 | cpu_to_le16((uint16_t) | 719 | cpu_to_le16((uint16_t) |
| 720 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz) / | 720 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz) / |
| 721 | 100); | 721 | 1000); |
| 722 | table->WatermarkRow[1][i].MinUclk = | 722 | table->WatermarkRow[1][i].MinUclk = |
| 723 | cpu_to_le16((uint16_t) | 723 | cpu_to_le16((uint16_t) |
| 724 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz) / | 724 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz) / |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 419a1d77d661..8c4db86bb4b7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | |||
| @@ -1333,7 +1333,6 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) | |||
| 1333 | if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) | 1333 | if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) |
| 1334 | hwmgr->platform_descriptor.overdriveLimit.memoryClock = | 1334 | hwmgr->platform_descriptor.overdriveLimit.memoryClock = |
| 1335 | dpm_table->dpm_levels[dpm_table->count-1].value; | 1335 | dpm_table->dpm_levels[dpm_table->count-1].value; |
| 1336 | |||
| 1337 | vega10_init_dpm_state(&(dpm_table->dpm_state)); | 1336 | vega10_init_dpm_state(&(dpm_table->dpm_state)); |
| 1338 | 1337 | ||
| 1339 | data->dpm_table.eclk_table.count = 0; | 1338 | data->dpm_table.eclk_table.count = 0; |
| @@ -3249,6 +3248,37 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, | |||
| 3249 | static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) | 3248 | static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) |
| 3250 | { | 3249 | { |
| 3251 | struct vega10_hwmgr *data = hwmgr->backend; | 3250 | struct vega10_hwmgr *data = hwmgr->backend; |
| 3251 | const struct phm_set_power_state_input *states = | ||
| 3252 | (const struct phm_set_power_state_input *)input; | ||
| 3253 | const struct vega10_power_state *vega10_ps = | ||
| 3254 | cast_const_phw_vega10_power_state(states->pnew_state); | ||
| 3255 | struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); | ||
| 3256 | uint32_t sclk = vega10_ps->performance_levels | ||
| 3257 | [vega10_ps->performance_level_count - 1].gfx_clock; | ||
| 3258 | struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); | ||
| 3259 | uint32_t mclk = vega10_ps->performance_levels | ||
| 3260 | [vega10_ps->performance_level_count - 1].mem_clock; | ||
| 3261 | uint32_t i; | ||
| 3262 | |||
| 3263 | for (i = 0; i < sclk_table->count; i++) { | ||
| 3264 | if (sclk == sclk_table->dpm_levels[i].value) | ||
| 3265 | break; | ||
| 3266 | } | ||
| 3267 | |||
| 3268 | if (i >= sclk_table->count) { | ||
| 3269 | data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; | ||
| 3270 | sclk_table->dpm_levels[i-1].value = sclk; | ||
| 3271 | } | ||
| 3272 | |||
| 3273 | for (i = 0; i < mclk_table->count; i++) { | ||
| 3274 | if (mclk == mclk_table->dpm_levels[i].value) | ||
| 3275 | break; | ||
| 3276 | } | ||
| 3277 | |||
| 3278 | if (i >= mclk_table->count) { | ||
| 3279 | data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; | ||
| 3280 | mclk_table->dpm_levels[i-1].value = mclk; | ||
| 3281 | } | ||
| 3252 | 3282 | ||
| 3253 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) | 3283 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) |
| 3254 | data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; | 3284 | data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; |
| @@ -4529,11 +4559,13 @@ static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) | |||
| 4529 | 4559 | ||
| 4530 | if (vega10_ps->performance_levels | 4560 | if (vega10_ps->performance_levels |
| 4531 | [vega10_ps->performance_level_count - 1].gfx_clock > | 4561 | [vega10_ps->performance_level_count - 1].gfx_clock > |
| 4532 | hwmgr->platform_descriptor.overdriveLimit.engineClock) | 4562 | hwmgr->platform_descriptor.overdriveLimit.engineClock) { |
| 4533 | vega10_ps->performance_levels | 4563 | vega10_ps->performance_levels |
| 4534 | [vega10_ps->performance_level_count - 1].gfx_clock = | 4564 | [vega10_ps->performance_level_count - 1].gfx_clock = |
| 4535 | hwmgr->platform_descriptor.overdriveLimit.engineClock; | 4565 | hwmgr->platform_descriptor.overdriveLimit.engineClock; |
| 4536 | 4566 | pr_warn("max sclk supported by vbios is %d\n", | |
| 4567 | hwmgr->platform_descriptor.overdriveLimit.engineClock); | ||
| 4568 | } | ||
| 4537 | return 0; | 4569 | return 0; |
| 4538 | } | 4570 | } |
| 4539 | 4571 | ||
| @@ -4581,10 +4613,13 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) | |||
| 4581 | 4613 | ||
| 4582 | if (vega10_ps->performance_levels | 4614 | if (vega10_ps->performance_levels |
| 4583 | [vega10_ps->performance_level_count - 1].mem_clock > | 4615 | [vega10_ps->performance_level_count - 1].mem_clock > |
| 4584 | hwmgr->platform_descriptor.overdriveLimit.memoryClock) | 4616 | hwmgr->platform_descriptor.overdriveLimit.memoryClock) { |
| 4585 | vega10_ps->performance_levels | 4617 | vega10_ps->performance_levels |
| 4586 | [vega10_ps->performance_level_count - 1].mem_clock = | 4618 | [vega10_ps->performance_level_count - 1].mem_clock = |
| 4587 | hwmgr->platform_descriptor.overdriveLimit.memoryClock; | 4619 | hwmgr->platform_descriptor.overdriveLimit.memoryClock; |
| 4620 | pr_warn("max mclk supported by vbios is %d\n", | ||
| 4621 | hwmgr->platform_descriptor.overdriveLimit.memoryClock); | ||
| 4622 | } | ||
| 4588 | 4623 | ||
| 4589 | return 0; | 4624 | return 0; |
| 4590 | } | 4625 | } |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 9600e2f226e9..74bc37308dc0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | |||
| @@ -2356,6 +2356,13 @@ static int vega12_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) | |||
| 2356 | return vega12_disable_gfx_off(hwmgr); | 2356 | return vega12_disable_gfx_off(hwmgr); |
| 2357 | } | 2357 | } |
| 2358 | 2358 | ||
| 2359 | static int vega12_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, | ||
| 2360 | PHM_PerformanceLevelDesignation designation, uint32_t index, | ||
| 2361 | PHM_PerformanceLevel *level) | ||
| 2362 | { | ||
| 2363 | return 0; | ||
| 2364 | } | ||
| 2365 | |||
| 2359 | static const struct pp_hwmgr_func vega12_hwmgr_funcs = { | 2366 | static const struct pp_hwmgr_func vega12_hwmgr_funcs = { |
| 2360 | .backend_init = vega12_hwmgr_backend_init, | 2367 | .backend_init = vega12_hwmgr_backend_init, |
| 2361 | .backend_fini = vega12_hwmgr_backend_fini, | 2368 | .backend_fini = vega12_hwmgr_backend_fini, |
| @@ -2406,6 +2413,7 @@ static const struct pp_hwmgr_func vega12_hwmgr_funcs = { | |||
| 2406 | .register_irq_handlers = smu9_register_irq_handlers, | 2413 | .register_irq_handlers = smu9_register_irq_handlers, |
| 2407 | .start_thermal_controller = vega12_start_thermal_controller, | 2414 | .start_thermal_controller = vega12_start_thermal_controller, |
| 2408 | .powergate_gfx = vega12_gfx_off_control, | 2415 | .powergate_gfx = vega12_gfx_off_control, |
| 2416 | .get_performance_level = vega12_get_performance_level, | ||
| 2409 | }; | 2417 | }; |
| 2410 | 2418 | ||
| 2411 | int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) | 2419 | int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index b4dbbb7c334c..57143d51e3ee 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | |||
| @@ -1875,38 +1875,20 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, | |||
| 1875 | return ret; | 1875 | return ret; |
| 1876 | } | 1876 | } |
| 1877 | 1877 | ||
| 1878 | static int vega20_get_current_gfx_clk_freq(struct pp_hwmgr *hwmgr, uint32_t *gfx_freq) | 1878 | static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr, |
| 1879 | PPCLK_e clk_id, uint32_t *clk_freq) | ||
| 1879 | { | 1880 | { |
| 1880 | uint32_t gfx_clk = 0; | ||
| 1881 | int ret = 0; | 1881 | int ret = 0; |
| 1882 | 1882 | ||
| 1883 | *gfx_freq = 0; | 1883 | *clk_freq = 0; |
| 1884 | 1884 | ||
| 1885 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, | 1885 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, |
| 1886 | PPSMC_MSG_GetDpmClockFreq, (PPCLK_GFXCLK << 16))) == 0, | 1886 | PPSMC_MSG_GetDpmClockFreq, (clk_id << 16))) == 0, |
| 1887 | "[GetCurrentGfxClkFreq] Attempt to get Current GFXCLK Frequency Failed!", | 1887 | "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!", |
| 1888 | return ret); | 1888 | return ret); |
| 1889 | gfx_clk = smum_get_argument(hwmgr); | 1889 | *clk_freq = smum_get_argument(hwmgr); |
| 1890 | 1890 | ||
| 1891 | *gfx_freq = gfx_clk * 100; | 1891 | *clk_freq = *clk_freq * 100; |
| 1892 | |||
| 1893 | return 0; | ||
| 1894 | } | ||
| 1895 | |||
| 1896 | static int vega20_get_current_mclk_freq(struct pp_hwmgr *hwmgr, uint32_t *mclk_freq) | ||
| 1897 | { | ||
| 1898 | uint32_t mem_clk = 0; | ||
| 1899 | int ret = 0; | ||
| 1900 | |||
| 1901 | *mclk_freq = 0; | ||
| 1902 | |||
| 1903 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, | ||
| 1904 | PPSMC_MSG_GetDpmClockFreq, (PPCLK_UCLK << 16))) == 0, | ||
| 1905 | "[GetCurrentMClkFreq] Attempt to get Current MCLK Frequency Failed!", | ||
| 1906 | return ret); | ||
| 1907 | mem_clk = smum_get_argument(hwmgr); | ||
| 1908 | |||
| 1909 | *mclk_freq = mem_clk * 100; | ||
| 1910 | 1892 | ||
| 1911 | return 0; | 1893 | return 0; |
| 1912 | } | 1894 | } |
| @@ -1937,12 +1919,16 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, | |||
| 1937 | 1919 | ||
| 1938 | switch (idx) { | 1920 | switch (idx) { |
| 1939 | case AMDGPU_PP_SENSOR_GFX_SCLK: | 1921 | case AMDGPU_PP_SENSOR_GFX_SCLK: |
| 1940 | ret = vega20_get_current_gfx_clk_freq(hwmgr, (uint32_t *)value); | 1922 | ret = vega20_get_current_clk_freq(hwmgr, |
| 1923 | PPCLK_GFXCLK, | ||
| 1924 | (uint32_t *)value); | ||
| 1941 | if (!ret) | 1925 | if (!ret) |
| 1942 | *size = 4; | 1926 | *size = 4; |
| 1943 | break; | 1927 | break; |
| 1944 | case AMDGPU_PP_SENSOR_GFX_MCLK: | 1928 | case AMDGPU_PP_SENSOR_GFX_MCLK: |
| 1945 | ret = vega20_get_current_mclk_freq(hwmgr, (uint32_t *)value); | 1929 | ret = vega20_get_current_clk_freq(hwmgr, |
| 1930 | PPCLK_UCLK, | ||
| 1931 | (uint32_t *)value); | ||
| 1946 | if (!ret) | 1932 | if (!ret) |
| 1947 | *size = 4; | 1933 | *size = 4; |
| 1948 | break; | 1934 | break; |
| @@ -2012,7 +1998,6 @@ int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, | |||
| 2012 | if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { | 1998 | if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { |
| 2013 | switch (clk_type) { | 1999 | switch (clk_type) { |
| 2014 | case amd_pp_dcef_clock: | 2000 | case amd_pp_dcef_clock: |
| 2015 | clk_freq = clock_req->clock_freq_in_khz / 100; | ||
| 2016 | clk_select = PPCLK_DCEFCLK; | 2001 | clk_select = PPCLK_DCEFCLK; |
| 2017 | break; | 2002 | break; |
| 2018 | case amd_pp_disp_clock: | 2003 | case amd_pp_disp_clock: |
| @@ -2041,11 +2026,20 @@ int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, | |||
| 2041 | return result; | 2026 | return result; |
| 2042 | } | 2027 | } |
| 2043 | 2028 | ||
| 2029 | static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, | ||
| 2030 | PHM_PerformanceLevelDesignation designation, uint32_t index, | ||
| 2031 | PHM_PerformanceLevel *level) | ||
| 2032 | { | ||
| 2033 | return 0; | ||
| 2034 | } | ||
| 2035 | |||
| 2044 | static int vega20_notify_smc_display_config_after_ps_adjustment( | 2036 | static int vega20_notify_smc_display_config_after_ps_adjustment( |
| 2045 | struct pp_hwmgr *hwmgr) | 2037 | struct pp_hwmgr *hwmgr) |
| 2046 | { | 2038 | { |
| 2047 | struct vega20_hwmgr *data = | 2039 | struct vega20_hwmgr *data = |
| 2048 | (struct vega20_hwmgr *)(hwmgr->backend); | 2040 | (struct vega20_hwmgr *)(hwmgr->backend); |
| 2041 | struct vega20_single_dpm_table *dpm_table = | ||
| 2042 | &data->dpm_table.mem_table; | ||
| 2049 | struct PP_Clocks min_clocks = {0}; | 2043 | struct PP_Clocks min_clocks = {0}; |
| 2050 | struct pp_display_clock_request clock_req; | 2044 | struct pp_display_clock_request clock_req; |
| 2051 | int ret = 0; | 2045 | int ret = 0; |
| @@ -2063,7 +2057,7 @@ static int vega20_notify_smc_display_config_after_ps_adjustment( | |||
| 2063 | 2057 | ||
| 2064 | if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { | 2058 | if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { |
| 2065 | clock_req.clock_type = amd_pp_dcef_clock; | 2059 | clock_req.clock_type = amd_pp_dcef_clock; |
| 2066 | clock_req.clock_freq_in_khz = min_clocks.dcefClock; | 2060 | clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10; |
| 2067 | if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { | 2061 | if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { |
| 2068 | if (data->smu_features[GNLD_DS_DCEFCLK].supported) | 2062 | if (data->smu_features[GNLD_DS_DCEFCLK].supported) |
| 2069 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( | 2063 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( |
| @@ -2076,6 +2070,15 @@ static int vega20_notify_smc_display_config_after_ps_adjustment( | |||
| 2076 | } | 2070 | } |
| 2077 | } | 2071 | } |
| 2078 | 2072 | ||
| 2073 | if (data->smu_features[GNLD_DPM_UCLK].enabled) { | ||
| 2074 | dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100; | ||
| 2075 | PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, | ||
| 2076 | PPSMC_MSG_SetHardMinByFreq, | ||
| 2077 | (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)), | ||
| 2078 | "[SetHardMinFreq] Set hard min uclk failed!", | ||
| 2079 | return ret); | ||
| 2080 | } | ||
| 2081 | |||
| 2079 | return 0; | 2082 | return 0; |
| 2080 | } | 2083 | } |
| 2081 | 2084 | ||
| @@ -2353,7 +2356,7 @@ static int vega20_get_sclks(struct pp_hwmgr *hwmgr, | |||
| 2353 | 2356 | ||
| 2354 | for (i = 0; i < count; i++) { | 2357 | for (i = 0; i < count; i++) { |
| 2355 | clocks->data[i].clocks_in_khz = | 2358 | clocks->data[i].clocks_in_khz = |
| 2356 | dpm_table->dpm_levels[i].value * 100; | 2359 | dpm_table->dpm_levels[i].value * 1000; |
| 2357 | clocks->data[i].latency_in_us = 0; | 2360 | clocks->data[i].latency_in_us = 0; |
| 2358 | } | 2361 | } |
| 2359 | 2362 | ||
| @@ -2383,7 +2386,7 @@ static int vega20_get_memclocks(struct pp_hwmgr *hwmgr, | |||
| 2383 | for (i = 0; i < count; i++) { | 2386 | for (i = 0; i < count; i++) { |
| 2384 | clocks->data[i].clocks_in_khz = | 2387 | clocks->data[i].clocks_in_khz = |
| 2385 | data->mclk_latency_table.entries[i].frequency = | 2388 | data->mclk_latency_table.entries[i].frequency = |
| 2386 | dpm_table->dpm_levels[i].value * 100; | 2389 | dpm_table->dpm_levels[i].value * 1000; |
| 2387 | clocks->data[i].latency_in_us = | 2390 | clocks->data[i].latency_in_us = |
| 2388 | data->mclk_latency_table.entries[i].latency = | 2391 | data->mclk_latency_table.entries[i].latency = |
| 2389 | vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); | 2392 | vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); |
| @@ -2408,7 +2411,7 @@ static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr, | |||
| 2408 | 2411 | ||
| 2409 | for (i = 0; i < count; i++) { | 2412 | for (i = 0; i < count; i++) { |
| 2410 | clocks->data[i].clocks_in_khz = | 2413 | clocks->data[i].clocks_in_khz = |
| 2411 | dpm_table->dpm_levels[i].value * 100; | 2414 | dpm_table->dpm_levels[i].value * 1000; |
| 2412 | clocks->data[i].latency_in_us = 0; | 2415 | clocks->data[i].latency_in_us = 0; |
| 2413 | } | 2416 | } |
| 2414 | 2417 | ||
| @@ -2431,7 +2434,7 @@ static int vega20_get_socclocks(struct pp_hwmgr *hwmgr, | |||
| 2431 | 2434 | ||
| 2432 | for (i = 0; i < count; i++) { | 2435 | for (i = 0; i < count; i++) { |
| 2433 | clocks->data[i].clocks_in_khz = | 2436 | clocks->data[i].clocks_in_khz = |
| 2434 | dpm_table->dpm_levels[i].value * 100; | 2437 | dpm_table->dpm_levels[i].value * 1000; |
| 2435 | clocks->data[i].latency_in_us = 0; | 2438 | clocks->data[i].latency_in_us = 0; |
| 2436 | } | 2439 | } |
| 2437 | 2440 | ||
| @@ -2582,11 +2585,11 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, | |||
| 2582 | return -EINVAL; | 2585 | return -EINVAL; |
| 2583 | } | 2586 | } |
| 2584 | 2587 | ||
| 2585 | if (input_clk < clocks.data[0].clocks_in_khz / 100 || | 2588 | if (input_clk < clocks.data[0].clocks_in_khz / 1000 || |
| 2586 | input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { | 2589 | input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { |
| 2587 | pr_info("clock freq %d is not within allowed range [%d - %d]\n", | 2590 | pr_info("clock freq %d is not within allowed range [%d - %d]\n", |
| 2588 | input_clk, | 2591 | input_clk, |
| 2589 | clocks.data[0].clocks_in_khz / 100, | 2592 | clocks.data[0].clocks_in_khz / 1000, |
| 2590 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); | 2593 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); |
| 2591 | return -EINVAL; | 2594 | return -EINVAL; |
| 2592 | } | 2595 | } |
| @@ -2726,7 +2729,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2726 | 2729 | ||
| 2727 | switch (type) { | 2730 | switch (type) { |
| 2728 | case PP_SCLK: | 2731 | case PP_SCLK: |
| 2729 | ret = vega20_get_current_gfx_clk_freq(hwmgr, &now); | 2732 | ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now); |
| 2730 | PP_ASSERT_WITH_CODE(!ret, | 2733 | PP_ASSERT_WITH_CODE(!ret, |
| 2731 | "Attempt to get current gfx clk Failed!", | 2734 | "Attempt to get current gfx clk Failed!", |
| 2732 | return ret); | 2735 | return ret); |
| @@ -2738,12 +2741,12 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2738 | 2741 | ||
| 2739 | for (i = 0; i < clocks.num_levels; i++) | 2742 | for (i = 0; i < clocks.num_levels; i++) |
| 2740 | size += sprintf(buf + size, "%d: %uMhz %s\n", | 2743 | size += sprintf(buf + size, "%d: %uMhz %s\n", |
| 2741 | i, clocks.data[i].clocks_in_khz / 100, | 2744 | i, clocks.data[i].clocks_in_khz / 1000, |
| 2742 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); | 2745 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); |
| 2743 | break; | 2746 | break; |
| 2744 | 2747 | ||
| 2745 | case PP_MCLK: | 2748 | case PP_MCLK: |
| 2746 | ret = vega20_get_current_mclk_freq(hwmgr, &now); | 2749 | ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now); |
| 2747 | PP_ASSERT_WITH_CODE(!ret, | 2750 | PP_ASSERT_WITH_CODE(!ret, |
| 2748 | "Attempt to get current mclk freq Failed!", | 2751 | "Attempt to get current mclk freq Failed!", |
| 2749 | return ret); | 2752 | return ret); |
| @@ -2755,7 +2758,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2755 | 2758 | ||
| 2756 | for (i = 0; i < clocks.num_levels; i++) | 2759 | for (i = 0; i < clocks.num_levels; i++) |
| 2757 | size += sprintf(buf + size, "%d: %uMhz %s\n", | 2760 | size += sprintf(buf + size, "%d: %uMhz %s\n", |
| 2758 | i, clocks.data[i].clocks_in_khz / 100, | 2761 | i, clocks.data[i].clocks_in_khz / 1000, |
| 2759 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); | 2762 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); |
| 2760 | break; | 2763 | break; |
| 2761 | 2764 | ||
| @@ -2820,7 +2823,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2820 | return ret); | 2823 | return ret); |
| 2821 | 2824 | ||
| 2822 | size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", | 2825 | size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", |
| 2823 | clocks.data[0].clocks_in_khz / 100, | 2826 | clocks.data[0].clocks_in_khz / 1000, |
| 2824 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); | 2827 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); |
| 2825 | } | 2828 | } |
| 2826 | 2829 | ||
| @@ -3476,6 +3479,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = { | |||
| 3476 | vega20_set_watermarks_for_clocks_ranges, | 3479 | vega20_set_watermarks_for_clocks_ranges, |
| 3477 | .display_clock_voltage_request = | 3480 | .display_clock_voltage_request = |
| 3478 | vega20_display_clock_voltage_request, | 3481 | vega20_display_clock_voltage_request, |
| 3482 | .get_performance_level = | ||
| 3483 | vega20_get_performance_level, | ||
| 3479 | /* UMD pstate, profile related */ | 3484 | /* UMD pstate, profile related */ |
| 3480 | .force_dpm_level = | 3485 | .force_dpm_level = |
| 3481 | vega20_dpm_force_dpm_level, | 3486 | vega20_dpm_force_dpm_level, |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c index e5f7f8230065..97f8a1a970c3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c | |||
| @@ -642,8 +642,14 @@ static int check_powerplay_tables( | |||
| 642 | "Unsupported PPTable format!", return -1); | 642 | "Unsupported PPTable format!", return -1); |
| 643 | PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, | 643 | PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, |
| 644 | "Invalid PowerPlay Table!", return -1); | 644 | "Invalid PowerPlay Table!", return -1); |
| 645 | PP_ASSERT_WITH_CODE(powerplay_table->smcPPTable.Version == PPTABLE_V20_SMU_VERSION, | 645 | |
| 646 | "Unmatch PPTable version, vbios update may be needed!", return -1); | 646 | if (powerplay_table->smcPPTable.Version != PPTABLE_V20_SMU_VERSION) { |
| 647 | pr_info("Unmatch PPTable version: " | ||
| 648 | "pptable from VBIOS is V%d while driver supported is V%d!", | ||
| 649 | powerplay_table->smcPPTable.Version, | ||
| 650 | PPTABLE_V20_SMU_VERSION); | ||
| 651 | return -EINVAL; | ||
| 652 | } | ||
| 647 | 653 | ||
| 648 | //dump_pptable(&powerplay_table->smcPPTable); | 654 | //dump_pptable(&powerplay_table->smcPPTable); |
| 649 | 655 | ||
| @@ -716,10 +722,6 @@ static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable | |||
| 716 | "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", | 722 | "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", |
| 717 | return -1); | 723 | return -1); |
| 718 | 724 | ||
| 719 | memset(ppsmc_pptable->Padding32, | ||
| 720 | 0, | ||
| 721 | sizeof(struct atom_smc_dpm_info_v4_4) - | ||
| 722 | sizeof(struct atom_common_table_header)); | ||
| 723 | ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; | 725 | ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; |
| 724 | ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; | 726 | ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; |
| 725 | 727 | ||
| @@ -778,22 +780,19 @@ static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable | |||
| 778 | ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; | 780 | ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; |
| 779 | ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; | 781 | ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; |
| 780 | 782 | ||
| 781 | if ((smc_dpm_table->table_header.format_revision == 4) && | 783 | for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { |
| 782 | (smc_dpm_table->table_header.content_revision == 4)) { | 784 | ppsmc_pptable->I2cControllers[i].Enabled = |
| 783 | for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { | 785 | smc_dpm_table->i2ccontrollers[i].enabled; |
| 784 | ppsmc_pptable->I2cControllers[i].Enabled = | 786 | ppsmc_pptable->I2cControllers[i].SlaveAddress = |
| 785 | smc_dpm_table->i2ccontrollers[i].enabled; | 787 | smc_dpm_table->i2ccontrollers[i].slaveaddress; |
| 786 | ppsmc_pptable->I2cControllers[i].SlaveAddress = | 788 | ppsmc_pptable->I2cControllers[i].ControllerPort = |
| 787 | smc_dpm_table->i2ccontrollers[i].slaveaddress; | 789 | smc_dpm_table->i2ccontrollers[i].controllerport; |
| 788 | ppsmc_pptable->I2cControllers[i].ControllerPort = | 790 | ppsmc_pptable->I2cControllers[i].ThermalThrottler = |
| 789 | smc_dpm_table->i2ccontrollers[i].controllerport; | 791 | smc_dpm_table->i2ccontrollers[i].thermalthrottler; |
| 790 | ppsmc_pptable->I2cControllers[i].ThermalThrottler = | 792 | ppsmc_pptable->I2cControllers[i].I2cProtocol = |
| 791 | smc_dpm_table->i2ccontrollers[i].thermalthrottler; | 793 | smc_dpm_table->i2ccontrollers[i].i2cprotocol; |
| 792 | ppsmc_pptable->I2cControllers[i].I2cProtocol = | 794 | ppsmc_pptable->I2cControllers[i].I2cSpeed = |
| 793 | smc_dpm_table->i2ccontrollers[i].i2cprotocol; | 795 | smc_dpm_table->i2ccontrollers[i].i2cspeed; |
| 794 | ppsmc_pptable->I2cControllers[i].I2cSpeed = | ||
| 795 | smc_dpm_table->i2ccontrollers[i].i2cspeed; | ||
| 796 | } | ||
| 797 | } | 796 | } |
| 798 | 797 | ||
| 799 | return 0; | 798 | return 0; |
| @@ -882,15 +881,10 @@ static int init_powerplay_table_information( | |||
| 882 | if (pptable_information->smc_pptable == NULL) | 881 | if (pptable_information->smc_pptable == NULL) |
| 883 | return -ENOMEM; | 882 | return -ENOMEM; |
| 884 | 883 | ||
| 885 | if (powerplay_table->smcPPTable.Version <= 2) | 884 | memcpy(pptable_information->smc_pptable, |
| 886 | memcpy(pptable_information->smc_pptable, | 885 | &(powerplay_table->smcPPTable), |
| 887 | &(powerplay_table->smcPPTable), | 886 | sizeof(PPTable_t)); |
| 888 | sizeof(PPTable_t) - | 887 | |
| 889 | sizeof(I2cControllerConfig_t) * I2C_CONTROLLER_NAME_COUNT); | ||
| 890 | else | ||
| 891 | memcpy(pptable_information->smc_pptable, | ||
| 892 | &(powerplay_table->smcPPTable), | ||
| 893 | sizeof(PPTable_t)); | ||
| 894 | 888 | ||
| 895 | result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); | 889 | result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); |
| 896 | 890 | ||
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h index 2998a49960ed..63d5cf691549 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | // any structure is changed in this file | 29 | // any structure is changed in this file |
| 30 | #define SMU11_DRIVER_IF_VERSION 0x12 | 30 | #define SMU11_DRIVER_IF_VERSION 0x12 |
| 31 | 31 | ||
| 32 | #define PPTABLE_V20_SMU_VERSION 2 | 32 | #define PPTABLE_V20_SMU_VERSION 3 |
| 33 | 33 | ||
| 34 | #define NUM_GFXCLK_DPM_LEVELS 16 | 34 | #define NUM_GFXCLK_DPM_LEVELS 16 |
| 35 | #define NUM_VCLK_DPM_LEVELS 8 | 35 | #define NUM_VCLK_DPM_LEVELS 8 |
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c index f836d30fdd44..09b844ec3eab 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | |||
| @@ -71,7 +71,11 @@ static int smu8_send_msg_to_smc_async(struct pp_hwmgr *hwmgr, uint16_t msg) | |||
| 71 | result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, | 71 | result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, |
| 72 | SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); | 72 | SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); |
| 73 | if (result != 0) { | 73 | if (result != 0) { |
| 74 | /* Read the last message to SMU, to report actual cause */ | ||
| 75 | uint32_t val = cgs_read_register(hwmgr->device, | ||
| 76 | mmSMU_MP1_SRBM2P_MSG_0); | ||
| 74 | pr_err("smu8_send_msg_to_smc_async (0x%04x) failed\n", msg); | 77 | pr_err("smu8_send_msg_to_smc_async (0x%04x) failed\n", msg); |
| 78 | pr_err("SMU still servicing msg (0x%04x)\n", val); | ||
| 75 | return result; | 79 | return result; |
| 76 | } | 80 | } |
| 77 | 81 | ||
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index f8a931cf3665..680566d97adc 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c | |||
| @@ -458,18 +458,6 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) | |||
| 458 | unsigned int val; | 458 | unsigned int val; |
| 459 | int ret; | 459 | int ret; |
| 460 | 460 | ||
| 461 | /* | ||
| 462 | * FIXME: | ||
| 463 | * This 70ms was found necessary by experimentation. If it's not | ||
| 464 | * present, link training fails. It seems like it can go anywhere from | ||
| 465 | * pre_enable() up to semi-auto link training initiation below. | ||
| 466 | * | ||
| 467 | * Neither the datasheet for the bridge nor the panel tested mention a | ||
| 468 | * delay of this magnitude in the timing requirements. So for now, add | ||
| 469 | * the mystery delay until someone figures out a better fix. | ||
| 470 | */ | ||
| 471 | msleep(70); | ||
| 472 | |||
| 473 | /* DSI_A lane config */ | 461 | /* DSI_A lane config */ |
| 474 | val = CHA_DSI_LANES(4 - pdata->dsi->lanes); | 462 | val = CHA_DSI_LANES(4 - pdata->dsi->lanes); |
| 475 | regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, | 463 | regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, |
| @@ -536,7 +524,22 @@ static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge) | |||
| 536 | /* configure bridge ref_clk */ | 524 | /* configure bridge ref_clk */ |
| 537 | ti_sn_bridge_set_refclk_freq(pdata); | 525 | ti_sn_bridge_set_refclk_freq(pdata); |
| 538 | 526 | ||
| 539 | /* in case drm_panel is connected then HPD is not supported */ | 527 | /* |
| 528 | * HPD on this bridge chip is a bit useless. This is an eDP bridge | ||
| 529 | * so the HPD is an internal signal that's only there to signal that | ||
| 530 | * the panel is done powering up. ...but the bridge chip debounces | ||
| 531 | * this signal by between 100 ms and 400 ms (depending on process, | ||
| 532 | * voltage, and temperate--I measured it at about 200 ms). One | ||
| 533 | * particular panel asserted HPD 84 ms after it was powered on meaning | ||
| 534 | * that we saw HPD 284 ms after power on. ...but the same panel said | ||
| 535 | * that instead of looking at HPD you could just hardcode a delay of | ||
| 536 | * 200 ms. We'll assume that the panel driver will have the hardcoded | ||
| 537 | * delay in its prepare and always disable HPD. | ||
| 538 | * | ||
| 539 | * If HPD somehow makes sense on some future panel we'll have to | ||
| 540 | * change this to be conditional on someone specifying that HPD should | ||
| 541 | * be used. | ||
| 542 | */ | ||
| 540 | regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, | 543 | regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, |
| 541 | HPD_DISABLE); | 544 | HPD_DISABLE); |
| 542 | 545 | ||
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 701cb334e1ea..d8b526b7932c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -308,6 +308,26 @@ update_connector_routing(struct drm_atomic_state *state, | |||
| 308 | return 0; | 308 | return 0; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | crtc_state = drm_atomic_get_new_crtc_state(state, | ||
| 312 | new_connector_state->crtc); | ||
| 313 | /* | ||
| 314 | * For compatibility with legacy users, we want to make sure that | ||
| 315 | * we allow DPMS On->Off modesets on unregistered connectors. Modesets | ||
| 316 | * which would result in anything else must be considered invalid, to | ||
| 317 | * avoid turning on new displays on dead connectors. | ||
| 318 | * | ||
| 319 | * Since the connector can be unregistered at any point during an | ||
| 320 | * atomic check or commit, this is racy. But that's OK: all we care | ||
| 321 | * about is ensuring that userspace can't do anything but shut off the | ||
| 322 | * display on a connector that was destroyed after its been notified, | ||
| 323 | * not before. | ||
| 324 | */ | ||
| 325 | if (drm_connector_is_unregistered(connector) && crtc_state->active) { | ||
| 326 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n", | ||
| 327 | connector->base.id, connector->name); | ||
| 328 | return -EINVAL; | ||
| 329 | } | ||
| 330 | |||
| 311 | funcs = connector->helper_private; | 331 | funcs = connector->helper_private; |
| 312 | 332 | ||
| 313 | if (funcs->atomic_best_encoder) | 333 | if (funcs->atomic_best_encoder) |
| @@ -352,7 +372,6 @@ update_connector_routing(struct drm_atomic_state *state, | |||
| 352 | 372 | ||
| 353 | set_best_encoder(state, new_connector_state, new_encoder); | 373 | set_best_encoder(state, new_connector_state, new_encoder); |
| 354 | 374 | ||
| 355 | crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc); | ||
| 356 | crtc_state->connectors_changed = true; | 375 | crtc_state->connectors_changed = true; |
| 357 | 376 | ||
| 358 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", | 377 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", |
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 1e40e5decbe9..4943cef178be 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c | |||
| @@ -379,7 +379,8 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
| 379 | /* The connector should have been removed from userspace long before | 379 | /* The connector should have been removed from userspace long before |
| 380 | * it is finally destroyed. | 380 | * it is finally destroyed. |
| 381 | */ | 381 | */ |
| 382 | if (WARN_ON(connector->registered)) | 382 | if (WARN_ON(connector->registration_state == |
| 383 | DRM_CONNECTOR_REGISTERED)) | ||
| 383 | drm_connector_unregister(connector); | 384 | drm_connector_unregister(connector); |
| 384 | 385 | ||
| 385 | if (connector->tile_group) { | 386 | if (connector->tile_group) { |
| @@ -436,7 +437,7 @@ int drm_connector_register(struct drm_connector *connector) | |||
| 436 | return 0; | 437 | return 0; |
| 437 | 438 | ||
| 438 | mutex_lock(&connector->mutex); | 439 | mutex_lock(&connector->mutex); |
| 439 | if (connector->registered) | 440 | if (connector->registration_state != DRM_CONNECTOR_INITIALIZING) |
| 440 | goto unlock; | 441 | goto unlock; |
| 441 | 442 | ||
| 442 | ret = drm_sysfs_connector_add(connector); | 443 | ret = drm_sysfs_connector_add(connector); |
| @@ -456,7 +457,7 @@ int drm_connector_register(struct drm_connector *connector) | |||
| 456 | 457 | ||
| 457 | drm_mode_object_register(connector->dev, &connector->base); | 458 | drm_mode_object_register(connector->dev, &connector->base); |
| 458 | 459 | ||
| 459 | connector->registered = true; | 460 | connector->registration_state = DRM_CONNECTOR_REGISTERED; |
| 460 | goto unlock; | 461 | goto unlock; |
| 461 | 462 | ||
| 462 | err_debugfs: | 463 | err_debugfs: |
| @@ -478,7 +479,7 @@ EXPORT_SYMBOL(drm_connector_register); | |||
| 478 | void drm_connector_unregister(struct drm_connector *connector) | 479 | void drm_connector_unregister(struct drm_connector *connector) |
| 479 | { | 480 | { |
| 480 | mutex_lock(&connector->mutex); | 481 | mutex_lock(&connector->mutex); |
| 481 | if (!connector->registered) { | 482 | if (connector->registration_state != DRM_CONNECTOR_REGISTERED) { |
| 482 | mutex_unlock(&connector->mutex); | 483 | mutex_unlock(&connector->mutex); |
| 483 | return; | 484 | return; |
| 484 | } | 485 | } |
| @@ -489,7 +490,7 @@ void drm_connector_unregister(struct drm_connector *connector) | |||
| 489 | drm_sysfs_connector_remove(connector); | 490 | drm_sysfs_connector_remove(connector); |
| 490 | drm_debugfs_connector_remove(connector); | 491 | drm_debugfs_connector_remove(connector); |
| 491 | 492 | ||
| 492 | connector->registered = false; | 493 | connector->registration_state = DRM_CONNECTOR_UNREGISTERED; |
| 493 | mutex_unlock(&connector->mutex); | 494 | mutex_unlock(&connector->mutex); |
| 494 | } | 495 | } |
| 495 | EXPORT_SYMBOL(drm_connector_unregister); | 496 | EXPORT_SYMBOL(drm_connector_unregister); |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ff0bfc65a8c1..b506e3622b08 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -122,6 +122,9 @@ static const struct edid_quirk { | |||
| 122 | /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ | 122 | /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ |
| 123 | { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC }, | 123 | { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC }, |
| 124 | 124 | ||
| 125 | /* BOE model 0x0771 reports 8 bpc, but is a 6 bpc panel */ | ||
| 126 | { "BOE", 0x0771, EDID_QUIRK_FORCE_6BPC }, | ||
| 127 | |||
| 125 | /* Belinea 10 15 55 */ | 128 | /* Belinea 10 15 55 */ |
| 126 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, | 129 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, |
| 127 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, | 130 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3fae4dab295f..13f9b56a9ce7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -5102,19 +5102,13 @@ intel_dp_long_pulse(struct intel_connector *connector, | |||
| 5102 | */ | 5102 | */ |
| 5103 | status = connector_status_disconnected; | 5103 | status = connector_status_disconnected; |
| 5104 | goto out; | 5104 | goto out; |
| 5105 | } else { | 5105 | } |
| 5106 | /* | 5106 | |
| 5107 | * If display is now connected check links status, | 5107 | /* |
| 5108 | * there has been known issues of link loss triggering | 5108 | * Some external monitors do not signal loss of link synchronization |
| 5109 | * long pulse. | 5109 | * with an IRQ_HPD, so force a link status check. |
| 5110 | * | 5110 | */ |
| 5111 | * Some sinks (eg. ASUS PB287Q) seem to perform some | 5111 | if (!intel_dp_is_edp(intel_dp)) { |
| 5112 | * weird HPD ping pong during modesets. So we can apparently | ||
| 5113 | * end up with HPD going low during a modeset, and then | ||
| 5114 | * going back up soon after. And once that happens we must | ||
| 5115 | * retrain the link to get a picture. That's in case no | ||
| 5116 | * userspace component reacted to intermittent HPD dip. | ||
| 5117 | */ | ||
| 5118 | struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; | 5112 | struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; |
| 5119 | 5113 | ||
| 5120 | intel_dp_retrain_link(encoder, ctx); | 5114 | intel_dp_retrain_link(encoder, ctx); |
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 7f155b4f1a7d..1b00f8ea145b 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
| @@ -77,7 +77,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, | |||
| 77 | pipe_config->pbn = mst_pbn; | 77 | pipe_config->pbn = mst_pbn; |
| 78 | 78 | ||
| 79 | /* Zombie connectors can't have VCPI slots */ | 79 | /* Zombie connectors can't have VCPI slots */ |
| 80 | if (READ_ONCE(connector->registered)) { | 80 | if (!drm_connector_is_unregistered(connector)) { |
| 81 | slots = drm_dp_atomic_find_vcpi_slots(state, | 81 | slots = drm_dp_atomic_find_vcpi_slots(state, |
| 82 | &intel_dp->mst_mgr, | 82 | &intel_dp->mst_mgr, |
| 83 | port, | 83 | port, |
| @@ -313,7 +313,7 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) | |||
| 313 | struct edid *edid; | 313 | struct edid *edid; |
| 314 | int ret; | 314 | int ret; |
| 315 | 315 | ||
| 316 | if (!READ_ONCE(connector->registered)) | 316 | if (drm_connector_is_unregistered(connector)) |
| 317 | return intel_connector_update_modes(connector, NULL); | 317 | return intel_connector_update_modes(connector, NULL); |
| 318 | 318 | ||
| 319 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); | 319 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); |
| @@ -329,7 +329,7 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force) | |||
| 329 | struct intel_connector *intel_connector = to_intel_connector(connector); | 329 | struct intel_connector *intel_connector = to_intel_connector(connector); |
| 330 | struct intel_dp *intel_dp = intel_connector->mst_port; | 330 | struct intel_dp *intel_dp = intel_connector->mst_port; |
| 331 | 331 | ||
| 332 | if (!READ_ONCE(connector->registered)) | 332 | if (drm_connector_is_unregistered(connector)) |
| 333 | return connector_status_disconnected; | 333 | return connector_status_disconnected; |
| 334 | return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, | 334 | return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, |
| 335 | intel_connector->port); | 335 | intel_connector->port); |
| @@ -372,7 +372,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, | |||
| 372 | int bpp = 24; /* MST uses fixed bpp */ | 372 | int bpp = 24; /* MST uses fixed bpp */ |
| 373 | int max_rate, mode_rate, max_lanes, max_link_clock; | 373 | int max_rate, mode_rate, max_lanes, max_link_clock; |
| 374 | 374 | ||
| 375 | if (!READ_ONCE(connector->registered)) | 375 | if (drm_connector_is_unregistered(connector)) |
| 376 | return MODE_ERROR; | 376 | return MODE_ERROR; |
| 377 | 377 | ||
| 378 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 378 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 6bb78076b5b5..6cbbae3f438b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c | |||
| @@ -881,22 +881,16 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector, | |||
| 881 | { | 881 | { |
| 882 | struct nv50_head *head = nv50_head(connector_state->crtc); | 882 | struct nv50_head *head = nv50_head(connector_state->crtc); |
| 883 | struct nv50_mstc *mstc = nv50_mstc(connector); | 883 | struct nv50_mstc *mstc = nv50_mstc(connector); |
| 884 | if (mstc->port) { | 884 | |
| 885 | struct nv50_mstm *mstm = mstc->mstm; | 885 | return &mstc->mstm->msto[head->base.index]->encoder; |
| 886 | return &mstm->msto[head->base.index]->encoder; | ||
| 887 | } | ||
| 888 | return NULL; | ||
| 889 | } | 886 | } |
| 890 | 887 | ||
| 891 | static struct drm_encoder * | 888 | static struct drm_encoder * |
| 892 | nv50_mstc_best_encoder(struct drm_connector *connector) | 889 | nv50_mstc_best_encoder(struct drm_connector *connector) |
| 893 | { | 890 | { |
| 894 | struct nv50_mstc *mstc = nv50_mstc(connector); | 891 | struct nv50_mstc *mstc = nv50_mstc(connector); |
| 895 | if (mstc->port) { | 892 | |
| 896 | struct nv50_mstm *mstm = mstc->mstm; | 893 | return &mstc->mstm->msto[0]->encoder; |
| 897 | return &mstm->msto[0]->encoder; | ||
| 898 | } | ||
| 899 | return NULL; | ||
| 900 | } | 894 | } |
| 901 | 895 | ||
| 902 | static enum drm_mode_status | 896 | static enum drm_mode_status |
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 97964f7f2ace..a04ffb3b2174 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c | |||
| @@ -56,6 +56,8 @@ struct panel_desc { | |||
| 56 | /** | 56 | /** |
| 57 | * @prepare: the time (in milliseconds) that it takes for the panel to | 57 | * @prepare: the time (in milliseconds) that it takes for the panel to |
| 58 | * become ready and start receiving video data | 58 | * become ready and start receiving video data |
| 59 | * @hpd_absent_delay: Add this to the prepare delay if we know Hot | ||
| 60 | * Plug Detect isn't used. | ||
| 59 | * @enable: the time (in milliseconds) that it takes for the panel to | 61 | * @enable: the time (in milliseconds) that it takes for the panel to |
| 60 | * display the first valid frame after starting to receive | 62 | * display the first valid frame after starting to receive |
| 61 | * video data | 63 | * video data |
| @@ -66,6 +68,7 @@ struct panel_desc { | |||
| 66 | */ | 68 | */ |
| 67 | struct { | 69 | struct { |
| 68 | unsigned int prepare; | 70 | unsigned int prepare; |
| 71 | unsigned int hpd_absent_delay; | ||
| 69 | unsigned int enable; | 72 | unsigned int enable; |
| 70 | unsigned int disable; | 73 | unsigned int disable; |
| 71 | unsigned int unprepare; | 74 | unsigned int unprepare; |
| @@ -79,6 +82,7 @@ struct panel_simple { | |||
| 79 | struct drm_panel base; | 82 | struct drm_panel base; |
| 80 | bool prepared; | 83 | bool prepared; |
| 81 | bool enabled; | 84 | bool enabled; |
| 85 | bool no_hpd; | ||
| 82 | 86 | ||
| 83 | const struct panel_desc *desc; | 87 | const struct panel_desc *desc; |
| 84 | 88 | ||
| @@ -202,6 +206,7 @@ static int panel_simple_unprepare(struct drm_panel *panel) | |||
| 202 | static int panel_simple_prepare(struct drm_panel *panel) | 206 | static int panel_simple_prepare(struct drm_panel *panel) |
| 203 | { | 207 | { |
| 204 | struct panel_simple *p = to_panel_simple(panel); | 208 | struct panel_simple *p = to_panel_simple(panel); |
| 209 | unsigned int delay; | ||
| 205 | int err; | 210 | int err; |
| 206 | 211 | ||
| 207 | if (p->prepared) | 212 | if (p->prepared) |
| @@ -215,8 +220,11 @@ static int panel_simple_prepare(struct drm_panel *panel) | |||
| 215 | 220 | ||
| 216 | gpiod_set_value_cansleep(p->enable_gpio, 1); | 221 | gpiod_set_value_cansleep(p->enable_gpio, 1); |
| 217 | 222 | ||
| 218 | if (p->desc->delay.prepare) | 223 | delay = p->desc->delay.prepare; |
| 219 | msleep(p->desc->delay.prepare); | 224 | if (p->no_hpd) |
| 225 | delay += p->desc->delay.hpd_absent_delay; | ||
| 226 | if (delay) | ||
| 227 | msleep(delay); | ||
| 220 | 228 | ||
| 221 | p->prepared = true; | 229 | p->prepared = true; |
| 222 | 230 | ||
| @@ -305,6 +313,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) | |||
| 305 | panel->prepared = false; | 313 | panel->prepared = false; |
| 306 | panel->desc = desc; | 314 | panel->desc = desc; |
| 307 | 315 | ||
| 316 | panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd"); | ||
| 317 | |||
| 308 | panel->supply = devm_regulator_get(dev, "power"); | 318 | panel->supply = devm_regulator_get(dev, "power"); |
| 309 | if (IS_ERR(panel->supply)) | 319 | if (IS_ERR(panel->supply)) |
| 310 | return PTR_ERR(panel->supply); | 320 | return PTR_ERR(panel->supply); |
| @@ -1363,7 +1373,7 @@ static const struct panel_desc innolux_n156bge_l21 = { | |||
| 1363 | }, | 1373 | }, |
| 1364 | }; | 1374 | }; |
| 1365 | 1375 | ||
| 1366 | static const struct drm_display_mode innolux_tv123wam_mode = { | 1376 | static const struct drm_display_mode innolux_p120zdg_bf1_mode = { |
| 1367 | .clock = 206016, | 1377 | .clock = 206016, |
| 1368 | .hdisplay = 2160, | 1378 | .hdisplay = 2160, |
| 1369 | .hsync_start = 2160 + 48, | 1379 | .hsync_start = 2160 + 48, |
| @@ -1377,15 +1387,16 @@ static const struct drm_display_mode innolux_tv123wam_mode = { | |||
| 1377 | .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, | 1387 | .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, |
| 1378 | }; | 1388 | }; |
| 1379 | 1389 | ||
| 1380 | static const struct panel_desc innolux_tv123wam = { | 1390 | static const struct panel_desc innolux_p120zdg_bf1 = { |
| 1381 | .modes = &innolux_tv123wam_mode, | 1391 | .modes = &innolux_p120zdg_bf1_mode, |
| 1382 | .num_modes = 1, | 1392 | .num_modes = 1, |
| 1383 | .bpc = 8, | 1393 | .bpc = 8, |
| 1384 | .size = { | 1394 | .size = { |
| 1385 | .width = 259, | 1395 | .width = 254, |
| 1386 | .height = 173, | 1396 | .height = 169, |
| 1387 | }, | 1397 | }, |
| 1388 | .delay = { | 1398 | .delay = { |
| 1399 | .hpd_absent_delay = 200, | ||
| 1389 | .unprepare = 500, | 1400 | .unprepare = 500, |
| 1390 | }, | 1401 | }, |
| 1391 | }; | 1402 | }; |
| @@ -2445,8 +2456,8 @@ static const struct of_device_id platform_of_match[] = { | |||
| 2445 | .compatible = "innolux,n156bge-l21", | 2456 | .compatible = "innolux,n156bge-l21", |
| 2446 | .data = &innolux_n156bge_l21, | 2457 | .data = &innolux_n156bge_l21, |
| 2447 | }, { | 2458 | }, { |
| 2448 | .compatible = "innolux,tv123wam", | 2459 | .compatible = "innolux,p120zdg-bf1", |
| 2449 | .data = &innolux_tv123wam, | 2460 | .data = &innolux_p120zdg_bf1, |
| 2450 | }, { | 2461 | }, { |
| 2451 | .compatible = "innolux,zj070na-01p", | 2462 | .compatible = "innolux,zj070na-01p", |
| 2452 | .data = &innolux_zj070na_01p, | 2463 | .data = &innolux_zj070na_01p, |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index f3fb5bb8c82a..ac1cffd2a09b 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
| @@ -542,7 +542,7 @@ static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) | |||
| 542 | !discard_bio) | 542 | !discard_bio) |
| 543 | continue; | 543 | continue; |
| 544 | bio_chain(discard_bio, bio); | 544 | bio_chain(discard_bio, bio); |
| 545 | bio_clone_blkg_association(discard_bio, bio); | 545 | bio_clone_blkcg_association(discard_bio, bio); |
| 546 | if (mddev->gendisk) | 546 | if (mddev->gendisk) |
| 547 | trace_block_bio_remap(bdev_get_queue(rdev->bdev), | 547 | trace_block_bio_remap(bdev_get_queue(rdev->bdev), |
| 548 | discard_bio, disk_devt(mddev->gendisk), | 548 | discard_bio, disk_devt(mddev->gendisk), |
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index e52b9d3c0bd6..0b70c8bab045 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c | |||
| @@ -1704,7 +1704,6 @@ __nvme_fc_init_request(struct nvme_fc_ctrl *ctrl, | |||
| 1704 | op->fcp_req.rspaddr = &op->rsp_iu; | 1704 | op->fcp_req.rspaddr = &op->rsp_iu; |
| 1705 | op->fcp_req.rsplen = sizeof(op->rsp_iu); | 1705 | op->fcp_req.rsplen = sizeof(op->rsp_iu); |
| 1706 | op->fcp_req.done = nvme_fc_fcpio_done; | 1706 | op->fcp_req.done = nvme_fc_fcpio_done; |
| 1707 | op->fcp_req.private = &op->fcp_req.first_sgl[SG_CHUNK_SIZE]; | ||
| 1708 | op->ctrl = ctrl; | 1707 | op->ctrl = ctrl; |
| 1709 | op->queue = queue; | 1708 | op->queue = queue; |
| 1710 | op->rq = rq; | 1709 | op->rq = rq; |
| @@ -1752,6 +1751,7 @@ nvme_fc_init_request(struct blk_mq_tag_set *set, struct request *rq, | |||
| 1752 | if (res) | 1751 | if (res) |
| 1753 | return res; | 1752 | return res; |
| 1754 | op->op.fcp_req.first_sgl = &op->sgl[0]; | 1753 | op->op.fcp_req.first_sgl = &op->sgl[0]; |
| 1754 | op->op.fcp_req.private = &op->priv[0]; | ||
| 1755 | return res; | 1755 | return res; |
| 1756 | } | 1756 | } |
| 1757 | 1757 | ||
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index f30031945ee4..c33bb201b884 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c | |||
| @@ -1663,6 +1663,9 @@ static void nvme_map_cmb(struct nvme_dev *dev) | |||
| 1663 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 1663 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 1664 | int bar; | 1664 | int bar; |
| 1665 | 1665 | ||
| 1666 | if (dev->cmb_size) | ||
| 1667 | return; | ||
| 1668 | |||
| 1666 | dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ); | 1669 | dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ); |
| 1667 | if (!dev->cmbsz) | 1670 | if (!dev->cmbsz) |
| 1668 | return; | 1671 | return; |
| @@ -2147,7 +2150,6 @@ static void nvme_pci_disable(struct nvme_dev *dev) | |||
| 2147 | { | 2150 | { |
| 2148 | struct pci_dev *pdev = to_pci_dev(dev->dev); | 2151 | struct pci_dev *pdev = to_pci_dev(dev->dev); |
| 2149 | 2152 | ||
| 2150 | nvme_release_cmb(dev); | ||
| 2151 | pci_free_irq_vectors(pdev); | 2153 | pci_free_irq_vectors(pdev); |
| 2152 | 2154 | ||
| 2153 | if (pci_is_enabled(pdev)) { | 2155 | if (pci_is_enabled(pdev)) { |
| @@ -2595,6 +2597,7 @@ static void nvme_remove(struct pci_dev *pdev) | |||
| 2595 | nvme_stop_ctrl(&dev->ctrl); | 2597 | nvme_stop_ctrl(&dev->ctrl); |
| 2596 | nvme_remove_namespaces(&dev->ctrl); | 2598 | nvme_remove_namespaces(&dev->ctrl); |
| 2597 | nvme_dev_disable(dev, true); | 2599 | nvme_dev_disable(dev, true); |
| 2600 | nvme_release_cmb(dev); | ||
| 2598 | nvme_free_host_mem(dev); | 2601 | nvme_free_host_mem(dev); |
| 2599 | nvme_dev_remove_admin(dev); | 2602 | nvme_dev_remove_admin(dev); |
| 2600 | nvme_free_queues(dev, 0); | 2603 | nvme_free_queues(dev, 0); |
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 504d252716f2..27e5dd47a01f 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
| @@ -447,10 +447,9 @@ config PWM_TEGRA | |||
| 447 | 447 | ||
| 448 | config PWM_TIECAP | 448 | config PWM_TIECAP |
| 449 | tristate "ECAP PWM support" | 449 | tristate "ECAP PWM support" |
| 450 | depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE | 450 | depends on ARCH_OMAP2PLUS || ARCH_DAVINCI_DA8XX || ARCH_KEYSTONE || ARCH_K3 |
| 451 | help | 451 | help |
| 452 | PWM driver support for the ECAP APWM controller found on AM33XX | 452 | PWM driver support for the ECAP APWM controller found on TI SOCs |
| 453 | TI SOC | ||
| 454 | 453 | ||
| 455 | To compile this driver as a module, choose M here: the module | 454 | To compile this driver as a module, choose M here: the module |
| 456 | will be called pwm-tiecap. | 455 | will be called pwm-tiecap. |
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c index 5561b9e190f8..757230e1f575 100644 --- a/drivers/pwm/pwm-lpss-platform.c +++ b/drivers/pwm/pwm-lpss-platform.c | |||
| @@ -30,6 +30,7 @@ static const struct pwm_lpss_boardinfo pwm_lpss_bsw_info = { | |||
| 30 | .clk_rate = 19200000, | 30 | .clk_rate = 19200000, |
| 31 | .npwm = 1, | 31 | .npwm = 1, |
| 32 | .base_unit_bits = 16, | 32 | .base_unit_bits = 16, |
| 33 | .other_devices_aml_touches_pwm_regs = true, | ||
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | /* Broxton */ | 36 | /* Broxton */ |
| @@ -60,6 +61,7 @@ static int pwm_lpss_probe_platform(struct platform_device *pdev) | |||
| 60 | 61 | ||
| 61 | platform_set_drvdata(pdev, lpwm); | 62 | platform_set_drvdata(pdev, lpwm); |
| 62 | 63 | ||
| 64 | dev_pm_set_driver_flags(&pdev->dev, DPM_FLAG_SMART_PREPARE); | ||
| 63 | pm_runtime_set_active(&pdev->dev); | 65 | pm_runtime_set_active(&pdev->dev); |
| 64 | pm_runtime_enable(&pdev->dev); | 66 | pm_runtime_enable(&pdev->dev); |
| 65 | 67 | ||
| @@ -74,13 +76,29 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev) | |||
| 74 | return pwm_lpss_remove(lpwm); | 76 | return pwm_lpss_remove(lpwm); |
| 75 | } | 77 | } |
| 76 | 78 | ||
| 77 | static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops, | 79 | static int pwm_lpss_prepare(struct device *dev) |
| 78 | pwm_lpss_suspend, | 80 | { |
| 79 | pwm_lpss_resume); | 81 | struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev); |
| 82 | |||
| 83 | /* | ||
| 84 | * If other device's AML code touches the PWM regs on suspend/resume | ||
| 85 | * force runtime-resume the PWM controller to allow this. | ||
| 86 | */ | ||
| 87 | if (lpwm->info->other_devices_aml_touches_pwm_regs) | ||
| 88 | return 0; /* Force runtime-resume */ | ||
| 89 | |||
| 90 | return 1; /* If runtime-suspended leave as is */ | ||
| 91 | } | ||
| 92 | |||
| 93 | static const struct dev_pm_ops pwm_lpss_platform_pm_ops = { | ||
| 94 | .prepare = pwm_lpss_prepare, | ||
| 95 | SET_SYSTEM_SLEEP_PM_OPS(pwm_lpss_suspend, pwm_lpss_resume) | ||
| 96 | }; | ||
| 80 | 97 | ||
| 81 | static const struct acpi_device_id pwm_lpss_acpi_match[] = { | 98 | static const struct acpi_device_id pwm_lpss_acpi_match[] = { |
| 82 | { "80860F09", (unsigned long)&pwm_lpss_byt_info }, | 99 | { "80860F09", (unsigned long)&pwm_lpss_byt_info }, |
| 83 | { "80862288", (unsigned long)&pwm_lpss_bsw_info }, | 100 | { "80862288", (unsigned long)&pwm_lpss_bsw_info }, |
| 101 | { "80862289", (unsigned long)&pwm_lpss_bsw_info }, | ||
| 84 | { "80865AC8", (unsigned long)&pwm_lpss_bxt_info }, | 102 | { "80865AC8", (unsigned long)&pwm_lpss_bxt_info }, |
| 85 | { }, | 103 | { }, |
| 86 | }; | 104 | }; |
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c index 4721a264bac2..2ac3a2aa9e53 100644 --- a/drivers/pwm/pwm-lpss.c +++ b/drivers/pwm/pwm-lpss.c | |||
| @@ -32,15 +32,6 @@ | |||
| 32 | /* Size of each PWM register space if multiple */ | 32 | /* Size of each PWM register space if multiple */ |
| 33 | #define PWM_SIZE 0x400 | 33 | #define PWM_SIZE 0x400 |
| 34 | 34 | ||
| 35 | #define MAX_PWMS 4 | ||
| 36 | |||
| 37 | struct pwm_lpss_chip { | ||
| 38 | struct pwm_chip chip; | ||
| 39 | void __iomem *regs; | ||
| 40 | const struct pwm_lpss_boardinfo *info; | ||
| 41 | u32 saved_ctrl[MAX_PWMS]; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) | 35 | static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip) |
| 45 | { | 36 | { |
| 46 | return container_of(chip, struct pwm_lpss_chip, chip); | 37 | return container_of(chip, struct pwm_lpss_chip, chip); |
| @@ -97,7 +88,7 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, | |||
| 97 | unsigned long long on_time_div; | 88 | unsigned long long on_time_div; |
| 98 | unsigned long c = lpwm->info->clk_rate, base_unit_range; | 89 | unsigned long c = lpwm->info->clk_rate, base_unit_range; |
| 99 | unsigned long long base_unit, freq = NSEC_PER_SEC; | 90 | unsigned long long base_unit, freq = NSEC_PER_SEC; |
| 100 | u32 ctrl; | 91 | u32 orig_ctrl, ctrl; |
| 101 | 92 | ||
| 102 | do_div(freq, period_ns); | 93 | do_div(freq, period_ns); |
| 103 | 94 | ||
| @@ -114,13 +105,17 @@ static void pwm_lpss_prepare(struct pwm_lpss_chip *lpwm, struct pwm_device *pwm, | |||
| 114 | do_div(on_time_div, period_ns); | 105 | do_div(on_time_div, period_ns); |
| 115 | on_time_div = 255ULL - on_time_div; | 106 | on_time_div = 255ULL - on_time_div; |
| 116 | 107 | ||
| 117 | ctrl = pwm_lpss_read(pwm); | 108 | orig_ctrl = ctrl = pwm_lpss_read(pwm); |
| 118 | ctrl &= ~PWM_ON_TIME_DIV_MASK; | 109 | ctrl &= ~PWM_ON_TIME_DIV_MASK; |
| 119 | ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT); | 110 | ctrl &= ~(base_unit_range << PWM_BASE_UNIT_SHIFT); |
| 120 | base_unit &= base_unit_range; | 111 | base_unit &= base_unit_range; |
| 121 | ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; | 112 | ctrl |= (u32) base_unit << PWM_BASE_UNIT_SHIFT; |
| 122 | ctrl |= on_time_div; | 113 | ctrl |= on_time_div; |
| 123 | pwm_lpss_write(pwm, ctrl); | 114 | |
| 115 | if (orig_ctrl != ctrl) { | ||
| 116 | pwm_lpss_write(pwm, ctrl); | ||
| 117 | pwm_lpss_write(pwm, ctrl | PWM_SW_UPDATE); | ||
| 118 | } | ||
| 124 | } | 119 | } |
| 125 | 120 | ||
| 126 | static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) | 121 | static inline void pwm_lpss_cond_enable(struct pwm_device *pwm, bool cond) |
| @@ -144,7 +139,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
| 144 | return ret; | 139 | return ret; |
| 145 | } | 140 | } |
| 146 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); | 141 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); |
| 147 | pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); | ||
| 148 | pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); | 142 | pwm_lpss_cond_enable(pwm, lpwm->info->bypass == false); |
| 149 | ret = pwm_lpss_wait_for_update(pwm); | 143 | ret = pwm_lpss_wait_for_update(pwm); |
| 150 | if (ret) { | 144 | if (ret) { |
| @@ -157,7 +151,6 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
| 157 | if (ret) | 151 | if (ret) |
| 158 | return ret; | 152 | return ret; |
| 159 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); | 153 | pwm_lpss_prepare(lpwm, pwm, state->duty_cycle, state->period); |
| 160 | pwm_lpss_write(pwm, pwm_lpss_read(pwm) | PWM_SW_UPDATE); | ||
| 161 | return pwm_lpss_wait_for_update(pwm); | 154 | return pwm_lpss_wait_for_update(pwm); |
| 162 | } | 155 | } |
| 163 | } else if (pwm_is_enabled(pwm)) { | 156 | } else if (pwm_is_enabled(pwm)) { |
| @@ -168,8 +161,42 @@ static int pwm_lpss_apply(struct pwm_chip *chip, struct pwm_device *pwm, | |||
| 168 | return 0; | 161 | return 0; |
| 169 | } | 162 | } |
| 170 | 163 | ||
| 164 | /* This function gets called once from pwmchip_add to get the initial state */ | ||
| 165 | static void pwm_lpss_get_state(struct pwm_chip *chip, struct pwm_device *pwm, | ||
| 166 | struct pwm_state *state) | ||
| 167 | { | ||
| 168 | struct pwm_lpss_chip *lpwm = to_lpwm(chip); | ||
| 169 | unsigned long base_unit_range; | ||
| 170 | unsigned long long base_unit, freq, on_time_div; | ||
| 171 | u32 ctrl; | ||
| 172 | |||
| 173 | base_unit_range = BIT(lpwm->info->base_unit_bits); | ||
| 174 | |||
| 175 | ctrl = pwm_lpss_read(pwm); | ||
| 176 | on_time_div = 255 - (ctrl & PWM_ON_TIME_DIV_MASK); | ||
| 177 | base_unit = (ctrl >> PWM_BASE_UNIT_SHIFT) & (base_unit_range - 1); | ||
| 178 | |||
| 179 | freq = base_unit * lpwm->info->clk_rate; | ||
| 180 | do_div(freq, base_unit_range); | ||
| 181 | if (freq == 0) | ||
| 182 | state->period = NSEC_PER_SEC; | ||
| 183 | else | ||
| 184 | state->period = NSEC_PER_SEC / (unsigned long)freq; | ||
| 185 | |||
| 186 | on_time_div *= state->period; | ||
| 187 | do_div(on_time_div, 255); | ||
| 188 | state->duty_cycle = on_time_div; | ||
| 189 | |||
| 190 | state->polarity = PWM_POLARITY_NORMAL; | ||
| 191 | state->enabled = !!(ctrl & PWM_ENABLE); | ||
| 192 | |||
| 193 | if (state->enabled) | ||
| 194 | pm_runtime_get(chip->dev); | ||
| 195 | } | ||
| 196 | |||
| 171 | static const struct pwm_ops pwm_lpss_ops = { | 197 | static const struct pwm_ops pwm_lpss_ops = { |
| 172 | .apply = pwm_lpss_apply, | 198 | .apply = pwm_lpss_apply, |
| 199 | .get_state = pwm_lpss_get_state, | ||
| 173 | .owner = THIS_MODULE, | 200 | .owner = THIS_MODULE, |
| 174 | }; | 201 | }; |
| 175 | 202 | ||
| @@ -214,6 +241,12 @@ EXPORT_SYMBOL_GPL(pwm_lpss_probe); | |||
| 214 | 241 | ||
| 215 | int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) | 242 | int pwm_lpss_remove(struct pwm_lpss_chip *lpwm) |
| 216 | { | 243 | { |
| 244 | int i; | ||
| 245 | |||
| 246 | for (i = 0; i < lpwm->info->npwm; i++) { | ||
| 247 | if (pwm_is_enabled(&lpwm->chip.pwms[i])) | ||
| 248 | pm_runtime_put(lpwm->chip.dev); | ||
| 249 | } | ||
| 217 | return pwmchip_remove(&lpwm->chip); | 250 | return pwmchip_remove(&lpwm->chip); |
| 218 | } | 251 | } |
| 219 | EXPORT_SYMBOL_GPL(pwm_lpss_remove); | 252 | EXPORT_SYMBOL_GPL(pwm_lpss_remove); |
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h index 7a4238ad1fcb..3236be835bd9 100644 --- a/drivers/pwm/pwm-lpss.h +++ b/drivers/pwm/pwm-lpss.h | |||
| @@ -16,13 +16,25 @@ | |||
| 16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/pwm.h> | 17 | #include <linux/pwm.h> |
| 18 | 18 | ||
| 19 | struct pwm_lpss_chip; | 19 | #define MAX_PWMS 4 |
| 20 | |||
| 21 | struct pwm_lpss_chip { | ||
| 22 | struct pwm_chip chip; | ||
| 23 | void __iomem *regs; | ||
| 24 | const struct pwm_lpss_boardinfo *info; | ||
| 25 | u32 saved_ctrl[MAX_PWMS]; | ||
| 26 | }; | ||
| 20 | 27 | ||
| 21 | struct pwm_lpss_boardinfo { | 28 | struct pwm_lpss_boardinfo { |
| 22 | unsigned long clk_rate; | 29 | unsigned long clk_rate; |
| 23 | unsigned int npwm; | 30 | unsigned int npwm; |
| 24 | unsigned long base_unit_bits; | 31 | unsigned long base_unit_bits; |
| 25 | bool bypass; | 32 | bool bypass; |
| 33 | /* | ||
| 34 | * On some devices the _PS0/_PS3 AML code of the GPU (GFX0) device | ||
| 35 | * messes with the PWM0 controllers state, | ||
| 36 | */ | ||
| 37 | bool other_devices_aml_touches_pwm_regs; | ||
| 26 | }; | 38 | }; |
| 27 | 39 | ||
| 28 | struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, | 40 | struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r, |
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c index 748f614d5375..a41812fc6f95 100644 --- a/drivers/pwm/pwm-rcar.c +++ b/drivers/pwm/pwm-rcar.c | |||
| @@ -1,11 +1,8 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * R-Car PWM Timer driver | 3 | * R-Car PWM Timer driver |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2015 Renesas Electronics Corporation | 5 | * Copyright (C) 2015 Renesas Electronics Corporation |
| 5 | * | ||
| 6 | * This is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of version 2 of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | 6 | */ |
| 10 | 7 | ||
| 11 | #include <linux/clk.h> | 8 | #include <linux/clk.h> |
diff --git a/drivers/pwm/pwm-renesas-tpu.c b/drivers/pwm/pwm-renesas-tpu.c index 29267d12fb4c..4a855a21b782 100644 --- a/drivers/pwm/pwm-renesas-tpu.c +++ b/drivers/pwm/pwm-renesas-tpu.c | |||
| @@ -1,16 +1,8 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * R-Mobile TPU PWM driver | 3 | * R-Mobile TPU PWM driver |
| 3 | * | 4 | * |
| 4 | * Copyright (C) 2012 Renesas Solutions Corp. | 5 | * Copyright (C) 2012 Renesas Solutions Corp. |
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 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 | */ | 6 | */ |
| 15 | 7 | ||
| 16 | #include <linux/clk.h> | 8 | #include <linux/clk.h> |
diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index f8ebbece57b7..48c4595a0ffc 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c | |||
| @@ -300,7 +300,6 @@ static const struct of_device_id tegra_pwm_of_match[] = { | |||
| 300 | { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, | 300 | { .compatible = "nvidia,tegra186-pwm", .data = &tegra186_pwm_soc }, |
| 301 | { } | 301 | { } |
| 302 | }; | 302 | }; |
| 303 | |||
| 304 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); | 303 | MODULE_DEVICE_TABLE(of, tegra_pwm_of_match); |
| 305 | 304 | ||
| 306 | static const struct dev_pm_ops tegra_pwm_pm_ops = { | 305 | static const struct dev_pm_ops tegra_pwm_pm_ops = { |
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 7c71cdb8a9d8..ceb233dd6048 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c | |||
| @@ -249,6 +249,7 @@ static void pwm_export_release(struct device *child) | |||
| 249 | static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | 249 | static int pwm_export_child(struct device *parent, struct pwm_device *pwm) |
| 250 | { | 250 | { |
| 251 | struct pwm_export *export; | 251 | struct pwm_export *export; |
| 252 | char *pwm_prop[2]; | ||
| 252 | int ret; | 253 | int ret; |
| 253 | 254 | ||
| 254 | if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) | 255 | if (test_and_set_bit(PWMF_EXPORTED, &pwm->flags)) |
| @@ -263,7 +264,6 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | |||
| 263 | export->pwm = pwm; | 264 | export->pwm = pwm; |
| 264 | mutex_init(&export->lock); | 265 | mutex_init(&export->lock); |
| 265 | 266 | ||
| 266 | export->child.class = parent->class; | ||
| 267 | export->child.release = pwm_export_release; | 267 | export->child.release = pwm_export_release; |
| 268 | export->child.parent = parent; | 268 | export->child.parent = parent; |
| 269 | export->child.devt = MKDEV(0, 0); | 269 | export->child.devt = MKDEV(0, 0); |
| @@ -277,6 +277,10 @@ static int pwm_export_child(struct device *parent, struct pwm_device *pwm) | |||
| 277 | export = NULL; | 277 | export = NULL; |
| 278 | return ret; | 278 | return ret; |
| 279 | } | 279 | } |
| 280 | pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm); | ||
| 281 | pwm_prop[1] = NULL; | ||
| 282 | kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); | ||
| 283 | kfree(pwm_prop[0]); | ||
| 280 | 284 | ||
| 281 | return 0; | 285 | return 0; |
| 282 | } | 286 | } |
| @@ -289,6 +293,7 @@ static int pwm_unexport_match(struct device *child, void *data) | |||
| 289 | static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) | 293 | static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) |
| 290 | { | 294 | { |
| 291 | struct device *child; | 295 | struct device *child; |
| 296 | char *pwm_prop[2]; | ||
| 292 | 297 | ||
| 293 | if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) | 298 | if (!test_and_clear_bit(PWMF_EXPORTED, &pwm->flags)) |
| 294 | return -ENODEV; | 299 | return -ENODEV; |
| @@ -297,6 +302,11 @@ static int pwm_unexport_child(struct device *parent, struct pwm_device *pwm) | |||
| 297 | if (!child) | 302 | if (!child) |
| 298 | return -ENODEV; | 303 | return -ENODEV; |
| 299 | 304 | ||
| 305 | pwm_prop[0] = kasprintf(GFP_KERNEL, "UNEXPORT=pwm%u", pwm->hwpwm); | ||
| 306 | pwm_prop[1] = NULL; | ||
| 307 | kobject_uevent_env(&parent->kobj, KOBJ_CHANGE, pwm_prop); | ||
| 308 | kfree(pwm_prop[0]); | ||
| 309 | |||
| 300 | /* for device_find_child() */ | 310 | /* for device_find_child() */ |
| 301 | put_device(child); | 311 | put_device(child); |
| 302 | device_unregister(child); | 312 | device_unregister(child); |
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 05293babb031..2d655a97b959 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
| @@ -143,7 +143,9 @@ static int twa_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int secon | |||
| 143 | static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); | 143 | static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, char internal); |
| 144 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev); | 144 | static int twa_reset_device_extension(TW_Device_Extension *tw_dev); |
| 145 | static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); | 145 | static int twa_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset); |
| 146 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg); | 146 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, |
| 147 | unsigned char *cdb, int use_sg, | ||
| 148 | TW_SG_Entry *sglistarg); | ||
| 147 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); | 149 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id); |
| 148 | static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); | 150 | static char *twa_string_lookup(twa_message_type *table, unsigned int aen_code); |
| 149 | 151 | ||
| @@ -278,7 +280,7 @@ out: | |||
| 278 | static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) | 280 | static int twa_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) |
| 279 | { | 281 | { |
| 280 | int request_id = 0; | 282 | int request_id = 0; |
| 281 | char cdb[TW_MAX_CDB_LEN]; | 283 | unsigned char cdb[TW_MAX_CDB_LEN]; |
| 282 | TW_SG_Entry sglist[1]; | 284 | TW_SG_Entry sglist[1]; |
| 283 | int finished = 0, count = 0; | 285 | int finished = 0, count = 0; |
| 284 | TW_Command_Full *full_command_packet; | 286 | TW_Command_Full *full_command_packet; |
| @@ -423,7 +425,7 @@ static void twa_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_H | |||
| 423 | /* This function will read the aen queue from the isr */ | 425 | /* This function will read the aen queue from the isr */ |
| 424 | static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) | 426 | static int twa_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) |
| 425 | { | 427 | { |
| 426 | char cdb[TW_MAX_CDB_LEN]; | 428 | unsigned char cdb[TW_MAX_CDB_LEN]; |
| 427 | TW_SG_Entry sglist[1]; | 429 | TW_SG_Entry sglist[1]; |
| 428 | TW_Command_Full *full_command_packet; | 430 | TW_Command_Full *full_command_packet; |
| 429 | int retval = 1; | 431 | int retval = 1; |
| @@ -1798,7 +1800,9 @@ out: | |||
| 1798 | static DEF_SCSI_QCMD(twa_scsi_queue) | 1800 | static DEF_SCSI_QCMD(twa_scsi_queue) |
| 1799 | 1801 | ||
| 1800 | /* This function hands scsi cdb's to the firmware */ | 1802 | /* This function hands scsi cdb's to the firmware */ |
| 1801 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry *sglistarg) | 1803 | static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, |
| 1804 | unsigned char *cdb, int use_sg, | ||
| 1805 | TW_SG_Entry *sglistarg) | ||
| 1802 | { | 1806 | { |
| 1803 | TW_Command_Full *full_command_packet; | 1807 | TW_Command_Full *full_command_packet; |
| 1804 | TW_Command_Apache *command_packet; | 1808 | TW_Command_Apache *command_packet; |
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c index 266bdac75304..480cf82700e9 100644 --- a/drivers/scsi/3w-sas.c +++ b/drivers/scsi/3w-sas.c | |||
| @@ -287,7 +287,9 @@ static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id) | |||
| 287 | } /* End twl_post_command_packet() */ | 287 | } /* End twl_post_command_packet() */ |
| 288 | 288 | ||
| 289 | /* This function hands scsi cdb's to the firmware */ | 289 | /* This function hands scsi cdb's to the firmware */ |
| 290 | static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg) | 290 | static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, |
| 291 | unsigned char *cdb, int use_sg, | ||
| 292 | TW_SG_Entry_ISO *sglistarg) | ||
| 291 | { | 293 | { |
| 292 | TW_Command_Full *full_command_packet; | 294 | TW_Command_Full *full_command_packet; |
| 293 | TW_Command_Apache *command_packet; | 295 | TW_Command_Apache *command_packet; |
| @@ -372,7 +374,7 @@ out: | |||
| 372 | /* This function will read the aen queue from the isr */ | 374 | /* This function will read the aen queue from the isr */ |
| 373 | static int twl_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) | 375 | static int twl_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) |
| 374 | { | 376 | { |
| 375 | char cdb[TW_MAX_CDB_LEN]; | 377 | unsigned char cdb[TW_MAX_CDB_LEN]; |
| 376 | TW_SG_Entry_ISO sglist[1]; | 378 | TW_SG_Entry_ISO sglist[1]; |
| 377 | TW_Command_Full *full_command_packet; | 379 | TW_Command_Full *full_command_packet; |
| 378 | int retval = 1; | 380 | int retval = 1; |
| @@ -554,7 +556,7 @@ out: | |||
| 554 | static int twl_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) | 556 | static int twl_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset) |
| 555 | { | 557 | { |
| 556 | int request_id = 0; | 558 | int request_id = 0; |
| 557 | char cdb[TW_MAX_CDB_LEN]; | 559 | unsigned char cdb[TW_MAX_CDB_LEN]; |
| 558 | TW_SG_Entry_ISO sglist[1]; | 560 | TW_SG_Entry_ISO sglist[1]; |
| 559 | int finished = 0, count = 0; | 561 | int finished = 0, count = 0; |
| 560 | TW_Command_Full *full_command_packet; | 562 | TW_Command_Full *full_command_packet; |
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 70988c381268..f07444d30b21 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
| @@ -538,7 +538,7 @@ config SCSI_HPTIOP | |||
| 538 | 538 | ||
| 539 | config SCSI_BUSLOGIC | 539 | config SCSI_BUSLOGIC |
| 540 | tristate "BusLogic SCSI support" | 540 | tristate "BusLogic SCSI support" |
| 541 | depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API && VIRT_TO_BUS | 541 | depends on (PCI || ISA) && SCSI && ISA_DMA_API && VIRT_TO_BUS |
| 542 | ---help--- | 542 | ---help--- |
| 543 | This is support for BusLogic MultiMaster and FlashPoint SCSI Host | 543 | This is support for BusLogic MultiMaster and FlashPoint SCSI Host |
| 544 | Adapters. Consult the SCSI-HOWTO, available from | 544 | Adapters. Consult the SCSI-HOWTO, available from |
| @@ -1175,12 +1175,12 @@ config SCSI_LPFC_DEBUG_FS | |||
| 1175 | 1175 | ||
| 1176 | config SCSI_SIM710 | 1176 | config SCSI_SIM710 |
| 1177 | tristate "Simple 53c710 SCSI support (Compaq, NCR machines)" | 1177 | tristate "Simple 53c710 SCSI support (Compaq, NCR machines)" |
| 1178 | depends on (EISA || MCA) && SCSI | 1178 | depends on EISA && SCSI |
| 1179 | select SCSI_SPI_ATTRS | 1179 | select SCSI_SPI_ATTRS |
| 1180 | ---help--- | 1180 | ---help--- |
| 1181 | This driver is for NCR53c710 based SCSI host adapters. | 1181 | This driver is for NCR53c710 based SCSI host adapters. |
| 1182 | 1182 | ||
| 1183 | It currently supports Compaq EISA cards and NCR MCA cards | 1183 | It currently supports Compaq EISA cards. |
| 1184 | 1184 | ||
| 1185 | config SCSI_DC395x | 1185 | config SCSI_DC395x |
| 1186 | tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support" | 1186 | tristate "Tekram DC395(U/UW/F) and DC315(U) SCSI support" |
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 4d7b0e0adbf7..301b3cad15f8 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c | |||
| @@ -269,7 +269,7 @@ static LIST_HEAD(aha152x_host_list); | |||
| 269 | /* DEFINES */ | 269 | /* DEFINES */ |
| 270 | 270 | ||
| 271 | /* For PCMCIA cards, always use AUTOCONF */ | 271 | /* For PCMCIA cards, always use AUTOCONF */ |
| 272 | #if defined(PCMCIA) || defined(MODULE) | 272 | #if defined(AHA152X_PCMCIA) || defined(MODULE) |
| 273 | #if !defined(AUTOCONF) | 273 | #if !defined(AUTOCONF) |
| 274 | #define AUTOCONF | 274 | #define AUTOCONF |
| 275 | #endif | 275 | #endif |
| @@ -297,7 +297,7 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int inc) | |||
| 297 | 297 | ||
| 298 | #define DELAY_DEFAULT 1000 | 298 | #define DELAY_DEFAULT 1000 |
| 299 | 299 | ||
| 300 | #if defined(PCMCIA) | 300 | #if defined(AHA152X_PCMCIA) |
| 301 | #define IRQ_MIN 0 | 301 | #define IRQ_MIN 0 |
| 302 | #define IRQ_MAX 16 | 302 | #define IRQ_MAX 16 |
| 303 | #else | 303 | #else |
| @@ -328,7 +328,7 @@ MODULE_AUTHOR("Jürgen Fischer"); | |||
| 328 | MODULE_DESCRIPTION(AHA152X_REVID); | 328 | MODULE_DESCRIPTION(AHA152X_REVID); |
| 329 | MODULE_LICENSE("GPL"); | 329 | MODULE_LICENSE("GPL"); |
| 330 | 330 | ||
| 331 | #if !defined(PCMCIA) | 331 | #if !defined(AHA152X_PCMCIA) |
| 332 | #if defined(MODULE) | 332 | #if defined(MODULE) |
| 333 | static int io[] = {0, 0}; | 333 | static int io[] = {0, 0}; |
| 334 | module_param_hw_array(io, int, ioport, NULL, 0); | 334 | module_param_hw_array(io, int, ioport, NULL, 0); |
| @@ -391,7 +391,7 @@ static struct isapnp_device_id id_table[] = { | |||
| 391 | MODULE_DEVICE_TABLE(isapnp, id_table); | 391 | MODULE_DEVICE_TABLE(isapnp, id_table); |
| 392 | #endif /* ISAPNP */ | 392 | #endif /* ISAPNP */ |
| 393 | 393 | ||
| 394 | #endif /* !PCMCIA */ | 394 | #endif /* !AHA152X_PCMCIA */ |
| 395 | 395 | ||
| 396 | static struct scsi_host_template aha152x_driver_template; | 396 | static struct scsi_host_template aha152x_driver_template; |
| 397 | 397 | ||
| @@ -863,7 +863,7 @@ void aha152x_release(struct Scsi_Host *shpnt) | |||
| 863 | if (shpnt->irq) | 863 | if (shpnt->irq) |
| 864 | free_irq(shpnt->irq, shpnt); | 864 | free_irq(shpnt->irq, shpnt); |
| 865 | 865 | ||
| 866 | #if !defined(PCMCIA) | 866 | #if !defined(AHA152X_PCMCIA) |
| 867 | if (shpnt->io_port) | 867 | if (shpnt->io_port) |
| 868 | release_region(shpnt->io_port, IO_RANGE); | 868 | release_region(shpnt->io_port, IO_RANGE); |
| 869 | #endif | 869 | #endif |
| @@ -2924,7 +2924,7 @@ static struct scsi_host_template aha152x_driver_template = { | |||
| 2924 | .slave_alloc = aha152x_adjust_queue, | 2924 | .slave_alloc = aha152x_adjust_queue, |
| 2925 | }; | 2925 | }; |
| 2926 | 2926 | ||
| 2927 | #if !defined(PCMCIA) | 2927 | #if !defined(AHA152X_PCMCIA) |
| 2928 | static int setup_count; | 2928 | static int setup_count; |
| 2929 | static struct aha152x_setup setup[2]; | 2929 | static struct aha152x_setup setup[2]; |
| 2930 | 2930 | ||
| @@ -3392,4 +3392,4 @@ static int __init aha152x_setup(char *str) | |||
| 3392 | __setup("aha152x=", aha152x_setup); | 3392 | __setup("aha152x=", aha152x_setup); |
| 3393 | #endif | 3393 | #endif |
| 3394 | 3394 | ||
| 3395 | #endif /* !PCMCIA */ | 3395 | #endif /* !AHA152X_PCMCIA */ |
diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index 3df1428df317..311d23c727ce 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c | |||
| @@ -790,12 +790,11 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf | |||
| 790 | slot->n_elem = n_elem; | 790 | slot->n_elem = n_elem; |
| 791 | slot->slot_tag = tag; | 791 | slot->slot_tag = tag; |
| 792 | 792 | ||
| 793 | slot->buf = dma_pool_alloc(mvi->dma_pool, GFP_ATOMIC, &slot->buf_dma); | 793 | slot->buf = dma_pool_zalloc(mvi->dma_pool, GFP_ATOMIC, &slot->buf_dma); |
| 794 | if (!slot->buf) { | 794 | if (!slot->buf) { |
| 795 | rc = -ENOMEM; | 795 | rc = -ENOMEM; |
| 796 | goto err_out_tag; | 796 | goto err_out_tag; |
| 797 | } | 797 | } |
| 798 | memset(slot->buf, 0, MVS_SLOT_BUF_SZ); | ||
| 799 | 798 | ||
| 800 | tei.task = task; | 799 | tei.task = task; |
| 801 | tei.hdr = &mvi->slot[tag]; | 800 | tei.hdr = &mvi->slot[tag]; |
| @@ -1906,8 +1905,7 @@ static void mvs_work_queue(struct work_struct *work) | |||
| 1906 | 1905 | ||
| 1907 | if (phy->phy_event & PHY_PLUG_OUT) { | 1906 | if (phy->phy_event & PHY_PLUG_OUT) { |
| 1908 | u32 tmp; | 1907 | u32 tmp; |
| 1909 | struct sas_identify_frame *id; | 1908 | |
| 1910 | id = (struct sas_identify_frame *)phy->frame_rcvd; | ||
| 1911 | tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no); | 1909 | tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no); |
| 1912 | phy->phy_event &= ~PHY_PLUG_OUT; | 1910 | phy->phy_event &= ~PHY_PLUG_OUT; |
| 1913 | if (!(tmp & PHY_READY_MASK)) { | 1911 | if (!(tmp & PHY_READY_MASK)) { |
diff --git a/drivers/scsi/pcmcia/aha152x_core.c b/drivers/scsi/pcmcia/aha152x_core.c index dba3716511c5..24b89228b241 100644 --- a/drivers/scsi/pcmcia/aha152x_core.c +++ b/drivers/scsi/pcmcia/aha152x_core.c | |||
| @@ -1,3 +1,3 @@ | |||
| 1 | #define PCMCIA 1 | 1 | #define AHA152X_PCMCIA 1 |
| 2 | #define AHA152X_STAT 1 | 2 | #define AHA152X_STAT 1 |
| 3 | #include "aha152x.c" | 3 | #include "aha152x.c" |
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index b28f159fdaee..0bb9ac6ece92 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c | |||
| @@ -218,7 +218,7 @@ qla2x00_sysfs_write_nvram(struct file *filp, struct kobject *kobj, | |||
| 218 | 218 | ||
| 219 | mutex_lock(&ha->optrom_mutex); | 219 | mutex_lock(&ha->optrom_mutex); |
| 220 | if (qla2x00_chip_is_down(vha)) { | 220 | if (qla2x00_chip_is_down(vha)) { |
| 221 | mutex_unlock(&vha->hw->optrom_mutex); | 221 | mutex_unlock(&ha->optrom_mutex); |
| 222 | return -EAGAIN; | 222 | return -EAGAIN; |
| 223 | } | 223 | } |
| 224 | 224 | ||
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index c72d8012fe2a..6fe20c27acc1 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
| @@ -425,7 +425,7 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea) | |||
| 425 | __qla24xx_handle_gpdb_event(vha, ea); | 425 | __qla24xx_handle_gpdb_event(vha, ea); |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport) | 428 | static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport) |
| 429 | { | 429 | { |
| 430 | struct qla_work_evt *e; | 430 | struct qla_work_evt *e; |
| 431 | 431 | ||
| @@ -680,7 +680,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, | |||
| 680 | fcport); | 680 | fcport); |
| 681 | break; | 681 | break; |
| 682 | } | 682 | } |
| 683 | /* drop through */ | 683 | /* fall through */ |
| 684 | default: | 684 | default: |
| 685 | if (fcport_is_smaller(fcport)) { | 685 | if (fcport_is_smaller(fcport)) { |
| 686 | /* local adapter is bigger */ | 686 | /* local adapter is bigger */ |
| @@ -1551,7 +1551,8 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha, | |||
| 1551 | } | 1551 | } |
| 1552 | 1552 | ||
| 1553 | 1553 | ||
| 1554 | void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea) | 1554 | static void qla_handle_els_plogi_done(scsi_qla_host_t *vha, |
| 1555 | struct event_arg *ea) | ||
| 1555 | { | 1556 | { |
| 1556 | ql_dbg(ql_dbg_disc, vha, 0x2118, | 1557 | ql_dbg(ql_dbg_disc, vha, 0x2118, |
| 1557 | "%s %d %8phC post PRLI\n", | 1558 | "%s %d %8phC post PRLI\n", |
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 86fb8b21aa71..032635321ad6 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
| @@ -1195,8 +1195,8 @@ qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, | |||
| 1195 | * @sp: SRB command to process | 1195 | * @sp: SRB command to process |
| 1196 | * @cmd_pkt: Command type 3 IOCB | 1196 | * @cmd_pkt: Command type 3 IOCB |
| 1197 | * @tot_dsds: Total number of segments to transfer | 1197 | * @tot_dsds: Total number of segments to transfer |
| 1198 | * @tot_prot_dsds: | 1198 | * @tot_prot_dsds: Total number of segments with protection information |
| 1199 | * @fw_prot_opts: | 1199 | * @fw_prot_opts: Protection options to be passed to firmware |
| 1200 | */ | 1200 | */ |
| 1201 | inline int | 1201 | inline int |
| 1202 | qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, | 1202 | qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d73b04e40590..30d3090842f8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
| @@ -25,7 +25,7 @@ static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *, | |||
| 25 | 25 | ||
| 26 | /** | 26 | /** |
| 27 | * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. | 27 | * qla2100_intr_handler() - Process interrupts for the ISP2100 and ISP2200. |
| 28 | * @irq: | 28 | * @irq: interrupt number |
| 29 | * @dev_id: SCSI driver HA context | 29 | * @dev_id: SCSI driver HA context |
| 30 | * | 30 | * |
| 31 | * Called by system whenever the host adapter generates an interrupt. | 31 | * Called by system whenever the host adapter generates an interrupt. |
| @@ -144,7 +144,7 @@ qla2x00_check_reg16_for_disconnect(scsi_qla_host_t *vha, uint16_t reg) | |||
| 144 | 144 | ||
| 145 | /** | 145 | /** |
| 146 | * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. | 146 | * qla2300_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. |
| 147 | * @irq: | 147 | * @irq: interrupt number |
| 148 | * @dev_id: SCSI driver HA context | 148 | * @dev_id: SCSI driver HA context |
| 149 | * | 149 | * |
| 150 | * Called by system whenever the host adapter generates an interrupt. | 150 | * Called by system whenever the host adapter generates an interrupt. |
| @@ -3109,7 +3109,7 @@ done: | |||
| 3109 | 3109 | ||
| 3110 | /** | 3110 | /** |
| 3111 | * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP24xx. | 3111 | * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP24xx. |
| 3112 | * @irq: | 3112 | * @irq: interrupt number |
| 3113 | * @dev_id: SCSI driver HA context | 3113 | * @dev_id: SCSI driver HA context |
| 3114 | * | 3114 | * |
| 3115 | * Called by system whenever the host adapter generates an interrupt. | 3115 | * Called by system whenever the host adapter generates an interrupt. |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 2f3e5075ae76..191b6b7c8747 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
| @@ -3478,9 +3478,9 @@ qla8044_read_serdes_word(scsi_qla_host_t *vha, uint32_t addr, uint32_t *data) | |||
| 3478 | /** | 3478 | /** |
| 3479 | * qla2x00_set_serdes_params() - | 3479 | * qla2x00_set_serdes_params() - |
| 3480 | * @vha: HA context | 3480 | * @vha: HA context |
| 3481 | * @sw_em_1g: | 3481 | * @sw_em_1g: serial link options |
| 3482 | * @sw_em_2g: | 3482 | * @sw_em_2g: serial link options |
| 3483 | * @sw_em_4g: | 3483 | * @sw_em_4g: serial link options |
| 3484 | * | 3484 | * |
| 3485 | * Returns | 3485 | * Returns |
| 3486 | */ | 3486 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index 521a51370554..60f964c53c01 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c | |||
| @@ -2212,7 +2212,7 @@ qlafx00_ioctl_iosb_entry(scsi_qla_host_t *vha, struct req_que *req, | |||
| 2212 | struct bsg_job *bsg_job; | 2212 | struct bsg_job *bsg_job; |
| 2213 | struct fc_bsg_reply *bsg_reply; | 2213 | struct fc_bsg_reply *bsg_reply; |
| 2214 | struct srb_iocb *iocb_job; | 2214 | struct srb_iocb *iocb_job; |
| 2215 | int res; | 2215 | int res = 0; |
| 2216 | struct qla_mt_iocb_rsp_fx00 fstatus; | 2216 | struct qla_mt_iocb_rsp_fx00 fstatus; |
| 2217 | uint8_t *fw_sts_ptr; | 2217 | uint8_t *fw_sts_ptr; |
| 2218 | 2218 | ||
| @@ -2624,7 +2624,7 @@ qlafx00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt) | |||
| 2624 | * qlafx00_multistatus_entry() - Process Multi response queue entries. | 2624 | * qlafx00_multistatus_entry() - Process Multi response queue entries. |
| 2625 | * @vha: SCSI driver HA context | 2625 | * @vha: SCSI driver HA context |
| 2626 | * @rsp: response queue | 2626 | * @rsp: response queue |
| 2627 | * @pkt: | 2627 | * @pkt: received packet |
| 2628 | */ | 2628 | */ |
| 2629 | static void | 2629 | static void |
| 2630 | qlafx00_multistatus_entry(struct scsi_qla_host *vha, | 2630 | qlafx00_multistatus_entry(struct scsi_qla_host *vha, |
| @@ -2681,12 +2681,10 @@ qlafx00_multistatus_entry(struct scsi_qla_host *vha, | |||
| 2681 | * @vha: SCSI driver HA context | 2681 | * @vha: SCSI driver HA context |
| 2682 | * @rsp: response queue | 2682 | * @rsp: response queue |
| 2683 | * @pkt: Entry pointer | 2683 | * @pkt: Entry pointer |
| 2684 | * @estatus: | ||
| 2685 | * @etype: | ||
| 2686 | */ | 2684 | */ |
| 2687 | static void | 2685 | static void |
| 2688 | qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, | 2686 | qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, |
| 2689 | struct sts_entry_fx00 *pkt, uint8_t estatus, uint8_t etype) | 2687 | struct sts_entry_fx00 *pkt) |
| 2690 | { | 2688 | { |
| 2691 | srb_t *sp; | 2689 | srb_t *sp; |
| 2692 | struct qla_hw_data *ha = vha->hw; | 2690 | struct qla_hw_data *ha = vha->hw; |
| @@ -2695,9 +2693,6 @@ qlafx00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, | |||
| 2695 | struct req_que *req = NULL; | 2693 | struct req_que *req = NULL; |
| 2696 | int res = DID_ERROR << 16; | 2694 | int res = DID_ERROR << 16; |
| 2697 | 2695 | ||
| 2698 | ql_dbg(ql_dbg_async, vha, 0x507f, | ||
| 2699 | "type of error status in response: 0x%x\n", estatus); | ||
| 2700 | |||
| 2701 | req = ha->req_q_map[que]; | 2696 | req = ha->req_q_map[que]; |
| 2702 | 2697 | ||
| 2703 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); | 2698 | sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); |
| @@ -2745,9 +2740,11 @@ qlafx00_process_response_queue(struct scsi_qla_host *vha, | |||
| 2745 | 2740 | ||
| 2746 | if (pkt->entry_status != 0 && | 2741 | if (pkt->entry_status != 0 && |
| 2747 | pkt->entry_type != IOCTL_IOSB_TYPE_FX00) { | 2742 | pkt->entry_type != IOCTL_IOSB_TYPE_FX00) { |
| 2743 | ql_dbg(ql_dbg_async, vha, 0x507f, | ||
| 2744 | "type of error status in response: 0x%x\n", | ||
| 2745 | pkt->entry_status); | ||
| 2748 | qlafx00_error_entry(vha, rsp, | 2746 | qlafx00_error_entry(vha, rsp, |
| 2749 | (struct sts_entry_fx00 *)pkt, pkt->entry_status, | 2747 | (struct sts_entry_fx00 *)pkt); |
| 2750 | pkt->entry_type); | ||
| 2751 | continue; | 2748 | continue; |
| 2752 | } | 2749 | } |
| 2753 | 2750 | ||
| @@ -2867,7 +2864,7 @@ qlafx00_async_event(scsi_qla_host_t *vha) | |||
| 2867 | /** | 2864 | /** |
| 2868 | * qlafx00x_mbx_completion() - Process mailbox command completions. | 2865 | * qlafx00x_mbx_completion() - Process mailbox command completions. |
| 2869 | * @vha: SCSI driver HA context | 2866 | * @vha: SCSI driver HA context |
| 2870 | * @mb0: | 2867 | * @mb0: value to be written into mailbox register 0 |
| 2871 | */ | 2868 | */ |
| 2872 | static void | 2869 | static void |
| 2873 | qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0) | 2870 | qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0) |
| @@ -2893,7 +2890,7 @@ qlafx00_mbx_completion(scsi_qla_host_t *vha, uint32_t mb0) | |||
| 2893 | 2890 | ||
| 2894 | /** | 2891 | /** |
| 2895 | * qlafx00_intr_handler() - Process interrupts for the ISPFX00. | 2892 | * qlafx00_intr_handler() - Process interrupts for the ISPFX00. |
| 2896 | * @irq: | 2893 | * @irq: interrupt number |
| 2897 | * @dev_id: SCSI driver HA context | 2894 | * @dev_id: SCSI driver HA context |
| 2898 | * | 2895 | * |
| 2899 | * Called by system whenever the host adapter generates an interrupt. | 2896 | * Called by system whenever the host adapter generates an interrupt. |
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c index 121e18b3b9f8..f2f54806f4da 100644 --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c | |||
| @@ -2010,7 +2010,7 @@ qla82xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0) | |||
| 2010 | 2010 | ||
| 2011 | /** | 2011 | /** |
| 2012 | * qla82xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. | 2012 | * qla82xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. |
| 2013 | * @irq: | 2013 | * @irq: interrupt number |
| 2014 | * @dev_id: SCSI driver HA context | 2014 | * @dev_id: SCSI driver HA context |
| 2015 | * | 2015 | * |
| 2016 | * Called by system whenever the host adapter generates an interrupt. | 2016 | * Called by system whenever the host adapter generates an interrupt. |
diff --git a/drivers/scsi/qla2xxx/qla_nx2.c b/drivers/scsi/qla2xxx/qla_nx2.c index 3a2b0282df14..fe856b602e03 100644 --- a/drivers/scsi/qla2xxx/qla_nx2.c +++ b/drivers/scsi/qla2xxx/qla_nx2.c | |||
| @@ -3878,7 +3878,7 @@ out: | |||
| 3878 | #define PF_BITS_MASK (0xF << 16) | 3878 | #define PF_BITS_MASK (0xF << 16) |
| 3879 | /** | 3879 | /** |
| 3880 | * qla8044_intr_handler() - Process interrupts for the ISP8044 | 3880 | * qla8044_intr_handler() - Process interrupts for the ISP8044 |
| 3881 | * @irq: | 3881 | * @irq: interrupt number |
| 3882 | * @dev_id: SCSI driver HA context | 3882 | * @dev_id: SCSI driver HA context |
| 3883 | * | 3883 | * |
| 3884 | * Called by system whenever the host adapter generates an interrupt. | 3884 | * Called by system whenever the host adapter generates an interrupt. |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 8794e54f43a9..518f15141170 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
| @@ -1749,7 +1749,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha) | |||
| 1749 | static void | 1749 | static void |
| 1750 | __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) | 1750 | __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) |
| 1751 | { | 1751 | { |
| 1752 | int cnt, status; | 1752 | int cnt; |
| 1753 | unsigned long flags; | 1753 | unsigned long flags; |
| 1754 | srb_t *sp; | 1754 | srb_t *sp; |
| 1755 | scsi_qla_host_t *vha = qp->vha; | 1755 | scsi_qla_host_t *vha = qp->vha; |
| @@ -1799,8 +1799,8 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res) | |||
| 1799 | if (!sp_get(sp)) { | 1799 | if (!sp_get(sp)) { |
| 1800 | spin_unlock_irqrestore | 1800 | spin_unlock_irqrestore |
| 1801 | (qp->qp_lock_ptr, flags); | 1801 | (qp->qp_lock_ptr, flags); |
| 1802 | status = qla2xxx_eh_abort( | 1802 | qla2xxx_eh_abort( |
| 1803 | GET_CMD_SP(sp)); | 1803 | GET_CMD_SP(sp)); |
| 1804 | spin_lock_irqsave | 1804 | spin_lock_irqsave |
| 1805 | (qp->qp_lock_ptr, flags); | 1805 | (qp->qp_lock_ptr, flags); |
| 1806 | } | 1806 | } |
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index 4499c787165f..2a3055c799fb 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
| @@ -2229,7 +2229,7 @@ qla2x00_erase_flash_sector(struct qla_hw_data *ha, uint32_t addr, | |||
| 2229 | 2229 | ||
| 2230 | /** | 2230 | /** |
| 2231 | * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. | 2231 | * qla2x00_get_flash_manufacturer() - Read manufacturer ID from flash chip. |
| 2232 | * @ha: | 2232 | * @ha: host adapter |
| 2233 | * @man_id: Flash manufacturer ID | 2233 | * @man_id: Flash manufacturer ID |
| 2234 | * @flash_id: Flash ID | 2234 | * @flash_id: Flash ID |
| 2235 | */ | 2235 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 39828207bc1d..c4504740f0e2 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
| @@ -4540,7 +4540,7 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, | |||
| 4540 | case QLA_TGT_CLEAR_TS: | 4540 | case QLA_TGT_CLEAR_TS: |
| 4541 | case QLA_TGT_ABORT_TS: | 4541 | case QLA_TGT_ABORT_TS: |
| 4542 | abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); | 4542 | abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); |
| 4543 | /* drop through */ | 4543 | /* fall through */ |
| 4544 | case QLA_TGT_CLEAR_ACA: | 4544 | case QLA_TGT_CLEAR_ACA: |
| 4545 | h = qlt_find_qphint(vha, mcmd->unpacked_lun); | 4545 | h = qlt_find_qphint(vha, mcmd->unpacked_lun); |
| 4546 | mcmd->qpair = h->qpair; | 4546 | mcmd->qpair = h->qpair; |
| @@ -6598,9 +6598,9 @@ static void qlt_lport_dump(struct scsi_qla_host *vha, u64 wwpn, | |||
| 6598 | * qla_tgt_lport_register - register lport with external module | 6598 | * qla_tgt_lport_register - register lport with external module |
| 6599 | * | 6599 | * |
| 6600 | * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data | 6600 | * @target_lport_ptr: pointer for tcm_qla2xxx specific lport data |
| 6601 | * @phys_wwpn: | 6601 | * @phys_wwpn: physical port WWPN |
| 6602 | * @npiv_wwpn: | 6602 | * @npiv_wwpn: NPIV WWPN |
| 6603 | * @npiv_wwnn: | 6603 | * @npiv_wwnn: NPIV WWNN |
| 6604 | * @callback: lport initialization callback for tcm_qla2xxx code | 6604 | * @callback: lport initialization callback for tcm_qla2xxx code |
| 6605 | */ | 6605 | */ |
| 6606 | int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, | 6606 | int qlt_lport_register(void *target_lport_ptr, u64 phys_wwpn, |
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index e46ca968009c..4f134b0c3e29 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
| @@ -268,7 +268,7 @@ target_emulate_report_target_port_groups(struct se_cmd *cmd) | |||
| 268 | } | 268 | } |
| 269 | transport_kunmap_data_sg(cmd); | 269 | transport_kunmap_data_sg(cmd); |
| 270 | 270 | ||
| 271 | target_complete_cmd(cmd, GOOD); | 271 | target_complete_cmd_with_length(cmd, GOOD, rd_len + 4); |
| 272 | return 0; | 272 | return 0; |
| 273 | } | 273 | } |
| 274 | 274 | ||
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 4cf33e2cc705..e31e4fc31aa1 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -205,19 +205,19 @@ void transport_subsystem_check_init(void) | |||
| 205 | if (sub_api_initialized) | 205 | if (sub_api_initialized) |
| 206 | return; | 206 | return; |
| 207 | 207 | ||
| 208 | ret = request_module("target_core_iblock"); | 208 | ret = IS_ENABLED(CONFIG_TCM_IBLOCK) && request_module("target_core_iblock"); |
| 209 | if (ret != 0) | 209 | if (ret != 0) |
| 210 | pr_err("Unable to load target_core_iblock\n"); | 210 | pr_err("Unable to load target_core_iblock\n"); |
| 211 | 211 | ||
| 212 | ret = request_module("target_core_file"); | 212 | ret = IS_ENABLED(CONFIG_TCM_FILEIO) && request_module("target_core_file"); |
| 213 | if (ret != 0) | 213 | if (ret != 0) |
| 214 | pr_err("Unable to load target_core_file\n"); | 214 | pr_err("Unable to load target_core_file\n"); |
| 215 | 215 | ||
| 216 | ret = request_module("target_core_pscsi"); | 216 | ret = IS_ENABLED(CONFIG_TCM_PSCSI) && request_module("target_core_pscsi"); |
| 217 | if (ret != 0) | 217 | if (ret != 0) |
| 218 | pr_err("Unable to load target_core_pscsi\n"); | 218 | pr_err("Unable to load target_core_pscsi\n"); |
| 219 | 219 | ||
| 220 | ret = request_module("target_core_user"); | 220 | ret = IS_ENABLED(CONFIG_TCM_USER2) && request_module("target_core_user"); |
| 221 | if (ret != 0) | 221 | if (ret != 0) |
| 222 | pr_err("Unable to load target_core_user\n"); | 222 | pr_err("Unable to load target_core_user\n"); |
| 223 | 223 | ||
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 9a69392f1fb3..d81c148682e7 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
| @@ -350,7 +350,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 350 | 350 | ||
| 351 | s->s_magic = BFS_MAGIC; | 351 | s->s_magic = BFS_MAGIC; |
| 352 | 352 | ||
| 353 | if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) { | 353 | if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end) || |
| 354 | le32_to_cpu(bfs_sb->s_start) < BFS_BSIZE) { | ||
| 354 | printf("Superblock is corrupted\n"); | 355 | printf("Superblock is corrupted\n"); |
| 355 | goto out1; | 356 | goto out1; |
| 356 | } | 357 | } |
| @@ -359,9 +360,11 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) | |||
| 359 | sizeof(struct bfs_inode) | 360 | sizeof(struct bfs_inode) |
| 360 | + BFS_ROOT_INO - 1; | 361 | + BFS_ROOT_INO - 1; |
| 361 | imap_len = (info->si_lasti / 8) + 1; | 362 | imap_len = (info->si_lasti / 8) + 1; |
| 362 | info->si_imap = kzalloc(imap_len, GFP_KERNEL); | 363 | info->si_imap = kzalloc(imap_len, GFP_KERNEL | __GFP_NOWARN); |
| 363 | if (!info->si_imap) | 364 | if (!info->si_imap) { |
| 365 | printf("Cannot allocate %u bytes\n", imap_len); | ||
| 364 | goto out1; | 366 | goto out1; |
| 367 | } | ||
| 365 | for (i = 0; i < BFS_ROOT_INO; i++) | 368 | for (i = 0; i < BFS_ROOT_INO; i++) |
| 366 | set_bit(i, info->si_imap); | 369 | set_bit(i, info->si_imap); |
| 367 | 370 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 68ca41dbbef3..80953528572d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -3201,9 +3201,6 @@ void btrfs_get_block_group_info(struct list_head *groups_list, | |||
| 3201 | struct btrfs_ioctl_space_info *space); | 3201 | struct btrfs_ioctl_space_info *space); |
| 3202 | void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info, | 3202 | void btrfs_update_ioctl_balance_args(struct btrfs_fs_info *fs_info, |
| 3203 | struct btrfs_ioctl_balance_args *bargs); | 3203 | struct btrfs_ioctl_balance_args *bargs); |
| 3204 | int btrfs_dedupe_file_range(struct file *src_file, loff_t src_loff, | ||
| 3205 | struct file *dst_file, loff_t dst_loff, | ||
| 3206 | u64 olen); | ||
| 3207 | 3204 | ||
| 3208 | /* file.c */ | 3205 | /* file.c */ |
| 3209 | int __init btrfs_auto_defrag_init(void); | 3206 | int __init btrfs_auto_defrag_init(void); |
| @@ -3233,8 +3230,9 @@ int btrfs_dirty_pages(struct inode *inode, struct page **pages, | |||
| 3233 | size_t num_pages, loff_t pos, size_t write_bytes, | 3230 | size_t num_pages, loff_t pos, size_t write_bytes, |
| 3234 | struct extent_state **cached); | 3231 | struct extent_state **cached); |
| 3235 | int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end); | 3232 | int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end); |
| 3236 | int btrfs_clone_file_range(struct file *file_in, loff_t pos_in, | 3233 | loff_t btrfs_remap_file_range(struct file *file_in, loff_t pos_in, |
| 3237 | struct file *file_out, loff_t pos_out, u64 len); | 3234 | struct file *file_out, loff_t pos_out, |
| 3235 | loff_t len, unsigned int remap_flags); | ||
| 3238 | 3236 | ||
| 3239 | /* tree-defrag.c */ | 3237 | /* tree-defrag.c */ |
| 3240 | int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, | 3238 | int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 97c7a086f7bd..a3c22e16509b 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -3298,8 +3298,7 @@ const struct file_operations btrfs_file_operations = { | |||
| 3298 | #ifdef CONFIG_COMPAT | 3298 | #ifdef CONFIG_COMPAT |
| 3299 | .compat_ioctl = btrfs_compat_ioctl, | 3299 | .compat_ioctl = btrfs_compat_ioctl, |
| 3300 | #endif | 3300 | #endif |
| 3301 | .clone_file_range = btrfs_clone_file_range, | 3301 | .remap_file_range = btrfs_remap_file_range, |
| 3302 | .dedupe_file_range = btrfs_dedupe_file_range, | ||
| 3303 | }; | 3302 | }; |
| 3304 | 3303 | ||
| 3305 | void __cold btrfs_auto_defrag_exit(void) | 3304 | void __cold btrfs_auto_defrag_exit(void) |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index a990a9045139..3ca6943827ef 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -3629,26 +3629,6 @@ out_unlock: | |||
| 3629 | return ret; | 3629 | return ret; |
| 3630 | } | 3630 | } |
| 3631 | 3631 | ||
| 3632 | int btrfs_dedupe_file_range(struct file *src_file, loff_t src_loff, | ||
| 3633 | struct file *dst_file, loff_t dst_loff, | ||
| 3634 | u64 olen) | ||
| 3635 | { | ||
| 3636 | struct inode *src = file_inode(src_file); | ||
| 3637 | struct inode *dst = file_inode(dst_file); | ||
| 3638 | u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize; | ||
| 3639 | |||
| 3640 | if (WARN_ON_ONCE(bs < PAGE_SIZE)) { | ||
| 3641 | /* | ||
| 3642 | * Btrfs does not support blocksize < page_size. As a | ||
| 3643 | * result, btrfs_cmp_data() won't correctly handle | ||
| 3644 | * this situation without an update. | ||
| 3645 | */ | ||
| 3646 | return -EINVAL; | ||
| 3647 | } | ||
| 3648 | |||
| 3649 | return btrfs_extent_same(src, src_loff, olen, dst, dst_loff); | ||
| 3650 | } | ||
| 3651 | |||
| 3652 | static int clone_finish_inode_update(struct btrfs_trans_handle *trans, | 3632 | static int clone_finish_inode_update(struct btrfs_trans_handle *trans, |
| 3653 | struct inode *inode, | 3633 | struct inode *inode, |
| 3654 | u64 endoff, | 3634 | u64 endoff, |
| @@ -4350,10 +4330,34 @@ out_unlock: | |||
| 4350 | return ret; | 4330 | return ret; |
| 4351 | } | 4331 | } |
| 4352 | 4332 | ||
| 4353 | int btrfs_clone_file_range(struct file *src_file, loff_t off, | 4333 | loff_t btrfs_remap_file_range(struct file *src_file, loff_t off, |
| 4354 | struct file *dst_file, loff_t destoff, u64 len) | 4334 | struct file *dst_file, loff_t destoff, loff_t len, |
| 4335 | unsigned int remap_flags) | ||
| 4355 | { | 4336 | { |
| 4356 | return btrfs_clone_files(dst_file, src_file, off, len, destoff); | 4337 | int ret; |
| 4338 | |||
| 4339 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) | ||
| 4340 | return -EINVAL; | ||
| 4341 | |||
| 4342 | if (remap_flags & REMAP_FILE_DEDUP) { | ||
| 4343 | struct inode *src = file_inode(src_file); | ||
| 4344 | struct inode *dst = file_inode(dst_file); | ||
| 4345 | u64 bs = BTRFS_I(src)->root->fs_info->sb->s_blocksize; | ||
| 4346 | |||
| 4347 | if (WARN_ON_ONCE(bs < PAGE_SIZE)) { | ||
| 4348 | /* | ||
| 4349 | * Btrfs does not support blocksize < page_size. As a | ||
| 4350 | * result, btrfs_cmp_data() won't correctly handle | ||
| 4351 | * this situation without an update. | ||
| 4352 | */ | ||
| 4353 | return -EINVAL; | ||
| 4354 | } | ||
| 4355 | |||
| 4356 | ret = btrfs_extent_same(src, off, len, dst, destoff); | ||
| 4357 | } else { | ||
| 4358 | ret = btrfs_clone_files(dst_file, src_file, off, len, destoff); | ||
| 4359 | } | ||
| 4360 | return ret < 0 ? ret : len; | ||
| 4357 | } | 4361 | } |
| 4358 | 4362 | ||
| 4359 | static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) | 4363 | static long btrfs_ioctl_default_subvol(struct file *file, void __user *argp) |
diff --git a/fs/buffer.c b/fs/buffer.c index d60d61e8ed7d..1286c2b95498 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -3060,6 +3060,11 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, | |||
| 3060 | */ | 3060 | */ |
| 3061 | bio = bio_alloc(GFP_NOIO, 1); | 3061 | bio = bio_alloc(GFP_NOIO, 1); |
| 3062 | 3062 | ||
| 3063 | if (wbc) { | ||
| 3064 | wbc_init_bio(wbc, bio); | ||
| 3065 | wbc_account_io(wbc, bh->b_page, bh->b_size); | ||
| 3066 | } | ||
| 3067 | |||
| 3063 | bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); | 3068 | bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); |
| 3064 | bio_set_dev(bio, bh->b_bdev); | 3069 | bio_set_dev(bio, bh->b_bdev); |
| 3065 | bio->bi_write_hint = write_hint; | 3070 | bio->bi_write_hint = write_hint; |
| @@ -3079,11 +3084,6 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, | |||
| 3079 | op_flags |= REQ_PRIO; | 3084 | op_flags |= REQ_PRIO; |
| 3080 | bio_set_op_attrs(bio, op, op_flags); | 3085 | bio_set_op_attrs(bio, op, op_flags); |
| 3081 | 3086 | ||
| 3082 | if (wbc) { | ||
| 3083 | wbc_init_bio(wbc, bio); | ||
| 3084 | wbc_account_io(wbc, bh->b_page, bh->b_size); | ||
| 3085 | } | ||
| 3086 | |||
| 3087 | submit_bio(bio); | 3087 | submit_bio(bio); |
| 3088 | return 0; | 3088 | return 0; |
| 3089 | } | 3089 | } |
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 3e812428ac8d..ba178b09de0b 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c | |||
| @@ -145,6 +145,58 @@ cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface) | |||
| 145 | seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr); | 145 | seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | static int cifs_debug_files_proc_show(struct seq_file *m, void *v) | ||
| 149 | { | ||
| 150 | struct list_head *stmp, *tmp, *tmp1, *tmp2; | ||
| 151 | struct TCP_Server_Info *server; | ||
| 152 | struct cifs_ses *ses; | ||
| 153 | struct cifs_tcon *tcon; | ||
| 154 | struct cifsFileInfo *cfile; | ||
| 155 | |||
| 156 | seq_puts(m, "# Version:1\n"); | ||
| 157 | seq_puts(m, "# Format:\n"); | ||
| 158 | seq_puts(m, "# <tree id> <persistent fid> <flags> <count> <pid> <uid>"); | ||
| 159 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 160 | seq_printf(m, " <filename> <mid>\n"); | ||
| 161 | #else | ||
| 162 | seq_printf(m, " <filename>\n"); | ||
| 163 | #endif /* CIFS_DEBUG2 */ | ||
| 164 | spin_lock(&cifs_tcp_ses_lock); | ||
| 165 | list_for_each(stmp, &cifs_tcp_ses_list) { | ||
| 166 | server = list_entry(stmp, struct TCP_Server_Info, | ||
| 167 | tcp_ses_list); | ||
| 168 | list_for_each(tmp, &server->smb_ses_list) { | ||
| 169 | ses = list_entry(tmp, struct cifs_ses, smb_ses_list); | ||
| 170 | list_for_each(tmp1, &ses->tcon_list) { | ||
| 171 | tcon = list_entry(tmp1, struct cifs_tcon, tcon_list); | ||
| 172 | spin_lock(&tcon->open_file_lock); | ||
| 173 | list_for_each(tmp2, &tcon->openFileList) { | ||
| 174 | cfile = list_entry(tmp2, struct cifsFileInfo, | ||
| 175 | tlist); | ||
| 176 | seq_printf(m, | ||
| 177 | "0x%x 0x%llx 0x%x %d %d %d %s", | ||
| 178 | tcon->tid, | ||
| 179 | cfile->fid.persistent_fid, | ||
| 180 | cfile->f_flags, | ||
| 181 | cfile->count, | ||
| 182 | cfile->pid, | ||
| 183 | from_kuid(&init_user_ns, cfile->uid), | ||
| 184 | cfile->dentry->d_name.name); | ||
| 185 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 186 | seq_printf(m, " 0x%llx\n", cfile->fid.mid); | ||
| 187 | #else | ||
| 188 | seq_printf(m, "\n"); | ||
| 189 | #endif /* CIFS_DEBUG2 */ | ||
| 190 | } | ||
| 191 | spin_unlock(&tcon->open_file_lock); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | } | ||
| 195 | spin_unlock(&cifs_tcp_ses_lock); | ||
| 196 | seq_putc(m, '\n'); | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 148 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) | 200 | static int cifs_debug_data_proc_show(struct seq_file *m, void *v) |
| 149 | { | 201 | { |
| 150 | struct list_head *tmp1, *tmp2, *tmp3; | 202 | struct list_head *tmp1, *tmp2, *tmp3; |
| @@ -565,6 +617,9 @@ cifs_proc_init(void) | |||
| 565 | proc_create_single("DebugData", 0, proc_fs_cifs, | 617 | proc_create_single("DebugData", 0, proc_fs_cifs, |
| 566 | cifs_debug_data_proc_show); | 618 | cifs_debug_data_proc_show); |
| 567 | 619 | ||
| 620 | proc_create_single("open_files", 0400, proc_fs_cifs, | ||
| 621 | cifs_debug_files_proc_show); | ||
| 622 | |||
| 568 | proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_fops); | 623 | proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_fops); |
| 569 | proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_fops); | 624 | proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_fops); |
| 570 | proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_fops); | 625 | proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_fops); |
| @@ -601,6 +656,7 @@ cifs_proc_clean(void) | |||
| 601 | return; | 656 | return; |
| 602 | 657 | ||
| 603 | remove_proc_entry("DebugData", proc_fs_cifs); | 658 | remove_proc_entry("DebugData", proc_fs_cifs); |
| 659 | remove_proc_entry("open_files", proc_fs_cifs); | ||
| 604 | remove_proc_entry("cifsFYI", proc_fs_cifs); | 660 | remove_proc_entry("cifsFYI", proc_fs_cifs); |
| 605 | remove_proc_entry("traceSMB", proc_fs_cifs); | 661 | remove_proc_entry("traceSMB", proc_fs_cifs); |
| 606 | remove_proc_entry("Stats", proc_fs_cifs); | 662 | remove_proc_entry("Stats", proc_fs_cifs); |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index b611fc2e8984..7f01c6e60791 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
| @@ -147,8 +147,10 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) | |||
| 147 | sprintf(dp, ";sec=krb5"); | 147 | sprintf(dp, ";sec=krb5"); |
| 148 | else if (server->sec_mskerberos) | 148 | else if (server->sec_mskerberos) |
| 149 | sprintf(dp, ";sec=mskrb5"); | 149 | sprintf(dp, ";sec=mskrb5"); |
| 150 | else | 150 | else { |
| 151 | goto out; | 151 | cifs_dbg(VFS, "unknown or missing server auth type, use krb5\n"); |
| 152 | sprintf(dp, ";sec=krb5"); | ||
| 153 | } | ||
| 152 | 154 | ||
| 153 | dp = description + strlen(description); | 155 | dp = description + strlen(description); |
| 154 | sprintf(dp, ";uid=0x%x", | 156 | sprintf(dp, ";uid=0x%x", |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 7de9603c54f1..865706edb307 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -992,17 +992,21 @@ const struct inode_operations cifs_symlink_inode_ops = { | |||
| 992 | .listxattr = cifs_listxattr, | 992 | .listxattr = cifs_listxattr, |
| 993 | }; | 993 | }; |
| 994 | 994 | ||
| 995 | static int cifs_clone_file_range(struct file *src_file, loff_t off, | 995 | static loff_t cifs_remap_file_range(struct file *src_file, loff_t off, |
| 996 | struct file *dst_file, loff_t destoff, u64 len) | 996 | struct file *dst_file, loff_t destoff, loff_t len, |
| 997 | unsigned int remap_flags) | ||
| 997 | { | 998 | { |
| 998 | struct inode *src_inode = file_inode(src_file); | 999 | struct inode *src_inode = file_inode(src_file); |
| 999 | struct inode *target_inode = file_inode(dst_file); | 1000 | struct inode *target_inode = file_inode(dst_file); |
| 1000 | struct cifsFileInfo *smb_file_src = src_file->private_data; | 1001 | struct cifsFileInfo *smb_file_src = src_file->private_data; |
| 1001 | struct cifsFileInfo *smb_file_target = dst_file->private_data; | 1002 | struct cifsFileInfo *smb_file_target; |
| 1002 | struct cifs_tcon *target_tcon = tlink_tcon(smb_file_target->tlink); | 1003 | struct cifs_tcon *target_tcon; |
| 1003 | unsigned int xid; | 1004 | unsigned int xid; |
| 1004 | int rc; | 1005 | int rc; |
| 1005 | 1006 | ||
| 1007 | if (remap_flags & ~REMAP_FILE_ADVISORY) | ||
| 1008 | return -EINVAL; | ||
| 1009 | |||
| 1006 | cifs_dbg(FYI, "clone range\n"); | 1010 | cifs_dbg(FYI, "clone range\n"); |
| 1007 | 1011 | ||
| 1008 | xid = get_xid(); | 1012 | xid = get_xid(); |
| @@ -1013,6 +1017,9 @@ static int cifs_clone_file_range(struct file *src_file, loff_t off, | |||
| 1013 | goto out; | 1017 | goto out; |
| 1014 | } | 1018 | } |
| 1015 | 1019 | ||
| 1020 | smb_file_target = dst_file->private_data; | ||
| 1021 | target_tcon = tlink_tcon(smb_file_target->tlink); | ||
| 1022 | |||
| 1016 | /* | 1023 | /* |
| 1017 | * Note: cifs case is easier than btrfs since server responsible for | 1024 | * Note: cifs case is easier than btrfs since server responsible for |
| 1018 | * checks for proper open modes and file type and if it wants | 1025 | * checks for proper open modes and file type and if it wants |
| @@ -1042,7 +1049,7 @@ static int cifs_clone_file_range(struct file *src_file, loff_t off, | |||
| 1042 | unlock_two_nondirectories(src_inode, target_inode); | 1049 | unlock_two_nondirectories(src_inode, target_inode); |
| 1043 | out: | 1050 | out: |
| 1044 | free_xid(xid); | 1051 | free_xid(xid); |
| 1045 | return rc; | 1052 | return rc < 0 ? rc : len; |
| 1046 | } | 1053 | } |
| 1047 | 1054 | ||
| 1048 | ssize_t cifs_file_copychunk_range(unsigned int xid, | 1055 | ssize_t cifs_file_copychunk_range(unsigned int xid, |
| @@ -1151,7 +1158,7 @@ const struct file_operations cifs_file_ops = { | |||
| 1151 | .llseek = cifs_llseek, | 1158 | .llseek = cifs_llseek, |
| 1152 | .unlocked_ioctl = cifs_ioctl, | 1159 | .unlocked_ioctl = cifs_ioctl, |
| 1153 | .copy_file_range = cifs_copy_file_range, | 1160 | .copy_file_range = cifs_copy_file_range, |
| 1154 | .clone_file_range = cifs_clone_file_range, | 1161 | .remap_file_range = cifs_remap_file_range, |
| 1155 | .setlease = cifs_setlease, | 1162 | .setlease = cifs_setlease, |
| 1156 | .fallocate = cifs_fallocate, | 1163 | .fallocate = cifs_fallocate, |
| 1157 | }; | 1164 | }; |
| @@ -1170,15 +1177,14 @@ const struct file_operations cifs_file_strict_ops = { | |||
| 1170 | .llseek = cifs_llseek, | 1177 | .llseek = cifs_llseek, |
| 1171 | .unlocked_ioctl = cifs_ioctl, | 1178 | .unlocked_ioctl = cifs_ioctl, |
| 1172 | .copy_file_range = cifs_copy_file_range, | 1179 | .copy_file_range = cifs_copy_file_range, |
| 1173 | .clone_file_range = cifs_clone_file_range, | 1180 | .remap_file_range = cifs_remap_file_range, |
| 1174 | .setlease = cifs_setlease, | 1181 | .setlease = cifs_setlease, |
| 1175 | .fallocate = cifs_fallocate, | 1182 | .fallocate = cifs_fallocate, |
| 1176 | }; | 1183 | }; |
| 1177 | 1184 | ||
| 1178 | const struct file_operations cifs_file_direct_ops = { | 1185 | const struct file_operations cifs_file_direct_ops = { |
| 1179 | /* BB reevaluate whether they can be done with directio, no cache */ | 1186 | .read_iter = cifs_direct_readv, |
| 1180 | .read_iter = cifs_user_readv, | 1187 | .write_iter = cifs_direct_writev, |
| 1181 | .write_iter = cifs_user_writev, | ||
| 1182 | .open = cifs_open, | 1188 | .open = cifs_open, |
| 1183 | .release = cifs_close, | 1189 | .release = cifs_close, |
| 1184 | .lock = cifs_lock, | 1190 | .lock = cifs_lock, |
| @@ -1189,7 +1195,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
| 1189 | .splice_write = iter_file_splice_write, | 1195 | .splice_write = iter_file_splice_write, |
| 1190 | .unlocked_ioctl = cifs_ioctl, | 1196 | .unlocked_ioctl = cifs_ioctl, |
| 1191 | .copy_file_range = cifs_copy_file_range, | 1197 | .copy_file_range = cifs_copy_file_range, |
| 1192 | .clone_file_range = cifs_clone_file_range, | 1198 | .remap_file_range = cifs_remap_file_range, |
| 1193 | .llseek = cifs_llseek, | 1199 | .llseek = cifs_llseek, |
| 1194 | .setlease = cifs_setlease, | 1200 | .setlease = cifs_setlease, |
| 1195 | .fallocate = cifs_fallocate, | 1201 | .fallocate = cifs_fallocate, |
| @@ -1208,7 +1214,7 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
| 1208 | .llseek = cifs_llseek, | 1214 | .llseek = cifs_llseek, |
| 1209 | .unlocked_ioctl = cifs_ioctl, | 1215 | .unlocked_ioctl = cifs_ioctl, |
| 1210 | .copy_file_range = cifs_copy_file_range, | 1216 | .copy_file_range = cifs_copy_file_range, |
| 1211 | .clone_file_range = cifs_clone_file_range, | 1217 | .remap_file_range = cifs_remap_file_range, |
| 1212 | .setlease = cifs_setlease, | 1218 | .setlease = cifs_setlease, |
| 1213 | .fallocate = cifs_fallocate, | 1219 | .fallocate = cifs_fallocate, |
| 1214 | }; | 1220 | }; |
| @@ -1226,15 +1232,14 @@ const struct file_operations cifs_file_strict_nobrl_ops = { | |||
| 1226 | .llseek = cifs_llseek, | 1232 | .llseek = cifs_llseek, |
| 1227 | .unlocked_ioctl = cifs_ioctl, | 1233 | .unlocked_ioctl = cifs_ioctl, |
| 1228 | .copy_file_range = cifs_copy_file_range, | 1234 | .copy_file_range = cifs_copy_file_range, |
| 1229 | .clone_file_range = cifs_clone_file_range, | 1235 | .remap_file_range = cifs_remap_file_range, |
| 1230 | .setlease = cifs_setlease, | 1236 | .setlease = cifs_setlease, |
| 1231 | .fallocate = cifs_fallocate, | 1237 | .fallocate = cifs_fallocate, |
| 1232 | }; | 1238 | }; |
| 1233 | 1239 | ||
| 1234 | const struct file_operations cifs_file_direct_nobrl_ops = { | 1240 | const struct file_operations cifs_file_direct_nobrl_ops = { |
| 1235 | /* BB reevaluate whether they can be done with directio, no cache */ | 1241 | .read_iter = cifs_direct_readv, |
| 1236 | .read_iter = cifs_user_readv, | 1242 | .write_iter = cifs_direct_writev, |
| 1237 | .write_iter = cifs_user_writev, | ||
| 1238 | .open = cifs_open, | 1243 | .open = cifs_open, |
| 1239 | .release = cifs_close, | 1244 | .release = cifs_close, |
| 1240 | .fsync = cifs_fsync, | 1245 | .fsync = cifs_fsync, |
| @@ -1244,7 +1249,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = { | |||
| 1244 | .splice_write = iter_file_splice_write, | 1249 | .splice_write = iter_file_splice_write, |
| 1245 | .unlocked_ioctl = cifs_ioctl, | 1250 | .unlocked_ioctl = cifs_ioctl, |
| 1246 | .copy_file_range = cifs_copy_file_range, | 1251 | .copy_file_range = cifs_copy_file_range, |
| 1247 | .clone_file_range = cifs_clone_file_range, | 1252 | .remap_file_range = cifs_remap_file_range, |
| 1248 | .llseek = cifs_llseek, | 1253 | .llseek = cifs_llseek, |
| 1249 | .setlease = cifs_setlease, | 1254 | .setlease = cifs_setlease, |
| 1250 | .fallocate = cifs_fallocate, | 1255 | .fallocate = cifs_fallocate, |
| @@ -1256,7 +1261,7 @@ const struct file_operations cifs_dir_ops = { | |||
| 1256 | .read = generic_read_dir, | 1261 | .read = generic_read_dir, |
| 1257 | .unlocked_ioctl = cifs_ioctl, | 1262 | .unlocked_ioctl = cifs_ioctl, |
| 1258 | .copy_file_range = cifs_copy_file_range, | 1263 | .copy_file_range = cifs_copy_file_range, |
| 1259 | .clone_file_range = cifs_clone_file_range, | 1264 | .remap_file_range = cifs_remap_file_range, |
| 1260 | .llseek = generic_file_llseek, | 1265 | .llseek = generic_file_llseek, |
| 1261 | .fsync = cifs_dir_fsync, | 1266 | .fsync = cifs_dir_fsync, |
| 1262 | }; | 1267 | }; |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 24e265a51874..4c3b5cfccc49 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -101,8 +101,10 @@ extern int cifs_open(struct inode *inode, struct file *file); | |||
| 101 | extern int cifs_close(struct inode *inode, struct file *file); | 101 | extern int cifs_close(struct inode *inode, struct file *file); |
| 102 | extern int cifs_closedir(struct inode *inode, struct file *file); | 102 | extern int cifs_closedir(struct inode *inode, struct file *file); |
| 103 | extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to); | 103 | extern ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to); |
| 104 | extern ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to); | ||
| 104 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to); | 105 | extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to); |
| 105 | extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from); | 106 | extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from); |
| 107 | extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from); | ||
| 106 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from); | 108 | extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from); |
| 107 | extern int cifs_lock(struct file *, int, struct file_lock *); | 109 | extern int cifs_lock(struct file *, int, struct file_lock *); |
| 108 | extern int cifs_fsync(struct file *, loff_t, loff_t, int); | 110 | extern int cifs_fsync(struct file *, loff_t, loff_t, int); |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index ed1e0fcb69e3..38ab0fca49e1 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -1125,6 +1125,9 @@ struct cifs_fid { | |||
| 1125 | __u8 create_guid[16]; | 1125 | __u8 create_guid[16]; |
| 1126 | struct cifs_pending_open *pending_open; | 1126 | struct cifs_pending_open *pending_open; |
| 1127 | unsigned int epoch; | 1127 | unsigned int epoch; |
| 1128 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 1129 | __u64 mid; | ||
| 1130 | #endif /* CIFS_DEBUG2 */ | ||
| 1128 | bool purge_cache; | 1131 | bool purge_cache; |
| 1129 | }; | 1132 | }; |
| 1130 | 1133 | ||
| @@ -1183,6 +1186,11 @@ struct cifs_aio_ctx { | |||
| 1183 | unsigned int len; | 1186 | unsigned int len; |
| 1184 | unsigned int total_len; | 1187 | unsigned int total_len; |
| 1185 | bool should_dirty; | 1188 | bool should_dirty; |
| 1189 | /* | ||
| 1190 | * Indicates if this aio_ctx is for direct_io, | ||
| 1191 | * If yes, iter is a copy of the user passed iov_iter | ||
| 1192 | */ | ||
| 1193 | bool direct_io; | ||
| 1186 | }; | 1194 | }; |
| 1187 | 1195 | ||
| 1188 | struct cifs_readdata; | 1196 | struct cifs_readdata; |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 1ce733f3582f..79d842e7240c 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
| @@ -1539,6 +1539,9 @@ struct reparse_symlink_data { | |||
| 1539 | char PathBuffer[0]; | 1539 | char PathBuffer[0]; |
| 1540 | } __attribute__((packed)); | 1540 | } __attribute__((packed)); |
| 1541 | 1541 | ||
| 1542 | /* Flag above */ | ||
| 1543 | #define SYMLINK_FLAG_RELATIVE 0x00000001 | ||
| 1544 | |||
| 1542 | /* For IO_REPARSE_TAG_NFS */ | 1545 | /* For IO_REPARSE_TAG_NFS */ |
| 1543 | #define NFS_SPECFILE_LNK 0x00000000014B4E4C | 1546 | #define NFS_SPECFILE_LNK 0x00000000014B4E4C |
| 1544 | #define NFS_SPECFILE_CHR 0x0000000000524843 | 1547 | #define NFS_SPECFILE_CHR 0x0000000000524843 |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e262a05a98bf..74c33d5fafc8 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -1005,7 +1005,7 @@ cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) | |||
| 1005 | * Set the byte-range lock (mandatory style). Returns: | 1005 | * Set the byte-range lock (mandatory style). Returns: |
| 1006 | * 1) 0, if we set the lock and don't need to request to the server; | 1006 | * 1) 0, if we set the lock and don't need to request to the server; |
| 1007 | * 2) 1, if no locks prevent us but we need to request to the server; | 1007 | * 2) 1, if no locks prevent us but we need to request to the server; |
| 1008 | * 3) -EACCESS, if there is a lock that prevents us and wait is false. | 1008 | * 3) -EACCES, if there is a lock that prevents us and wait is false. |
| 1009 | */ | 1009 | */ |
| 1010 | static int | 1010 | static int |
| 1011 | cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, | 1011 | cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, |
| @@ -2538,6 +2538,61 @@ wdata_fill_from_iovec(struct cifs_writedata *wdata, struct iov_iter *from, | |||
| 2538 | } | 2538 | } |
| 2539 | 2539 | ||
| 2540 | static int | 2540 | static int |
| 2541 | cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, | ||
| 2542 | struct cifs_aio_ctx *ctx) | ||
| 2543 | { | ||
| 2544 | int wait_retry = 0; | ||
| 2545 | unsigned int wsize, credits; | ||
| 2546 | int rc; | ||
| 2547 | struct TCP_Server_Info *server = | ||
| 2548 | tlink_tcon(wdata->cfile->tlink)->ses->server; | ||
| 2549 | |||
| 2550 | /* | ||
| 2551 | * Try to resend this wdata, waiting for credits up to 3 seconds. | ||
| 2552 | * Note: we are attempting to resend the whole wdata not in segments | ||
| 2553 | */ | ||
| 2554 | do { | ||
| 2555 | rc = server->ops->wait_mtu_credits( | ||
| 2556 | server, wdata->bytes, &wsize, &credits); | ||
| 2557 | |||
| 2558 | if (rc) | ||
| 2559 | break; | ||
| 2560 | |||
| 2561 | if (wsize < wdata->bytes) { | ||
| 2562 | add_credits_and_wake_if(server, credits, 0); | ||
| 2563 | msleep(1000); | ||
| 2564 | wait_retry++; | ||
| 2565 | } | ||
| 2566 | } while (wsize < wdata->bytes && wait_retry < 3); | ||
| 2567 | |||
| 2568 | if (wsize < wdata->bytes) { | ||
| 2569 | rc = -EBUSY; | ||
| 2570 | goto out; | ||
| 2571 | } | ||
| 2572 | |||
| 2573 | rc = -EAGAIN; | ||
| 2574 | while (rc == -EAGAIN) { | ||
| 2575 | rc = 0; | ||
| 2576 | if (wdata->cfile->invalidHandle) | ||
| 2577 | rc = cifs_reopen_file(wdata->cfile, false); | ||
| 2578 | if (!rc) | ||
| 2579 | rc = server->ops->async_writev(wdata, | ||
| 2580 | cifs_uncached_writedata_release); | ||
| 2581 | } | ||
| 2582 | |||
| 2583 | if (!rc) { | ||
| 2584 | list_add_tail(&wdata->list, wdata_list); | ||
| 2585 | return 0; | ||
| 2586 | } | ||
| 2587 | |||
| 2588 | add_credits_and_wake_if(server, wdata->credits, 0); | ||
| 2589 | out: | ||
| 2590 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); | ||
| 2591 | |||
| 2592 | return rc; | ||
| 2593 | } | ||
| 2594 | |||
| 2595 | static int | ||
| 2541 | cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | 2596 | cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, |
| 2542 | struct cifsFileInfo *open_file, | 2597 | struct cifsFileInfo *open_file, |
| 2543 | struct cifs_sb_info *cifs_sb, struct list_head *wdata_list, | 2598 | struct cifs_sb_info *cifs_sb, struct list_head *wdata_list, |
| @@ -2551,6 +2606,8 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
| 2551 | loff_t saved_offset = offset; | 2606 | loff_t saved_offset = offset; |
| 2552 | pid_t pid; | 2607 | pid_t pid; |
| 2553 | struct TCP_Server_Info *server; | 2608 | struct TCP_Server_Info *server; |
| 2609 | struct page **pagevec; | ||
| 2610 | size_t start; | ||
| 2554 | 2611 | ||
| 2555 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) | 2612 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) |
| 2556 | pid = open_file->pid; | 2613 | pid = open_file->pid; |
| @@ -2567,38 +2624,79 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
| 2567 | if (rc) | 2624 | if (rc) |
| 2568 | break; | 2625 | break; |
| 2569 | 2626 | ||
| 2570 | nr_pages = get_numpages(wsize, len, &cur_len); | 2627 | if (ctx->direct_io) { |
| 2571 | wdata = cifs_writedata_alloc(nr_pages, | 2628 | ssize_t result; |
| 2629 | |||
| 2630 | result = iov_iter_get_pages_alloc( | ||
| 2631 | from, &pagevec, wsize, &start); | ||
| 2632 | if (result < 0) { | ||
| 2633 | cifs_dbg(VFS, | ||
| 2634 | "direct_writev couldn't get user pages " | ||
| 2635 | "(rc=%zd) iter type %d iov_offset %zd " | ||
| 2636 | "count %zd\n", | ||
| 2637 | result, from->type, | ||
| 2638 | from->iov_offset, from->count); | ||
| 2639 | dump_stack(); | ||
| 2640 | break; | ||
| 2641 | } | ||
| 2642 | cur_len = (size_t)result; | ||
| 2643 | iov_iter_advance(from, cur_len); | ||
| 2644 | |||
| 2645 | nr_pages = | ||
| 2646 | (cur_len + start + PAGE_SIZE - 1) / PAGE_SIZE; | ||
| 2647 | |||
| 2648 | wdata = cifs_writedata_direct_alloc(pagevec, | ||
| 2572 | cifs_uncached_writev_complete); | 2649 | cifs_uncached_writev_complete); |
| 2573 | if (!wdata) { | 2650 | if (!wdata) { |
| 2574 | rc = -ENOMEM; | 2651 | rc = -ENOMEM; |
| 2575 | add_credits_and_wake_if(server, credits, 0); | 2652 | add_credits_and_wake_if(server, credits, 0); |
| 2576 | break; | 2653 | break; |
| 2577 | } | 2654 | } |
| 2578 | 2655 | ||
| 2579 | rc = cifs_write_allocate_pages(wdata->pages, nr_pages); | ||
| 2580 | if (rc) { | ||
| 2581 | kfree(wdata); | ||
| 2582 | add_credits_and_wake_if(server, credits, 0); | ||
| 2583 | break; | ||
| 2584 | } | ||
| 2585 | 2656 | ||
| 2586 | num_pages = nr_pages; | 2657 | wdata->page_offset = start; |
| 2587 | rc = wdata_fill_from_iovec(wdata, from, &cur_len, &num_pages); | 2658 | wdata->tailsz = |
| 2588 | if (rc) { | 2659 | nr_pages > 1 ? |
| 2589 | for (i = 0; i < nr_pages; i++) | 2660 | cur_len - (PAGE_SIZE - start) - |
| 2590 | put_page(wdata->pages[i]); | 2661 | (nr_pages - 2) * PAGE_SIZE : |
| 2591 | kfree(wdata); | 2662 | cur_len; |
| 2592 | add_credits_and_wake_if(server, credits, 0); | 2663 | } else { |
| 2593 | break; | 2664 | nr_pages = get_numpages(wsize, len, &cur_len); |
| 2594 | } | 2665 | wdata = cifs_writedata_alloc(nr_pages, |
| 2666 | cifs_uncached_writev_complete); | ||
| 2667 | if (!wdata) { | ||
| 2668 | rc = -ENOMEM; | ||
| 2669 | add_credits_and_wake_if(server, credits, 0); | ||
| 2670 | break; | ||
| 2671 | } | ||
| 2595 | 2672 | ||
| 2596 | /* | 2673 | rc = cifs_write_allocate_pages(wdata->pages, nr_pages); |
| 2597 | * Bring nr_pages down to the number of pages we actually used, | 2674 | if (rc) { |
| 2598 | * and free any pages that we didn't use. | 2675 | kfree(wdata); |
| 2599 | */ | 2676 | add_credits_and_wake_if(server, credits, 0); |
| 2600 | for ( ; nr_pages > num_pages; nr_pages--) | 2677 | break; |
| 2601 | put_page(wdata->pages[nr_pages - 1]); | 2678 | } |
| 2679 | |||
| 2680 | num_pages = nr_pages; | ||
| 2681 | rc = wdata_fill_from_iovec( | ||
| 2682 | wdata, from, &cur_len, &num_pages); | ||
| 2683 | if (rc) { | ||
| 2684 | for (i = 0; i < nr_pages; i++) | ||
| 2685 | put_page(wdata->pages[i]); | ||
| 2686 | kfree(wdata); | ||
| 2687 | add_credits_and_wake_if(server, credits, 0); | ||
| 2688 | break; | ||
| 2689 | } | ||
| 2690 | |||
| 2691 | /* | ||
| 2692 | * Bring nr_pages down to the number of pages we | ||
| 2693 | * actually used, and free any pages that we didn't use. | ||
| 2694 | */ | ||
| 2695 | for ( ; nr_pages > num_pages; nr_pages--) | ||
| 2696 | put_page(wdata->pages[nr_pages - 1]); | ||
| 2697 | |||
| 2698 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | ||
| 2699 | } | ||
| 2602 | 2700 | ||
| 2603 | wdata->sync_mode = WB_SYNC_ALL; | 2701 | wdata->sync_mode = WB_SYNC_ALL; |
| 2604 | wdata->nr_pages = nr_pages; | 2702 | wdata->nr_pages = nr_pages; |
| @@ -2607,7 +2705,6 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from, | |||
| 2607 | wdata->pid = pid; | 2705 | wdata->pid = pid; |
| 2608 | wdata->bytes = cur_len; | 2706 | wdata->bytes = cur_len; |
| 2609 | wdata->pagesz = PAGE_SIZE; | 2707 | wdata->pagesz = PAGE_SIZE; |
| 2610 | wdata->tailsz = cur_len - ((nr_pages - 1) * PAGE_SIZE); | ||
| 2611 | wdata->credits = credits; | 2708 | wdata->credits = credits; |
| 2612 | wdata->ctx = ctx; | 2709 | wdata->ctx = ctx; |
| 2613 | kref_get(&ctx->refcount); | 2710 | kref_get(&ctx->refcount); |
| @@ -2682,13 +2779,18 @@ restart_loop: | |||
| 2682 | INIT_LIST_HEAD(&tmp_list); | 2779 | INIT_LIST_HEAD(&tmp_list); |
| 2683 | list_del_init(&wdata->list); | 2780 | list_del_init(&wdata->list); |
| 2684 | 2781 | ||
| 2685 | iov_iter_advance(&tmp_from, | 2782 | if (ctx->direct_io) |
| 2783 | rc = cifs_resend_wdata( | ||
| 2784 | wdata, &tmp_list, ctx); | ||
| 2785 | else { | ||
| 2786 | iov_iter_advance(&tmp_from, | ||
| 2686 | wdata->offset - ctx->pos); | 2787 | wdata->offset - ctx->pos); |
| 2687 | 2788 | ||
| 2688 | rc = cifs_write_from_iter(wdata->offset, | 2789 | rc = cifs_write_from_iter(wdata->offset, |
| 2689 | wdata->bytes, &tmp_from, | 2790 | wdata->bytes, &tmp_from, |
| 2690 | ctx->cfile, cifs_sb, &tmp_list, | 2791 | ctx->cfile, cifs_sb, &tmp_list, |
| 2691 | ctx); | 2792 | ctx); |
| 2793 | } | ||
| 2692 | 2794 | ||
| 2693 | list_splice(&tmp_list, &ctx->list); | 2795 | list_splice(&tmp_list, &ctx->list); |
| 2694 | 2796 | ||
| @@ -2701,8 +2803,9 @@ restart_loop: | |||
| 2701 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); | 2803 | kref_put(&wdata->refcount, cifs_uncached_writedata_release); |
| 2702 | } | 2804 | } |
| 2703 | 2805 | ||
| 2704 | for (i = 0; i < ctx->npages; i++) | 2806 | if (!ctx->direct_io) |
| 2705 | put_page(ctx->bv[i].bv_page); | 2807 | for (i = 0; i < ctx->npages; i++) |
| 2808 | put_page(ctx->bv[i].bv_page); | ||
| 2706 | 2809 | ||
| 2707 | cifs_stats_bytes_written(tcon, ctx->total_len); | 2810 | cifs_stats_bytes_written(tcon, ctx->total_len); |
| 2708 | set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags); | 2811 | set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags); |
| @@ -2717,7 +2820,8 @@ restart_loop: | |||
| 2717 | complete(&ctx->done); | 2820 | complete(&ctx->done); |
| 2718 | } | 2821 | } |
| 2719 | 2822 | ||
| 2720 | ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | 2823 | static ssize_t __cifs_writev( |
| 2824 | struct kiocb *iocb, struct iov_iter *from, bool direct) | ||
| 2721 | { | 2825 | { |
| 2722 | struct file *file = iocb->ki_filp; | 2826 | struct file *file = iocb->ki_filp; |
| 2723 | ssize_t total_written = 0; | 2827 | ssize_t total_written = 0; |
| @@ -2726,13 +2830,18 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 2726 | struct cifs_sb_info *cifs_sb; | 2830 | struct cifs_sb_info *cifs_sb; |
| 2727 | struct cifs_aio_ctx *ctx; | 2831 | struct cifs_aio_ctx *ctx; |
| 2728 | struct iov_iter saved_from = *from; | 2832 | struct iov_iter saved_from = *from; |
| 2833 | size_t len = iov_iter_count(from); | ||
| 2729 | int rc; | 2834 | int rc; |
| 2730 | 2835 | ||
| 2731 | /* | 2836 | /* |
| 2732 | * BB - optimize the way when signing is disabled. We can drop this | 2837 | * iov_iter_get_pages_alloc doesn't work with ITER_KVEC. |
| 2733 | * extra memory-to-memory copying and use iovec buffers for constructing | 2838 | * In this case, fall back to non-direct write function. |
| 2734 | * write request. | 2839 | * this could be improved by getting pages directly in ITER_KVEC |
| 2735 | */ | 2840 | */ |
| 2841 | if (direct && from->type & ITER_KVEC) { | ||
| 2842 | cifs_dbg(FYI, "use non-direct cifs_writev for kvec I/O\n"); | ||
| 2843 | direct = false; | ||
| 2844 | } | ||
| 2736 | 2845 | ||
| 2737 | rc = generic_write_checks(iocb, from); | 2846 | rc = generic_write_checks(iocb, from); |
| 2738 | if (rc <= 0) | 2847 | if (rc <= 0) |
| @@ -2756,10 +2865,16 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 2756 | 2865 | ||
| 2757 | ctx->pos = iocb->ki_pos; | 2866 | ctx->pos = iocb->ki_pos; |
| 2758 | 2867 | ||
| 2759 | rc = setup_aio_ctx_iter(ctx, from, WRITE); | 2868 | if (direct) { |
| 2760 | if (rc) { | 2869 | ctx->direct_io = true; |
| 2761 | kref_put(&ctx->refcount, cifs_aio_ctx_release); | 2870 | ctx->iter = *from; |
| 2762 | return rc; | 2871 | ctx->len = len; |
| 2872 | } else { | ||
| 2873 | rc = setup_aio_ctx_iter(ctx, from, WRITE); | ||
| 2874 | if (rc) { | ||
| 2875 | kref_put(&ctx->refcount, cifs_aio_ctx_release); | ||
| 2876 | return rc; | ||
| 2877 | } | ||
| 2763 | } | 2878 | } |
| 2764 | 2879 | ||
| 2765 | /* grab a lock here due to read response handlers can access ctx */ | 2880 | /* grab a lock here due to read response handlers can access ctx */ |
| @@ -2809,6 +2924,16 @@ ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | |||
| 2809 | return total_written; | 2924 | return total_written; |
| 2810 | } | 2925 | } |
| 2811 | 2926 | ||
| 2927 | ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from) | ||
| 2928 | { | ||
| 2929 | return __cifs_writev(iocb, from, true); | ||
| 2930 | } | ||
| 2931 | |||
| 2932 | ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) | ||
| 2933 | { | ||
| 2934 | return __cifs_writev(iocb, from, false); | ||
| 2935 | } | ||
| 2936 | |||
| 2812 | static ssize_t | 2937 | static ssize_t |
| 2813 | cifs_writev(struct kiocb *iocb, struct iov_iter *from) | 2938 | cifs_writev(struct kiocb *iocb, struct iov_iter *from) |
| 2814 | { | 2939 | { |
| @@ -2979,7 +3104,6 @@ cifs_uncached_readdata_release(struct kref *refcount) | |||
| 2979 | kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release); | 3104 | kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release); |
| 2980 | for (i = 0; i < rdata->nr_pages; i++) { | 3105 | for (i = 0; i < rdata->nr_pages; i++) { |
| 2981 | put_page(rdata->pages[i]); | 3106 | put_page(rdata->pages[i]); |
| 2982 | rdata->pages[i] = NULL; | ||
| 2983 | } | 3107 | } |
| 2984 | cifs_readdata_release(refcount); | 3108 | cifs_readdata_release(refcount); |
| 2985 | } | 3109 | } |
| @@ -3106,6 +3230,67 @@ cifs_uncached_copy_into_pages(struct TCP_Server_Info *server, | |||
| 3106 | return uncached_fill_pages(server, rdata, iter, iter->count); | 3230 | return uncached_fill_pages(server, rdata, iter, iter->count); |
| 3107 | } | 3231 | } |
| 3108 | 3232 | ||
| 3233 | static int cifs_resend_rdata(struct cifs_readdata *rdata, | ||
| 3234 | struct list_head *rdata_list, | ||
| 3235 | struct cifs_aio_ctx *ctx) | ||
| 3236 | { | ||
| 3237 | int wait_retry = 0; | ||
| 3238 | unsigned int rsize, credits; | ||
| 3239 | int rc; | ||
| 3240 | struct TCP_Server_Info *server = | ||
| 3241 | tlink_tcon(rdata->cfile->tlink)->ses->server; | ||
| 3242 | |||
| 3243 | /* | ||
| 3244 | * Try to resend this rdata, waiting for credits up to 3 seconds. | ||
| 3245 | * Note: we are attempting to resend the whole rdata not in segments | ||
| 3246 | */ | ||
| 3247 | do { | ||
| 3248 | rc = server->ops->wait_mtu_credits(server, rdata->bytes, | ||
| 3249 | &rsize, &credits); | ||
| 3250 | |||
| 3251 | if (rc) | ||
| 3252 | break; | ||
| 3253 | |||
| 3254 | if (rsize < rdata->bytes) { | ||
| 3255 | add_credits_and_wake_if(server, credits, 0); | ||
| 3256 | msleep(1000); | ||
| 3257 | wait_retry++; | ||
| 3258 | } | ||
| 3259 | } while (rsize < rdata->bytes && wait_retry < 3); | ||
| 3260 | |||
| 3261 | /* | ||
| 3262 | * If we can't find enough credits to send this rdata | ||
| 3263 | * release the rdata and return failure, this will pass | ||
| 3264 | * whatever I/O amount we have finished to VFS. | ||
| 3265 | */ | ||
| 3266 | if (rsize < rdata->bytes) { | ||
| 3267 | rc = -EBUSY; | ||
| 3268 | goto out; | ||
| 3269 | } | ||
| 3270 | |||
| 3271 | rc = -EAGAIN; | ||
| 3272 | while (rc == -EAGAIN) { | ||
| 3273 | rc = 0; | ||
| 3274 | if (rdata->cfile->invalidHandle) | ||
| 3275 | rc = cifs_reopen_file(rdata->cfile, true); | ||
| 3276 | if (!rc) | ||
| 3277 | rc = server->ops->async_readv(rdata); | ||
| 3278 | } | ||
| 3279 | |||
| 3280 | if (!rc) { | ||
| 3281 | /* Add to aio pending list */ | ||
| 3282 | list_add_tail(&rdata->list, rdata_list); | ||
| 3283 | return 0; | ||
| 3284 | } | ||
| 3285 | |||
| 3286 | add_credits_and_wake_if(server, rdata->credits, 0); | ||
| 3287 | out: | ||
| 3288 | kref_put(&rdata->refcount, | ||
| 3289 | cifs_uncached_readdata_release); | ||
| 3290 | |||
| 3291 | return rc; | ||
| 3292 | } | ||
| 3293 | |||
| 3109 | static int | 3294 | static int |
| 3110 | cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | 3295 | cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, |
| 3111 | struct cifs_sb_info *cifs_sb, struct list_head *rdata_list, | 3296 | struct cifs_sb_info *cifs_sb, struct list_head *rdata_list, |
| @@ -3117,6 +3302,9 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3117 | int rc; | 3302 | int rc; |
| 3118 | pid_t pid; | 3303 | pid_t pid; |
| 3119 | struct TCP_Server_Info *server; | 3304 | struct TCP_Server_Info *server; |
| 3305 | struct page **pagevec; | ||
| 3306 | size_t start; | ||
| 3307 | struct iov_iter direct_iov = ctx->iter; | ||
| 3120 | 3308 | ||
| 3121 | server = tlink_tcon(open_file->tlink)->ses->server; | 3309 | server = tlink_tcon(open_file->tlink)->ses->server; |
| 3122 | 3310 | ||
| @@ -3125,6 +3313,9 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3125 | else | 3313 | else |
| 3126 | pid = current->tgid; | 3314 | pid = current->tgid; |
| 3127 | 3315 | ||
| 3316 | if (ctx->direct_io) | ||
| 3317 | iov_iter_advance(&direct_iov, offset - ctx->pos); | ||
| 3318 | |||
| 3128 | do { | 3319 | do { |
| 3129 | rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize, | 3320 | rc = server->ops->wait_mtu_credits(server, cifs_sb->rsize, |
| 3130 | &rsize, &credits); | 3321 | &rsize, &credits); |
| @@ -3132,20 +3323,59 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3132 | break; | 3323 | break; |
| 3133 | 3324 | ||
| 3134 | cur_len = min_t(const size_t, len, rsize); | 3325 | cur_len = min_t(const size_t, len, rsize); |
| 3135 | npages = DIV_ROUND_UP(cur_len, PAGE_SIZE); | ||
| 3136 | 3326 | ||
| 3137 | /* allocate a readdata struct */ | 3327 | if (ctx->direct_io) { |
| 3138 | rdata = cifs_readdata_alloc(npages, | 3328 | ssize_t result; |
| 3329 | |||
| 3330 | result = iov_iter_get_pages_alloc( | ||
| 3331 | &direct_iov, &pagevec, | ||
| 3332 | cur_len, &start); | ||
| 3333 | if (result < 0) { | ||
| 3334 | cifs_dbg(VFS, | ||
| 3335 | "couldn't get user pages (cur_len=%zd)" | ||
| 3336 | " iter type %d" | ||
| 3337 | " iov_offset %zd count %zd\n", | ||
| 3338 | result, direct_iov.type, | ||
| 3339 | direct_iov.iov_offset, | ||
| 3340 | direct_iov.count); | ||
| 3341 | dump_stack(); | ||
| 3342 | break; | ||
| 3343 | } | ||
| 3344 | cur_len = (size_t)result; | ||
| 3345 | iov_iter_advance(&direct_iov, cur_len); | ||
| 3346 | |||
| 3347 | rdata = cifs_readdata_direct_alloc( | ||
| 3348 | pagevec, cifs_uncached_readv_complete); | ||
| 3349 | if (!rdata) { | ||
| 3350 | add_credits_and_wake_if(server, credits, 0); | ||
| 3351 | rc = -ENOMEM; | ||
| 3352 | break; | ||
| 3353 | } | ||
| 3354 | |||
| 3355 | npages = (cur_len + start + PAGE_SIZE-1) / PAGE_SIZE; | ||
| 3356 | rdata->page_offset = start; | ||
| 3357 | rdata->tailsz = npages > 1 ? | ||
| 3358 | cur_len-(PAGE_SIZE-start)-(npages-2)*PAGE_SIZE : | ||
| 3359 | cur_len; | ||
| 3360 | |||
| 3361 | } else { | ||
| 3362 | |||
| 3363 | npages = DIV_ROUND_UP(cur_len, PAGE_SIZE); | ||
| 3364 | /* allocate a readdata struct */ | ||
| 3365 | rdata = cifs_readdata_alloc(npages, | ||
| 3139 | cifs_uncached_readv_complete); | 3366 | cifs_uncached_readv_complete); |
| 3140 | if (!rdata) { | 3367 | if (!rdata) { |
| 3141 | add_credits_and_wake_if(server, credits, 0); | 3368 | add_credits_and_wake_if(server, credits, 0); |
| 3142 | rc = -ENOMEM; | 3369 | rc = -ENOMEM; |
| 3143 | break; | 3370 | break; |
| 3144 | } | 3371 | } |
| 3145 | 3372 | ||
| 3146 | rc = cifs_read_allocate_pages(rdata, npages); | 3373 | rc = cifs_read_allocate_pages(rdata, npages); |
| 3147 | if (rc) | 3374 | if (rc) |
| 3148 | goto error; | 3375 | goto error; |
| 3376 | |||
| 3377 | rdata->tailsz = PAGE_SIZE; | ||
| 3378 | } | ||
| 3149 | 3379 | ||
| 3150 | rdata->cfile = cifsFileInfo_get(open_file); | 3380 | rdata->cfile = cifsFileInfo_get(open_file); |
| 3151 | rdata->nr_pages = npages; | 3381 | rdata->nr_pages = npages; |
| @@ -3153,7 +3383,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file, | |||
| 3153 | rdata->bytes = cur_len; | 3383 | rdata->bytes = cur_len; |
| 3154 | rdata->pid = pid; | 3384 | rdata->pid = pid; |
| 3155 | rdata->pagesz = PAGE_SIZE; | 3385 | rdata->pagesz = PAGE_SIZE; |
| 3156 | rdata->tailsz = PAGE_SIZE; | ||
| 3157 | rdata->read_into_pages = cifs_uncached_read_into_pages; | 3386 | rdata->read_into_pages = cifs_uncached_read_into_pages; |
| 3158 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; | 3387 | rdata->copy_into_pages = cifs_uncached_copy_into_pages; |
| 3159 | rdata->credits = credits; | 3388 | rdata->credits = credits; |
| @@ -3167,9 +3396,11 @@ error: | |||
| 3167 | if (rc) { | 3396 | if (rc) { |
| 3168 | add_credits_and_wake_if(server, rdata->credits, 0); | 3397 | add_credits_and_wake_if(server, rdata->credits, 0); |
| 3169 | kref_put(&rdata->refcount, | 3398 | kref_put(&rdata->refcount, |
| 3170 | cifs_uncached_readdata_release); | 3399 | cifs_uncached_readdata_release); |
| 3171 | if (rc == -EAGAIN) | 3400 | if (rc == -EAGAIN) { |
| 3401 | iov_iter_revert(&direct_iov, cur_len); | ||
| 3172 | continue; | 3402 | continue; |
| 3403 | } | ||
| 3173 | break; | 3404 | break; |
| 3174 | } | 3405 | } |
| 3175 | 3406 | ||
| @@ -3225,45 +3456,62 @@ again: | |||
| 3225 | * reading. | 3456 | * reading. |
| 3226 | */ | 3457 | */ |
| 3227 | if (got_bytes && got_bytes < rdata->bytes) { | 3458 | if (got_bytes && got_bytes < rdata->bytes) { |
| 3228 | rc = cifs_readdata_to_iov(rdata, to); | 3459 | rc = 0; |
| 3460 | if (!ctx->direct_io) | ||
| 3461 | rc = cifs_readdata_to_iov(rdata, to); | ||
| 3229 | if (rc) { | 3462 | if (rc) { |
| 3230 | kref_put(&rdata->refcount, | 3463 | kref_put(&rdata->refcount, |
| 3231 | cifs_uncached_readdata_release); | 3464 | cifs_uncached_readdata_release); |
| 3232 | continue; | 3465 | continue; |
| 3233 | } | 3466 | } |
| 3234 | } | 3467 | } |
| 3235 | 3468 | ||
| 3236 | rc = cifs_send_async_read( | 3469 | if (ctx->direct_io) { |
| 3470 | /* | ||
| 3471 | * Re-use rdata as this is a | ||
| 3472 | * direct I/O | ||
| 3473 | */ | ||
| 3474 | rc = cifs_resend_rdata( | ||
| 3475 | rdata, | ||
| 3476 | &tmp_list, ctx); | ||
| 3477 | } else { | ||
| 3478 | rc = cifs_send_async_read( | ||
| 3237 | rdata->offset + got_bytes, | 3479 | rdata->offset + got_bytes, |
| 3238 | rdata->bytes - got_bytes, | 3480 | rdata->bytes - got_bytes, |
| 3239 | rdata->cfile, cifs_sb, | 3481 | rdata->cfile, cifs_sb, |
| 3240 | &tmp_list, ctx); | 3482 | &tmp_list, ctx); |
| 3241 | 3483 | ||
| 3484 | kref_put(&rdata->refcount, | ||
| 3485 | cifs_uncached_readdata_release); | ||
| 3486 | } | ||
| 3487 | |||
| 3242 | list_splice(&tmp_list, &ctx->list); | 3488 | list_splice(&tmp_list, &ctx->list); |
| 3243 | 3489 | ||
| 3244 | kref_put(&rdata->refcount, | ||
| 3245 | cifs_uncached_readdata_release); | ||
| 3246 | goto again; | 3490 | goto again; |
| 3247 | } else if (rdata->result) | 3491 | } else if (rdata->result) |
| 3248 | rc = rdata->result; | 3492 | rc = rdata->result; |
| 3249 | else | 3493 | else if (!ctx->direct_io) |
| 3250 | rc = cifs_readdata_to_iov(rdata, to); | 3494 | rc = cifs_readdata_to_iov(rdata, to); |
| 3251 | 3495 | ||
| 3252 | /* if there was a short read -- discard anything left */ | 3496 | /* if there was a short read -- discard anything left */ |
| 3253 | if (rdata->got_bytes && rdata->got_bytes < rdata->bytes) | 3497 | if (rdata->got_bytes && rdata->got_bytes < rdata->bytes) |
| 3254 | rc = -ENODATA; | 3498 | rc = -ENODATA; |
| 3499 | |||
| 3500 | ctx->total_len += rdata->got_bytes; | ||
| 3255 | } | 3501 | } |
| 3256 | list_del_init(&rdata->list); | 3502 | list_del_init(&rdata->list); |
| 3257 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); | 3503 | kref_put(&rdata->refcount, cifs_uncached_readdata_release); |
| 3258 | } | 3504 | } |
| 3259 | 3505 | ||
| 3260 | for (i = 0; i < ctx->npages; i++) { | 3506 | if (!ctx->direct_io) { |
| 3261 | if (ctx->should_dirty) | 3507 | for (i = 0; i < ctx->npages; i++) { |
| 3262 | set_page_dirty(ctx->bv[i].bv_page); | 3508 | if (ctx->should_dirty) |
| 3263 | put_page(ctx->bv[i].bv_page); | 3509 | set_page_dirty(ctx->bv[i].bv_page); |
| 3264 | } | 3510 | put_page(ctx->bv[i].bv_page); |
| 3511 | } | ||
| 3265 | 3512 | ||
| 3266 | ctx->total_len = ctx->len - iov_iter_count(to); | 3513 | ctx->total_len = ctx->len - iov_iter_count(to); |
| 3514 | } | ||
| 3267 | 3515 | ||
| 3268 | cifs_stats_bytes_read(tcon, ctx->total_len); | 3516 | cifs_stats_bytes_read(tcon, ctx->total_len); |
| 3269 | 3517 | ||
| @@ -3281,18 +3529,28 @@ again: | |||
| 3281 | complete(&ctx->done); | 3529 | complete(&ctx->done); |
| 3282 | } | 3530 | } |
| 3283 | 3531 | ||
| 3284 | ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | 3532 | static ssize_t __cifs_readv( |
| 3533 | struct kiocb *iocb, struct iov_iter *to, bool direct) | ||
| 3285 | { | 3534 | { |
| 3286 | struct file *file = iocb->ki_filp; | ||
| 3287 | ssize_t rc; | ||
| 3288 | size_t len; | 3535 | size_t len; |
| 3289 | ssize_t total_read = 0; | 3536 | struct file *file = iocb->ki_filp; |
| 3290 | loff_t offset = iocb->ki_pos; | ||
| 3291 | struct cifs_sb_info *cifs_sb; | 3537 | struct cifs_sb_info *cifs_sb; |
| 3292 | struct cifs_tcon *tcon; | ||
| 3293 | struct cifsFileInfo *cfile; | 3538 | struct cifsFileInfo *cfile; |
| 3539 | struct cifs_tcon *tcon; | ||
| 3540 | ssize_t rc, total_read = 0; | ||
| 3541 | loff_t offset = iocb->ki_pos; | ||
| 3294 | struct cifs_aio_ctx *ctx; | 3542 | struct cifs_aio_ctx *ctx; |
| 3295 | 3543 | ||
| 3544 | /* | ||
| 3545 | * iov_iter_get_pages_alloc() doesn't work with ITER_KVEC, | ||
| 3546 | * fall back to data copy read path | ||
| 3547 | * this could be improved by getting pages directly in ITER_KVEC | ||
| 3548 | */ | ||
| 3549 | if (direct && to->type & ITER_KVEC) { | ||
| 3550 | cifs_dbg(FYI, "use non-direct cifs_user_readv for kvec I/O\n"); | ||
| 3551 | direct = false; | ||
| 3552 | } | ||
| 3553 | |||
| 3296 | len = iov_iter_count(to); | 3554 | len = iov_iter_count(to); |
| 3297 | if (!len) | 3555 | if (!len) |
| 3298 | return 0; | 3556 | return 0; |
| @@ -3319,14 +3577,20 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | |||
| 3319 | if (iter_is_iovec(to)) | 3577 | if (iter_is_iovec(to)) |
| 3320 | ctx->should_dirty = true; | 3578 | ctx->should_dirty = true; |
| 3321 | 3579 | ||
| 3322 | rc = setup_aio_ctx_iter(ctx, to, READ); | 3580 | if (direct) { |
| 3323 | if (rc) { | 3581 | ctx->pos = offset; |
| 3324 | kref_put(&ctx->refcount, cifs_aio_ctx_release); | 3582 | ctx->direct_io = true; |
| 3325 | return rc; | 3583 | ctx->iter = *to; |
| 3584 | ctx->len = len; | ||
| 3585 | } else { | ||
| 3586 | rc = setup_aio_ctx_iter(ctx, to, READ); | ||
| 3587 | if (rc) { | ||
| 3588 | kref_put(&ctx->refcount, cifs_aio_ctx_release); | ||
| 3589 | return rc; | ||
| 3590 | } | ||
| 3591 | len = ctx->len; | ||
| 3326 | } | 3592 | } |
| 3327 | 3593 | ||
| 3328 | len = ctx->len; | ||
| 3329 | |||
| 3330 | /* grab a lock here due to read response handlers can access ctx */ | 3594 | /* grab a lock here due to read response handlers can access ctx */ |
| 3331 | mutex_lock(&ctx->aio_mutex); | 3595 | mutex_lock(&ctx->aio_mutex); |
| 3332 | 3596 | ||
| @@ -3368,6 +3632,16 @@ ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | |||
| 3368 | return rc; | 3632 | return rc; |
| 3369 | } | 3633 | } |
| 3370 | 3634 | ||
| 3635 | ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to) | ||
| 3636 | { | ||
| 3637 | return __cifs_readv(iocb, to, true); | ||
| 3638 | } | ||
| 3639 | |||
| 3640 | ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) | ||
| 3641 | { | ||
| 3642 | return __cifs_readv(iocb, to, false); | ||
| 3643 | } | ||
| 3644 | |||
| 3371 | ssize_t | 3645 | ssize_t |
| 3372 | cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) | 3646 | cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) |
| 3373 | { | 3647 | { |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 1023d78673fb..a81a9df997c1 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1320,8 +1320,8 @@ cifs_drop_nlink(struct inode *inode) | |||
| 1320 | /* | 1320 | /* |
| 1321 | * If d_inode(dentry) is null (usually meaning the cached dentry | 1321 | * If d_inode(dentry) is null (usually meaning the cached dentry |
| 1322 | * is a negative dentry) then we would attempt a standard SMB delete, but | 1322 | * is a negative dentry) then we would attempt a standard SMB delete, but |
| 1323 | * if that fails we can not attempt the fall back mechanisms on EACCESS | 1323 | * if that fails we can not attempt the fall back mechanisms on EACCES |
| 1324 | * but will return the EACCESS to the caller. Note that the VFS does not call | 1324 | * but will return the EACCES to the caller. Note that the VFS does not call |
| 1325 | * unlink on negative dentries currently. | 1325 | * unlink on negative dentries currently. |
| 1326 | */ | 1326 | */ |
| 1327 | int cifs_unlink(struct inode *dir, struct dentry *dentry) | 1327 | int cifs_unlink(struct inode *dir, struct dentry *dentry) |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 23c0a21a66f8..225fec1cfa67 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
| @@ -747,6 +747,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, | |||
| 747 | int rc = 0; | 747 | int rc = 0; |
| 748 | unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0; | 748 | unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0; |
| 749 | char *name, *value; | 749 | char *name, *value; |
| 750 | size_t buf_size = dst_size; | ||
| 750 | size_t name_len, value_len, user_name_len; | 751 | size_t name_len, value_len, user_name_len; |
| 751 | 752 | ||
| 752 | while (src_size > 0) { | 753 | while (src_size > 0) { |
| @@ -782,9 +783,10 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, | |||
| 782 | /* 'user.' plus a terminating null */ | 783 | /* 'user.' plus a terminating null */ |
| 783 | user_name_len = 5 + 1 + name_len; | 784 | user_name_len = 5 + 1 + name_len; |
| 784 | 785 | ||
| 785 | rc += user_name_len; | 786 | if (buf_size == 0) { |
| 786 | 787 | /* skip copy - calc size only */ | |
| 787 | if (dst_size >= user_name_len) { | 788 | rc += user_name_len; |
| 789 | } else if (dst_size >= user_name_len) { | ||
| 788 | dst_size -= user_name_len; | 790 | dst_size -= user_name_len; |
| 789 | memcpy(dst, "user.", 5); | 791 | memcpy(dst, "user.", 5); |
| 790 | dst += 5; | 792 | dst += 5; |
| @@ -792,8 +794,7 @@ move_smb2_ea_to_cifs(char *dst, size_t dst_size, | |||
| 792 | dst += name_len; | 794 | dst += name_len; |
| 793 | *dst = 0; | 795 | *dst = 0; |
| 794 | ++dst; | 796 | ++dst; |
| 795 | } else if (dst_size == 0) { | 797 | rc += user_name_len; |
| 796 | /* skip copy - calc size only */ | ||
| 797 | } else { | 798 | } else { |
| 798 | /* stop before overrun buffer */ | 799 | /* stop before overrun buffer */ |
| 799 | rc = -ERANGE; | 800 | rc = -ERANGE; |
| @@ -1078,6 +1079,9 @@ smb2_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) | |||
| 1078 | 1079 | ||
| 1079 | cfile->fid.persistent_fid = fid->persistent_fid; | 1080 | cfile->fid.persistent_fid = fid->persistent_fid; |
| 1080 | cfile->fid.volatile_fid = fid->volatile_fid; | 1081 | cfile->fid.volatile_fid = fid->volatile_fid; |
| 1082 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 1083 | cfile->fid.mid = fid->mid; | ||
| 1084 | #endif /* CIFS_DEBUG2 */ | ||
| 1081 | server->ops->set_oplock_level(cinode, oplock, fid->epoch, | 1085 | server->ops->set_oplock_level(cinode, oplock, fid->epoch, |
| 1082 | &fid->purge_cache); | 1086 | &fid->purge_cache); |
| 1083 | cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode); | 1087 | cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode); |
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 7d7b016fe8bb..27f86537a5d1 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
| @@ -1512,7 +1512,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1512 | rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); | 1512 | rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov); |
| 1513 | cifs_small_buf_release(req); | 1513 | cifs_small_buf_release(req); |
| 1514 | rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; | 1514 | rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base; |
| 1515 | 1515 | trace_smb3_tcon(xid, tcon->tid, ses->Suid, tree, rc); | |
| 1516 | if (rc != 0) { | 1516 | if (rc != 0) { |
| 1517 | if (tcon) { | 1517 | if (tcon) { |
| 1518 | cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); | 1518 | cifs_stats_fail_inc(tcon, SMB2_TREE_CONNECT_HE); |
| @@ -1559,6 +1559,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree, | |||
| 1559 | if (tcon->ses->server->ops->validate_negotiate) | 1559 | if (tcon->ses->server->ops->validate_negotiate) |
| 1560 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); | 1560 | rc = tcon->ses->server->ops->validate_negotiate(xid, tcon); |
| 1561 | tcon_exit: | 1561 | tcon_exit: |
| 1562 | |||
| 1562 | free_rsp_buf(resp_buftype, rsp); | 1563 | free_rsp_buf(resp_buftype, rsp); |
| 1563 | kfree(unc_path); | 1564 | kfree(unc_path); |
| 1564 | return rc; | 1565 | return rc; |
| @@ -2308,6 +2309,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, | |||
| 2308 | atomic_inc(&tcon->num_remote_opens); | 2309 | atomic_inc(&tcon->num_remote_opens); |
| 2309 | oparms->fid->persistent_fid = rsp->PersistentFileId; | 2310 | oparms->fid->persistent_fid = rsp->PersistentFileId; |
| 2310 | oparms->fid->volatile_fid = rsp->VolatileFileId; | 2311 | oparms->fid->volatile_fid = rsp->VolatileFileId; |
| 2312 | #ifdef CONFIG_CIFS_DEBUG2 | ||
| 2313 | oparms->fid->mid = le64_to_cpu(rsp->sync_hdr.MessageId); | ||
| 2314 | #endif /* CIFS_DEBUG2 */ | ||
| 2311 | 2315 | ||
| 2312 | if (buf) { | 2316 | if (buf) { |
| 2313 | memcpy(buf, &rsp->CreationTime, 32); | 2317 | memcpy(buf, &rsp->CreationTime, 32); |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index f753f424d7f1..5671d5ee7f58 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
| @@ -842,6 +842,41 @@ struct fsctl_get_integrity_information_rsp { | |||
| 842 | /* Integrity flags for above */ | 842 | /* Integrity flags for above */ |
| 843 | #define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 | 843 | #define FSCTL_INTEGRITY_FLAG_CHECKSUM_ENFORCEMENT_OFF 0x00000001 |
| 844 | 844 | ||
| 845 | /* Reparse structures - see MS-FSCC 2.1.2 */ | ||
| 846 | |||
| 847 | /* struct fsctl_reparse_info_req is empty, only response structs (see below) */ | ||
| 848 | |||
| 849 | struct reparse_data_buffer { | ||
| 850 | __le32 ReparseTag; | ||
| 851 | __le16 ReparseDataLength; | ||
| 852 | __u16 Reserved; | ||
| 853 | __u8 DataBuffer[0]; /* Variable Length */ | ||
| 854 | } __packed; | ||
| 855 | |||
| 856 | struct reparse_guid_data_buffer { | ||
| 857 | __le32 ReparseTag; | ||
| 858 | __le16 ReparseDataLength; | ||
| 859 | __u16 Reserved; | ||
| 860 | __u8 ReparseGuid[16]; | ||
| 861 | __u8 DataBuffer[0]; /* Variable Length */ | ||
| 862 | } __packed; | ||
| 863 | |||
| 864 | struct reparse_mount_point_data_buffer { | ||
| 865 | __le32 ReparseTag; | ||
| 866 | __le16 ReparseDataLength; | ||
| 867 | __u16 Reserved; | ||
| 868 | __le16 SubstituteNameOffset; | ||
| 869 | __le16 SubstituteNameLength; | ||
| 870 | __le16 PrintNameOffset; | ||
| 871 | __le16 PrintNameLength; | ||
| 872 | __u8 PathBuffer[0]; /* Variable Length */ | ||
| 873 | } __packed; | ||
| 874 | |||
| 875 | /* See MS-FSCC 2.1.2.4 and cifspdu.h for struct reparse_symlink_data */ | ||
| 876 | |||
| 877 | /* See MS-FSCC 2.1.2.6 and cifspdu.h for struct reparse_posix_data */ | ||
| 878 | |||
| 879 | |||
| 845 | /* See MS-DFSC 2.2.2 */ | 880 | /* See MS-DFSC 2.2.2 */ |
| 846 | struct fsctl_get_dfs_referral_req { | 881 | struct fsctl_get_dfs_referral_req { |
| 847 | __le16 MaxReferralLevel; | 882 | __le16 MaxReferralLevel; |
diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h index cce8414fe7ec..fb049809555f 100644 --- a/fs/cifs/trace.h +++ b/fs/cifs/trace.h | |||
| @@ -374,6 +374,48 @@ DEFINE_SMB3_ENTER_EXIT_EVENT(enter); | |||
| 374 | DEFINE_SMB3_ENTER_EXIT_EVENT(exit_done); | 374 | DEFINE_SMB3_ENTER_EXIT_EVENT(exit_done); |
| 375 | 375 | ||
| 376 | /* | 376 | /* |
| 377 | * For SMB2/SMB3 tree connect | ||
| 378 | */ | ||
| 379 | |||
| 380 | DECLARE_EVENT_CLASS(smb3_tcon_class, | ||
| 381 | TP_PROTO(unsigned int xid, | ||
| 382 | __u32 tid, | ||
| 383 | __u64 sesid, | ||
| 384 | const char *unc_name, | ||
| 385 | int rc), | ||
| 386 | TP_ARGS(xid, tid, sesid, unc_name, rc), | ||
| 387 | TP_STRUCT__entry( | ||
| 388 | __field(unsigned int, xid) | ||
| 389 | __field(__u32, tid) | ||
| 390 | __field(__u64, sesid) | ||
| 391 | __field(const char *, unc_name) | ||
| 392 | __field(int, rc) | ||
| 393 | ), | ||
| 394 | TP_fast_assign( | ||
| 395 | __entry->xid = xid; | ||
| 396 | __entry->tid = tid; | ||
| 397 | __entry->sesid = sesid; | ||
| 398 | __entry->unc_name = unc_name; | ||
| 399 | __entry->rc = rc; | ||
| 400 | ), | ||
| 401 | TP_printk("xid=%u sid=0x%llx tid=0x%x unc_name=%s rc=%d", | ||
| 402 | __entry->xid, __entry->sesid, __entry->tid, | ||
| 403 | __entry->unc_name, __entry->rc) | ||
| 404 | ) | ||
| 405 | |||
| 406 | #define DEFINE_SMB3_TCON_EVENT(name) \ | ||
| 407 | DEFINE_EVENT(smb3_tcon_class, smb3_##name, \ | ||
| 408 | TP_PROTO(unsigned int xid, \ | ||
| 409 | __u32 tid, \ | ||
| 410 | __u64 sesid, \ | ||
| 411 | const char *unc_name, \ | ||
| 412 | int rc), \ | ||
| 413 | TP_ARGS(xid, tid, sesid, unc_name, rc)) | ||
| 414 | |||
| 415 | DEFINE_SMB3_TCON_EVENT(tcon); | ||
| 416 | |||
| 417 | |||
| 418 | /* | ||
| 377 | * For smb2/smb3 open call | 419 | * For smb2/smb3 open call |
| 378 | */ | 420 | */ |
| 379 | DECLARE_EVENT_CLASS(smb3_open_err_class, | 421 | DECLARE_EVENT_CLASS(smb3_open_err_class, |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 2aa62d58d8dd..db7590178dfc 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
| @@ -374,13 +374,13 @@ static int io_submit_init_bio(struct ext4_io_submit *io, | |||
| 374 | bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); | 374 | bio = bio_alloc(GFP_NOIO, BIO_MAX_PAGES); |
| 375 | if (!bio) | 375 | if (!bio) |
| 376 | return -ENOMEM; | 376 | return -ENOMEM; |
| 377 | wbc_init_bio(io->io_wbc, bio); | ||
| 377 | bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); | 378 | bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9); |
| 378 | bio_set_dev(bio, bh->b_bdev); | 379 | bio_set_dev(bio, bh->b_bdev); |
| 379 | bio->bi_end_io = ext4_end_bio; | 380 | bio->bi_end_io = ext4_end_bio; |
| 380 | bio->bi_private = ext4_get_io_end(io->io_end); | 381 | bio->bi_private = ext4_get_io_end(io->io_end); |
| 381 | io->io_bio = bio; | 382 | io->io_bio = bio; |
| 382 | io->io_next_block = bh->b_blocknr; | 383 | io->io_next_block = bh->b_blocknr; |
| 383 | wbc_init_bio(io->io_wbc, bio); | ||
| 384 | return 0; | 384 | return 0; |
| 385 | } | 385 | } |
| 386 | 386 | ||
diff --git a/fs/ioctl.c b/fs/ioctl.c index 0400297c8d72..d64f622cac8b 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
| @@ -223,6 +223,7 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, | |||
| 223 | u64 off, u64 olen, u64 destoff) | 223 | u64 off, u64 olen, u64 destoff) |
| 224 | { | 224 | { |
| 225 | struct fd src_file = fdget(srcfd); | 225 | struct fd src_file = fdget(srcfd); |
| 226 | loff_t cloned; | ||
| 226 | int ret; | 227 | int ret; |
| 227 | 228 | ||
| 228 | if (!src_file.file) | 229 | if (!src_file.file) |
| @@ -230,7 +231,14 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, | |||
| 230 | ret = -EXDEV; | 231 | ret = -EXDEV; |
| 231 | if (src_file.file->f_path.mnt != dst_file->f_path.mnt) | 232 | if (src_file.file->f_path.mnt != dst_file->f_path.mnt) |
| 232 | goto fdput; | 233 | goto fdput; |
| 233 | ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen); | 234 | cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff, |
| 235 | olen, 0); | ||
| 236 | if (cloned < 0) | ||
| 237 | ret = cloned; | ||
| 238 | else if (olen && cloned != olen) | ||
| 239 | ret = -EINVAL; | ||
| 240 | else | ||
| 241 | ret = 0; | ||
| 234 | fdput: | 242 | fdput: |
| 235 | fdput(src_file); | 243 | fdput(src_file); |
| 236 | return ret; | 244 | return ret; |
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index 4288a6ecaf75..46d691ba04bc 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c | |||
| @@ -180,8 +180,9 @@ static long nfs42_fallocate(struct file *filep, int mode, loff_t offset, loff_t | |||
| 180 | return nfs42_proc_allocate(filep, offset, len); | 180 | return nfs42_proc_allocate(filep, offset, len); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | static int nfs42_clone_file_range(struct file *src_file, loff_t src_off, | 183 | static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off, |
| 184 | struct file *dst_file, loff_t dst_off, u64 count) | 184 | struct file *dst_file, loff_t dst_off, loff_t count, |
| 185 | unsigned int remap_flags) | ||
| 185 | { | 186 | { |
| 186 | struct inode *dst_inode = file_inode(dst_file); | 187 | struct inode *dst_inode = file_inode(dst_file); |
| 187 | struct nfs_server *server = NFS_SERVER(dst_inode); | 188 | struct nfs_server *server = NFS_SERVER(dst_inode); |
| @@ -190,6 +191,9 @@ static int nfs42_clone_file_range(struct file *src_file, loff_t src_off, | |||
| 190 | bool same_inode = false; | 191 | bool same_inode = false; |
| 191 | int ret; | 192 | int ret; |
| 192 | 193 | ||
| 194 | if (remap_flags & ~REMAP_FILE_ADVISORY) | ||
| 195 | return -EINVAL; | ||
| 196 | |||
| 193 | /* check alignment w.r.t. clone_blksize */ | 197 | /* check alignment w.r.t. clone_blksize */ |
| 194 | ret = -EINVAL; | 198 | ret = -EINVAL; |
| 195 | if (bs) { | 199 | if (bs) { |
| @@ -240,7 +244,7 @@ out_unlock: | |||
| 240 | inode_unlock(src_inode); | 244 | inode_unlock(src_inode); |
| 241 | } | 245 | } |
| 242 | out: | 246 | out: |
| 243 | return ret; | 247 | return ret < 0 ? ret : count; |
| 244 | } | 248 | } |
| 245 | #endif /* CONFIG_NFS_V4_2 */ | 249 | #endif /* CONFIG_NFS_V4_2 */ |
| 246 | 250 | ||
| @@ -262,7 +266,7 @@ const struct file_operations nfs4_file_operations = { | |||
| 262 | .copy_file_range = nfs4_copy_file_range, | 266 | .copy_file_range = nfs4_copy_file_range, |
| 263 | .llseek = nfs4_file_llseek, | 267 | .llseek = nfs4_file_llseek, |
| 264 | .fallocate = nfs42_fallocate, | 268 | .fallocate = nfs42_fallocate, |
| 265 | .clone_file_range = nfs42_clone_file_range, | 269 | .remap_file_range = nfs42_remap_file_range, |
| 266 | #else | 270 | #else |
| 267 | .llseek = nfs_file_llseek, | 271 | .llseek = nfs_file_llseek, |
| 268 | #endif | 272 | #endif |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index fb28be653014..eb67098117b4 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -541,8 +541,12 @@ __be32 nfsd4_set_nfs4_label(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
| 541 | __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, | 541 | __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst, |
| 542 | u64 dst_pos, u64 count) | 542 | u64 dst_pos, u64 count) |
| 543 | { | 543 | { |
| 544 | return nfserrno(vfs_clone_file_range(src, src_pos, dst, dst_pos, | 544 | loff_t cloned; |
| 545 | count)); | 545 | |
| 546 | cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0); | ||
| 547 | if (count && cloned != count) | ||
| 548 | cloned = -EINVAL; | ||
| 549 | return nfserrno(cloned < 0 ? cloned : 0); | ||
| 546 | } | 550 | } |
| 547 | 551 | ||
| 548 | ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, | 552 | ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst, |
diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index 1d098c3c00e0..4ebbd57cbf84 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c | |||
| @@ -99,25 +99,34 @@ out: | |||
| 99 | return ret; | 99 | return ret; |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /* Caller must provide a bhs[] with all NULL or non-NULL entries, so it | ||
| 103 | * will be easier to handle read failure. | ||
| 104 | */ | ||
| 102 | int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, | 105 | int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, |
| 103 | unsigned int nr, struct buffer_head *bhs[]) | 106 | unsigned int nr, struct buffer_head *bhs[]) |
| 104 | { | 107 | { |
| 105 | int status = 0; | 108 | int status = 0; |
| 106 | unsigned int i; | 109 | unsigned int i; |
| 107 | struct buffer_head *bh; | 110 | struct buffer_head *bh; |
| 111 | int new_bh = 0; | ||
| 108 | 112 | ||
| 109 | trace_ocfs2_read_blocks_sync((unsigned long long)block, nr); | 113 | trace_ocfs2_read_blocks_sync((unsigned long long)block, nr); |
| 110 | 114 | ||
| 111 | if (!nr) | 115 | if (!nr) |
| 112 | goto bail; | 116 | goto bail; |
| 113 | 117 | ||
| 118 | /* Don't put buffer head and re-assign it to NULL if it is allocated | ||
| 119 | * outside since the caller can't be aware of this alternation! | ||
| 120 | */ | ||
| 121 | new_bh = (bhs[0] == NULL); | ||
| 122 | |||
| 114 | for (i = 0 ; i < nr ; i++) { | 123 | for (i = 0 ; i < nr ; i++) { |
| 115 | if (bhs[i] == NULL) { | 124 | if (bhs[i] == NULL) { |
| 116 | bhs[i] = sb_getblk(osb->sb, block++); | 125 | bhs[i] = sb_getblk(osb->sb, block++); |
| 117 | if (bhs[i] == NULL) { | 126 | if (bhs[i] == NULL) { |
| 118 | status = -ENOMEM; | 127 | status = -ENOMEM; |
| 119 | mlog_errno(status); | 128 | mlog_errno(status); |
| 120 | goto bail; | 129 | break; |
| 121 | } | 130 | } |
| 122 | } | 131 | } |
| 123 | bh = bhs[i]; | 132 | bh = bhs[i]; |
| @@ -158,9 +167,26 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, | |||
| 158 | submit_bh(REQ_OP_READ, 0, bh); | 167 | submit_bh(REQ_OP_READ, 0, bh); |
| 159 | } | 168 | } |
| 160 | 169 | ||
| 170 | read_failure: | ||
| 161 | for (i = nr; i > 0; i--) { | 171 | for (i = nr; i > 0; i--) { |
| 162 | bh = bhs[i - 1]; | 172 | bh = bhs[i - 1]; |
| 163 | 173 | ||
| 174 | if (unlikely(status)) { | ||
| 175 | if (new_bh && bh) { | ||
| 176 | /* If middle bh fails, let previous bh | ||
| 177 | * finish its read and then put it to | ||
| 178 | * aovoid bh leak | ||
| 179 | */ | ||
| 180 | if (!buffer_jbd(bh)) | ||
| 181 | wait_on_buffer(bh); | ||
| 182 | put_bh(bh); | ||
| 183 | bhs[i - 1] = NULL; | ||
| 184 | } else if (bh && buffer_uptodate(bh)) { | ||
| 185 | clear_buffer_uptodate(bh); | ||
| 186 | } | ||
| 187 | continue; | ||
| 188 | } | ||
| 189 | |||
| 164 | /* No need to wait on the buffer if it's managed by JBD. */ | 190 | /* No need to wait on the buffer if it's managed by JBD. */ |
| 165 | if (!buffer_jbd(bh)) | 191 | if (!buffer_jbd(bh)) |
| 166 | wait_on_buffer(bh); | 192 | wait_on_buffer(bh); |
| @@ -170,8 +196,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, | |||
| 170 | * so we can safely record this and loop back | 196 | * so we can safely record this and loop back |
| 171 | * to cleanup the other buffers. */ | 197 | * to cleanup the other buffers. */ |
| 172 | status = -EIO; | 198 | status = -EIO; |
| 173 | put_bh(bh); | 199 | goto read_failure; |
| 174 | bhs[i - 1] = NULL; | ||
| 175 | } | 200 | } |
| 176 | } | 201 | } |
| 177 | 202 | ||
| @@ -179,6 +204,9 @@ bail: | |||
| 179 | return status; | 204 | return status; |
| 180 | } | 205 | } |
| 181 | 206 | ||
| 207 | /* Caller must provide a bhs[] with all NULL or non-NULL entries, so it | ||
| 208 | * will be easier to handle read failure. | ||
| 209 | */ | ||
| 182 | int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | 210 | int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, |
| 183 | struct buffer_head *bhs[], int flags, | 211 | struct buffer_head *bhs[], int flags, |
| 184 | int (*validate)(struct super_block *sb, | 212 | int (*validate)(struct super_block *sb, |
| @@ -188,6 +216,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | |||
| 188 | int i, ignore_cache = 0; | 216 | int i, ignore_cache = 0; |
| 189 | struct buffer_head *bh; | 217 | struct buffer_head *bh; |
| 190 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); | 218 | struct super_block *sb = ocfs2_metadata_cache_get_super(ci); |
| 219 | int new_bh = 0; | ||
| 191 | 220 | ||
| 192 | trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags); | 221 | trace_ocfs2_read_blocks_begin(ci, (unsigned long long)block, nr, flags); |
| 193 | 222 | ||
| @@ -213,6 +242,11 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | |||
| 213 | goto bail; | 242 | goto bail; |
| 214 | } | 243 | } |
| 215 | 244 | ||
| 245 | /* Don't put buffer head and re-assign it to NULL if it is allocated | ||
| 246 | * outside since the caller can't be aware of this alternation! | ||
| 247 | */ | ||
| 248 | new_bh = (bhs[0] == NULL); | ||
| 249 | |||
| 216 | ocfs2_metadata_cache_io_lock(ci); | 250 | ocfs2_metadata_cache_io_lock(ci); |
| 217 | for (i = 0 ; i < nr ; i++) { | 251 | for (i = 0 ; i < nr ; i++) { |
| 218 | if (bhs[i] == NULL) { | 252 | if (bhs[i] == NULL) { |
| @@ -221,7 +255,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | |||
| 221 | ocfs2_metadata_cache_io_unlock(ci); | 255 | ocfs2_metadata_cache_io_unlock(ci); |
| 222 | status = -ENOMEM; | 256 | status = -ENOMEM; |
| 223 | mlog_errno(status); | 257 | mlog_errno(status); |
| 224 | goto bail; | 258 | /* Don't forget to put previous bh! */ |
| 259 | break; | ||
| 225 | } | 260 | } |
| 226 | } | 261 | } |
| 227 | bh = bhs[i]; | 262 | bh = bhs[i]; |
| @@ -316,16 +351,27 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | |||
| 316 | } | 351 | } |
| 317 | } | 352 | } |
| 318 | 353 | ||
| 319 | status = 0; | 354 | read_failure: |
| 320 | |||
| 321 | for (i = (nr - 1); i >= 0; i--) { | 355 | for (i = (nr - 1); i >= 0; i--) { |
| 322 | bh = bhs[i]; | 356 | bh = bhs[i]; |
| 323 | 357 | ||
| 324 | if (!(flags & OCFS2_BH_READAHEAD)) { | 358 | if (!(flags & OCFS2_BH_READAHEAD)) { |
| 325 | if (status) { | 359 | if (unlikely(status)) { |
| 326 | /* Clear the rest of the buffers on error */ | 360 | /* Clear the buffers on error including those |
| 327 | put_bh(bh); | 361 | * ever succeeded in reading |
| 328 | bhs[i] = NULL; | 362 | */ |
| 363 | if (new_bh && bh) { | ||
| 364 | /* If middle bh fails, let previous bh | ||
| 365 | * finish its read and then put it to | ||
| 366 | * aovoid bh leak | ||
| 367 | */ | ||
| 368 | if (!buffer_jbd(bh)) | ||
| 369 | wait_on_buffer(bh); | ||
| 370 | put_bh(bh); | ||
| 371 | bhs[i] = NULL; | ||
| 372 | } else if (bh && buffer_uptodate(bh)) { | ||
| 373 | clear_buffer_uptodate(bh); | ||
| 374 | } | ||
| 329 | continue; | 375 | continue; |
| 330 | } | 376 | } |
| 331 | /* We know this can't have changed as we hold the | 377 | /* We know this can't have changed as we hold the |
| @@ -343,9 +389,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | |||
| 343 | * uptodate. */ | 389 | * uptodate. */ |
| 344 | status = -EIO; | 390 | status = -EIO; |
| 345 | clear_buffer_needs_validate(bh); | 391 | clear_buffer_needs_validate(bh); |
| 346 | put_bh(bh); | 392 | goto read_failure; |
| 347 | bhs[i] = NULL; | ||
| 348 | continue; | ||
| 349 | } | 393 | } |
| 350 | 394 | ||
| 351 | if (buffer_needs_validate(bh)) { | 395 | if (buffer_needs_validate(bh)) { |
| @@ -355,11 +399,8 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, | |||
| 355 | BUG_ON(buffer_jbd(bh)); | 399 | BUG_ON(buffer_jbd(bh)); |
| 356 | clear_buffer_needs_validate(bh); | 400 | clear_buffer_needs_validate(bh); |
| 357 | status = validate(sb, bh); | 401 | status = validate(sb, bh); |
| 358 | if (status) { | 402 | if (status) |
| 359 | put_bh(bh); | 403 | goto read_failure; |
| 360 | bhs[i] = NULL; | ||
| 361 | continue; | ||
| 362 | } | ||
| 363 | } | 404 | } |
| 364 | } | 405 | } |
| 365 | 406 | ||
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index b048d4fa3959..c121abbdfc7d 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c | |||
| @@ -1897,8 +1897,7 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, | |||
| 1897 | /* On error, skip the f_pos to the | 1897 | /* On error, skip the f_pos to the |
| 1898 | next block. */ | 1898 | next block. */ |
| 1899 | ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1; | 1899 | ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1; |
| 1900 | brelse(bh); | 1900 | break; |
| 1901 | continue; | ||
| 1902 | } | 1901 | } |
| 1903 | if (le64_to_cpu(de->inode)) { | 1902 | if (le64_to_cpu(de->inode)) { |
| 1904 | unsigned char d_type = DT_UNKNOWN; | 1903 | unsigned char d_type = DT_UNKNOWN; |
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 933aac5da193..7c835824247e 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -2123,10 +2123,10 @@ static void ocfs2_downconvert_on_unlock(struct ocfs2_super *osb, | |||
| 2123 | 2123 | ||
| 2124 | /* LVB only has room for 64 bits of time here so we pack it for | 2124 | /* LVB only has room for 64 bits of time here so we pack it for |
| 2125 | * now. */ | 2125 | * now. */ |
| 2126 | static u64 ocfs2_pack_timespec(struct timespec *spec) | 2126 | static u64 ocfs2_pack_timespec(struct timespec64 *spec) |
| 2127 | { | 2127 | { |
| 2128 | u64 res; | 2128 | u64 res; |
| 2129 | u64 sec = spec->tv_sec; | 2129 | u64 sec = clamp_t(time64_t, spec->tv_sec, 0, 0x3ffffffffull); |
| 2130 | u32 nsec = spec->tv_nsec; | 2130 | u32 nsec = spec->tv_nsec; |
| 2131 | 2131 | ||
| 2132 | res = (sec << OCFS2_SEC_SHIFT) | (nsec & OCFS2_NSEC_MASK); | 2132 | res = (sec << OCFS2_SEC_SHIFT) | (nsec & OCFS2_NSEC_MASK); |
| @@ -2142,7 +2142,6 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) | |||
| 2142 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 2142 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 2143 | struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; | 2143 | struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; |
| 2144 | struct ocfs2_meta_lvb *lvb; | 2144 | struct ocfs2_meta_lvb *lvb; |
| 2145 | struct timespec ts; | ||
| 2146 | 2145 | ||
| 2147 | lvb = ocfs2_dlm_lvb(&lockres->l_lksb); | 2146 | lvb = ocfs2_dlm_lvb(&lockres->l_lksb); |
| 2148 | 2147 | ||
| @@ -2163,15 +2162,12 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode) | |||
| 2163 | lvb->lvb_igid = cpu_to_be32(i_gid_read(inode)); | 2162 | lvb->lvb_igid = cpu_to_be32(i_gid_read(inode)); |
| 2164 | lvb->lvb_imode = cpu_to_be16(inode->i_mode); | 2163 | lvb->lvb_imode = cpu_to_be16(inode->i_mode); |
| 2165 | lvb->lvb_inlink = cpu_to_be16(inode->i_nlink); | 2164 | lvb->lvb_inlink = cpu_to_be16(inode->i_nlink); |
| 2166 | ts = timespec64_to_timespec(inode->i_atime); | ||
| 2167 | lvb->lvb_iatime_packed = | 2165 | lvb->lvb_iatime_packed = |
| 2168 | cpu_to_be64(ocfs2_pack_timespec(&ts)); | 2166 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_atime)); |
| 2169 | ts = timespec64_to_timespec(inode->i_ctime); | ||
| 2170 | lvb->lvb_ictime_packed = | 2167 | lvb->lvb_ictime_packed = |
| 2171 | cpu_to_be64(ocfs2_pack_timespec(&ts)); | 2168 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); |
| 2172 | ts = timespec64_to_timespec(inode->i_mtime); | ||
| 2173 | lvb->lvb_imtime_packed = | 2169 | lvb->lvb_imtime_packed = |
| 2174 | cpu_to_be64(ocfs2_pack_timespec(&ts)); | 2170 | cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); |
| 2175 | lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); | 2171 | lvb->lvb_iattr = cpu_to_be32(oi->ip_attr); |
| 2176 | lvb->lvb_idynfeatures = cpu_to_be16(oi->ip_dyn_features); | 2172 | lvb->lvb_idynfeatures = cpu_to_be16(oi->ip_dyn_features); |
| 2177 | lvb->lvb_igeneration = cpu_to_be32(inode->i_generation); | 2173 | lvb->lvb_igeneration = cpu_to_be32(inode->i_generation); |
| @@ -2180,7 +2176,7 @@ out: | |||
| 2180 | mlog_meta_lvb(0, lockres); | 2176 | mlog_meta_lvb(0, lockres); |
| 2181 | } | 2177 | } |
| 2182 | 2178 | ||
| 2183 | static void ocfs2_unpack_timespec(struct timespec *spec, | 2179 | static void ocfs2_unpack_timespec(struct timespec64 *spec, |
| 2184 | u64 packed_time) | 2180 | u64 packed_time) |
| 2185 | { | 2181 | { |
| 2186 | spec->tv_sec = packed_time >> OCFS2_SEC_SHIFT; | 2182 | spec->tv_sec = packed_time >> OCFS2_SEC_SHIFT; |
| @@ -2189,7 +2185,6 @@ static void ocfs2_unpack_timespec(struct timespec *spec, | |||
| 2189 | 2185 | ||
| 2190 | static void ocfs2_refresh_inode_from_lvb(struct inode *inode) | 2186 | static void ocfs2_refresh_inode_from_lvb(struct inode *inode) |
| 2191 | { | 2187 | { |
| 2192 | struct timespec ts; | ||
| 2193 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 2188 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
| 2194 | struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; | 2189 | struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; |
| 2195 | struct ocfs2_meta_lvb *lvb; | 2190 | struct ocfs2_meta_lvb *lvb; |
| @@ -2217,15 +2212,12 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode) | |||
| 2217 | i_gid_write(inode, be32_to_cpu(lvb->lvb_igid)); | 2212 | i_gid_write(inode, be32_to_cpu(lvb->lvb_igid)); |
| 2218 | inode->i_mode = be16_to_cpu(lvb->lvb_imode); | 2213 | inode->i_mode = be16_to_cpu(lvb->lvb_imode); |
| 2219 | set_nlink(inode, be16_to_cpu(lvb->lvb_inlink)); | 2214 | set_nlink(inode, be16_to_cpu(lvb->lvb_inlink)); |
| 2220 | ocfs2_unpack_timespec(&ts, | 2215 | ocfs2_unpack_timespec(&inode->i_atime, |
| 2221 | be64_to_cpu(lvb->lvb_iatime_packed)); | 2216 | be64_to_cpu(lvb->lvb_iatime_packed)); |
| 2222 | inode->i_atime = timespec_to_timespec64(ts); | 2217 | ocfs2_unpack_timespec(&inode->i_mtime, |
| 2223 | ocfs2_unpack_timespec(&ts, | ||
| 2224 | be64_to_cpu(lvb->lvb_imtime_packed)); | 2218 | be64_to_cpu(lvb->lvb_imtime_packed)); |
| 2225 | inode->i_mtime = timespec_to_timespec64(ts); | 2219 | ocfs2_unpack_timespec(&inode->i_ctime, |
| 2226 | ocfs2_unpack_timespec(&ts, | ||
| 2227 | be64_to_cpu(lvb->lvb_ictime_packed)); | 2220 | be64_to_cpu(lvb->lvb_ictime_packed)); |
| 2228 | inode->i_ctime = timespec_to_timespec64(ts); | ||
| 2229 | spin_unlock(&oi->ip_lock); | 2221 | spin_unlock(&oi->ip_lock); |
| 2230 | } | 2222 | } |
| 2231 | 2223 | ||
| @@ -3603,7 +3595,7 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, | |||
| 3603 | * we can recover correctly from node failure. Otherwise, we may get | 3595 | * we can recover correctly from node failure. Otherwise, we may get |
| 3604 | * invalid LVB in LKB, but without DLM_SBF_VALNOTVALID being set. | 3596 | * invalid LVB in LKB, but without DLM_SBF_VALNOTVALID being set. |
| 3605 | */ | 3597 | */ |
| 3606 | if (!ocfs2_is_o2cb_active() && | 3598 | if (ocfs2_userspace_stack(osb) && |
| 3607 | lockres->l_ops->flags & LOCK_TYPE_USES_LVB) | 3599 | lockres->l_ops->flags & LOCK_TYPE_USES_LVB) |
| 3608 | lvb = 1; | 3600 | lvb = 1; |
| 3609 | 3601 | ||
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 9fa35cb6f6e0..d640c5f8a85d 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -2343,7 +2343,7 @@ static ssize_t ocfs2_file_write_iter(struct kiocb *iocb, | |||
| 2343 | 2343 | ||
| 2344 | written = __generic_file_write_iter(iocb, from); | 2344 | written = __generic_file_write_iter(iocb, from); |
| 2345 | /* buffered aio wouldn't have proper lock coverage today */ | 2345 | /* buffered aio wouldn't have proper lock coverage today */ |
| 2346 | BUG_ON(written == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT)); | 2346 | BUG_ON(written == -EIOCBQUEUED && !direct_io); |
| 2347 | 2347 | ||
| 2348 | /* | 2348 | /* |
| 2349 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io | 2349 | * deep in g_f_a_w_n()->ocfs2_direct_IO we pass in a ocfs2_dio_end_io |
| @@ -2463,7 +2463,7 @@ static ssize_t ocfs2_file_read_iter(struct kiocb *iocb, | |||
| 2463 | trace_generic_file_read_iter_ret(ret); | 2463 | trace_generic_file_read_iter_ret(ret); |
| 2464 | 2464 | ||
| 2465 | /* buffered aio wouldn't have proper lock coverage today */ | 2465 | /* buffered aio wouldn't have proper lock coverage today */ |
| 2466 | BUG_ON(ret == -EIOCBQUEUED && !(iocb->ki_flags & IOCB_DIRECT)); | 2466 | BUG_ON(ret == -EIOCBQUEUED && !direct_io); |
| 2467 | 2467 | ||
| 2468 | /* see ocfs2_file_write_iter */ | 2468 | /* see ocfs2_file_write_iter */ |
| 2469 | if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) { | 2469 | if (ret == -EIOCBQUEUED || !ocfs2_iocb_is_rw_locked(iocb)) { |
| @@ -2527,24 +2527,79 @@ out: | |||
| 2527 | return offset; | 2527 | return offset; |
| 2528 | } | 2528 | } |
| 2529 | 2529 | ||
| 2530 | static int ocfs2_file_clone_range(struct file *file_in, | 2530 | static loff_t ocfs2_remap_file_range(struct file *file_in, loff_t pos_in, |
| 2531 | loff_t pos_in, | 2531 | struct file *file_out, loff_t pos_out, |
| 2532 | struct file *file_out, | 2532 | loff_t len, unsigned int remap_flags) |
| 2533 | loff_t pos_out, | ||
| 2534 | u64 len) | ||
| 2535 | { | 2533 | { |
| 2536 | return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, | 2534 | struct inode *inode_in = file_inode(file_in); |
| 2537 | len, false); | 2535 | struct inode *inode_out = file_inode(file_out); |
| 2538 | } | 2536 | struct ocfs2_super *osb = OCFS2_SB(inode_in->i_sb); |
| 2537 | struct buffer_head *in_bh = NULL, *out_bh = NULL; | ||
| 2538 | bool same_inode = (inode_in == inode_out); | ||
| 2539 | loff_t remapped = 0; | ||
| 2540 | ssize_t ret; | ||
| 2539 | 2541 | ||
| 2540 | static int ocfs2_file_dedupe_range(struct file *file_in, | 2542 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) |
| 2541 | loff_t pos_in, | 2543 | return -EINVAL; |
| 2542 | struct file *file_out, | 2544 | if (!ocfs2_refcount_tree(osb)) |
| 2543 | loff_t pos_out, | 2545 | return -EOPNOTSUPP; |
| 2544 | u64 len) | 2546 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) |
| 2545 | { | 2547 | return -EROFS; |
| 2546 | return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out, | 2548 | |
| 2547 | len, true); | 2549 | /* Lock both files against IO */ |
| 2550 | ret = ocfs2_reflink_inodes_lock(inode_in, &in_bh, inode_out, &out_bh); | ||
| 2551 | if (ret) | ||
| 2552 | return ret; | ||
| 2553 | |||
| 2554 | /* Check file eligibility and prepare for block sharing. */ | ||
| 2555 | ret = -EINVAL; | ||
| 2556 | if ((OCFS2_I(inode_in)->ip_flags & OCFS2_INODE_SYSTEM_FILE) || | ||
| 2557 | (OCFS2_I(inode_out)->ip_flags & OCFS2_INODE_SYSTEM_FILE)) | ||
| 2558 | goto out_unlock; | ||
| 2559 | |||
| 2560 | ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, | ||
| 2561 | &len, remap_flags); | ||
| 2562 | if (ret < 0 || len == 0) | ||
| 2563 | goto out_unlock; | ||
| 2564 | |||
| 2565 | /* Lock out changes to the allocation maps and remap. */ | ||
| 2566 | down_write(&OCFS2_I(inode_in)->ip_alloc_sem); | ||
| 2567 | if (!same_inode) | ||
| 2568 | down_write_nested(&OCFS2_I(inode_out)->ip_alloc_sem, | ||
| 2569 | SINGLE_DEPTH_NESTING); | ||
| 2570 | |||
| 2571 | /* Zap any page cache for the destination file's range. */ | ||
| 2572 | truncate_inode_pages_range(&inode_out->i_data, | ||
| 2573 | round_down(pos_out, PAGE_SIZE), | ||
| 2574 | round_up(pos_out + len, PAGE_SIZE) - 1); | ||
| 2575 | |||
| 2576 | remapped = ocfs2_reflink_remap_blocks(inode_in, in_bh, pos_in, | ||
| 2577 | inode_out, out_bh, pos_out, len); | ||
| 2578 | up_write(&OCFS2_I(inode_in)->ip_alloc_sem); | ||
| 2579 | if (!same_inode) | ||
| 2580 | up_write(&OCFS2_I(inode_out)->ip_alloc_sem); | ||
| 2581 | if (remapped < 0) { | ||
| 2582 | ret = remapped; | ||
| 2583 | mlog_errno(ret); | ||
| 2584 | goto out_unlock; | ||
| 2585 | } | ||
| 2586 | |||
| 2587 | /* | ||
| 2588 | * Empty the extent map so that we may get the right extent | ||
| 2589 | * record from the disk. | ||
| 2590 | */ | ||
| 2591 | ocfs2_extent_map_trunc(inode_in, 0); | ||
| 2592 | ocfs2_extent_map_trunc(inode_out, 0); | ||
| 2593 | |||
| 2594 | ret = ocfs2_reflink_update_dest(inode_out, out_bh, pos_out + len); | ||
| 2595 | if (ret) { | ||
| 2596 | mlog_errno(ret); | ||
| 2597 | goto out_unlock; | ||
| 2598 | } | ||
| 2599 | |||
| 2600 | out_unlock: | ||
| 2601 | ocfs2_reflink_inodes_unlock(inode_in, in_bh, inode_out, out_bh); | ||
| 2602 | return remapped > 0 ? remapped : ret; | ||
| 2548 | } | 2603 | } |
| 2549 | 2604 | ||
| 2550 | const struct inode_operations ocfs2_file_iops = { | 2605 | const struct inode_operations ocfs2_file_iops = { |
| @@ -2586,8 +2641,7 @@ const struct file_operations ocfs2_fops = { | |||
| 2586 | .splice_read = generic_file_splice_read, | 2641 | .splice_read = generic_file_splice_read, |
| 2587 | .splice_write = iter_file_splice_write, | 2642 | .splice_write = iter_file_splice_write, |
| 2588 | .fallocate = ocfs2_fallocate, | 2643 | .fallocate = ocfs2_fallocate, |
| 2589 | .clone_file_range = ocfs2_file_clone_range, | 2644 | .remap_file_range = ocfs2_remap_file_range, |
| 2590 | .dedupe_file_range = ocfs2_file_dedupe_range, | ||
| 2591 | }; | 2645 | }; |
| 2592 | 2646 | ||
| 2593 | const struct file_operations ocfs2_dops = { | 2647 | const struct file_operations ocfs2_dops = { |
| @@ -2633,8 +2687,7 @@ const struct file_operations ocfs2_fops_no_plocks = { | |||
| 2633 | .splice_read = generic_file_splice_read, | 2687 | .splice_read = generic_file_splice_read, |
| 2634 | .splice_write = iter_file_splice_write, | 2688 | .splice_write = iter_file_splice_write, |
| 2635 | .fallocate = ocfs2_fallocate, | 2689 | .fallocate = ocfs2_fallocate, |
| 2636 | .clone_file_range = ocfs2_file_clone_range, | 2690 | .remap_file_range = ocfs2_remap_file_range, |
| 2637 | .dedupe_file_range = ocfs2_file_dedupe_range, | ||
| 2638 | }; | 2691 | }; |
| 2639 | 2692 | ||
| 2640 | const struct file_operations ocfs2_dops_no_plocks = { | 2693 | const struct file_operations ocfs2_dops_no_plocks = { |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index bd3475694e83..b63c97f4318e 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
| @@ -1378,15 +1378,23 @@ static int __ocfs2_recovery_thread(void *arg) | |||
| 1378 | int rm_quota_used = 0, i; | 1378 | int rm_quota_used = 0, i; |
| 1379 | struct ocfs2_quota_recovery *qrec; | 1379 | struct ocfs2_quota_recovery *qrec; |
| 1380 | 1380 | ||
| 1381 | /* Whether the quota supported. */ | ||
| 1382 | int quota_enabled = OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, | ||
| 1383 | OCFS2_FEATURE_RO_COMPAT_USRQUOTA) | ||
| 1384 | || OCFS2_HAS_RO_COMPAT_FEATURE(osb->sb, | ||
| 1385 | OCFS2_FEATURE_RO_COMPAT_GRPQUOTA); | ||
| 1386 | |||
| 1381 | status = ocfs2_wait_on_mount(osb); | 1387 | status = ocfs2_wait_on_mount(osb); |
| 1382 | if (status < 0) { | 1388 | if (status < 0) { |
| 1383 | goto bail; | 1389 | goto bail; |
| 1384 | } | 1390 | } |
| 1385 | 1391 | ||
| 1386 | rm_quota = kcalloc(osb->max_slots, sizeof(int), GFP_NOFS); | 1392 | if (quota_enabled) { |
| 1387 | if (!rm_quota) { | 1393 | rm_quota = kcalloc(osb->max_slots, sizeof(int), GFP_NOFS); |
| 1388 | status = -ENOMEM; | 1394 | if (!rm_quota) { |
| 1389 | goto bail; | 1395 | status = -ENOMEM; |
| 1396 | goto bail; | ||
| 1397 | } | ||
| 1390 | } | 1398 | } |
| 1391 | restart: | 1399 | restart: |
| 1392 | status = ocfs2_super_lock(osb, 1); | 1400 | status = ocfs2_super_lock(osb, 1); |
| @@ -1422,9 +1430,14 @@ restart: | |||
| 1422 | * then quota usage would be out of sync until some node takes | 1430 | * then quota usage would be out of sync until some node takes |
| 1423 | * the slot. So we remember which nodes need quota recovery | 1431 | * the slot. So we remember which nodes need quota recovery |
| 1424 | * and when everything else is done, we recover quotas. */ | 1432 | * and when everything else is done, we recover quotas. */ |
| 1425 | for (i = 0; i < rm_quota_used && rm_quota[i] != slot_num; i++); | 1433 | if (quota_enabled) { |
| 1426 | if (i == rm_quota_used) | 1434 | for (i = 0; i < rm_quota_used |
| 1427 | rm_quota[rm_quota_used++] = slot_num; | 1435 | && rm_quota[i] != slot_num; i++) |
| 1436 | ; | ||
| 1437 | |||
| 1438 | if (i == rm_quota_used) | ||
| 1439 | rm_quota[rm_quota_used++] = slot_num; | ||
| 1440 | } | ||
| 1428 | 1441 | ||
| 1429 | status = ocfs2_recover_node(osb, node_num, slot_num); | 1442 | status = ocfs2_recover_node(osb, node_num, slot_num); |
| 1430 | skip_recovery: | 1443 | skip_recovery: |
| @@ -1452,16 +1465,19 @@ skip_recovery: | |||
| 1452 | /* Now it is right time to recover quotas... We have to do this under | 1465 | /* Now it is right time to recover quotas... We have to do this under |
| 1453 | * superblock lock so that no one can start using the slot (and crash) | 1466 | * superblock lock so that no one can start using the slot (and crash) |
| 1454 | * before we recover it */ | 1467 | * before we recover it */ |
| 1455 | for (i = 0; i < rm_quota_used; i++) { | 1468 | if (quota_enabled) { |
| 1456 | qrec = ocfs2_begin_quota_recovery(osb, rm_quota[i]); | 1469 | for (i = 0; i < rm_quota_used; i++) { |
| 1457 | if (IS_ERR(qrec)) { | 1470 | qrec = ocfs2_begin_quota_recovery(osb, rm_quota[i]); |
| 1458 | status = PTR_ERR(qrec); | 1471 | if (IS_ERR(qrec)) { |
| 1459 | mlog_errno(status); | 1472 | status = PTR_ERR(qrec); |
| 1460 | continue; | 1473 | mlog_errno(status); |
| 1474 | continue; | ||
| 1475 | } | ||
| 1476 | ocfs2_queue_recovery_completion(osb->journal, | ||
| 1477 | rm_quota[i], | ||
| 1478 | NULL, NULL, qrec, | ||
| 1479 | ORPHAN_NEED_TRUNCATE); | ||
| 1461 | } | 1480 | } |
| 1462 | ocfs2_queue_recovery_completion(osb->journal, rm_quota[i], | ||
| 1463 | NULL, NULL, qrec, | ||
| 1464 | ORPHAN_NEED_TRUNCATE); | ||
| 1465 | } | 1481 | } |
| 1466 | 1482 | ||
| 1467 | ocfs2_super_unlock(osb, 1); | 1483 | ocfs2_super_unlock(osb, 1); |
| @@ -1483,7 +1499,8 @@ bail: | |||
| 1483 | 1499 | ||
| 1484 | mutex_unlock(&osb->recovery_lock); | 1500 | mutex_unlock(&osb->recovery_lock); |
| 1485 | 1501 | ||
| 1486 | kfree(rm_quota); | 1502 | if (quota_enabled) |
| 1503 | kfree(rm_quota); | ||
| 1487 | 1504 | ||
| 1488 | /* no one is callint kthread_stop() for us so the kthread() api | 1505 | /* no one is callint kthread_stop() for us so the kthread() api |
| 1489 | * requires that we call do_exit(). And it isn't exported, but | 1506 | * requires that we call do_exit(). And it isn't exported, but |
diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 7eb3b0a6347e..3f1685d7d43b 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include "ocfs2_ioctl.h" | 25 | #include "ocfs2_ioctl.h" |
| 26 | 26 | ||
| 27 | #include "alloc.h" | 27 | #include "alloc.h" |
| 28 | #include "localalloc.h" | ||
| 28 | #include "aops.h" | 29 | #include "aops.h" |
| 29 | #include "dlmglue.h" | 30 | #include "dlmglue.h" |
| 30 | #include "extent_map.h" | 31 | #include "extent_map.h" |
| @@ -233,6 +234,7 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, | |||
| 233 | struct ocfs2_refcount_tree *ref_tree = NULL; | 234 | struct ocfs2_refcount_tree *ref_tree = NULL; |
| 234 | u32 new_phys_cpos, new_len; | 235 | u32 new_phys_cpos, new_len; |
| 235 | u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); | 236 | u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); |
| 237 | int need_free = 0; | ||
| 236 | 238 | ||
| 237 | if ((ext_flags & OCFS2_EXT_REFCOUNTED) && *len) { | 239 | if ((ext_flags & OCFS2_EXT_REFCOUNTED) && *len) { |
| 238 | BUG_ON(!ocfs2_is_refcount_inode(inode)); | 240 | BUG_ON(!ocfs2_is_refcount_inode(inode)); |
| @@ -308,6 +310,7 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, | |||
| 308 | if (!partial) { | 310 | if (!partial) { |
| 309 | context->range->me_flags &= ~OCFS2_MOVE_EXT_FL_COMPLETE; | 311 | context->range->me_flags &= ~OCFS2_MOVE_EXT_FL_COMPLETE; |
| 310 | ret = -ENOSPC; | 312 | ret = -ENOSPC; |
| 313 | need_free = 1; | ||
| 311 | goto out_commit; | 314 | goto out_commit; |
| 312 | } | 315 | } |
| 313 | } | 316 | } |
| @@ -332,6 +335,20 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context, | |||
| 332 | mlog_errno(ret); | 335 | mlog_errno(ret); |
| 333 | 336 | ||
| 334 | out_commit: | 337 | out_commit: |
| 338 | if (need_free && context->data_ac) { | ||
| 339 | struct ocfs2_alloc_context *data_ac = context->data_ac; | ||
| 340 | |||
| 341 | if (context->data_ac->ac_which == OCFS2_AC_USE_LOCAL) | ||
| 342 | ocfs2_free_local_alloc_bits(osb, handle, data_ac, | ||
| 343 | new_phys_cpos, new_len); | ||
| 344 | else | ||
| 345 | ocfs2_free_clusters(handle, | ||
| 346 | data_ac->ac_inode, | ||
| 347 | data_ac->ac_bh, | ||
| 348 | ocfs2_clusters_to_blocks(osb->sb, new_phys_cpos), | ||
| 349 | new_len); | ||
| 350 | } | ||
| 351 | |||
| 335 | ocfs2_commit_trans(osb, handle); | 352 | ocfs2_commit_trans(osb, handle); |
| 336 | 353 | ||
| 337 | out_unlock_mutex: | 354 | out_unlock_mutex: |
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 1114ef02e780..a35259eebc56 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -4466,9 +4466,9 @@ out: | |||
| 4466 | } | 4466 | } |
| 4467 | 4467 | ||
| 4468 | /* Update destination inode size, if necessary. */ | 4468 | /* Update destination inode size, if necessary. */ |
| 4469 | static int ocfs2_reflink_update_dest(struct inode *dest, | 4469 | int ocfs2_reflink_update_dest(struct inode *dest, |
| 4470 | struct buffer_head *d_bh, | 4470 | struct buffer_head *d_bh, |
| 4471 | loff_t newlen) | 4471 | loff_t newlen) |
| 4472 | { | 4472 | { |
| 4473 | handle_t *handle; | 4473 | handle_t *handle; |
| 4474 | int ret; | 4474 | int ret; |
| @@ -4505,14 +4505,14 @@ out_commit: | |||
| 4505 | } | 4505 | } |
| 4506 | 4506 | ||
| 4507 | /* Remap the range pos_in:len in s_inode to pos_out:len in t_inode. */ | 4507 | /* Remap the range pos_in:len in s_inode to pos_out:len in t_inode. */ |
| 4508 | static int ocfs2_reflink_remap_extent(struct inode *s_inode, | 4508 | static loff_t ocfs2_reflink_remap_extent(struct inode *s_inode, |
| 4509 | struct buffer_head *s_bh, | 4509 | struct buffer_head *s_bh, |
| 4510 | loff_t pos_in, | 4510 | loff_t pos_in, |
| 4511 | struct inode *t_inode, | 4511 | struct inode *t_inode, |
| 4512 | struct buffer_head *t_bh, | 4512 | struct buffer_head *t_bh, |
| 4513 | loff_t pos_out, | 4513 | loff_t pos_out, |
| 4514 | loff_t len, | 4514 | loff_t len, |
| 4515 | struct ocfs2_cached_dealloc_ctxt *dealloc) | 4515 | struct ocfs2_cached_dealloc_ctxt *dealloc) |
| 4516 | { | 4516 | { |
| 4517 | struct ocfs2_extent_tree s_et; | 4517 | struct ocfs2_extent_tree s_et; |
| 4518 | struct ocfs2_extent_tree t_et; | 4518 | struct ocfs2_extent_tree t_et; |
| @@ -4520,8 +4520,9 @@ static int ocfs2_reflink_remap_extent(struct inode *s_inode, | |||
| 4520 | struct buffer_head *ref_root_bh = NULL; | 4520 | struct buffer_head *ref_root_bh = NULL; |
| 4521 | struct ocfs2_refcount_tree *ref_tree; | 4521 | struct ocfs2_refcount_tree *ref_tree; |
| 4522 | struct ocfs2_super *osb; | 4522 | struct ocfs2_super *osb; |
| 4523 | loff_t remapped_bytes = 0; | ||
| 4523 | loff_t pstart, plen; | 4524 | loff_t pstart, plen; |
| 4524 | u32 p_cluster, num_clusters, slast, spos, tpos; | 4525 | u32 p_cluster, num_clusters, slast, spos, tpos, remapped_clus = 0; |
| 4525 | unsigned int ext_flags; | 4526 | unsigned int ext_flags; |
| 4526 | int ret = 0; | 4527 | int ret = 0; |
| 4527 | 4528 | ||
| @@ -4603,30 +4604,34 @@ static int ocfs2_reflink_remap_extent(struct inode *s_inode, | |||
| 4603 | next_loop: | 4604 | next_loop: |
| 4604 | spos += num_clusters; | 4605 | spos += num_clusters; |
| 4605 | tpos += num_clusters; | 4606 | tpos += num_clusters; |
| 4607 | remapped_clus += num_clusters; | ||
| 4606 | } | 4608 | } |
| 4607 | 4609 | ||
| 4608 | out: | 4610 | goto out; |
| 4609 | return ret; | ||
| 4610 | out_unlock_refcount: | 4611 | out_unlock_refcount: |
| 4611 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); | 4612 | ocfs2_unlock_refcount_tree(osb, ref_tree, 1); |
| 4612 | brelse(ref_root_bh); | 4613 | brelse(ref_root_bh); |
| 4613 | return ret; | 4614 | out: |
| 4615 | remapped_bytes = ocfs2_clusters_to_bytes(t_inode->i_sb, remapped_clus); | ||
| 4616 | remapped_bytes = min_t(loff_t, len, remapped_bytes); | ||
| 4617 | |||
| 4618 | return remapped_bytes > 0 ? remapped_bytes : ret; | ||
| 4614 | } | 4619 | } |
| 4615 | 4620 | ||
| 4616 | /* Set up refcount tree and remap s_inode to t_inode. */ | 4621 | /* Set up refcount tree and remap s_inode to t_inode. */ |
| 4617 | static int ocfs2_reflink_remap_blocks(struct inode *s_inode, | 4622 | loff_t ocfs2_reflink_remap_blocks(struct inode *s_inode, |
| 4618 | struct buffer_head *s_bh, | 4623 | struct buffer_head *s_bh, |
| 4619 | loff_t pos_in, | 4624 | loff_t pos_in, |
| 4620 | struct inode *t_inode, | 4625 | struct inode *t_inode, |
| 4621 | struct buffer_head *t_bh, | 4626 | struct buffer_head *t_bh, |
| 4622 | loff_t pos_out, | 4627 | loff_t pos_out, |
| 4623 | loff_t len) | 4628 | loff_t len) |
| 4624 | { | 4629 | { |
| 4625 | struct ocfs2_cached_dealloc_ctxt dealloc; | 4630 | struct ocfs2_cached_dealloc_ctxt dealloc; |
| 4626 | struct ocfs2_super *osb; | 4631 | struct ocfs2_super *osb; |
| 4627 | struct ocfs2_dinode *dis; | 4632 | struct ocfs2_dinode *dis; |
| 4628 | struct ocfs2_dinode *dit; | 4633 | struct ocfs2_dinode *dit; |
| 4629 | int ret; | 4634 | loff_t ret; |
| 4630 | 4635 | ||
| 4631 | osb = OCFS2_SB(s_inode->i_sb); | 4636 | osb = OCFS2_SB(s_inode->i_sb); |
| 4632 | dis = (struct ocfs2_dinode *)s_bh->b_data; | 4637 | dis = (struct ocfs2_dinode *)s_bh->b_data; |
| @@ -4698,7 +4703,7 @@ static int ocfs2_reflink_remap_blocks(struct inode *s_inode, | |||
| 4698 | /* Actually remap extents now. */ | 4703 | /* Actually remap extents now. */ |
| 4699 | ret = ocfs2_reflink_remap_extent(s_inode, s_bh, pos_in, t_inode, t_bh, | 4704 | ret = ocfs2_reflink_remap_extent(s_inode, s_bh, pos_in, t_inode, t_bh, |
| 4700 | pos_out, len, &dealloc); | 4705 | pos_out, len, &dealloc); |
| 4701 | if (ret) { | 4706 | if (ret < 0) { |
| 4702 | mlog_errno(ret); | 4707 | mlog_errno(ret); |
| 4703 | goto out; | 4708 | goto out; |
| 4704 | } | 4709 | } |
| @@ -4713,10 +4718,10 @@ out: | |||
| 4713 | } | 4718 | } |
| 4714 | 4719 | ||
| 4715 | /* Lock an inode and grab a bh pointing to the inode. */ | 4720 | /* Lock an inode and grab a bh pointing to the inode. */ |
| 4716 | static int ocfs2_reflink_inodes_lock(struct inode *s_inode, | 4721 | int ocfs2_reflink_inodes_lock(struct inode *s_inode, |
| 4717 | struct buffer_head **bh1, | 4722 | struct buffer_head **bh1, |
| 4718 | struct inode *t_inode, | 4723 | struct inode *t_inode, |
| 4719 | struct buffer_head **bh2) | 4724 | struct buffer_head **bh2) |
| 4720 | { | 4725 | { |
| 4721 | struct inode *inode1; | 4726 | struct inode *inode1; |
| 4722 | struct inode *inode2; | 4727 | struct inode *inode2; |
| @@ -4801,10 +4806,10 @@ out_i1: | |||
| 4801 | } | 4806 | } |
| 4802 | 4807 | ||
| 4803 | /* Unlock both inodes and release buffers. */ | 4808 | /* Unlock both inodes and release buffers. */ |
| 4804 | static void ocfs2_reflink_inodes_unlock(struct inode *s_inode, | 4809 | void ocfs2_reflink_inodes_unlock(struct inode *s_inode, |
| 4805 | struct buffer_head *s_bh, | 4810 | struct buffer_head *s_bh, |
| 4806 | struct inode *t_inode, | 4811 | struct inode *t_inode, |
| 4807 | struct buffer_head *t_bh) | 4812 | struct buffer_head *t_bh) |
| 4808 | { | 4813 | { |
| 4809 | ocfs2_inode_unlock(s_inode, 1); | 4814 | ocfs2_inode_unlock(s_inode, 1); |
| 4810 | ocfs2_rw_unlock(s_inode, 1); | 4815 | ocfs2_rw_unlock(s_inode, 1); |
| @@ -4816,82 +4821,3 @@ static void ocfs2_reflink_inodes_unlock(struct inode *s_inode, | |||
| 4816 | } | 4821 | } |
| 4817 | unlock_two_nondirectories(s_inode, t_inode); | 4822 | unlock_two_nondirectories(s_inode, t_inode); |
| 4818 | } | 4823 | } |
| 4819 | |||
| 4820 | /* Link a range of blocks from one file to another. */ | ||
| 4821 | int ocfs2_reflink_remap_range(struct file *file_in, | ||
| 4822 | loff_t pos_in, | ||
| 4823 | struct file *file_out, | ||
| 4824 | loff_t pos_out, | ||
| 4825 | u64 len, | ||
| 4826 | bool is_dedupe) | ||
| 4827 | { | ||
| 4828 | struct inode *inode_in = file_inode(file_in); | ||
| 4829 | struct inode *inode_out = file_inode(file_out); | ||
| 4830 | struct ocfs2_super *osb = OCFS2_SB(inode_in->i_sb); | ||
| 4831 | struct buffer_head *in_bh = NULL, *out_bh = NULL; | ||
| 4832 | bool same_inode = (inode_in == inode_out); | ||
| 4833 | ssize_t ret; | ||
| 4834 | |||
| 4835 | if (!ocfs2_refcount_tree(osb)) | ||
| 4836 | return -EOPNOTSUPP; | ||
| 4837 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) | ||
| 4838 | return -EROFS; | ||
| 4839 | |||
| 4840 | /* Lock both files against IO */ | ||
| 4841 | ret = ocfs2_reflink_inodes_lock(inode_in, &in_bh, inode_out, &out_bh); | ||
| 4842 | if (ret) | ||
| 4843 | return ret; | ||
| 4844 | |||
| 4845 | /* Check file eligibility and prepare for block sharing. */ | ||
| 4846 | ret = -EINVAL; | ||
| 4847 | if ((OCFS2_I(inode_in)->ip_flags & OCFS2_INODE_SYSTEM_FILE) || | ||
| 4848 | (OCFS2_I(inode_out)->ip_flags & OCFS2_INODE_SYSTEM_FILE)) | ||
| 4849 | goto out_unlock; | ||
| 4850 | |||
| 4851 | ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out, | ||
| 4852 | &len, is_dedupe); | ||
| 4853 | if (ret <= 0) | ||
| 4854 | goto out_unlock; | ||
| 4855 | |||
| 4856 | /* Lock out changes to the allocation maps and remap. */ | ||
| 4857 | down_write(&OCFS2_I(inode_in)->ip_alloc_sem); | ||
| 4858 | if (!same_inode) | ||
| 4859 | down_write_nested(&OCFS2_I(inode_out)->ip_alloc_sem, | ||
| 4860 | SINGLE_DEPTH_NESTING); | ||
| 4861 | |||
| 4862 | ret = ocfs2_reflink_remap_blocks(inode_in, in_bh, pos_in, inode_out, | ||
| 4863 | out_bh, pos_out, len); | ||
| 4864 | |||
| 4865 | /* Zap any page cache for the destination file's range. */ | ||
| 4866 | if (!ret) | ||
| 4867 | truncate_inode_pages_range(&inode_out->i_data, pos_out, | ||
| 4868 | PAGE_ALIGN(pos_out + len) - 1); | ||
| 4869 | |||
| 4870 | up_write(&OCFS2_I(inode_in)->ip_alloc_sem); | ||
| 4871 | if (!same_inode) | ||
| 4872 | up_write(&OCFS2_I(inode_out)->ip_alloc_sem); | ||
| 4873 | if (ret) { | ||
| 4874 | mlog_errno(ret); | ||
| 4875 | goto out_unlock; | ||
| 4876 | } | ||
| 4877 | |||
| 4878 | /* | ||
| 4879 | * Empty the extent map so that we may get the right extent | ||
| 4880 | * record from the disk. | ||
| 4881 | */ | ||
| 4882 | ocfs2_extent_map_trunc(inode_in, 0); | ||
| 4883 | ocfs2_extent_map_trunc(inode_out, 0); | ||
| 4884 | |||
| 4885 | ret = ocfs2_reflink_update_dest(inode_out, out_bh, pos_out + len); | ||
| 4886 | if (ret) { | ||
| 4887 | mlog_errno(ret); | ||
| 4888 | goto out_unlock; | ||
| 4889 | } | ||
| 4890 | |||
| 4891 | ocfs2_reflink_inodes_unlock(inode_in, in_bh, inode_out, out_bh); | ||
| 4892 | return 0; | ||
| 4893 | |||
| 4894 | out_unlock: | ||
| 4895 | ocfs2_reflink_inodes_unlock(inode_in, in_bh, inode_out, out_bh); | ||
| 4896 | return ret; | ||
| 4897 | } | ||
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h index 4af55bf4b35b..e9e862be4a1e 100644 --- a/fs/ocfs2/refcounttree.h +++ b/fs/ocfs2/refcounttree.h | |||
| @@ -115,11 +115,23 @@ int ocfs2_reflink_ioctl(struct inode *inode, | |||
| 115 | const char __user *oldname, | 115 | const char __user *oldname, |
| 116 | const char __user *newname, | 116 | const char __user *newname, |
| 117 | bool preserve); | 117 | bool preserve); |
| 118 | int ocfs2_reflink_remap_range(struct file *file_in, | 118 | loff_t ocfs2_reflink_remap_blocks(struct inode *s_inode, |
| 119 | loff_t pos_in, | 119 | struct buffer_head *s_bh, |
| 120 | struct file *file_out, | 120 | loff_t pos_in, |
| 121 | loff_t pos_out, | 121 | struct inode *t_inode, |
| 122 | u64 len, | 122 | struct buffer_head *t_bh, |
| 123 | bool is_dedupe); | 123 | loff_t pos_out, |
| 124 | loff_t len); | ||
| 125 | int ocfs2_reflink_inodes_lock(struct inode *s_inode, | ||
| 126 | struct buffer_head **bh1, | ||
| 127 | struct inode *t_inode, | ||
| 128 | struct buffer_head **bh2); | ||
| 129 | void ocfs2_reflink_inodes_unlock(struct inode *s_inode, | ||
| 130 | struct buffer_head *s_bh, | ||
| 131 | struct inode *t_inode, | ||
| 132 | struct buffer_head *t_bh); | ||
| 133 | int ocfs2_reflink_update_dest(struct inode *dest, | ||
| 134 | struct buffer_head *d_bh, | ||
| 135 | loff_t newlen); | ||
| 124 | 136 | ||
| 125 | #endif /* OCFS2_REFCOUNTTREE_H */ | 137 | #endif /* OCFS2_REFCOUNTTREE_H */ |
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index d6c350ba25b9..c4b029c43464 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
| @@ -48,12 +48,6 @@ static char ocfs2_hb_ctl_path[OCFS2_MAX_HB_CTL_PATH] = "/sbin/ocfs2_hb_ctl"; | |||
| 48 | */ | 48 | */ |
| 49 | static struct ocfs2_stack_plugin *active_stack; | 49 | static struct ocfs2_stack_plugin *active_stack; |
| 50 | 50 | ||
| 51 | inline int ocfs2_is_o2cb_active(void) | ||
| 52 | { | ||
| 53 | return !strcmp(active_stack->sp_name, OCFS2_STACK_PLUGIN_O2CB); | ||
| 54 | } | ||
| 55 | EXPORT_SYMBOL_GPL(ocfs2_is_o2cb_active); | ||
| 56 | |||
| 57 | static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name) | 51 | static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name) |
| 58 | { | 52 | { |
| 59 | struct ocfs2_stack_plugin *p; | 53 | struct ocfs2_stack_plugin *p; |
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h index e3036e1790e8..f2dce10fae54 100644 --- a/fs/ocfs2/stackglue.h +++ b/fs/ocfs2/stackglue.h | |||
| @@ -298,9 +298,6 @@ void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_p | |||
| 298 | int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin); | 298 | int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin); |
| 299 | void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin); | 299 | void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin); |
| 300 | 300 | ||
| 301 | /* In ocfs2_downconvert_lock(), we need to know which stack we are using */ | ||
| 302 | int ocfs2_is_o2cb_active(void); | ||
| 303 | |||
| 304 | extern struct kset *ocfs2_kset; | 301 | extern struct kset *ocfs2_kset; |
| 305 | 302 | ||
| 306 | #endif /* STACKGLUE_H */ | 303 | #endif /* STACKGLUE_H */ |
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index d6a3346e2672..9e62dcf06fc4 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
| @@ -125,6 +125,7 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) | |||
| 125 | struct file *new_file; | 125 | struct file *new_file; |
| 126 | loff_t old_pos = 0; | 126 | loff_t old_pos = 0; |
| 127 | loff_t new_pos = 0; | 127 | loff_t new_pos = 0; |
| 128 | loff_t cloned; | ||
| 128 | int error = 0; | 129 | int error = 0; |
| 129 | 130 | ||
| 130 | if (len == 0) | 131 | if (len == 0) |
| @@ -141,11 +142,10 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len) | |||
| 141 | } | 142 | } |
| 142 | 143 | ||
| 143 | /* Try to use clone_file_range to clone up within the same fs */ | 144 | /* Try to use clone_file_range to clone up within the same fs */ |
| 144 | error = do_clone_file_range(old_file, 0, new_file, 0, len); | 145 | cloned = do_clone_file_range(old_file, 0, new_file, 0, len, 0); |
| 145 | if (!error) | 146 | if (cloned == len) |
| 146 | goto out; | 147 | goto out; |
| 147 | /* Couldn't clone, so now we try to copy the data */ | 148 | /* Couldn't clone, so now we try to copy the data */ |
| 148 | error = 0; | ||
| 149 | 149 | ||
| 150 | /* FIXME: copy up sparse files efficiently */ | 150 | /* FIXME: copy up sparse files efficiently */ |
| 151 | while (len) { | 151 | while (len) { |
diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c index 986313da0c88..84dd957efa24 100644 --- a/fs/overlayfs/file.c +++ b/fs/overlayfs/file.c | |||
| @@ -434,14 +434,14 @@ enum ovl_copyop { | |||
| 434 | OVL_DEDUPE, | 434 | OVL_DEDUPE, |
| 435 | }; | 435 | }; |
| 436 | 436 | ||
| 437 | static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, | 437 | static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, |
| 438 | struct file *file_out, loff_t pos_out, | 438 | struct file *file_out, loff_t pos_out, |
| 439 | u64 len, unsigned int flags, enum ovl_copyop op) | 439 | loff_t len, unsigned int flags, enum ovl_copyop op) |
| 440 | { | 440 | { |
| 441 | struct inode *inode_out = file_inode(file_out); | 441 | struct inode *inode_out = file_inode(file_out); |
| 442 | struct fd real_in, real_out; | 442 | struct fd real_in, real_out; |
| 443 | const struct cred *old_cred; | 443 | const struct cred *old_cred; |
| 444 | ssize_t ret; | 444 | loff_t ret; |
| 445 | 445 | ||
| 446 | ret = ovl_real_fdget(file_out, &real_out); | 446 | ret = ovl_real_fdget(file_out, &real_out); |
| 447 | if (ret) | 447 | if (ret) |
| @@ -462,12 +462,13 @@ static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, | |||
| 462 | 462 | ||
| 463 | case OVL_CLONE: | 463 | case OVL_CLONE: |
| 464 | ret = vfs_clone_file_range(real_in.file, pos_in, | 464 | ret = vfs_clone_file_range(real_in.file, pos_in, |
| 465 | real_out.file, pos_out, len); | 465 | real_out.file, pos_out, len, flags); |
| 466 | break; | 466 | break; |
| 467 | 467 | ||
| 468 | case OVL_DEDUPE: | 468 | case OVL_DEDUPE: |
| 469 | ret = vfs_dedupe_file_range_one(real_in.file, pos_in, | 469 | ret = vfs_dedupe_file_range_one(real_in.file, pos_in, |
| 470 | real_out.file, pos_out, len); | 470 | real_out.file, pos_out, len, |
| 471 | flags); | ||
| 471 | break; | 472 | break; |
| 472 | } | 473 | } |
| 473 | revert_creds(old_cred); | 474 | revert_creds(old_cred); |
| @@ -489,26 +490,31 @@ static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, | |||
| 489 | OVL_COPY); | 490 | OVL_COPY); |
| 490 | } | 491 | } |
| 491 | 492 | ||
| 492 | static int ovl_clone_file_range(struct file *file_in, loff_t pos_in, | 493 | static loff_t ovl_remap_file_range(struct file *file_in, loff_t pos_in, |
| 493 | struct file *file_out, loff_t pos_out, u64 len) | 494 | struct file *file_out, loff_t pos_out, |
| 495 | loff_t len, unsigned int remap_flags) | ||
| 494 | { | 496 | { |
| 495 | return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0, | 497 | enum ovl_copyop op; |
| 496 | OVL_CLONE); | 498 | |
| 497 | } | 499 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) |
| 500 | return -EINVAL; | ||
| 501 | |||
| 502 | if (remap_flags & REMAP_FILE_DEDUP) | ||
| 503 | op = OVL_DEDUPE; | ||
| 504 | else | ||
| 505 | op = OVL_CLONE; | ||
| 498 | 506 | ||
| 499 | static int ovl_dedupe_file_range(struct file *file_in, loff_t pos_in, | ||
| 500 | struct file *file_out, loff_t pos_out, u64 len) | ||
| 501 | { | ||
| 502 | /* | 507 | /* |
| 503 | * Don't copy up because of a dedupe request, this wouldn't make sense | 508 | * Don't copy up because of a dedupe request, this wouldn't make sense |
| 504 | * most of the time (data would be duplicated instead of deduplicated). | 509 | * most of the time (data would be duplicated instead of deduplicated). |
| 505 | */ | 510 | */ |
| 506 | if (!ovl_inode_upper(file_inode(file_in)) || | 511 | if (op == OVL_DEDUPE && |
| 507 | !ovl_inode_upper(file_inode(file_out))) | 512 | (!ovl_inode_upper(file_inode(file_in)) || |
| 513 | !ovl_inode_upper(file_inode(file_out)))) | ||
| 508 | return -EPERM; | 514 | return -EPERM; |
| 509 | 515 | ||
| 510 | return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0, | 516 | return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, |
| 511 | OVL_DEDUPE); | 517 | remap_flags, op); |
| 512 | } | 518 | } |
| 513 | 519 | ||
| 514 | const struct file_operations ovl_file_operations = { | 520 | const struct file_operations ovl_file_operations = { |
| @@ -525,6 +531,5 @@ const struct file_operations ovl_file_operations = { | |||
| 525 | .compat_ioctl = ovl_compat_ioctl, | 531 | .compat_ioctl = ovl_compat_ioctl, |
| 526 | 532 | ||
| 527 | .copy_file_range = ovl_copy_file_range, | 533 | .copy_file_range = ovl_copy_file_range, |
| 528 | .clone_file_range = ovl_clone_file_range, | 534 | .remap_file_range = ovl_remap_file_range, |
| 529 | .dedupe_file_range = ovl_dedupe_file_range, | ||
| 530 | }; | 535 | }; |
diff --git a/fs/read_write.c b/fs/read_write.c index 5a2ee488c5d2..bfcb4ced5664 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -1587,11 +1587,15 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in, | |||
| 1587 | * Try cloning first, this is supported by more file systems, and | 1587 | * Try cloning first, this is supported by more file systems, and |
| 1588 | * more efficient if both clone and copy are supported (e.g. NFS). | 1588 | * more efficient if both clone and copy are supported (e.g. NFS). |
| 1589 | */ | 1589 | */ |
| 1590 | if (file_in->f_op->clone_file_range) { | 1590 | if (file_in->f_op->remap_file_range) { |
| 1591 | ret = file_in->f_op->clone_file_range(file_in, pos_in, | 1591 | loff_t cloned; |
| 1592 | file_out, pos_out, len); | 1592 | |
| 1593 | if (ret == 0) { | 1593 | cloned = file_in->f_op->remap_file_range(file_in, pos_in, |
| 1594 | ret = len; | 1594 | file_out, pos_out, |
| 1595 | min_t(loff_t, MAX_RW_COUNT, len), | ||
| 1596 | REMAP_FILE_CAN_SHORTEN); | ||
| 1597 | if (cloned > 0) { | ||
| 1598 | ret = cloned; | ||
| 1595 | goto done; | 1599 | goto done; |
| 1596 | } | 1600 | } |
| 1597 | } | 1601 | } |
| @@ -1685,11 +1689,12 @@ out2: | |||
| 1685 | return ret; | 1689 | return ret; |
| 1686 | } | 1690 | } |
| 1687 | 1691 | ||
| 1688 | static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write) | 1692 | static int remap_verify_area(struct file *file, loff_t pos, loff_t len, |
| 1693 | bool write) | ||
| 1689 | { | 1694 | { |
| 1690 | struct inode *inode = file_inode(file); | 1695 | struct inode *inode = file_inode(file); |
| 1691 | 1696 | ||
| 1692 | if (unlikely(pos < 0)) | 1697 | if (unlikely(pos < 0 || len < 0)) |
| 1693 | return -EINVAL; | 1698 | return -EINVAL; |
| 1694 | 1699 | ||
| 1695 | if (unlikely((loff_t) (pos + len) < 0)) | 1700 | if (unlikely((loff_t) (pos + len) < 0)) |
| @@ -1707,22 +1712,150 @@ static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write) | |||
| 1707 | 1712 | ||
| 1708 | return security_file_permission(file, write ? MAY_WRITE : MAY_READ); | 1713 | return security_file_permission(file, write ? MAY_WRITE : MAY_READ); |
| 1709 | } | 1714 | } |
| 1715 | /* | ||
| 1716 | * Ensure that we don't remap a partial EOF block in the middle of something | ||
| 1717 | * else. Assume that the offsets have already been checked for block | ||
| 1718 | * alignment. | ||
| 1719 | * | ||
| 1720 | * For deduplication we always scale down to the previous block because we | ||
| 1721 | * can't meaningfully compare post-EOF contents. | ||
| 1722 | * | ||
| 1723 | * For clone we only link a partial EOF block above the destination file's EOF. | ||
| 1724 | * | ||
| 1725 | * Shorten the request if possible. | ||
| 1726 | */ | ||
| 1727 | static int generic_remap_check_len(struct inode *inode_in, | ||
| 1728 | struct inode *inode_out, | ||
| 1729 | loff_t pos_out, | ||
| 1730 | loff_t *len, | ||
| 1731 | unsigned int remap_flags) | ||
| 1732 | { | ||
| 1733 | u64 blkmask = i_blocksize(inode_in) - 1; | ||
| 1734 | loff_t new_len = *len; | ||
| 1735 | |||
| 1736 | if ((*len & blkmask) == 0) | ||
| 1737 | return 0; | ||
| 1738 | |||
| 1739 | if ((remap_flags & REMAP_FILE_DEDUP) || | ||
| 1740 | pos_out + *len < i_size_read(inode_out)) | ||
| 1741 | new_len &= ~blkmask; | ||
| 1742 | |||
| 1743 | if (new_len == *len) | ||
| 1744 | return 0; | ||
| 1745 | |||
| 1746 | if (remap_flags & REMAP_FILE_CAN_SHORTEN) { | ||
| 1747 | *len = new_len; | ||
| 1748 | return 0; | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | return (remap_flags & REMAP_FILE_DEDUP) ? -EBADE : -EINVAL; | ||
| 1752 | } | ||
| 1753 | |||
| 1754 | /* | ||
| 1755 | * Read a page's worth of file data into the page cache. Return the page | ||
| 1756 | * locked. | ||
| 1757 | */ | ||
| 1758 | static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset) | ||
| 1759 | { | ||
| 1760 | struct page *page; | ||
| 1761 | |||
| 1762 | page = read_mapping_page(inode->i_mapping, offset >> PAGE_SHIFT, NULL); | ||
| 1763 | if (IS_ERR(page)) | ||
| 1764 | return page; | ||
| 1765 | if (!PageUptodate(page)) { | ||
| 1766 | put_page(page); | ||
| 1767 | return ERR_PTR(-EIO); | ||
| 1768 | } | ||
| 1769 | lock_page(page); | ||
| 1770 | return page; | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | /* | ||
| 1774 | * Compare extents of two files to see if they are the same. | ||
| 1775 | * Caller must have locked both inodes to prevent write races. | ||
| 1776 | */ | ||
| 1777 | static int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, | ||
| 1778 | struct inode *dest, loff_t destoff, | ||
| 1779 | loff_t len, bool *is_same) | ||
| 1780 | { | ||
| 1781 | loff_t src_poff; | ||
| 1782 | loff_t dest_poff; | ||
| 1783 | void *src_addr; | ||
| 1784 | void *dest_addr; | ||
| 1785 | struct page *src_page; | ||
| 1786 | struct page *dest_page; | ||
| 1787 | loff_t cmp_len; | ||
| 1788 | bool same; | ||
| 1789 | int error; | ||
| 1790 | |||
| 1791 | error = -EINVAL; | ||
| 1792 | same = true; | ||
| 1793 | while (len) { | ||
| 1794 | src_poff = srcoff & (PAGE_SIZE - 1); | ||
| 1795 | dest_poff = destoff & (PAGE_SIZE - 1); | ||
| 1796 | cmp_len = min(PAGE_SIZE - src_poff, | ||
| 1797 | PAGE_SIZE - dest_poff); | ||
| 1798 | cmp_len = min(cmp_len, len); | ||
| 1799 | if (cmp_len <= 0) | ||
| 1800 | goto out_error; | ||
| 1801 | |||
| 1802 | src_page = vfs_dedupe_get_page(src, srcoff); | ||
| 1803 | if (IS_ERR(src_page)) { | ||
| 1804 | error = PTR_ERR(src_page); | ||
| 1805 | goto out_error; | ||
| 1806 | } | ||
| 1807 | dest_page = vfs_dedupe_get_page(dest, destoff); | ||
| 1808 | if (IS_ERR(dest_page)) { | ||
| 1809 | error = PTR_ERR(dest_page); | ||
| 1810 | unlock_page(src_page); | ||
| 1811 | put_page(src_page); | ||
| 1812 | goto out_error; | ||
| 1813 | } | ||
| 1814 | src_addr = kmap_atomic(src_page); | ||
| 1815 | dest_addr = kmap_atomic(dest_page); | ||
| 1816 | |||
| 1817 | flush_dcache_page(src_page); | ||
| 1818 | flush_dcache_page(dest_page); | ||
| 1819 | |||
| 1820 | if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len)) | ||
| 1821 | same = false; | ||
| 1822 | |||
| 1823 | kunmap_atomic(dest_addr); | ||
| 1824 | kunmap_atomic(src_addr); | ||
| 1825 | unlock_page(dest_page); | ||
| 1826 | unlock_page(src_page); | ||
| 1827 | put_page(dest_page); | ||
| 1828 | put_page(src_page); | ||
| 1829 | |||
| 1830 | if (!same) | ||
| 1831 | break; | ||
| 1832 | |||
| 1833 | srcoff += cmp_len; | ||
| 1834 | destoff += cmp_len; | ||
| 1835 | len -= cmp_len; | ||
| 1836 | } | ||
| 1837 | |||
| 1838 | *is_same = same; | ||
| 1839 | return 0; | ||
| 1840 | |||
| 1841 | out_error: | ||
| 1842 | return error; | ||
| 1843 | } | ||
| 1710 | 1844 | ||
| 1711 | /* | 1845 | /* |
| 1712 | * Check that the two inodes are eligible for cloning, the ranges make | 1846 | * Check that the two inodes are eligible for cloning, the ranges make |
| 1713 | * sense, and then flush all dirty data. Caller must ensure that the | 1847 | * sense, and then flush all dirty data. Caller must ensure that the |
| 1714 | * inodes have been locked against any other modifications. | 1848 | * inodes have been locked against any other modifications. |
| 1715 | * | 1849 | * |
| 1716 | * Returns: 0 for "nothing to clone", 1 for "something to clone", or | 1850 | * If there's an error, then the usual negative error code is returned. |
| 1717 | * the usual negative error code. | 1851 | * Otherwise returns 0 with *len set to the request length. |
| 1718 | */ | 1852 | */ |
| 1719 | int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, | 1853 | int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, |
| 1720 | struct inode *inode_out, loff_t pos_out, | 1854 | struct file *file_out, loff_t pos_out, |
| 1721 | u64 *len, bool is_dedupe) | 1855 | loff_t *len, unsigned int remap_flags) |
| 1722 | { | 1856 | { |
| 1723 | loff_t bs = inode_out->i_sb->s_blocksize; | 1857 | struct inode *inode_in = file_inode(file_in); |
| 1724 | loff_t blen; | 1858 | struct inode *inode_out = file_inode(file_out); |
| 1725 | loff_t isize; | ||
| 1726 | bool same_inode = (inode_in == inode_out); | 1859 | bool same_inode = (inode_in == inode_out); |
| 1727 | int ret; | 1860 | int ret; |
| 1728 | 1861 | ||
| @@ -1739,50 +1872,24 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, | |||
| 1739 | if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) | 1872 | if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) |
| 1740 | return -EINVAL; | 1873 | return -EINVAL; |
| 1741 | 1874 | ||
| 1742 | /* Are we going all the way to the end? */ | ||
| 1743 | isize = i_size_read(inode_in); | ||
| 1744 | if (isize == 0) | ||
| 1745 | return 0; | ||
| 1746 | |||
| 1747 | /* Zero length dedupe exits immediately; reflink goes to EOF. */ | 1875 | /* Zero length dedupe exits immediately; reflink goes to EOF. */ |
| 1748 | if (*len == 0) { | 1876 | if (*len == 0) { |
| 1749 | if (is_dedupe || pos_in == isize) | 1877 | loff_t isize = i_size_read(inode_in); |
| 1878 | |||
| 1879 | if ((remap_flags & REMAP_FILE_DEDUP) || pos_in == isize) | ||
| 1750 | return 0; | 1880 | return 0; |
| 1751 | if (pos_in > isize) | 1881 | if (pos_in > isize) |
| 1752 | return -EINVAL; | 1882 | return -EINVAL; |
| 1753 | *len = isize - pos_in; | 1883 | *len = isize - pos_in; |
| 1884 | if (*len == 0) | ||
| 1885 | return 0; | ||
| 1754 | } | 1886 | } |
| 1755 | 1887 | ||
| 1756 | /* Ensure offsets don't wrap and the input is inside i_size */ | 1888 | /* Check that we don't violate system file offset limits. */ |
| 1757 | if (pos_in + *len < pos_in || pos_out + *len < pos_out || | 1889 | ret = generic_remap_checks(file_in, pos_in, file_out, pos_out, len, |
| 1758 | pos_in + *len > isize) | 1890 | remap_flags); |
| 1759 | return -EINVAL; | 1891 | if (ret) |
| 1760 | 1892 | return ret; | |
| 1761 | /* Don't allow dedupe past EOF in the dest file */ | ||
| 1762 | if (is_dedupe) { | ||
| 1763 | loff_t disize; | ||
| 1764 | |||
| 1765 | disize = i_size_read(inode_out); | ||
| 1766 | if (pos_out >= disize || pos_out + *len > disize) | ||
| 1767 | return -EINVAL; | ||
| 1768 | } | ||
| 1769 | |||
| 1770 | /* If we're linking to EOF, continue to the block boundary. */ | ||
| 1771 | if (pos_in + *len == isize) | ||
| 1772 | blen = ALIGN(isize, bs) - pos_in; | ||
| 1773 | else | ||
| 1774 | blen = *len; | ||
| 1775 | |||
| 1776 | /* Only reflink if we're aligned to block boundaries */ | ||
| 1777 | if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) || | ||
| 1778 | !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs)) | ||
| 1779 | return -EINVAL; | ||
| 1780 | |||
| 1781 | /* Don't allow overlapped reflink within the same file */ | ||
| 1782 | if (same_inode) { | ||
| 1783 | if (pos_out + blen > pos_in && pos_out < pos_in + blen) | ||
| 1784 | return -EINVAL; | ||
| 1785 | } | ||
| 1786 | 1893 | ||
| 1787 | /* Wait for the completion of any pending IOs on both files */ | 1894 | /* Wait for the completion of any pending IOs on both files */ |
| 1788 | inode_dio_wait(inode_in); | 1895 | inode_dio_wait(inode_in); |
| @@ -1802,7 +1909,7 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, | |||
| 1802 | /* | 1909 | /* |
| 1803 | * Check that the extents are the same. | 1910 | * Check that the extents are the same. |
| 1804 | */ | 1911 | */ |
| 1805 | if (is_dedupe) { | 1912 | if (remap_flags & REMAP_FILE_DEDUP) { |
| 1806 | bool is_same = false; | 1913 | bool is_same = false; |
| 1807 | 1914 | ||
| 1808 | ret = vfs_dedupe_file_range_compare(inode_in, pos_in, | 1915 | ret = vfs_dedupe_file_range_compare(inode_in, pos_in, |
| @@ -1813,16 +1920,43 @@ int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, | |||
| 1813 | return -EBADE; | 1920 | return -EBADE; |
| 1814 | } | 1921 | } |
| 1815 | 1922 | ||
| 1816 | return 1; | 1923 | ret = generic_remap_check_len(inode_in, inode_out, pos_out, len, |
| 1924 | remap_flags); | ||
| 1925 | if (ret) | ||
| 1926 | return ret; | ||
| 1927 | |||
| 1928 | /* If can't alter the file contents, we're done. */ | ||
| 1929 | if (!(remap_flags & REMAP_FILE_DEDUP)) { | ||
| 1930 | /* Update the timestamps, since we can alter file contents. */ | ||
| 1931 | if (!(file_out->f_mode & FMODE_NOCMTIME)) { | ||
| 1932 | ret = file_update_time(file_out); | ||
| 1933 | if (ret) | ||
| 1934 | return ret; | ||
| 1935 | } | ||
| 1936 | |||
| 1937 | /* | ||
| 1938 | * Clear the security bits if the process is not being run by | ||
| 1939 | * root. This keeps people from modifying setuid and setgid | ||
| 1940 | * binaries. | ||
| 1941 | */ | ||
| 1942 | ret = file_remove_privs(file_out); | ||
| 1943 | if (ret) | ||
| 1944 | return ret; | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | return 0; | ||
| 1817 | } | 1948 | } |
| 1818 | EXPORT_SYMBOL(vfs_clone_file_prep_inodes); | 1949 | EXPORT_SYMBOL(generic_remap_file_range_prep); |
| 1819 | 1950 | ||
| 1820 | int do_clone_file_range(struct file *file_in, loff_t pos_in, | 1951 | loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, |
| 1821 | struct file *file_out, loff_t pos_out, u64 len) | 1952 | struct file *file_out, loff_t pos_out, |
| 1953 | loff_t len, unsigned int remap_flags) | ||
| 1822 | { | 1954 | { |
| 1823 | struct inode *inode_in = file_inode(file_in); | 1955 | struct inode *inode_in = file_inode(file_in); |
| 1824 | struct inode *inode_out = file_inode(file_out); | 1956 | struct inode *inode_out = file_inode(file_out); |
| 1825 | int ret; | 1957 | loff_t ret; |
| 1958 | |||
| 1959 | WARN_ON_ONCE(remap_flags); | ||
| 1826 | 1960 | ||
| 1827 | if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) | 1961 | if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) |
| 1828 | return -EISDIR; | 1962 | return -EISDIR; |
| @@ -1842,140 +1976,43 @@ int do_clone_file_range(struct file *file_in, loff_t pos_in, | |||
| 1842 | (file_out->f_flags & O_APPEND)) | 1976 | (file_out->f_flags & O_APPEND)) |
| 1843 | return -EBADF; | 1977 | return -EBADF; |
| 1844 | 1978 | ||
| 1845 | if (!file_in->f_op->clone_file_range) | 1979 | if (!file_in->f_op->remap_file_range) |
| 1846 | return -EOPNOTSUPP; | 1980 | return -EOPNOTSUPP; |
| 1847 | 1981 | ||
| 1848 | ret = clone_verify_area(file_in, pos_in, len, false); | 1982 | ret = remap_verify_area(file_in, pos_in, len, false); |
| 1849 | if (ret) | 1983 | if (ret) |
| 1850 | return ret; | 1984 | return ret; |
| 1851 | 1985 | ||
| 1852 | ret = clone_verify_area(file_out, pos_out, len, true); | 1986 | ret = remap_verify_area(file_out, pos_out, len, true); |
| 1853 | if (ret) | 1987 | if (ret) |
| 1854 | return ret; | 1988 | return ret; |
| 1855 | 1989 | ||
| 1856 | if (pos_in + len > i_size_read(inode_in)) | 1990 | ret = file_in->f_op->remap_file_range(file_in, pos_in, |
| 1857 | return -EINVAL; | 1991 | file_out, pos_out, len, remap_flags); |
| 1858 | 1992 | if (ret < 0) | |
| 1859 | ret = file_in->f_op->clone_file_range(file_in, pos_in, | 1993 | return ret; |
| 1860 | file_out, pos_out, len); | ||
| 1861 | if (!ret) { | ||
| 1862 | fsnotify_access(file_in); | ||
| 1863 | fsnotify_modify(file_out); | ||
| 1864 | } | ||
| 1865 | 1994 | ||
| 1995 | fsnotify_access(file_in); | ||
| 1996 | fsnotify_modify(file_out); | ||
| 1866 | return ret; | 1997 | return ret; |
| 1867 | } | 1998 | } |
| 1868 | EXPORT_SYMBOL(do_clone_file_range); | 1999 | EXPORT_SYMBOL(do_clone_file_range); |
| 1869 | 2000 | ||
| 1870 | int vfs_clone_file_range(struct file *file_in, loff_t pos_in, | 2001 | loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in, |
| 1871 | struct file *file_out, loff_t pos_out, u64 len) | 2002 | struct file *file_out, loff_t pos_out, |
| 2003 | loff_t len, unsigned int remap_flags) | ||
| 1872 | { | 2004 | { |
| 1873 | int ret; | 2005 | loff_t ret; |
| 1874 | 2006 | ||
| 1875 | file_start_write(file_out); | 2007 | file_start_write(file_out); |
| 1876 | ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len); | 2008 | ret = do_clone_file_range(file_in, pos_in, file_out, pos_out, len, |
| 2009 | remap_flags); | ||
| 1877 | file_end_write(file_out); | 2010 | file_end_write(file_out); |
| 1878 | 2011 | ||
| 1879 | return ret; | 2012 | return ret; |
| 1880 | } | 2013 | } |
| 1881 | EXPORT_SYMBOL(vfs_clone_file_range); | 2014 | EXPORT_SYMBOL(vfs_clone_file_range); |
| 1882 | 2015 | ||
| 1883 | /* | ||
| 1884 | * Read a page's worth of file data into the page cache. Return the page | ||
| 1885 | * locked. | ||
| 1886 | */ | ||
| 1887 | static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset) | ||
| 1888 | { | ||
| 1889 | struct address_space *mapping; | ||
| 1890 | struct page *page; | ||
| 1891 | pgoff_t n; | ||
| 1892 | |||
| 1893 | n = offset >> PAGE_SHIFT; | ||
| 1894 | mapping = inode->i_mapping; | ||
| 1895 | page = read_mapping_page(mapping, n, NULL); | ||
| 1896 | if (IS_ERR(page)) | ||
| 1897 | return page; | ||
| 1898 | if (!PageUptodate(page)) { | ||
| 1899 | put_page(page); | ||
| 1900 | return ERR_PTR(-EIO); | ||
| 1901 | } | ||
| 1902 | lock_page(page); | ||
| 1903 | return page; | ||
| 1904 | } | ||
| 1905 | |||
| 1906 | /* | ||
| 1907 | * Compare extents of two files to see if they are the same. | ||
| 1908 | * Caller must have locked both inodes to prevent write races. | ||
| 1909 | */ | ||
| 1910 | int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, | ||
| 1911 | struct inode *dest, loff_t destoff, | ||
| 1912 | loff_t len, bool *is_same) | ||
| 1913 | { | ||
| 1914 | loff_t src_poff; | ||
| 1915 | loff_t dest_poff; | ||
| 1916 | void *src_addr; | ||
| 1917 | void *dest_addr; | ||
| 1918 | struct page *src_page; | ||
| 1919 | struct page *dest_page; | ||
| 1920 | loff_t cmp_len; | ||
| 1921 | bool same; | ||
| 1922 | int error; | ||
| 1923 | |||
| 1924 | error = -EINVAL; | ||
| 1925 | same = true; | ||
| 1926 | while (len) { | ||
| 1927 | src_poff = srcoff & (PAGE_SIZE - 1); | ||
| 1928 | dest_poff = destoff & (PAGE_SIZE - 1); | ||
| 1929 | cmp_len = min(PAGE_SIZE - src_poff, | ||
| 1930 | PAGE_SIZE - dest_poff); | ||
| 1931 | cmp_len = min(cmp_len, len); | ||
| 1932 | if (cmp_len <= 0) | ||
| 1933 | goto out_error; | ||
| 1934 | |||
| 1935 | src_page = vfs_dedupe_get_page(src, srcoff); | ||
| 1936 | if (IS_ERR(src_page)) { | ||
| 1937 | error = PTR_ERR(src_page); | ||
| 1938 | goto out_error; | ||
| 1939 | } | ||
| 1940 | dest_page = vfs_dedupe_get_page(dest, destoff); | ||
| 1941 | if (IS_ERR(dest_page)) { | ||
| 1942 | error = PTR_ERR(dest_page); | ||
| 1943 | unlock_page(src_page); | ||
| 1944 | put_page(src_page); | ||
| 1945 | goto out_error; | ||
| 1946 | } | ||
| 1947 | src_addr = kmap_atomic(src_page); | ||
| 1948 | dest_addr = kmap_atomic(dest_page); | ||
| 1949 | |||
| 1950 | flush_dcache_page(src_page); | ||
| 1951 | flush_dcache_page(dest_page); | ||
| 1952 | |||
| 1953 | if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len)) | ||
| 1954 | same = false; | ||
| 1955 | |||
| 1956 | kunmap_atomic(dest_addr); | ||
| 1957 | kunmap_atomic(src_addr); | ||
| 1958 | unlock_page(dest_page); | ||
| 1959 | unlock_page(src_page); | ||
| 1960 | put_page(dest_page); | ||
| 1961 | put_page(src_page); | ||
| 1962 | |||
| 1963 | if (!same) | ||
| 1964 | break; | ||
| 1965 | |||
| 1966 | srcoff += cmp_len; | ||
| 1967 | destoff += cmp_len; | ||
| 1968 | len -= cmp_len; | ||
| 1969 | } | ||
| 1970 | |||
| 1971 | *is_same = same; | ||
| 1972 | return 0; | ||
| 1973 | |||
| 1974 | out_error: | ||
| 1975 | return error; | ||
| 1976 | } | ||
| 1977 | EXPORT_SYMBOL(vfs_dedupe_file_range_compare); | ||
| 1978 | |||
| 1979 | /* Check whether we are allowed to dedupe the destination file */ | 2016 | /* Check whether we are allowed to dedupe the destination file */ |
| 1980 | static bool allow_file_dedupe(struct file *file) | 2017 | static bool allow_file_dedupe(struct file *file) |
| 1981 | { | 2018 | { |
| @@ -1990,16 +2027,20 @@ static bool allow_file_dedupe(struct file *file) | |||
| 1990 | return false; | 2027 | return false; |
| 1991 | } | 2028 | } |
| 1992 | 2029 | ||
| 1993 | int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, | 2030 | loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, |
| 1994 | struct file *dst_file, loff_t dst_pos, u64 len) | 2031 | struct file *dst_file, loff_t dst_pos, |
| 2032 | loff_t len, unsigned int remap_flags) | ||
| 1995 | { | 2033 | { |
| 1996 | s64 ret; | 2034 | loff_t ret; |
| 2035 | |||
| 2036 | WARN_ON_ONCE(remap_flags & ~(REMAP_FILE_DEDUP | | ||
| 2037 | REMAP_FILE_CAN_SHORTEN)); | ||
| 1997 | 2038 | ||
| 1998 | ret = mnt_want_write_file(dst_file); | 2039 | ret = mnt_want_write_file(dst_file); |
| 1999 | if (ret) | 2040 | if (ret) |
| 2000 | return ret; | 2041 | return ret; |
| 2001 | 2042 | ||
| 2002 | ret = clone_verify_area(dst_file, dst_pos, len, true); | 2043 | ret = remap_verify_area(dst_file, dst_pos, len, true); |
| 2003 | if (ret < 0) | 2044 | if (ret < 0) |
| 2004 | goto out_drop_write; | 2045 | goto out_drop_write; |
| 2005 | 2046 | ||
| @@ -2016,11 +2057,16 @@ int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, | |||
| 2016 | goto out_drop_write; | 2057 | goto out_drop_write; |
| 2017 | 2058 | ||
| 2018 | ret = -EINVAL; | 2059 | ret = -EINVAL; |
| 2019 | if (!dst_file->f_op->dedupe_file_range) | 2060 | if (!dst_file->f_op->remap_file_range) |
| 2020 | goto out_drop_write; | 2061 | goto out_drop_write; |
| 2021 | 2062 | ||
| 2022 | ret = dst_file->f_op->dedupe_file_range(src_file, src_pos, | 2063 | if (len == 0) { |
| 2023 | dst_file, dst_pos, len); | 2064 | ret = 0; |
| 2065 | goto out_drop_write; | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | ret = dst_file->f_op->remap_file_range(src_file, src_pos, dst_file, | ||
| 2069 | dst_pos, len, remap_flags | REMAP_FILE_DEDUP); | ||
| 2024 | out_drop_write: | 2070 | out_drop_write: |
| 2025 | mnt_drop_write_file(dst_file); | 2071 | mnt_drop_write_file(dst_file); |
| 2026 | 2072 | ||
| @@ -2037,7 +2083,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) | |||
| 2037 | int i; | 2083 | int i; |
| 2038 | int ret; | 2084 | int ret; |
| 2039 | u16 count = same->dest_count; | 2085 | u16 count = same->dest_count; |
| 2040 | int deduped; | 2086 | loff_t deduped; |
| 2041 | 2087 | ||
| 2042 | if (!(file->f_mode & FMODE_READ)) | 2088 | if (!(file->f_mode & FMODE_READ)) |
| 2043 | return -EINVAL; | 2089 | return -EINVAL; |
| @@ -2056,7 +2102,7 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) | |||
| 2056 | if (!S_ISREG(src->i_mode)) | 2102 | if (!S_ISREG(src->i_mode)) |
| 2057 | goto out; | 2103 | goto out; |
| 2058 | 2104 | ||
| 2059 | ret = clone_verify_area(file, off, len, false); | 2105 | ret = remap_verify_area(file, off, len, false); |
| 2060 | if (ret < 0) | 2106 | if (ret < 0) |
| 2061 | goto out; | 2107 | goto out; |
| 2062 | ret = 0; | 2108 | ret = 0; |
| @@ -2088,7 +2134,8 @@ int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same) | |||
| 2088 | } | 2134 | } |
| 2089 | 2135 | ||
| 2090 | deduped = vfs_dedupe_file_range_one(file, off, dst_file, | 2136 | deduped = vfs_dedupe_file_range_one(file, off, dst_file, |
| 2091 | info->dest_offset, len); | 2137 | info->dest_offset, len, |
| 2138 | REMAP_FILE_CAN_SHORTEN); | ||
| 2092 | if (deduped == -EBADE) | 2139 | if (deduped == -EBADE) |
| 2093 | info->status = FILE_DEDUPE_RANGE_DIFFERS; | 2140 | info->status = FILE_DEDUPE_RANGE_DIFFERS; |
| 2094 | else if (deduped < 0) | 2141 | else if (deduped < 0) |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 61a5ad2600e8..53c9ab8fb777 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -919,28 +919,67 @@ out_unlock: | |||
| 919 | return error; | 919 | return error; |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | STATIC int | ||
| 923 | xfs_file_clone_range( | ||
| 924 | struct file *file_in, | ||
| 925 | loff_t pos_in, | ||
| 926 | struct file *file_out, | ||
| 927 | loff_t pos_out, | ||
| 928 | u64 len) | ||
| 929 | { | ||
| 930 | return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, | ||
| 931 | len, false); | ||
| 932 | } | ||
| 933 | 922 | ||
| 934 | STATIC int | 923 | loff_t |
| 935 | xfs_file_dedupe_range( | 924 | xfs_file_remap_range( |
| 936 | struct file *file_in, | 925 | struct file *file_in, |
| 937 | loff_t pos_in, | 926 | loff_t pos_in, |
| 938 | struct file *file_out, | 927 | struct file *file_out, |
| 939 | loff_t pos_out, | 928 | loff_t pos_out, |
| 940 | u64 len) | 929 | loff_t len, |
| 930 | unsigned int remap_flags) | ||
| 941 | { | 931 | { |
| 942 | return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, | 932 | struct inode *inode_in = file_inode(file_in); |
| 943 | len, true); | 933 | struct xfs_inode *src = XFS_I(inode_in); |
| 934 | struct inode *inode_out = file_inode(file_out); | ||
| 935 | struct xfs_inode *dest = XFS_I(inode_out); | ||
| 936 | struct xfs_mount *mp = src->i_mount; | ||
| 937 | loff_t remapped = 0; | ||
| 938 | xfs_extlen_t cowextsize; | ||
| 939 | int ret; | ||
| 940 | |||
| 941 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) | ||
| 942 | return -EINVAL; | ||
| 943 | |||
| 944 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) | ||
| 945 | return -EOPNOTSUPP; | ||
| 946 | |||
| 947 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 948 | return -EIO; | ||
| 949 | |||
| 950 | /* Prepare and then clone file data. */ | ||
| 951 | ret = xfs_reflink_remap_prep(file_in, pos_in, file_out, pos_out, | ||
| 952 | &len, remap_flags); | ||
| 953 | if (ret < 0 || len == 0) | ||
| 954 | return ret; | ||
| 955 | |||
| 956 | trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); | ||
| 957 | |||
| 958 | ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len, | ||
| 959 | &remapped); | ||
| 960 | if (ret) | ||
| 961 | goto out_unlock; | ||
| 962 | |||
| 963 | /* | ||
| 964 | * Carry the cowextsize hint from src to dest if we're sharing the | ||
| 965 | * entire source file to the entire destination file, the source file | ||
| 966 | * has a cowextsize hint, and the destination file does not. | ||
| 967 | */ | ||
| 968 | cowextsize = 0; | ||
| 969 | if (pos_in == 0 && len == i_size_read(inode_in) && | ||
| 970 | (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) && | ||
| 971 | pos_out == 0 && len >= i_size_read(inode_out) && | ||
| 972 | !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) | ||
| 973 | cowextsize = src->i_d.di_cowextsize; | ||
| 974 | |||
| 975 | ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize, | ||
| 976 | remap_flags); | ||
| 977 | |||
| 978 | out_unlock: | ||
| 979 | xfs_reflink_remap_unlock(file_in, file_out); | ||
| 980 | if (ret) | ||
| 981 | trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); | ||
| 982 | return remapped > 0 ? remapped : ret; | ||
| 944 | } | 983 | } |
| 945 | 984 | ||
| 946 | STATIC int | 985 | STATIC int |
| @@ -1175,8 +1214,7 @@ const struct file_operations xfs_file_operations = { | |||
| 1175 | .fsync = xfs_file_fsync, | 1214 | .fsync = xfs_file_fsync, |
| 1176 | .get_unmapped_area = thp_get_unmapped_area, | 1215 | .get_unmapped_area = thp_get_unmapped_area, |
| 1177 | .fallocate = xfs_file_fallocate, | 1216 | .fallocate = xfs_file_fallocate, |
| 1178 | .clone_file_range = xfs_file_clone_range, | 1217 | .remap_file_range = xfs_file_remap_range, |
| 1179 | .dedupe_file_range = xfs_file_dedupe_range, | ||
| 1180 | }; | 1218 | }; |
| 1181 | 1219 | ||
| 1182 | const struct file_operations xfs_dir_file_operations = { | 1220 | const struct file_operations xfs_dir_file_operations = { |
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 8eaeec9d58ed..ecdb086bc23e 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c | |||
| @@ -913,18 +913,18 @@ out_error: | |||
| 913 | /* | 913 | /* |
| 914 | * Update destination inode size & cowextsize hint, if necessary. | 914 | * Update destination inode size & cowextsize hint, if necessary. |
| 915 | */ | 915 | */ |
| 916 | STATIC int | 916 | int |
| 917 | xfs_reflink_update_dest( | 917 | xfs_reflink_update_dest( |
| 918 | struct xfs_inode *dest, | 918 | struct xfs_inode *dest, |
| 919 | xfs_off_t newlen, | 919 | xfs_off_t newlen, |
| 920 | xfs_extlen_t cowextsize, | 920 | xfs_extlen_t cowextsize, |
| 921 | bool is_dedupe) | 921 | unsigned int remap_flags) |
| 922 | { | 922 | { |
| 923 | struct xfs_mount *mp = dest->i_mount; | 923 | struct xfs_mount *mp = dest->i_mount; |
| 924 | struct xfs_trans *tp; | 924 | struct xfs_trans *tp; |
| 925 | int error; | 925 | int error; |
| 926 | 926 | ||
| 927 | if (is_dedupe && newlen <= i_size_read(VFS_I(dest)) && cowextsize == 0) | 927 | if (newlen <= i_size_read(VFS_I(dest)) && cowextsize == 0) |
| 928 | return 0; | 928 | return 0; |
| 929 | 929 | ||
| 930 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); | 930 | error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); |
| @@ -945,10 +945,6 @@ xfs_reflink_update_dest( | |||
| 945 | dest->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; | 945 | dest->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; |
| 946 | } | 946 | } |
| 947 | 947 | ||
| 948 | if (!is_dedupe) { | ||
| 949 | xfs_trans_ichgtime(tp, dest, | ||
| 950 | XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
| 951 | } | ||
| 952 | xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE); | 948 | xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE); |
| 953 | 949 | ||
| 954 | error = xfs_trans_commit(tp); | 950 | error = xfs_trans_commit(tp); |
| @@ -1112,19 +1108,28 @@ out: | |||
| 1112 | /* | 1108 | /* |
| 1113 | * Iteratively remap one file's extents (and holes) to another's. | 1109 | * Iteratively remap one file's extents (and holes) to another's. |
| 1114 | */ | 1110 | */ |
| 1115 | STATIC int | 1111 | int |
| 1116 | xfs_reflink_remap_blocks( | 1112 | xfs_reflink_remap_blocks( |
| 1117 | struct xfs_inode *src, | 1113 | struct xfs_inode *src, |
| 1118 | xfs_fileoff_t srcoff, | 1114 | loff_t pos_in, |
| 1119 | struct xfs_inode *dest, | 1115 | struct xfs_inode *dest, |
| 1120 | xfs_fileoff_t destoff, | 1116 | loff_t pos_out, |
| 1121 | xfs_filblks_t len, | 1117 | loff_t remap_len, |
| 1122 | xfs_off_t new_isize) | 1118 | loff_t *remapped) |
| 1123 | { | 1119 | { |
| 1124 | struct xfs_bmbt_irec imap; | 1120 | struct xfs_bmbt_irec imap; |
| 1121 | xfs_fileoff_t srcoff; | ||
| 1122 | xfs_fileoff_t destoff; | ||
| 1123 | xfs_filblks_t len; | ||
| 1124 | xfs_filblks_t range_len; | ||
| 1125 | xfs_filblks_t remapped_len = 0; | ||
| 1126 | xfs_off_t new_isize = pos_out + remap_len; | ||
| 1125 | int nimaps; | 1127 | int nimaps; |
| 1126 | int error = 0; | 1128 | int error = 0; |
| 1127 | xfs_filblks_t range_len; | 1129 | |
| 1130 | destoff = XFS_B_TO_FSBT(src->i_mount, pos_out); | ||
| 1131 | srcoff = XFS_B_TO_FSBT(src->i_mount, pos_in); | ||
| 1132 | len = XFS_B_TO_FSB(src->i_mount, remap_len); | ||
| 1128 | 1133 | ||
| 1129 | /* drange = (destoff, destoff + len); srange = (srcoff, srcoff + len) */ | 1134 | /* drange = (destoff, destoff + len); srange = (srcoff, srcoff + len) */ |
| 1130 | while (len) { | 1135 | while (len) { |
| @@ -1139,7 +1144,7 @@ xfs_reflink_remap_blocks( | |||
| 1139 | error = xfs_bmapi_read(src, srcoff, len, &imap, &nimaps, 0); | 1144 | error = xfs_bmapi_read(src, srcoff, len, &imap, &nimaps, 0); |
| 1140 | xfs_iunlock(src, lock_mode); | 1145 | xfs_iunlock(src, lock_mode); |
| 1141 | if (error) | 1146 | if (error) |
| 1142 | goto err; | 1147 | break; |
| 1143 | ASSERT(nimaps == 1); | 1148 | ASSERT(nimaps == 1); |
| 1144 | 1149 | ||
| 1145 | trace_xfs_reflink_remap_imap(src, srcoff, len, XFS_IO_OVERWRITE, | 1150 | trace_xfs_reflink_remap_imap(src, srcoff, len, XFS_IO_OVERWRITE, |
| @@ -1153,23 +1158,24 @@ xfs_reflink_remap_blocks( | |||
| 1153 | error = xfs_reflink_remap_extent(dest, &imap, destoff, | 1158 | error = xfs_reflink_remap_extent(dest, &imap, destoff, |
| 1154 | new_isize); | 1159 | new_isize); |
| 1155 | if (error) | 1160 | if (error) |
| 1156 | goto err; | 1161 | break; |
| 1157 | 1162 | ||
| 1158 | if (fatal_signal_pending(current)) { | 1163 | if (fatal_signal_pending(current)) { |
| 1159 | error = -EINTR; | 1164 | error = -EINTR; |
| 1160 | goto err; | 1165 | break; |
| 1161 | } | 1166 | } |
| 1162 | 1167 | ||
| 1163 | /* Advance drange/srange */ | 1168 | /* Advance drange/srange */ |
| 1164 | srcoff += range_len; | 1169 | srcoff += range_len; |
| 1165 | destoff += range_len; | 1170 | destoff += range_len; |
| 1166 | len -= range_len; | 1171 | len -= range_len; |
| 1172 | remapped_len += range_len; | ||
| 1167 | } | 1173 | } |
| 1168 | 1174 | ||
| 1169 | return 0; | 1175 | if (error) |
| 1170 | 1176 | trace_xfs_reflink_remap_blocks_error(dest, error, _RET_IP_); | |
| 1171 | err: | 1177 | *remapped = min_t(loff_t, remap_len, |
| 1172 | trace_xfs_reflink_remap_blocks_error(dest, error, _RET_IP_); | 1178 | XFS_FSB_TO_B(src->i_mount, remapped_len)); |
| 1173 | return error; | 1179 | return error; |
| 1174 | } | 1180 | } |
| 1175 | 1181 | ||
| @@ -1218,7 +1224,7 @@ retry: | |||
| 1218 | } | 1224 | } |
| 1219 | 1225 | ||
| 1220 | /* Unlock both inodes after they've been prepped for a range clone. */ | 1226 | /* Unlock both inodes after they've been prepped for a range clone. */ |
| 1221 | STATIC void | 1227 | void |
| 1222 | xfs_reflink_remap_unlock( | 1228 | xfs_reflink_remap_unlock( |
| 1223 | struct file *file_in, | 1229 | struct file *file_in, |
| 1224 | struct file *file_out) | 1230 | struct file *file_out) |
| @@ -1286,21 +1292,20 @@ xfs_reflink_zero_posteof( | |||
| 1286 | * stale data in the destination file. Hence we reject these clone attempts with | 1292 | * stale data in the destination file. Hence we reject these clone attempts with |
| 1287 | * -EINVAL in this case. | 1293 | * -EINVAL in this case. |
| 1288 | */ | 1294 | */ |
| 1289 | STATIC int | 1295 | int |
| 1290 | xfs_reflink_remap_prep( | 1296 | xfs_reflink_remap_prep( |
| 1291 | struct file *file_in, | 1297 | struct file *file_in, |
| 1292 | loff_t pos_in, | 1298 | loff_t pos_in, |
| 1293 | struct file *file_out, | 1299 | struct file *file_out, |
| 1294 | loff_t pos_out, | 1300 | loff_t pos_out, |
| 1295 | u64 *len, | 1301 | loff_t *len, |
| 1296 | bool is_dedupe) | 1302 | unsigned int remap_flags) |
| 1297 | { | 1303 | { |
| 1298 | struct inode *inode_in = file_inode(file_in); | 1304 | struct inode *inode_in = file_inode(file_in); |
| 1299 | struct xfs_inode *src = XFS_I(inode_in); | 1305 | struct xfs_inode *src = XFS_I(inode_in); |
| 1300 | struct inode *inode_out = file_inode(file_out); | 1306 | struct inode *inode_out = file_inode(file_out); |
| 1301 | struct xfs_inode *dest = XFS_I(inode_out); | 1307 | struct xfs_inode *dest = XFS_I(inode_out); |
| 1302 | bool same_inode = (inode_in == inode_out); | 1308 | bool same_inode = (inode_in == inode_out); |
| 1303 | u64 blkmask = i_blocksize(inode_in) - 1; | ||
| 1304 | ssize_t ret; | 1309 | ssize_t ret; |
| 1305 | 1310 | ||
| 1306 | /* Lock both files against IO */ | 1311 | /* Lock both files against IO */ |
| @@ -1323,29 +1328,11 @@ xfs_reflink_remap_prep( | |||
| 1323 | if (IS_DAX(inode_in) || IS_DAX(inode_out)) | 1328 | if (IS_DAX(inode_in) || IS_DAX(inode_out)) |
| 1324 | goto out_unlock; | 1329 | goto out_unlock; |
| 1325 | 1330 | ||
| 1326 | ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out, | 1331 | ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out, |
| 1327 | len, is_dedupe); | 1332 | len, remap_flags); |
| 1328 | if (ret <= 0) | 1333 | if (ret < 0 || *len == 0) |
| 1329 | goto out_unlock; | 1334 | goto out_unlock; |
| 1330 | 1335 | ||
| 1331 | /* | ||
| 1332 | * If the dedupe data matches, chop off the partial EOF block | ||
| 1333 | * from the source file so we don't try to dedupe the partial | ||
| 1334 | * EOF block. | ||
| 1335 | */ | ||
| 1336 | if (is_dedupe) { | ||
| 1337 | *len &= ~blkmask; | ||
| 1338 | } else if (*len & blkmask) { | ||
| 1339 | /* | ||
| 1340 | * The user is attempting to share a partial EOF block, | ||
| 1341 | * if it's inside the destination EOF then reject it. | ||
| 1342 | */ | ||
| 1343 | if (pos_out + *len < i_size_read(inode_out)) { | ||
| 1344 | ret = -EINVAL; | ||
| 1345 | goto out_unlock; | ||
| 1346 | } | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | /* Attach dquots to dest inode before changing block map */ | 1336 | /* Attach dquots to dest inode before changing block map */ |
| 1350 | ret = xfs_qm_dqattach(dest); | 1337 | ret = xfs_qm_dqattach(dest); |
| 1351 | if (ret) | 1338 | if (ret) |
| @@ -1365,31 +1352,9 @@ xfs_reflink_remap_prep( | |||
| 1365 | goto out_unlock; | 1352 | goto out_unlock; |
| 1366 | 1353 | ||
| 1367 | /* Zap any page cache for the destination file's range. */ | 1354 | /* Zap any page cache for the destination file's range. */ |
| 1368 | truncate_inode_pages_range(&inode_out->i_data, pos_out, | 1355 | truncate_inode_pages_range(&inode_out->i_data, |
| 1369 | PAGE_ALIGN(pos_out + *len) - 1); | 1356 | round_down(pos_out, PAGE_SIZE), |
| 1370 | 1357 | round_up(pos_out + *len, PAGE_SIZE) - 1); | |
| 1371 | /* If we're altering the file contents... */ | ||
| 1372 | if (!is_dedupe) { | ||
| 1373 | /* | ||
| 1374 | * ...update the timestamps (which will grab the ilock again | ||
| 1375 | * from xfs_fs_dirty_inode, so we have to call it before we | ||
| 1376 | * take the ilock). | ||
| 1377 | */ | ||
| 1378 | if (!(file_out->f_mode & FMODE_NOCMTIME)) { | ||
| 1379 | ret = file_update_time(file_out); | ||
| 1380 | if (ret) | ||
| 1381 | goto out_unlock; | ||
| 1382 | } | ||
| 1383 | |||
| 1384 | /* | ||
| 1385 | * ...clear the security bits if the process is not being run | ||
| 1386 | * by root. This keeps people from modifying setuid and setgid | ||
| 1387 | * binaries. | ||
| 1388 | */ | ||
| 1389 | ret = file_remove_privs(file_out); | ||
| 1390 | if (ret) | ||
| 1391 | goto out_unlock; | ||
| 1392 | } | ||
| 1393 | 1358 | ||
| 1394 | return 1; | 1359 | return 1; |
| 1395 | out_unlock: | 1360 | out_unlock: |
| @@ -1398,72 +1363,6 @@ out_unlock: | |||
| 1398 | } | 1363 | } |
| 1399 | 1364 | ||
| 1400 | /* | 1365 | /* |
| 1401 | * Link a range of blocks from one file to another. | ||
| 1402 | */ | ||
| 1403 | int | ||
| 1404 | xfs_reflink_remap_range( | ||
| 1405 | struct file *file_in, | ||
| 1406 | loff_t pos_in, | ||
| 1407 | struct file *file_out, | ||
| 1408 | loff_t pos_out, | ||
| 1409 | u64 len, | ||
| 1410 | bool is_dedupe) | ||
| 1411 | { | ||
| 1412 | struct inode *inode_in = file_inode(file_in); | ||
| 1413 | struct xfs_inode *src = XFS_I(inode_in); | ||
| 1414 | struct inode *inode_out = file_inode(file_out); | ||
| 1415 | struct xfs_inode *dest = XFS_I(inode_out); | ||
| 1416 | struct xfs_mount *mp = src->i_mount; | ||
| 1417 | xfs_fileoff_t sfsbno, dfsbno; | ||
| 1418 | xfs_filblks_t fsblen; | ||
| 1419 | xfs_extlen_t cowextsize; | ||
| 1420 | ssize_t ret; | ||
| 1421 | |||
| 1422 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) | ||
| 1423 | return -EOPNOTSUPP; | ||
| 1424 | |||
| 1425 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 1426 | return -EIO; | ||
| 1427 | |||
| 1428 | /* Prepare and then clone file data. */ | ||
| 1429 | ret = xfs_reflink_remap_prep(file_in, pos_in, file_out, pos_out, | ||
| 1430 | &len, is_dedupe); | ||
| 1431 | if (ret <= 0) | ||
| 1432 | return ret; | ||
| 1433 | |||
| 1434 | trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); | ||
| 1435 | |||
| 1436 | dfsbno = XFS_B_TO_FSBT(mp, pos_out); | ||
| 1437 | sfsbno = XFS_B_TO_FSBT(mp, pos_in); | ||
| 1438 | fsblen = XFS_B_TO_FSB(mp, len); | ||
| 1439 | ret = xfs_reflink_remap_blocks(src, sfsbno, dest, dfsbno, fsblen, | ||
| 1440 | pos_out + len); | ||
| 1441 | if (ret) | ||
| 1442 | goto out_unlock; | ||
| 1443 | |||
| 1444 | /* | ||
| 1445 | * Carry the cowextsize hint from src to dest if we're sharing the | ||
| 1446 | * entire source file to the entire destination file, the source file | ||
| 1447 | * has a cowextsize hint, and the destination file does not. | ||
| 1448 | */ | ||
| 1449 | cowextsize = 0; | ||
| 1450 | if (pos_in == 0 && len == i_size_read(inode_in) && | ||
| 1451 | (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) && | ||
| 1452 | pos_out == 0 && len >= i_size_read(inode_out) && | ||
| 1453 | !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) | ||
| 1454 | cowextsize = src->i_d.di_cowextsize; | ||
| 1455 | |||
| 1456 | ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize, | ||
| 1457 | is_dedupe); | ||
| 1458 | |||
| 1459 | out_unlock: | ||
| 1460 | xfs_reflink_remap_unlock(file_in, file_out); | ||
| 1461 | if (ret) | ||
| 1462 | trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); | ||
| 1463 | return ret; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | /* | ||
| 1467 | * The user wants to preemptively CoW all shared blocks in this file, | 1366 | * The user wants to preemptively CoW all shared blocks in this file, |
| 1468 | * which enables us to turn off the reflink flag. Iterate all | 1367 | * which enables us to turn off the reflink flag. Iterate all |
| 1469 | * extents which are not prealloc/delalloc to see which ranges are | 1368 | * extents which are not prealloc/delalloc to see which ranges are |
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 7f47202b5639..6d73daef1f13 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h | |||
| @@ -27,13 +27,24 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, | |||
| 27 | extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, | 27 | extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, |
| 28 | xfs_off_t count); | 28 | xfs_off_t count); |
| 29 | extern int xfs_reflink_recover_cow(struct xfs_mount *mp); | 29 | extern int xfs_reflink_recover_cow(struct xfs_mount *mp); |
| 30 | extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, | 30 | extern loff_t xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, |
| 31 | struct file *file_out, loff_t pos_out, u64 len, bool is_dedupe); | 31 | struct file *file_out, loff_t pos_out, loff_t len, |
| 32 | unsigned int remap_flags); | ||
| 32 | extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, | 33 | extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, |
| 33 | struct xfs_inode *ip, bool *has_shared); | 34 | struct xfs_inode *ip, bool *has_shared); |
| 34 | extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip, | 35 | extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip, |
| 35 | struct xfs_trans **tpp); | 36 | struct xfs_trans **tpp); |
| 36 | extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, | 37 | extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, |
| 37 | xfs_off_t len); | 38 | xfs_off_t len); |
| 39 | extern int xfs_reflink_remap_prep(struct file *file_in, loff_t pos_in, | ||
| 40 | struct file *file_out, loff_t pos_out, loff_t *len, | ||
| 41 | unsigned int remap_flags); | ||
| 42 | extern int xfs_reflink_remap_blocks(struct xfs_inode *src, loff_t pos_in, | ||
| 43 | struct xfs_inode *dest, loff_t pos_out, loff_t remap_len, | ||
| 44 | loff_t *remapped); | ||
| 45 | extern int xfs_reflink_update_dest(struct xfs_inode *dest, xfs_off_t newlen, | ||
| 46 | xfs_extlen_t cowextsize, unsigned int remap_flags); | ||
| 47 | extern void xfs_reflink_remap_unlock(struct file *file_in, | ||
| 48 | struct file *file_out); | ||
| 38 | 49 | ||
| 39 | #endif /* __XFS_REFLINK_H */ | 50 | #endif /* __XFS_REFLINK_H */ |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 91a877fa00cb..9ccad6b062f2 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h | |||
| @@ -82,6 +82,53 @@ enum drm_connector_status { | |||
| 82 | connector_status_unknown = 3, | 82 | connector_status_unknown = 3, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | /** | ||
| 86 | * enum drm_connector_registration_status - userspace registration status for | ||
| 87 | * a &drm_connector | ||
| 88 | * | ||
| 89 | * This enum is used to track the status of initializing a connector and | ||
| 90 | * registering it with userspace, so that DRM can prevent bogus modesets on | ||
| 91 | * connectors that no longer exist. | ||
| 92 | */ | ||
| 93 | enum drm_connector_registration_state { | ||
| 94 | /** | ||
| 95 | * @DRM_CONNECTOR_INITIALIZING: The connector has just been created, | ||
| 96 | * but has yet to be exposed to userspace. There should be no | ||
| 97 | * additional restrictions to how the state of this connector may be | ||
| 98 | * modified. | ||
| 99 | */ | ||
| 100 | DRM_CONNECTOR_INITIALIZING = 0, | ||
| 101 | |||
| 102 | /** | ||
| 103 | * @DRM_CONNECTOR_REGISTERED: The connector has been fully initialized | ||
| 104 | * and registered with sysfs, as such it has been exposed to | ||
| 105 | * userspace. There should be no additional restrictions to how the | ||
| 106 | * state of this connector may be modified. | ||
| 107 | */ | ||
| 108 | DRM_CONNECTOR_REGISTERED = 1, | ||
| 109 | |||
| 110 | /** | ||
| 111 | * @DRM_CONNECTOR_UNREGISTERED: The connector has either been exposed | ||
| 112 | * to userspace and has since been unregistered and removed from | ||
| 113 | * userspace, or the connector was unregistered before it had a chance | ||
| 114 | * to be exposed to userspace (e.g. still in the | ||
| 115 | * @DRM_CONNECTOR_INITIALIZING state). When a connector is | ||
| 116 | * unregistered, there are additional restrictions to how its state | ||
| 117 | * may be modified: | ||
| 118 | * | ||
| 119 | * - An unregistered connector may only have its DPMS changed from | ||
| 120 | * On->Off. Once DPMS is changed to Off, it may not be switched back | ||
| 121 | * to On. | ||
| 122 | * - Modesets are not allowed on unregistered connectors, unless they | ||
| 123 | * would result in disabling its assigned CRTCs. This means | ||
| 124 | * disabling a CRTC on an unregistered connector is OK, but enabling | ||
| 125 | * one is not. | ||
| 126 | * - Removing a CRTC from an unregistered connector is OK, but new | ||
| 127 | * CRTCs may never be assigned to an unregistered connector. | ||
| 128 | */ | ||
| 129 | DRM_CONNECTOR_UNREGISTERED = 2, | ||
| 130 | }; | ||
| 131 | |||
| 85 | enum subpixel_order { | 132 | enum subpixel_order { |
| 86 | SubPixelUnknown = 0, | 133 | SubPixelUnknown = 0, |
| 87 | SubPixelHorizontalRGB, | 134 | SubPixelHorizontalRGB, |
| @@ -853,10 +900,12 @@ struct drm_connector { | |||
| 853 | bool ycbcr_420_allowed; | 900 | bool ycbcr_420_allowed; |
| 854 | 901 | ||
| 855 | /** | 902 | /** |
| 856 | * @registered: Is this connector exposed (registered) with userspace? | 903 | * @registration_state: Is this connector initializing, exposed |
| 904 | * (registered) with userspace, or unregistered? | ||
| 905 | * | ||
| 857 | * Protected by @mutex. | 906 | * Protected by @mutex. |
| 858 | */ | 907 | */ |
| 859 | bool registered; | 908 | enum drm_connector_registration_state registration_state; |
| 860 | 909 | ||
| 861 | /** | 910 | /** |
| 862 | * @modes: | 911 | * @modes: |
| @@ -1166,6 +1215,24 @@ static inline void drm_connector_unreference(struct drm_connector *connector) | |||
| 1166 | drm_connector_put(connector); | 1215 | drm_connector_put(connector); |
| 1167 | } | 1216 | } |
| 1168 | 1217 | ||
| 1218 | /** | ||
| 1219 | * drm_connector_is_unregistered - has the connector been unregistered from | ||
| 1220 | * userspace? | ||
| 1221 | * @connector: DRM connector | ||
| 1222 | * | ||
| 1223 | * Checks whether or not @connector has been unregistered from userspace. | ||
| 1224 | * | ||
| 1225 | * Returns: | ||
| 1226 | * True if the connector was unregistered, false if the connector is | ||
| 1227 | * registered or has not yet been registered with userspace. | ||
| 1228 | */ | ||
| 1229 | static inline bool | ||
| 1230 | drm_connector_is_unregistered(struct drm_connector *connector) | ||
| 1231 | { | ||
| 1232 | return READ_ONCE(connector->registration_state) == | ||
| 1233 | DRM_CONNECTOR_UNREGISTERED; | ||
| 1234 | } | ||
| 1235 | |||
| 1169 | const char *drm_get_connector_status_name(enum drm_connector_status status); | 1236 | const char *drm_get_connector_status_name(enum drm_connector_status status); |
| 1170 | const char *drm_get_subpixel_order_name(enum subpixel_order order); | 1237 | const char *drm_get_subpixel_order_name(enum subpixel_order order); |
| 1171 | const char *drm_get_dpms_name(int val); | 1238 | const char *drm_get_dpms_name(int val); |
diff --git a/include/linux/adxl.h b/include/linux/adxl.h index 2a629acb4c3f..2d29f55923e3 100644 --- a/include/linux/adxl.h +++ b/include/linux/adxl.h | |||
| @@ -7,7 +7,12 @@ | |||
| 7 | #ifndef _LINUX_ADXL_H | 7 | #ifndef _LINUX_ADXL_H |
| 8 | #define _LINUX_ADXL_H | 8 | #define _LINUX_ADXL_H |
| 9 | 9 | ||
| 10 | #ifdef CONFIG_ACPI_ADXL | ||
| 10 | const char * const *adxl_get_component_names(void); | 11 | const char * const *adxl_get_component_names(void); |
| 11 | int adxl_decode(u64 addr, u64 component_values[]); | 12 | int adxl_decode(u64 addr, u64 component_values[]); |
| 13 | #else | ||
| 14 | static inline const char * const *adxl_get_component_names(void) { return NULL; } | ||
| 15 | static inline int adxl_decode(u64 addr, u64 component_values[]) { return -EOPNOTSUPP; } | ||
| 16 | #endif | ||
| 12 | 17 | ||
| 13 | #endif /* _LINUX_ADXL_H */ | 18 | #endif /* _LINUX_ADXL_H */ |
diff --git a/include/linux/bio.h b/include/linux/bio.h index b47c7f716731..056fb627edb3 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h | |||
| @@ -503,31 +503,23 @@ do { \ | |||
| 503 | disk_devt((bio)->bi_disk) | 503 | disk_devt((bio)->bi_disk) |
| 504 | 504 | ||
| 505 | #if defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP) | 505 | #if defined(CONFIG_MEMCG) && defined(CONFIG_BLK_CGROUP) |
| 506 | int bio_associate_blkg_from_page(struct bio *bio, struct page *page); | 506 | int bio_associate_blkcg_from_page(struct bio *bio, struct page *page); |
| 507 | #else | 507 | #else |
| 508 | static inline int bio_associate_blkg_from_page(struct bio *bio, | 508 | static inline int bio_associate_blkcg_from_page(struct bio *bio, |
| 509 | struct page *page) { return 0; } | 509 | struct page *page) { return 0; } |
| 510 | #endif | 510 | #endif |
| 511 | 511 | ||
| 512 | #ifdef CONFIG_BLK_CGROUP | 512 | #ifdef CONFIG_BLK_CGROUP |
| 513 | int bio_associate_blkcg(struct bio *bio, struct cgroup_subsys_state *blkcg_css); | ||
| 513 | int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg); | 514 | int bio_associate_blkg(struct bio *bio, struct blkcg_gq *blkg); |
| 514 | int bio_associate_blkg_from_css(struct bio *bio, | ||
| 515 | struct cgroup_subsys_state *css); | ||
| 516 | int bio_associate_create_blkg(struct request_queue *q, struct bio *bio); | ||
| 517 | int bio_reassociate_blkg(struct request_queue *q, struct bio *bio); | ||
| 518 | void bio_disassociate_task(struct bio *bio); | 515 | void bio_disassociate_task(struct bio *bio); |
| 519 | void bio_clone_blkg_association(struct bio *dst, struct bio *src); | 516 | void bio_clone_blkcg_association(struct bio *dst, struct bio *src); |
| 520 | #else /* CONFIG_BLK_CGROUP */ | 517 | #else /* CONFIG_BLK_CGROUP */ |
| 521 | static inline int bio_associate_blkg_from_css(struct bio *bio, | 518 | static inline int bio_associate_blkcg(struct bio *bio, |
| 522 | struct cgroup_subsys_state *css) | 519 | struct cgroup_subsys_state *blkcg_css) { return 0; } |
| 523 | { return 0; } | ||
| 524 | static inline int bio_associate_create_blkg(struct request_queue *q, | ||
| 525 | struct bio *bio) { return 0; } | ||
| 526 | static inline int bio_reassociate_blkg(struct request_queue *q, struct bio *bio) | ||
| 527 | { return 0; } | ||
| 528 | static inline void bio_disassociate_task(struct bio *bio) { } | 520 | static inline void bio_disassociate_task(struct bio *bio) { } |
| 529 | static inline void bio_clone_blkg_association(struct bio *dst, | 521 | static inline void bio_clone_blkcg_association(struct bio *dst, |
| 530 | struct bio *src) { } | 522 | struct bio *src) { } |
| 531 | #endif /* CONFIG_BLK_CGROUP */ | 523 | #endif /* CONFIG_BLK_CGROUP */ |
| 532 | 524 | ||
| 533 | #ifdef CONFIG_HIGHMEM | 525 | #ifdef CONFIG_HIGHMEM |
diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 1e76ceebeb5d..6d766a19f2bb 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h | |||
| @@ -126,7 +126,7 @@ struct blkcg_gq { | |||
| 126 | struct request_list rl; | 126 | struct request_list rl; |
| 127 | 127 | ||
| 128 | /* reference count */ | 128 | /* reference count */ |
| 129 | struct percpu_ref refcnt; | 129 | atomic_t refcnt; |
| 130 | 130 | ||
| 131 | /* is this blkg online? protected by both blkcg and q locks */ | 131 | /* is this blkg online? protected by both blkcg and q locks */ |
| 132 | bool online; | 132 | bool online; |
| @@ -184,8 +184,6 @@ extern struct cgroup_subsys_state * const blkcg_root_css; | |||
| 184 | 184 | ||
| 185 | struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg, | 185 | struct blkcg_gq *blkg_lookup_slowpath(struct blkcg *blkcg, |
| 186 | struct request_queue *q, bool update_hint); | 186 | struct request_queue *q, bool update_hint); |
| 187 | struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg, | ||
| 188 | struct request_queue *q); | ||
| 189 | struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, | 187 | struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg, |
| 190 | struct request_queue *q); | 188 | struct request_queue *q); |
| 191 | int blkcg_init_queue(struct request_queue *q); | 189 | int blkcg_init_queue(struct request_queue *q); |
| @@ -232,59 +230,22 @@ int blkg_conf_prep(struct blkcg *blkcg, const struct blkcg_policy *pol, | |||
| 232 | char *input, struct blkg_conf_ctx *ctx); | 230 | char *input, struct blkg_conf_ctx *ctx); |
| 233 | void blkg_conf_finish(struct blkg_conf_ctx *ctx); | 231 | void blkg_conf_finish(struct blkg_conf_ctx *ctx); |
| 234 | 232 | ||
| 235 | /** | ||
| 236 | * blkcg_css - find the current css | ||
| 237 | * | ||
| 238 | * Find the css associated with either the kthread or the current task. | ||
| 239 | * This may return a dying css, so it is up to the caller to use tryget logic | ||
| 240 | * to confirm it is alive and well. | ||
| 241 | */ | ||
| 242 | static inline struct cgroup_subsys_state *blkcg_css(void) | ||
| 243 | { | ||
| 244 | struct cgroup_subsys_state *css; | ||
| 245 | |||
| 246 | css = kthread_blkcg(); | ||
| 247 | if (css) | ||
| 248 | return css; | ||
| 249 | return task_css(current, io_cgrp_id); | ||
| 250 | } | ||
| 251 | 233 | ||
| 252 | static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) | 234 | static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) |
| 253 | { | 235 | { |
| 254 | return css ? container_of(css, struct blkcg, css) : NULL; | 236 | return css ? container_of(css, struct blkcg, css) : NULL; |
| 255 | } | 237 | } |
| 256 | 238 | ||
| 257 | /** | ||
| 258 | * __bio_blkcg - internal version of bio_blkcg for bfq and cfq | ||
| 259 | * | ||
| 260 | * DO NOT USE. | ||
| 261 | * There is a flaw using this version of the function. In particular, this was | ||
| 262 | * used in a broken paradigm where association was called on the given css. It | ||
| 263 | * is possible though that the returned css from task_css() is in the process | ||
| 264 | * of dying due to migration of the current task. So it is improper to assume | ||
| 265 | * *_get() is going to succeed. Both BFQ and CFQ rely on this logic and will | ||
| 266 | * take additional work to handle more gracefully. | ||
| 267 | */ | ||
| 268 | static inline struct blkcg *__bio_blkcg(struct bio *bio) | ||
| 269 | { | ||
| 270 | if (bio && bio->bi_blkg) | ||
| 271 | return bio->bi_blkg->blkcg; | ||
| 272 | return css_to_blkcg(blkcg_css()); | ||
| 273 | } | ||
| 274 | |||
| 275 | /** | ||
| 276 | * bio_blkcg - grab the blkcg associated with a bio | ||
| 277 | * @bio: target bio | ||
| 278 | * | ||
| 279 | * This returns the blkcg associated with a bio, NULL if not associated. | ||
| 280 | * Callers are expected to either handle NULL or know association has been | ||
| 281 | * done prior to calling this. | ||
| 282 | */ | ||
| 283 | static inline struct blkcg *bio_blkcg(struct bio *bio) | 239 | static inline struct blkcg *bio_blkcg(struct bio *bio) |
| 284 | { | 240 | { |
| 285 | if (bio && bio->bi_blkg) | 241 | struct cgroup_subsys_state *css; |
| 286 | return bio->bi_blkg->blkcg; | 242 | |
| 287 | return NULL; | 243 | if (bio && bio->bi_css) |
| 244 | return css_to_blkcg(bio->bi_css); | ||
| 245 | css = kthread_blkcg(); | ||
| 246 | if (css) | ||
| 247 | return css_to_blkcg(css); | ||
| 248 | return css_to_blkcg(task_css(current, io_cgrp_id)); | ||
| 288 | } | 249 | } |
| 289 | 250 | ||
| 290 | static inline bool blk_cgroup_congested(void) | 251 | static inline bool blk_cgroup_congested(void) |
| @@ -490,35 +451,26 @@ static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen) | |||
| 490 | */ | 451 | */ |
| 491 | static inline void blkg_get(struct blkcg_gq *blkg) | 452 | static inline void blkg_get(struct blkcg_gq *blkg) |
| 492 | { | 453 | { |
| 493 | percpu_ref_get(&blkg->refcnt); | 454 | WARN_ON_ONCE(atomic_read(&blkg->refcnt) <= 0); |
| 455 | atomic_inc(&blkg->refcnt); | ||
| 494 | } | 456 | } |
| 495 | 457 | ||
| 496 | /** | 458 | /** |
| 497 | * blkg_tryget - try and get a blkg reference | 459 | * blkg_try_get - try and get a blkg reference |
| 498 | * @blkg: blkg to get | 460 | * @blkg: blkg to get |
| 499 | * | 461 | * |
| 500 | * This is for use when doing an RCU lookup of the blkg. We may be in the midst | 462 | * This is for use when doing an RCU lookup of the blkg. We may be in the midst |
| 501 | * of freeing this blkg, so we can only use it if the refcnt is not zero. | 463 | * of freeing this blkg, so we can only use it if the refcnt is not zero. |
| 502 | */ | 464 | */ |
| 503 | static inline bool blkg_tryget(struct blkcg_gq *blkg) | 465 | static inline struct blkcg_gq *blkg_try_get(struct blkcg_gq *blkg) |
| 504 | { | 466 | { |
| 505 | return percpu_ref_tryget(&blkg->refcnt); | 467 | if (atomic_inc_not_zero(&blkg->refcnt)) |
| 468 | return blkg; | ||
| 469 | return NULL; | ||
| 506 | } | 470 | } |
| 507 | 471 | ||
| 508 | /** | ||
| 509 | * blkg_tryget_closest - try and get a blkg ref on the closet blkg | ||
| 510 | * @blkg: blkg to get | ||
| 511 | * | ||
| 512 | * This walks up the blkg tree to find the closest non-dying blkg and returns | ||
| 513 | * the blkg that it did association with as it may not be the passed in blkg. | ||
| 514 | */ | ||
| 515 | static inline struct blkcg_gq *blkg_tryget_closest(struct blkcg_gq *blkg) | ||
| 516 | { | ||
| 517 | while (!percpu_ref_tryget(&blkg->refcnt)) | ||
| 518 | blkg = blkg->parent; | ||
| 519 | 472 | ||
| 520 | return blkg; | 473 | void __blkg_release_rcu(struct rcu_head *rcu); |
| 521 | } | ||
| 522 | 474 | ||
| 523 | /** | 475 | /** |
| 524 | * blkg_put - put a blkg reference | 476 | * blkg_put - put a blkg reference |
| @@ -526,7 +478,9 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct blkcg_gq *blkg) | |||
| 526 | */ | 478 | */ |
| 527 | static inline void blkg_put(struct blkcg_gq *blkg) | 479 | static inline void blkg_put(struct blkcg_gq *blkg) |
| 528 | { | 480 | { |
| 529 | percpu_ref_put(&blkg->refcnt); | 481 | WARN_ON_ONCE(atomic_read(&blkg->refcnt) <= 0); |
| 482 | if (atomic_dec_and_test(&blkg->refcnt)) | ||
| 483 | call_rcu(&blkg->rcu_head, __blkg_release_rcu); | ||
| 530 | } | 484 | } |
| 531 | 485 | ||
| 532 | /** | 486 | /** |
| @@ -579,36 +533,25 @@ static inline struct request_list *blk_get_rl(struct request_queue *q, | |||
| 579 | 533 | ||
| 580 | rcu_read_lock(); | 534 | rcu_read_lock(); |
| 581 | 535 | ||
| 582 | if (bio && bio->bi_blkg) { | 536 | blkcg = bio_blkcg(bio); |
| 583 | blkcg = bio->bi_blkg->blkcg; | ||
| 584 | if (blkcg == &blkcg_root) | ||
| 585 | goto rl_use_root; | ||
| 586 | |||
| 587 | blkg_get(bio->bi_blkg); | ||
| 588 | rcu_read_unlock(); | ||
| 589 | return &bio->bi_blkg->rl; | ||
| 590 | } | ||
| 591 | 537 | ||
| 592 | blkcg = css_to_blkcg(blkcg_css()); | 538 | /* bypass blkg lookup and use @q->root_rl directly for root */ |
| 593 | if (blkcg == &blkcg_root) | 539 | if (blkcg == &blkcg_root) |
| 594 | goto rl_use_root; | 540 | goto root_rl; |
| 595 | 541 | ||
| 542 | /* | ||
| 543 | * Try to use blkg->rl. blkg lookup may fail under memory pressure | ||
| 544 | * or if either the blkcg or queue is going away. Fall back to | ||
| 545 | * root_rl in such cases. | ||
| 546 | */ | ||
| 596 | blkg = blkg_lookup(blkcg, q); | 547 | blkg = blkg_lookup(blkcg, q); |
| 597 | if (unlikely(!blkg)) | 548 | if (unlikely(!blkg)) |
| 598 | blkg = __blkg_lookup_create(blkcg, q); | 549 | goto root_rl; |
| 599 | |||
| 600 | if (blkg->blkcg == &blkcg_root || !blkg_tryget(blkg)) | ||
| 601 | goto rl_use_root; | ||
| 602 | 550 | ||
| 551 | blkg_get(blkg); | ||
| 603 | rcu_read_unlock(); | 552 | rcu_read_unlock(); |
| 604 | return &blkg->rl; | 553 | return &blkg->rl; |
| 605 | 554 | root_rl: | |
| 606 | /* | ||
| 607 | * Each blkg has its own request_list, however, the root blkcg | ||
| 608 | * uses the request_queue's root_rl. This is to avoid most | ||
| 609 | * overhead for the root blkcg. | ||
| 610 | */ | ||
| 611 | rl_use_root: | ||
| 612 | rcu_read_unlock(); | 555 | rcu_read_unlock(); |
| 613 | return &q->root_rl; | 556 | return &q->root_rl; |
| 614 | } | 557 | } |
| @@ -854,26 +797,32 @@ static inline bool blk_throtl_bio(struct request_queue *q, struct blkcg_gq *blkg | |||
| 854 | struct bio *bio) { return false; } | 797 | struct bio *bio) { return false; } |
| 855 | #endif | 798 | #endif |
| 856 | 799 | ||
| 857 | |||
| 858 | static inline void blkcg_bio_issue_init(struct bio *bio) | ||
| 859 | { | ||
| 860 | bio_issue_init(&bio->bi_issue, bio_sectors(bio)); | ||
| 861 | } | ||
| 862 | |||
| 863 | static inline bool blkcg_bio_issue_check(struct request_queue *q, | 800 | static inline bool blkcg_bio_issue_check(struct request_queue *q, |
| 864 | struct bio *bio) | 801 | struct bio *bio) |
| 865 | { | 802 | { |
| 803 | struct blkcg *blkcg; | ||
| 866 | struct blkcg_gq *blkg; | 804 | struct blkcg_gq *blkg; |
| 867 | bool throtl = false; | 805 | bool throtl = false; |
| 868 | 806 | ||
| 869 | rcu_read_lock(); | 807 | rcu_read_lock(); |
| 808 | blkcg = bio_blkcg(bio); | ||
| 809 | |||
| 810 | /* associate blkcg if bio hasn't attached one */ | ||
| 811 | bio_associate_blkcg(bio, &blkcg->css); | ||
| 870 | 812 | ||
| 871 | bio_associate_create_blkg(q, bio); | 813 | blkg = blkg_lookup(blkcg, q); |
| 872 | blkg = bio->bi_blkg; | 814 | if (unlikely(!blkg)) { |
| 815 | spin_lock_irq(q->queue_lock); | ||
| 816 | blkg = blkg_lookup_create(blkcg, q); | ||
| 817 | if (IS_ERR(blkg)) | ||
| 818 | blkg = NULL; | ||
| 819 | spin_unlock_irq(q->queue_lock); | ||
| 820 | } | ||
| 873 | 821 | ||
| 874 | throtl = blk_throtl_bio(q, blkg, bio); | 822 | throtl = blk_throtl_bio(q, blkg, bio); |
| 875 | 823 | ||
| 876 | if (!throtl) { | 824 | if (!throtl) { |
| 825 | blkg = blkg ?: q->root_blkg; | ||
| 877 | /* | 826 | /* |
| 878 | * If the bio is flagged with BIO_QUEUE_ENTERED it means this | 827 | * If the bio is flagged with BIO_QUEUE_ENTERED it means this |
| 879 | * is a split bio and we would have already accounted for the | 828 | * is a split bio and we would have already accounted for the |
| @@ -885,8 +834,6 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q, | |||
| 885 | blkg_rwstat_add(&blkg->stat_ios, bio->bi_opf, 1); | 834 | blkg_rwstat_add(&blkg->stat_ios, bio->bi_opf, 1); |
| 886 | } | 835 | } |
| 887 | 836 | ||
| 888 | blkcg_bio_issue_init(bio); | ||
| 889 | |||
| 890 | rcu_read_unlock(); | 837 | rcu_read_unlock(); |
| 891 | return !throtl; | 838 | return !throtl; |
| 892 | } | 839 | } |
| @@ -983,7 +930,6 @@ static inline int blkcg_activate_policy(struct request_queue *q, | |||
| 983 | static inline void blkcg_deactivate_policy(struct request_queue *q, | 930 | static inline void blkcg_deactivate_policy(struct request_queue *q, |
| 984 | const struct blkcg_policy *pol) { } | 931 | const struct blkcg_policy *pol) { } |
| 985 | 932 | ||
| 986 | static inline struct blkcg *__bio_blkcg(struct bio *bio) { return NULL; } | ||
| 987 | static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; } | 933 | static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; } |
| 988 | 934 | ||
| 989 | static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg, | 935 | static inline struct blkg_policy_data *blkg_to_pd(struct blkcg_gq *blkg, |
| @@ -999,7 +945,6 @@ static inline void blk_put_rl(struct request_list *rl) { } | |||
| 999 | static inline void blk_rq_set_rl(struct request *rq, struct request_list *rl) { } | 945 | static inline void blk_rq_set_rl(struct request *rq, struct request_list *rl) { } |
| 1000 | static inline struct request_list *blk_rq_rl(struct request *rq) { return &rq->q->root_rl; } | 946 | static inline struct request_list *blk_rq_rl(struct request *rq) { return &rq->q->root_rl; } |
| 1001 | 947 | ||
| 1002 | static inline void blkcg_bio_issue_init(struct bio *bio) { } | ||
| 1003 | static inline bool blkcg_bio_issue_check(struct request_queue *q, | 948 | static inline bool blkcg_bio_issue_check(struct request_queue *q, |
| 1004 | struct bio *bio) { return true; } | 949 | struct bio *bio) { return true; } |
| 1005 | 950 | ||
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 093a818c5b68..1dcf652ba0aa 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h | |||
| @@ -178,6 +178,7 @@ struct bio { | |||
| 178 | * release. Read comment on top of bio_associate_current(). | 178 | * release. Read comment on top of bio_associate_current(). |
| 179 | */ | 179 | */ |
| 180 | struct io_context *bi_ioc; | 180 | struct io_context *bi_ioc; |
| 181 | struct cgroup_subsys_state *bi_css; | ||
| 181 | struct blkcg_gq *bi_blkg; | 182 | struct blkcg_gq *bi_blkg; |
| 182 | struct bio_issue bi_issue; | 183 | struct bio_issue bi_issue; |
| 183 | #endif | 184 | #endif |
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 9968332cceed..9d12757a65b0 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
| @@ -93,8 +93,6 @@ extern struct css_set init_css_set; | |||
| 93 | 93 | ||
| 94 | bool css_has_online_children(struct cgroup_subsys_state *css); | 94 | bool css_has_online_children(struct cgroup_subsys_state *css); |
| 95 | struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss); | 95 | struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss); |
| 96 | struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgroup, | ||
| 97 | struct cgroup_subsys *ss); | ||
| 98 | struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup, | 96 | struct cgroup_subsys_state *cgroup_get_e_css(struct cgroup *cgroup, |
| 99 | struct cgroup_subsys *ss); | 97 | struct cgroup_subsys *ss); |
| 100 | struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, | 98 | struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry, |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8252df30b9a1..c95c0807471f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1752,6 +1752,25 @@ struct block_device_operations; | |||
| 1752 | #define NOMMU_VMFLAGS \ | 1752 | #define NOMMU_VMFLAGS \ |
| 1753 | (NOMMU_MAP_READ | NOMMU_MAP_WRITE | NOMMU_MAP_EXEC) | 1753 | (NOMMU_MAP_READ | NOMMU_MAP_WRITE | NOMMU_MAP_EXEC) |
| 1754 | 1754 | ||
| 1755 | /* | ||
| 1756 | * These flags control the behavior of the remap_file_range function pointer. | ||
| 1757 | * If it is called with len == 0 that means "remap to end of source file". | ||
| 1758 | * See Documentation/filesystems/vfs.txt for more details about this call. | ||
| 1759 | * | ||
| 1760 | * REMAP_FILE_DEDUP: only remap if contents identical (i.e. deduplicate) | ||
| 1761 | * REMAP_FILE_CAN_SHORTEN: caller can handle a shortened request | ||
| 1762 | */ | ||
| 1763 | #define REMAP_FILE_DEDUP (1 << 0) | ||
| 1764 | #define REMAP_FILE_CAN_SHORTEN (1 << 1) | ||
| 1765 | |||
| 1766 | /* | ||
| 1767 | * These flags signal that the caller is ok with altering various aspects of | ||
| 1768 | * the behavior of the remap operation. The changes must be made by the | ||
| 1769 | * implementation; the vfs remap helper functions can take advantage of them. | ||
| 1770 | * Flags in this category exist to preserve the quirky behavior of the hoisted | ||
| 1771 | * btrfs clone/dedupe ioctls. | ||
| 1772 | */ | ||
| 1773 | #define REMAP_FILE_ADVISORY (REMAP_FILE_CAN_SHORTEN) | ||
| 1755 | 1774 | ||
| 1756 | struct iov_iter; | 1775 | struct iov_iter; |
| 1757 | 1776 | ||
| @@ -1790,10 +1809,9 @@ struct file_operations { | |||
| 1790 | #endif | 1809 | #endif |
| 1791 | ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, | 1810 | ssize_t (*copy_file_range)(struct file *, loff_t, struct file *, |
| 1792 | loff_t, size_t, unsigned int); | 1811 | loff_t, size_t, unsigned int); |
| 1793 | int (*clone_file_range)(struct file *, loff_t, struct file *, loff_t, | 1812 | loff_t (*remap_file_range)(struct file *file_in, loff_t pos_in, |
| 1794 | u64); | 1813 | struct file *file_out, loff_t pos_out, |
| 1795 | int (*dedupe_file_range)(struct file *, loff_t, struct file *, loff_t, | 1814 | loff_t len, unsigned int remap_flags); |
| 1796 | u64); | ||
| 1797 | int (*fadvise)(struct file *, loff_t, loff_t, int); | 1815 | int (*fadvise)(struct file *, loff_t, loff_t, int); |
| 1798 | } __randomize_layout; | 1816 | } __randomize_layout; |
| 1799 | 1817 | ||
| @@ -1856,21 +1874,21 @@ extern ssize_t vfs_readv(struct file *, const struct iovec __user *, | |||
| 1856 | unsigned long, loff_t *, rwf_t); | 1874 | unsigned long, loff_t *, rwf_t); |
| 1857 | extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, | 1875 | extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *, |
| 1858 | loff_t, size_t, unsigned int); | 1876 | loff_t, size_t, unsigned int); |
| 1859 | extern int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in, | 1877 | extern int generic_remap_file_range_prep(struct file *file_in, loff_t pos_in, |
| 1860 | struct inode *inode_out, loff_t pos_out, | 1878 | struct file *file_out, loff_t pos_out, |
| 1861 | u64 *len, bool is_dedupe); | 1879 | loff_t *count, |
| 1862 | extern int do_clone_file_range(struct file *file_in, loff_t pos_in, | 1880 | unsigned int remap_flags); |
| 1863 | struct file *file_out, loff_t pos_out, u64 len); | 1881 | extern loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, |
| 1864 | extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in, | 1882 | struct file *file_out, loff_t pos_out, |
| 1865 | struct file *file_out, loff_t pos_out, u64 len); | 1883 | loff_t len, unsigned int remap_flags); |
| 1866 | extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff, | 1884 | extern loff_t vfs_clone_file_range(struct file *file_in, loff_t pos_in, |
| 1867 | struct inode *dest, loff_t destoff, | 1885 | struct file *file_out, loff_t pos_out, |
| 1868 | loff_t len, bool *is_same); | 1886 | loff_t len, unsigned int remap_flags); |
| 1869 | extern int vfs_dedupe_file_range(struct file *file, | 1887 | extern int vfs_dedupe_file_range(struct file *file, |
| 1870 | struct file_dedupe_range *same); | 1888 | struct file_dedupe_range *same); |
| 1871 | extern int vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, | 1889 | extern loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, |
| 1872 | struct file *dst_file, loff_t dst_pos, | 1890 | struct file *dst_file, loff_t dst_pos, |
| 1873 | u64 len); | 1891 | loff_t len, unsigned int remap_flags); |
| 1874 | 1892 | ||
| 1875 | 1893 | ||
| 1876 | struct super_operations { | 1894 | struct super_operations { |
| @@ -2998,6 +3016,9 @@ extern int sb_min_blocksize(struct super_block *, int); | |||
| 2998 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); | 3016 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); |
| 2999 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); | 3017 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); |
| 3000 | extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); | 3018 | extern ssize_t generic_write_checks(struct kiocb *, struct iov_iter *); |
| 3019 | extern int generic_remap_checks(struct file *file_in, loff_t pos_in, | ||
| 3020 | struct file *file_out, loff_t pos_out, | ||
| 3021 | loff_t *count, unsigned int remap_flags); | ||
| 3001 | extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); | 3022 | extern ssize_t generic_file_read_iter(struct kiocb *, struct iov_iter *); |
| 3002 | extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); | 3023 | extern ssize_t __generic_file_write_iter(struct kiocb *, struct iov_iter *); |
| 3003 | extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); | 3024 | extern ssize_t generic_file_write_iter(struct kiocb *, struct iov_iter *); |
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 24bcc5eec6b4..76f8db0b0e71 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
| @@ -510,22 +510,18 @@ alloc_pages(gfp_t gfp_mask, unsigned int order) | |||
| 510 | } | 510 | } |
| 511 | extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order, | 511 | extern struct page *alloc_pages_vma(gfp_t gfp_mask, int order, |
| 512 | struct vm_area_struct *vma, unsigned long addr, | 512 | struct vm_area_struct *vma, unsigned long addr, |
| 513 | int node, bool hugepage); | 513 | int node); |
| 514 | #define alloc_hugepage_vma(gfp_mask, vma, addr, order) \ | ||
| 515 | alloc_pages_vma(gfp_mask, order, vma, addr, numa_node_id(), true) | ||
| 516 | #else | 514 | #else |
| 517 | #define alloc_pages(gfp_mask, order) \ | 515 | #define alloc_pages(gfp_mask, order) \ |
| 518 | alloc_pages_node(numa_node_id(), gfp_mask, order) | 516 | alloc_pages_node(numa_node_id(), gfp_mask, order) |
| 519 | #define alloc_pages_vma(gfp_mask, order, vma, addr, node, false)\ | 517 | #define alloc_pages_vma(gfp_mask, order, vma, addr, node)\ |
| 520 | alloc_pages(gfp_mask, order) | ||
| 521 | #define alloc_hugepage_vma(gfp_mask, vma, addr, order) \ | ||
| 522 | alloc_pages(gfp_mask, order) | 518 | alloc_pages(gfp_mask, order) |
| 523 | #endif | 519 | #endif |
| 524 | #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) | 520 | #define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) |
| 525 | #define alloc_page_vma(gfp_mask, vma, addr) \ | 521 | #define alloc_page_vma(gfp_mask, vma, addr) \ |
| 526 | alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id(), false) | 522 | alloc_pages_vma(gfp_mask, 0, vma, addr, numa_node_id()) |
| 527 | #define alloc_page_vma_node(gfp_mask, vma, addr, node) \ | 523 | #define alloc_page_vma_node(gfp_mask, vma, addr, node) \ |
| 528 | alloc_pages_vma(gfp_mask, 0, vma, addr, node, false) | 524 | alloc_pages_vma(gfp_mask, 0, vma, addr, node) |
| 529 | 525 | ||
| 530 | extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); | 526 | extern unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order); |
| 531 | extern unsigned long get_zeroed_page(gfp_t gfp_mask); | 527 | extern unsigned long get_zeroed_page(gfp_t gfp_mask); |
diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 5228c62af416..bac395f1d00a 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h | |||
| @@ -139,6 +139,8 @@ struct mempolicy *mpol_shared_policy_lookup(struct shared_policy *sp, | |||
| 139 | struct mempolicy *get_task_policy(struct task_struct *p); | 139 | struct mempolicy *get_task_policy(struct task_struct *p); |
| 140 | struct mempolicy *__get_vma_policy(struct vm_area_struct *vma, | 140 | struct mempolicy *__get_vma_policy(struct vm_area_struct *vma, |
| 141 | unsigned long addr); | 141 | unsigned long addr); |
| 142 | struct mempolicy *get_vma_policy(struct vm_area_struct *vma, | ||
| 143 | unsigned long addr); | ||
| 142 | bool vma_policy_mof(struct vm_area_struct *vma); | 144 | bool vma_policy_mof(struct vm_area_struct *vma); |
| 143 | 145 | ||
| 144 | extern void numa_default_policy(void); | 146 | extern void numa_default_policy(void); |
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index f35c7bf76143..0096a05395e3 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
| @@ -122,8 +122,7 @@ extern void srcu_init_notifier_head(struct srcu_notifier_head *nh); | |||
| 122 | 122 | ||
| 123 | #ifdef CONFIG_TREE_SRCU | 123 | #ifdef CONFIG_TREE_SRCU |
| 124 | #define _SRCU_NOTIFIER_HEAD(name, mod) \ | 124 | #define _SRCU_NOTIFIER_HEAD(name, mod) \ |
| 125 | static DEFINE_PER_CPU(struct srcu_data, \ | 125 | static DEFINE_PER_CPU(struct srcu_data, name##_head_srcu_data); \ |
| 126 | name##_head_srcu_data); \ | ||
| 127 | mod struct srcu_notifier_head name = \ | 126 | mod struct srcu_notifier_head name = \ |
| 128 | SRCU_NOTIFIER_INIT(name, name##_head_srcu_data) | 127 | SRCU_NOTIFIER_INIT(name, name##_head_srcu_data) |
| 129 | 128 | ||
diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 738a0c24874f..fdfd04e348f6 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h | |||
| @@ -246,8 +246,7 @@ static inline void wbc_attach_fdatawrite_inode(struct writeback_control *wbc, | |||
| 246 | * | 246 | * |
| 247 | * @bio is a part of the writeback in progress controlled by @wbc. Perform | 247 | * @bio is a part of the writeback in progress controlled by @wbc. Perform |
| 248 | * writeback specific initialization. This is used to apply the cgroup | 248 | * writeback specific initialization. This is used to apply the cgroup |
| 249 | * writeback context. Must be called after the bio has been associated with | 249 | * writeback context. |
| 250 | * a device. | ||
| 251 | */ | 250 | */ |
| 252 | static inline void wbc_init_bio(struct writeback_control *wbc, struct bio *bio) | 251 | static inline void wbc_init_bio(struct writeback_control *wbc, struct bio *bio) |
| 253 | { | 252 | { |
| @@ -258,7 +257,7 @@ static inline void wbc_init_bio(struct writeback_control *wbc, struct bio *bio) | |||
| 258 | * regular writeback instead of writing things out itself. | 257 | * regular writeback instead of writing things out itself. |
| 259 | */ | 258 | */ |
| 260 | if (wbc->wb) | 259 | if (wbc->wb) |
| 261 | bio_associate_blkg_from_css(bio, wbc->wb->blkcg_css); | 260 | bio_associate_blkcg(bio, wbc->wb->blkcg_css); |
| 262 | } | 261 | } |
| 263 | 262 | ||
| 264 | #else /* CONFIG_CGROUP_WRITEBACK */ | 263 | #else /* CONFIG_CGROUP_WRITEBACK */ |
diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 8b79318810ad..6aaf5dd5383b 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c | |||
| @@ -493,7 +493,7 @@ static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp, | |||
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | /** | 495 | /** |
| 496 | * cgroup_e_css_by_mask - obtain a cgroup's effective css for the specified ss | 496 | * cgroup_e_css - obtain a cgroup's effective css for the specified subsystem |
| 497 | * @cgrp: the cgroup of interest | 497 | * @cgrp: the cgroup of interest |
| 498 | * @ss: the subsystem of interest (%NULL returns @cgrp->self) | 498 | * @ss: the subsystem of interest (%NULL returns @cgrp->self) |
| 499 | * | 499 | * |
| @@ -502,8 +502,8 @@ static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp, | |||
| 502 | * enabled. If @ss is associated with the hierarchy @cgrp is on, this | 502 | * enabled. If @ss is associated with the hierarchy @cgrp is on, this |
| 503 | * function is guaranteed to return non-NULL css. | 503 | * function is guaranteed to return non-NULL css. |
| 504 | */ | 504 | */ |
| 505 | static struct cgroup_subsys_state *cgroup_e_css_by_mask(struct cgroup *cgrp, | 505 | static struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, |
| 506 | struct cgroup_subsys *ss) | 506 | struct cgroup_subsys *ss) |
| 507 | { | 507 | { |
| 508 | lockdep_assert_held(&cgroup_mutex); | 508 | lockdep_assert_held(&cgroup_mutex); |
| 509 | 509 | ||
| @@ -524,35 +524,6 @@ static struct cgroup_subsys_state *cgroup_e_css_by_mask(struct cgroup *cgrp, | |||
| 524 | } | 524 | } |
| 525 | 525 | ||
| 526 | /** | 526 | /** |
| 527 | * cgroup_e_css - obtain a cgroup's effective css for the specified subsystem | ||
| 528 | * @cgrp: the cgroup of interest | ||
| 529 | * @ss: the subsystem of interest | ||
| 530 | * | ||
| 531 | * Find and get the effective css of @cgrp for @ss. The effective css is | ||
| 532 | * defined as the matching css of the nearest ancestor including self which | ||
| 533 | * has @ss enabled. If @ss is not mounted on the hierarchy @cgrp is on, | ||
| 534 | * the root css is returned, so this function always returns a valid css. | ||
| 535 | * | ||
| 536 | * The returned css is not guaranteed to be online, and therefore it is the | ||
| 537 | * callers responsiblity to tryget a reference for it. | ||
| 538 | */ | ||
| 539 | struct cgroup_subsys_state *cgroup_e_css(struct cgroup *cgrp, | ||
| 540 | struct cgroup_subsys *ss) | ||
| 541 | { | ||
| 542 | struct cgroup_subsys_state *css; | ||
| 543 | |||
| 544 | do { | ||
| 545 | css = cgroup_css(cgrp, ss); | ||
| 546 | |||
| 547 | if (css) | ||
| 548 | return css; | ||
| 549 | cgrp = cgroup_parent(cgrp); | ||
| 550 | } while (cgrp); | ||
| 551 | |||
| 552 | return init_css_set.subsys[ss->id]; | ||
| 553 | } | ||
| 554 | |||
| 555 | /** | ||
| 556 | * cgroup_get_e_css - get a cgroup's effective css for the specified subsystem | 527 | * cgroup_get_e_css - get a cgroup's effective css for the specified subsystem |
| 557 | * @cgrp: the cgroup of interest | 528 | * @cgrp: the cgroup of interest |
| 558 | * @ss: the subsystem of interest | 529 | * @ss: the subsystem of interest |
| @@ -634,11 +605,10 @@ EXPORT_SYMBOL_GPL(of_css); | |||
| 634 | * | 605 | * |
| 635 | * Should be called under cgroup_[tree_]mutex. | 606 | * Should be called under cgroup_[tree_]mutex. |
| 636 | */ | 607 | */ |
| 637 | #define for_each_e_css(css, ssid, cgrp) \ | 608 | #define for_each_e_css(css, ssid, cgrp) \ |
| 638 | for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \ | 609 | for ((ssid) = 0; (ssid) < CGROUP_SUBSYS_COUNT; (ssid)++) \ |
| 639 | if (!((css) = cgroup_e_css_by_mask(cgrp, \ | 610 | if (!((css) = cgroup_e_css(cgrp, cgroup_subsys[(ssid)]))) \ |
| 640 | cgroup_subsys[(ssid)]))) \ | 611 | ; \ |
| 641 | ; \ | ||
| 642 | else | 612 | else |
| 643 | 613 | ||
| 644 | /** | 614 | /** |
| @@ -1037,7 +1007,7 @@ static struct css_set *find_existing_css_set(struct css_set *old_cset, | |||
| 1037 | * @ss is in this hierarchy, so we want the | 1007 | * @ss is in this hierarchy, so we want the |
| 1038 | * effective css from @cgrp. | 1008 | * effective css from @cgrp. |
| 1039 | */ | 1009 | */ |
| 1040 | template[i] = cgroup_e_css_by_mask(cgrp, ss); | 1010 | template[i] = cgroup_e_css(cgrp, ss); |
| 1041 | } else { | 1011 | } else { |
| 1042 | /* | 1012 | /* |
| 1043 | * @ss is not in this hierarchy, so we don't want | 1013 | * @ss is not in this hierarchy, so we don't want |
| @@ -3054,7 +3024,7 @@ static int cgroup_apply_control(struct cgroup *cgrp) | |||
| 3054 | return ret; | 3024 | return ret; |
| 3055 | 3025 | ||
| 3056 | /* | 3026 | /* |
| 3057 | * At this point, cgroup_e_css_by_mask() results reflect the new csses | 3027 | * At this point, cgroup_e_css() results reflect the new csses |
| 3058 | * making the following cgroup_update_dfl_csses() properly update | 3028 | * making the following cgroup_update_dfl_csses() properly update |
| 3059 | * css associations of all tasks in the subtree. | 3029 | * css associations of all tasks in the subtree. |
| 3060 | */ | 3030 | */ |
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index c6a3b6851372..35cf0ad29718 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c | |||
| @@ -25,8 +25,6 @@ | |||
| 25 | #include <linux/elf.h> | 25 | #include <linux/elf.h> |
| 26 | #include <linux/elfcore.h> | 26 | #include <linux/elfcore.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/kexec.h> | ||
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/syscalls.h> | 28 | #include <linux/syscalls.h> |
| 31 | #include <linux/vmalloc.h> | 29 | #include <linux/vmalloc.h> |
| 32 | #include "kexec_internal.h" | 30 | #include "kexec_internal.h" |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3ae223f7b5df..5fc724e4e454 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -66,7 +66,6 @@ | |||
| 66 | #include <linux/kexec.h> | 66 | #include <linux/kexec.h> |
| 67 | #include <linux/bpf.h> | 67 | #include <linux/bpf.h> |
| 68 | #include <linux/mount.h> | 68 | #include <linux/mount.h> |
| 69 | #include <linux/pipe_fs_i.h> | ||
| 70 | 69 | ||
| 71 | #include <linux/uaccess.h> | 70 | #include <linux/uaccess.h> |
| 72 | #include <asm/processor.h> | 71 | #include <asm/processor.h> |
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index fac0ddf8a8e2..2868d85f1fb1 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
| @@ -764,9 +764,9 @@ blk_trace_bio_get_cgid(struct request_queue *q, struct bio *bio) | |||
| 764 | if (!bt || !(blk_tracer_flags.val & TRACE_BLK_OPT_CGROUP)) | 764 | if (!bt || !(blk_tracer_flags.val & TRACE_BLK_OPT_CGROUP)) |
| 765 | return NULL; | 765 | return NULL; |
| 766 | 766 | ||
| 767 | if (!bio->bi_blkg) | 767 | if (!bio->bi_css) |
| 768 | return NULL; | 768 | return NULL; |
| 769 | return cgroup_get_kernfs_id(bio_blkcg(bio)->css.cgroup); | 769 | return cgroup_get_kernfs_id(bio->bi_css->cgroup); |
| 770 | } | 770 | } |
| 771 | #else | 771 | #else |
| 772 | static union kernfs_node_id * | 772 | static union kernfs_node_id * |
diff --git a/mm/filemap.c b/mm/filemap.c index 1fe6c4c37a35..81adec8ee02c 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
| @@ -2825,6 +2825,42 @@ struct page *read_cache_page_gfp(struct address_space *mapping, | |||
| 2825 | EXPORT_SYMBOL(read_cache_page_gfp); | 2825 | EXPORT_SYMBOL(read_cache_page_gfp); |
| 2826 | 2826 | ||
| 2827 | /* | 2827 | /* |
| 2828 | * Don't operate on ranges the page cache doesn't support, and don't exceed the | ||
| 2829 | * LFS limits. If pos is under the limit it becomes a short access. If it | ||
| 2830 | * exceeds the limit we return -EFBIG. | ||
| 2831 | */ | ||
| 2832 | static int generic_access_check_limits(struct file *file, loff_t pos, | ||
| 2833 | loff_t *count) | ||
| 2834 | { | ||
| 2835 | struct inode *inode = file->f_mapping->host; | ||
| 2836 | loff_t max_size = inode->i_sb->s_maxbytes; | ||
| 2837 | |||
| 2838 | if (!(file->f_flags & O_LARGEFILE)) | ||
| 2839 | max_size = MAX_NON_LFS; | ||
| 2840 | |||
| 2841 | if (unlikely(pos >= max_size)) | ||
| 2842 | return -EFBIG; | ||
| 2843 | *count = min(*count, max_size - pos); | ||
| 2844 | return 0; | ||
| 2845 | } | ||
| 2846 | |||
| 2847 | static int generic_write_check_limits(struct file *file, loff_t pos, | ||
| 2848 | loff_t *count) | ||
| 2849 | { | ||
| 2850 | loff_t limit = rlimit(RLIMIT_FSIZE); | ||
| 2851 | |||
| 2852 | if (limit != RLIM_INFINITY) { | ||
| 2853 | if (pos >= limit) { | ||
| 2854 | send_sig(SIGXFSZ, current, 0); | ||
| 2855 | return -EFBIG; | ||
| 2856 | } | ||
| 2857 | *count = min(*count, limit - pos); | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | return generic_access_check_limits(file, pos, count); | ||
| 2861 | } | ||
| 2862 | |||
| 2863 | /* | ||
| 2828 | * Performs necessary checks before doing a write | 2864 | * Performs necessary checks before doing a write |
| 2829 | * | 2865 | * |
| 2830 | * Can adjust writing position or amount of bytes to write. | 2866 | * Can adjust writing position or amount of bytes to write. |
| @@ -2835,8 +2871,8 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from) | |||
| 2835 | { | 2871 | { |
| 2836 | struct file *file = iocb->ki_filp; | 2872 | struct file *file = iocb->ki_filp; |
| 2837 | struct inode *inode = file->f_mapping->host; | 2873 | struct inode *inode = file->f_mapping->host; |
| 2838 | unsigned long limit = rlimit(RLIMIT_FSIZE); | 2874 | loff_t count; |
| 2839 | loff_t pos; | 2875 | int ret; |
| 2840 | 2876 | ||
| 2841 | if (!iov_iter_count(from)) | 2877 | if (!iov_iter_count(from)) |
| 2842 | return 0; | 2878 | return 0; |
| @@ -2845,43 +2881,99 @@ inline ssize_t generic_write_checks(struct kiocb *iocb, struct iov_iter *from) | |||
| 2845 | if (iocb->ki_flags & IOCB_APPEND) | 2881 | if (iocb->ki_flags & IOCB_APPEND) |
| 2846 | iocb->ki_pos = i_size_read(inode); | 2882 | iocb->ki_pos = i_size_read(inode); |
| 2847 | 2883 | ||
| 2848 | pos = iocb->ki_pos; | ||
| 2849 | |||
| 2850 | if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT)) | 2884 | if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT)) |
| 2851 | return -EINVAL; | 2885 | return -EINVAL; |
| 2852 | 2886 | ||
| 2853 | if (limit != RLIM_INFINITY) { | 2887 | count = iov_iter_count(from); |
| 2854 | if (iocb->ki_pos >= limit) { | 2888 | ret = generic_write_check_limits(file, iocb->ki_pos, &count); |
| 2855 | send_sig(SIGXFSZ, current, 0); | 2889 | if (ret) |
| 2856 | return -EFBIG; | 2890 | return ret; |
| 2857 | } | 2891 | |
| 2858 | iov_iter_truncate(from, limit - (unsigned long)pos); | 2892 | iov_iter_truncate(from, count); |
| 2859 | } | 2893 | return iov_iter_count(from); |
| 2894 | } | ||
| 2895 | EXPORT_SYMBOL(generic_write_checks); | ||
| 2896 | |||
| 2897 | /* | ||
| 2898 | * Performs necessary checks before doing a clone. | ||
| 2899 | * | ||
| 2900 | * Can adjust amount of bytes to clone. | ||
| 2901 | * Returns appropriate error code that caller should return or | ||
| 2902 | * zero in case the clone should be allowed. | ||
| 2903 | */ | ||
| 2904 | int generic_remap_checks(struct file *file_in, loff_t pos_in, | ||
| 2905 | struct file *file_out, loff_t pos_out, | ||
| 2906 | loff_t *req_count, unsigned int remap_flags) | ||
| 2907 | { | ||
| 2908 | struct inode *inode_in = file_in->f_mapping->host; | ||
| 2909 | struct inode *inode_out = file_out->f_mapping->host; | ||
| 2910 | uint64_t count = *req_count; | ||
| 2911 | uint64_t bcount; | ||
| 2912 | loff_t size_in, size_out; | ||
| 2913 | loff_t bs = inode_out->i_sb->s_blocksize; | ||
| 2914 | int ret; | ||
| 2915 | |||
| 2916 | /* The start of both ranges must be aligned to an fs block. */ | ||
| 2917 | if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_out, bs)) | ||
| 2918 | return -EINVAL; | ||
| 2919 | |||
| 2920 | /* Ensure offsets don't wrap. */ | ||
| 2921 | if (pos_in + count < pos_in || pos_out + count < pos_out) | ||
| 2922 | return -EINVAL; | ||
| 2923 | |||
| 2924 | size_in = i_size_read(inode_in); | ||
| 2925 | size_out = i_size_read(inode_out); | ||
| 2926 | |||
| 2927 | /* Dedupe requires both ranges to be within EOF. */ | ||
| 2928 | if ((remap_flags & REMAP_FILE_DEDUP) && | ||
| 2929 | (pos_in >= size_in || pos_in + count > size_in || | ||
| 2930 | pos_out >= size_out || pos_out + count > size_out)) | ||
| 2931 | return -EINVAL; | ||
| 2932 | |||
| 2933 | /* Ensure the infile range is within the infile. */ | ||
| 2934 | if (pos_in >= size_in) | ||
| 2935 | return -EINVAL; | ||
| 2936 | count = min(count, size_in - (uint64_t)pos_in); | ||
| 2937 | |||
| 2938 | ret = generic_access_check_limits(file_in, pos_in, &count); | ||
| 2939 | if (ret) | ||
| 2940 | return ret; | ||
| 2941 | |||
| 2942 | ret = generic_write_check_limits(file_out, pos_out, &count); | ||
| 2943 | if (ret) | ||
| 2944 | return ret; | ||
| 2860 | 2945 | ||
| 2861 | /* | 2946 | /* |
| 2862 | * LFS rule | 2947 | * If the user wanted us to link to the infile's EOF, round up to the |
| 2948 | * next block boundary for this check. | ||
| 2949 | * | ||
| 2950 | * Otherwise, make sure the count is also block-aligned, having | ||
| 2951 | * already confirmed the starting offsets' block alignment. | ||
| 2863 | */ | 2952 | */ |
| 2864 | if (unlikely(pos + iov_iter_count(from) > MAX_NON_LFS && | 2953 | if (pos_in + count == size_in) { |
| 2865 | !(file->f_flags & O_LARGEFILE))) { | 2954 | bcount = ALIGN(size_in, bs) - pos_in; |
| 2866 | if (pos >= MAX_NON_LFS) | 2955 | } else { |
| 2867 | return -EFBIG; | 2956 | if (!IS_ALIGNED(count, bs)) |
| 2868 | iov_iter_truncate(from, MAX_NON_LFS - (unsigned long)pos); | 2957 | count = ALIGN_DOWN(count, bs); |
| 2958 | bcount = count; | ||
| 2869 | } | 2959 | } |
| 2870 | 2960 | ||
| 2961 | /* Don't allow overlapped cloning within the same file. */ | ||
| 2962 | if (inode_in == inode_out && | ||
| 2963 | pos_out + bcount > pos_in && | ||
| 2964 | pos_out < pos_in + bcount) | ||
| 2965 | return -EINVAL; | ||
| 2966 | |||
| 2871 | /* | 2967 | /* |
| 2872 | * Are we about to exceed the fs block limit ? | 2968 | * We shortened the request but the caller can't deal with that, so |
| 2873 | * | 2969 | * bounce the request back to userspace. |
| 2874 | * If we have written data it becomes a short write. If we have | ||
| 2875 | * exceeded without writing data we send a signal and return EFBIG. | ||
| 2876 | * Linus frestrict idea will clean these up nicely.. | ||
| 2877 | */ | 2970 | */ |
| 2878 | if (unlikely(pos >= inode->i_sb->s_maxbytes)) | 2971 | if (*req_count != count && !(remap_flags & REMAP_FILE_CAN_SHORTEN)) |
| 2879 | return -EFBIG; | 2972 | return -EINVAL; |
| 2880 | 2973 | ||
| 2881 | iov_iter_truncate(from, inode->i_sb->s_maxbytes - pos); | 2974 | *req_count = count; |
| 2882 | return iov_iter_count(from); | 2975 | return 0; |
| 2883 | } | 2976 | } |
| 2884 | EXPORT_SYMBOL(generic_write_checks); | ||
| 2885 | 2977 | ||
| 2886 | int pagecache_write_begin(struct file *file, struct address_space *mapping, | 2978 | int pagecache_write_begin(struct file *file, struct address_space *mapping, |
| 2887 | loff_t pos, unsigned len, unsigned flags, | 2979 | loff_t pos, unsigned len, unsigned flags, |
diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 4e4ef8fa479d..55478ab3c83b 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c | |||
| @@ -629,21 +629,40 @@ release: | |||
| 629 | * available | 629 | * available |
| 630 | * never: never stall for any thp allocation | 630 | * never: never stall for any thp allocation |
| 631 | */ | 631 | */ |
| 632 | static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma) | 632 | static inline gfp_t alloc_hugepage_direct_gfpmask(struct vm_area_struct *vma, unsigned long addr) |
| 633 | { | 633 | { |
| 634 | const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE); | 634 | const bool vma_madvised = !!(vma->vm_flags & VM_HUGEPAGE); |
| 635 | gfp_t this_node = 0; | ||
| 636 | |||
| 637 | #ifdef CONFIG_NUMA | ||
| 638 | struct mempolicy *pol; | ||
| 639 | /* | ||
| 640 | * __GFP_THISNODE is used only when __GFP_DIRECT_RECLAIM is not | ||
| 641 | * specified, to express a general desire to stay on the current | ||
| 642 | * node for optimistic allocation attempts. If the defrag mode | ||
| 643 | * and/or madvise hint requires the direct reclaim then we prefer | ||
| 644 | * to fallback to other node rather than node reclaim because that | ||
| 645 | * can lead to excessive reclaim even though there is free memory | ||
| 646 | * on other nodes. We expect that NUMA preferences are specified | ||
| 647 | * by memory policies. | ||
| 648 | */ | ||
| 649 | pol = get_vma_policy(vma, addr); | ||
| 650 | if (pol->mode != MPOL_BIND) | ||
| 651 | this_node = __GFP_THISNODE; | ||
| 652 | mpol_cond_put(pol); | ||
| 653 | #endif | ||
| 635 | 654 | ||
| 636 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags)) | 655 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, &transparent_hugepage_flags)) |
| 637 | return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY); | 656 | return GFP_TRANSHUGE | (vma_madvised ? 0 : __GFP_NORETRY); |
| 638 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags)) | 657 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_FLAG, &transparent_hugepage_flags)) |
| 639 | return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM; | 658 | return GFP_TRANSHUGE_LIGHT | __GFP_KSWAPD_RECLAIM | this_node; |
| 640 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags)) | 659 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_KSWAPD_OR_MADV_FLAG, &transparent_hugepage_flags)) |
| 641 | return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM : | 660 | return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM : |
| 642 | __GFP_KSWAPD_RECLAIM); | 661 | __GFP_KSWAPD_RECLAIM | this_node); |
| 643 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags)) | 662 | if (test_bit(TRANSPARENT_HUGEPAGE_DEFRAG_REQ_MADV_FLAG, &transparent_hugepage_flags)) |
| 644 | return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM : | 663 | return GFP_TRANSHUGE_LIGHT | (vma_madvised ? __GFP_DIRECT_RECLAIM : |
| 645 | 0); | 664 | this_node); |
| 646 | return GFP_TRANSHUGE_LIGHT; | 665 | return GFP_TRANSHUGE_LIGHT | this_node; |
| 647 | } | 666 | } |
| 648 | 667 | ||
| 649 | /* Caller must hold page table lock. */ | 668 | /* Caller must hold page table lock. */ |
| @@ -715,8 +734,8 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf) | |||
| 715 | pte_free(vma->vm_mm, pgtable); | 734 | pte_free(vma->vm_mm, pgtable); |
| 716 | return ret; | 735 | return ret; |
| 717 | } | 736 | } |
| 718 | gfp = alloc_hugepage_direct_gfpmask(vma); | 737 | gfp = alloc_hugepage_direct_gfpmask(vma, haddr); |
| 719 | page = alloc_hugepage_vma(gfp, vma, haddr, HPAGE_PMD_ORDER); | 738 | page = alloc_pages_vma(gfp, HPAGE_PMD_ORDER, vma, haddr, numa_node_id()); |
| 720 | if (unlikely(!page)) { | 739 | if (unlikely(!page)) { |
| 721 | count_vm_event(THP_FAULT_FALLBACK); | 740 | count_vm_event(THP_FAULT_FALLBACK); |
| 722 | return VM_FAULT_FALLBACK; | 741 | return VM_FAULT_FALLBACK; |
| @@ -1286,8 +1305,9 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd) | |||
| 1286 | alloc: | 1305 | alloc: |
| 1287 | if (transparent_hugepage_enabled(vma) && | 1306 | if (transparent_hugepage_enabled(vma) && |
| 1288 | !transparent_hugepage_debug_cow()) { | 1307 | !transparent_hugepage_debug_cow()) { |
| 1289 | huge_gfp = alloc_hugepage_direct_gfpmask(vma); | 1308 | huge_gfp = alloc_hugepage_direct_gfpmask(vma, haddr); |
| 1290 | new_page = alloc_hugepage_vma(huge_gfp, vma, haddr, HPAGE_PMD_ORDER); | 1309 | new_page = alloc_pages_vma(huge_gfp, HPAGE_PMD_ORDER, vma, |
| 1310 | haddr, numa_node_id()); | ||
| 1291 | } else | 1311 | } else |
| 1292 | new_page = NULL; | 1312 | new_page = NULL; |
| 1293 | 1313 | ||
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 54920cbc46bf..6e1469b80cb7 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
| @@ -2593,7 +2593,7 @@ int memcg_kmem_charge(struct page *page, gfp_t gfp, int order) | |||
| 2593 | struct mem_cgroup *memcg; | 2593 | struct mem_cgroup *memcg; |
| 2594 | int ret = 0; | 2594 | int ret = 0; |
| 2595 | 2595 | ||
| 2596 | if (memcg_kmem_bypass()) | 2596 | if (mem_cgroup_disabled() || memcg_kmem_bypass()) |
| 2597 | return 0; | 2597 | return 0; |
| 2598 | 2598 | ||
| 2599 | memcg = get_mem_cgroup_from_current(); | 2599 | memcg = get_mem_cgroup_from_current(); |
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 61972da38d93..2b2b3ccbbfb5 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c | |||
| @@ -586,6 +586,7 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, | |||
| 586 | for (i = 0; i < sections_to_remove; i++) { | 586 | for (i = 0; i < sections_to_remove; i++) { |
| 587 | unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION; | 587 | unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION; |
| 588 | 588 | ||
| 589 | cond_resched(); | ||
| 589 | ret = __remove_section(zone, __pfn_to_section(pfn), map_offset, | 590 | ret = __remove_section(zone, __pfn_to_section(pfn), map_offset, |
| 590 | altmap); | 591 | altmap); |
| 591 | map_offset = 0; | 592 | map_offset = 0; |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index cfd26d7e61a1..5837a067124d 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
| @@ -1116,8 +1116,8 @@ static struct page *new_page(struct page *page, unsigned long start) | |||
| 1116 | } else if (PageTransHuge(page)) { | 1116 | } else if (PageTransHuge(page)) { |
| 1117 | struct page *thp; | 1117 | struct page *thp; |
| 1118 | 1118 | ||
| 1119 | thp = alloc_hugepage_vma(GFP_TRANSHUGE, vma, address, | 1119 | thp = alloc_pages_vma(GFP_TRANSHUGE, HPAGE_PMD_ORDER, vma, |
| 1120 | HPAGE_PMD_ORDER); | 1120 | address, numa_node_id()); |
| 1121 | if (!thp) | 1121 | if (!thp) |
| 1122 | return NULL; | 1122 | return NULL; |
| 1123 | prep_transhuge_page(thp); | 1123 | prep_transhuge_page(thp); |
| @@ -1662,7 +1662,7 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma, | |||
| 1662 | * freeing by another task. It is the caller's responsibility to free the | 1662 | * freeing by another task. It is the caller's responsibility to free the |
| 1663 | * extra reference for shared policies. | 1663 | * extra reference for shared policies. |
| 1664 | */ | 1664 | */ |
| 1665 | static struct mempolicy *get_vma_policy(struct vm_area_struct *vma, | 1665 | struct mempolicy *get_vma_policy(struct vm_area_struct *vma, |
| 1666 | unsigned long addr) | 1666 | unsigned long addr) |
| 1667 | { | 1667 | { |
| 1668 | struct mempolicy *pol = __get_vma_policy(vma, addr); | 1668 | struct mempolicy *pol = __get_vma_policy(vma, addr); |
| @@ -2011,7 +2011,6 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, | |||
| 2011 | * @vma: Pointer to VMA or NULL if not available. | 2011 | * @vma: Pointer to VMA or NULL if not available. |
| 2012 | * @addr: Virtual Address of the allocation. Must be inside the VMA. | 2012 | * @addr: Virtual Address of the allocation. Must be inside the VMA. |
| 2013 | * @node: Which node to prefer for allocation (modulo policy). | 2013 | * @node: Which node to prefer for allocation (modulo policy). |
| 2014 | * @hugepage: for hugepages try only the preferred node if possible | ||
| 2015 | * | 2014 | * |
| 2016 | * This function allocates a page from the kernel page pool and applies | 2015 | * This function allocates a page from the kernel page pool and applies |
| 2017 | * a NUMA policy associated with the VMA or the current process. | 2016 | * a NUMA policy associated with the VMA or the current process. |
| @@ -2022,7 +2021,7 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, | |||
| 2022 | */ | 2021 | */ |
| 2023 | struct page * | 2022 | struct page * |
| 2024 | alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma, | 2023 | alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma, |
| 2025 | unsigned long addr, int node, bool hugepage) | 2024 | unsigned long addr, int node) |
| 2026 | { | 2025 | { |
| 2027 | struct mempolicy *pol; | 2026 | struct mempolicy *pol; |
| 2028 | struct page *page; | 2027 | struct page *page; |
| @@ -2040,32 +2039,6 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma, | |||
| 2040 | goto out; | 2039 | goto out; |
| 2041 | } | 2040 | } |
| 2042 | 2041 | ||
| 2043 | if (unlikely(IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && hugepage)) { | ||
| 2044 | int hpage_node = node; | ||
| 2045 | |||
| 2046 | /* | ||
| 2047 | * For hugepage allocation and non-interleave policy which | ||
| 2048 | * allows the current node (or other explicitly preferred | ||
| 2049 | * node) we only try to allocate from the current/preferred | ||
| 2050 | * node and don't fall back to other nodes, as the cost of | ||
| 2051 | * remote accesses would likely offset THP benefits. | ||
| 2052 | * | ||
| 2053 | * If the policy is interleave, or does not allow the current | ||
| 2054 | * node in its nodemask, we allocate the standard way. | ||
| 2055 | */ | ||
| 2056 | if (pol->mode == MPOL_PREFERRED && | ||
| 2057 | !(pol->flags & MPOL_F_LOCAL)) | ||
| 2058 | hpage_node = pol->v.preferred_node; | ||
| 2059 | |||
| 2060 | nmask = policy_nodemask(gfp, pol); | ||
| 2061 | if (!nmask || node_isset(hpage_node, *nmask)) { | ||
| 2062 | mpol_cond_put(pol); | ||
| 2063 | page = __alloc_pages_node(hpage_node, | ||
| 2064 | gfp | __GFP_THISNODE, order); | ||
| 2065 | goto out; | ||
| 2066 | } | ||
| 2067 | } | ||
| 2068 | |||
| 2069 | nmask = policy_nodemask(gfp, pol); | 2042 | nmask = policy_nodemask(gfp, pol); |
| 2070 | preferred_nid = policy_node(gfp, pol, node); | 2043 | preferred_nid = policy_node(gfp, pol, node); |
| 2071 | page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask); | 2044 | page = __alloc_pages_nodemask(gfp, order, preferred_nid, nmask); |
diff --git a/mm/page_io.c b/mm/page_io.c index 27b835728442..d4d1c89bcddd 100644 --- a/mm/page_io.c +++ b/mm/page_io.c | |||
| @@ -339,7 +339,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, | |||
| 339 | goto out; | 339 | goto out; |
| 340 | } | 340 | } |
| 341 | bio->bi_opf = REQ_OP_WRITE | REQ_SWAP | wbc_to_write_flags(wbc); | 341 | bio->bi_opf = REQ_OP_WRITE | REQ_SWAP | wbc_to_write_flags(wbc); |
| 342 | bio_associate_blkg_from_page(bio, page); | 342 | bio_associate_blkcg_from_page(bio, page); |
| 343 | count_swpout_vm_event(page); | 343 | count_swpout_vm_event(page); |
| 344 | set_page_writeback(page); | 344 | set_page_writeback(page); |
| 345 | unlock_page(page); | 345 | unlock_page(page); |
diff --git a/mm/shmem.c b/mm/shmem.c index 56bf122e0bb4..ea26d7a0342d 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
| @@ -1435,7 +1435,7 @@ static struct page *shmem_alloc_hugepage(gfp_t gfp, | |||
| 1435 | 1435 | ||
| 1436 | shmem_pseudo_vma_init(&pvma, info, hindex); | 1436 | shmem_pseudo_vma_init(&pvma, info, hindex); |
| 1437 | page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN, | 1437 | page = alloc_pages_vma(gfp | __GFP_COMP | __GFP_NORETRY | __GFP_NOWARN, |
| 1438 | HPAGE_PMD_ORDER, &pvma, 0, numa_node_id(), true); | 1438 | HPAGE_PMD_ORDER, &pvma, 0, numa_node_id()); |
| 1439 | shmem_pseudo_vma_destroy(&pvma); | 1439 | shmem_pseudo_vma_destroy(&pvma); |
| 1440 | if (page) | 1440 | if (page) |
| 1441 | prep_transhuge_page(page); | 1441 | prep_transhuge_page(page); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 91981970f542..b1d39cabf125 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
| @@ -329,7 +329,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, | |||
| 329 | if (!iov_iter_count(data)) | 329 | if (!iov_iter_count(data)) |
| 330 | return 0; | 330 | return 0; |
| 331 | 331 | ||
| 332 | if (iov_iter_is_kvec(data)) { | 332 | if (!iov_iter_is_kvec(data)) { |
| 333 | int n; | 333 | int n; |
| 334 | /* | 334 | /* |
| 335 | * We allow only p9_max_pages pinned. We wait for the | 335 | * We allow only p9_max_pages pinned. We wait for the |
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index ca21a35fa244..bb015551c2d9 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include | |||
| @@ -140,17 +140,9 @@ cc-option-yn = $(call try-run,\ | |||
| 140 | cc-disable-warning = $(call try-run,\ | 140 | cc-disable-warning = $(call try-run,\ |
| 141 | $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) | 141 | $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) |
| 142 | 142 | ||
| 143 | # cc-name | ||
| 144 | # Expands to either gcc or clang | ||
| 145 | cc-name = $(shell $(CC) -v 2>&1 | grep -q "clang version" && echo clang || echo gcc) | ||
| 146 | |||
| 147 | # cc-version | 143 | # cc-version |
| 148 | cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) | 144 | cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) |
| 149 | 145 | ||
| 150 | # cc-fullversion | ||
| 151 | cc-fullversion = $(shell $(CONFIG_SHELL) \ | ||
| 152 | $(srctree)/scripts/gcc-version.sh -p $(CC)) | ||
| 153 | |||
| 154 | # cc-ifversion | 146 | # cc-ifversion |
| 155 | # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) | 147 | # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) |
| 156 | cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3) || echo $(4)) | 148 | cc-ifversion = $(shell [ $(cc-version) $(1) $(2) ] && echo $(3) || echo $(4)) |
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index cf6cd0ef6975..768306add591 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn | |||
| @@ -65,7 +65,7 @@ endif | |||
| 65 | KBUILD_CFLAGS += $(warning) | 65 | KBUILD_CFLAGS += $(warning) |
| 66 | else | 66 | else |
| 67 | 67 | ||
| 68 | ifeq ($(cc-name),clang) | 68 | ifdef CONFIG_CC_IS_CLANG |
| 69 | KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides) | 69 | KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides) |
| 70 | KBUILD_CFLAGS += $(call cc-disable-warning, unused-value) | 70 | KBUILD_CFLAGS += $(call cc-disable-warning, unused-value) |
| 71 | KBUILD_CFLAGS += $(call cc-disable-warning, format) | 71 | KBUILD_CFLAGS += $(call cc-disable-warning, format) |
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 67ed9f6ccdf8..63b609243d03 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile | |||
| @@ -68,21 +68,7 @@ PHONY += $(simple-targets) | |||
| 68 | $(simple-targets): $(obj)/conf | 68 | $(simple-targets): $(obj)/conf |
| 69 | $< $(silent) --$@ $(Kconfig) | 69 | $< $(silent) --$@ $(Kconfig) |
| 70 | 70 | ||
| 71 | PHONY += oldnoconfig silentoldconfig savedefconfig defconfig | 71 | PHONY += savedefconfig defconfig |
| 72 | |||
| 73 | # oldnoconfig is an alias of olddefconfig, because people already are dependent | ||
| 74 | # on its behavior (sets new symbols to their default value but not 'n') with the | ||
| 75 | # counter-intuitive name. | ||
| 76 | oldnoconfig: olddefconfig | ||
| 77 | @echo " WARNING: \"oldnoconfig\" target will be removed after Linux 4.19" | ||
| 78 | @echo " Please use \"olddefconfig\" instead, which is an alias." | ||
| 79 | |||
| 80 | # We do not expect manual invokcation of "silentoldcofig" (or "syncconfig"). | ||
| 81 | silentoldconfig: syncconfig | ||
| 82 | @echo " WARNING: \"silentoldconfig\" has been renamed to \"syncconfig\"" | ||
| 83 | @echo " and is now an internal implementation detail." | ||
| 84 | @echo " What you want is probably \"oldconfig\"." | ||
| 85 | @echo " \"silentoldconfig\" will be removed after Linux 4.19" | ||
| 86 | 72 | ||
| 87 | savedefconfig: $(obj)/conf | 73 | savedefconfig: $(obj)/conf |
| 88 | $< $(silent) --$@=defconfig $(Kconfig) | 74 | $< $(silent) --$@=defconfig $(Kconfig) |
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 7b2b37260669..98e0c7a34699 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c | |||
| @@ -460,12 +460,6 @@ static struct option long_opts[] = { | |||
| 460 | {"randconfig", no_argument, NULL, randconfig}, | 460 | {"randconfig", no_argument, NULL, randconfig}, |
| 461 | {"listnewconfig", no_argument, NULL, listnewconfig}, | 461 | {"listnewconfig", no_argument, NULL, listnewconfig}, |
| 462 | {"olddefconfig", no_argument, NULL, olddefconfig}, | 462 | {"olddefconfig", no_argument, NULL, olddefconfig}, |
| 463 | /* | ||
| 464 | * oldnoconfig is an alias of olddefconfig, because people already | ||
| 465 | * are dependent on its behavior(sets new symbols to their default | ||
| 466 | * value but not 'n') with the counter-intuitive name. | ||
| 467 | */ | ||
| 468 | {"oldnoconfig", no_argument, NULL, olddefconfig}, | ||
| 469 | {NULL, 0, NULL, 0} | 463 | {NULL, 0, NULL, 0} |
| 470 | }; | 464 | }; |
| 471 | 465 | ||
| @@ -480,7 +474,6 @@ static void conf_usage(const char *progname) | |||
| 480 | printf(" --syncconfig Similar to oldconfig but generates configuration in\n" | 474 | printf(" --syncconfig Similar to oldconfig but generates configuration in\n" |
| 481 | " include/{generated/,config/}\n"); | 475 | " include/{generated/,config/}\n"); |
| 482 | printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n"); | 476 | printf(" --olddefconfig Same as oldconfig but sets new symbols to their default value\n"); |
| 483 | printf(" --oldnoconfig An alias of olddefconfig\n"); | ||
| 484 | printf(" --defconfig <file> New config with default defined in <file>\n"); | 477 | printf(" --defconfig <file> New config with default defined in <file>\n"); |
| 485 | printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); | 478 | printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); |
| 486 | printf(" --allnoconfig New config where all options are answered with no\n"); | 479 | printf(" --allnoconfig New config where all options are answered with no\n"); |
diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh index 67d131447631..da66e7742282 100755 --- a/scripts/kconfig/merge_config.sh +++ b/scripts/kconfig/merge_config.sh | |||
| @@ -33,12 +33,15 @@ usage() { | |||
| 33 | echo " -n use allnoconfig instead of alldefconfig" | 33 | echo " -n use allnoconfig instead of alldefconfig" |
| 34 | echo " -r list redundant entries when merging fragments" | 34 | echo " -r list redundant entries when merging fragments" |
| 35 | echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead." | 35 | echo " -O dir to put generated output files. Consider setting \$KCONFIG_CONFIG instead." |
| 36 | echo | ||
| 37 | echo "Used prefix: '$CONFIG_PREFIX'. You can redefine it with \$CONFIG_ environment variable." | ||
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | RUNMAKE=true | 40 | RUNMAKE=true |
| 39 | ALLTARGET=alldefconfig | 41 | ALLTARGET=alldefconfig |
| 40 | WARNREDUN=false | 42 | WARNREDUN=false |
| 41 | OUTPUT=. | 43 | OUTPUT=. |
| 44 | CONFIG_PREFIX=${CONFIG_-CONFIG_} | ||
| 42 | 45 | ||
| 43 | while true; do | 46 | while true; do |
| 44 | case $1 in | 47 | case $1 in |
| @@ -99,7 +102,8 @@ if [ ! -r "$INITFILE" ]; then | |||
| 99 | fi | 102 | fi |
| 100 | 103 | ||
| 101 | MERGE_LIST=$* | 104 | MERGE_LIST=$* |
| 102 | SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(CONFIG_[a-zA-Z0-9_]*\)[= ].*/\2/p" | 105 | SED_CONFIG_EXP="s/^\(# \)\{0,1\}\(${CONFIG_PREFIX}[a-zA-Z0-9_]*\)[= ].*/\2/p" |
| 106 | |||
| 103 | TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) | 107 | TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX) |
| 104 | 108 | ||
| 105 | echo "Using $INITFILE as base" | 109 | echo "Using $INITFILE as base" |
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index e09fe4d7307c..8963203319ea 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c | |||
| @@ -1742,7 +1742,7 @@ static int ns_rmdir_op(struct inode *dir, struct dentry *dentry) | |||
| 1742 | if (error) | 1742 | if (error) |
| 1743 | return error; | 1743 | return error; |
| 1744 | 1744 | ||
| 1745 | parent = aa_get_ns(dir->i_private); | 1745 | parent = aa_get_ns(dir->i_private); |
| 1746 | /* rmdir calls the generic securityfs functions to remove files | 1746 | /* rmdir calls the generic securityfs functions to remove files |
| 1747 | * from the apparmor dir. It is up to the apparmor ns locking | 1747 | * from the apparmor dir. It is up to the apparmor ns locking |
| 1748 | * to avoid races. | 1748 | * to avoid races. |
diff --git a/security/apparmor/file.c b/security/apparmor/file.c index 4285943f7260..d0afed9ebd0e 100644 --- a/security/apparmor/file.c +++ b/security/apparmor/file.c | |||
| @@ -496,7 +496,7 @@ static void update_file_ctx(struct aa_file_ctx *fctx, struct aa_label *label, | |||
| 496 | /* update caching of label on file_ctx */ | 496 | /* update caching of label on file_ctx */ |
| 497 | spin_lock(&fctx->lock); | 497 | spin_lock(&fctx->lock); |
| 498 | old = rcu_dereference_protected(fctx->label, | 498 | old = rcu_dereference_protected(fctx->label, |
| 499 | spin_is_locked(&fctx->lock)); | 499 | lockdep_is_held(&fctx->lock)); |
| 500 | l = aa_label_merge(old, label, GFP_ATOMIC); | 500 | l = aa_label_merge(old, label, GFP_ATOMIC); |
| 501 | if (l) { | 501 | if (l) { |
| 502 | if (l != old) { | 502 | if (l != old) { |
diff --git a/security/apparmor/include/cred.h b/security/apparmor/include/cred.h index e287b7d0d4be..265ae6641a06 100644 --- a/security/apparmor/include/cred.h +++ b/security/apparmor/include/cred.h | |||
| @@ -151,6 +151,8 @@ static inline struct aa_label *begin_current_label_crit_section(void) | |||
| 151 | { | 151 | { |
| 152 | struct aa_label *label = aa_current_raw_label(); | 152 | struct aa_label *label = aa_current_raw_label(); |
| 153 | 153 | ||
| 154 | might_sleep(); | ||
| 155 | |||
| 154 | if (label_is_stale(label)) { | 156 | if (label_is_stale(label)) { |
| 155 | label = aa_get_newest_label(label); | 157 | label = aa_get_newest_label(label); |
| 156 | if (aa_replace_current_label(label) == 0) | 158 | if (aa_replace_current_label(label) == 0) |
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h index ec7228e857a9..7334ac966d01 100644 --- a/security/apparmor/include/net.h +++ b/security/apparmor/include/net.h | |||
| @@ -83,6 +83,13 @@ struct aa_sk_ctx { | |||
| 83 | __e; \ | 83 | __e; \ |
| 84 | }) | 84 | }) |
| 85 | 85 | ||
| 86 | struct aa_secmark { | ||
| 87 | u8 audit; | ||
| 88 | u8 deny; | ||
| 89 | u32 secid; | ||
| 90 | char *label; | ||
| 91 | }; | ||
| 92 | |||
| 86 | extern struct aa_sfs_entry aa_sfs_entry_network[]; | 93 | extern struct aa_sfs_entry aa_sfs_entry_network[]; |
| 87 | 94 | ||
| 88 | void audit_net_cb(struct audit_buffer *ab, void *va); | 95 | void audit_net_cb(struct audit_buffer *ab, void *va); |
| @@ -103,4 +110,7 @@ int aa_sk_perm(const char *op, u32 request, struct sock *sk); | |||
| 103 | int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, | 110 | int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, |
| 104 | struct socket *sock); | 111 | struct socket *sock); |
| 105 | 112 | ||
| 113 | int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, | ||
| 114 | u32 secid, struct sock *sk); | ||
| 115 | |||
| 106 | #endif /* __AA_NET_H */ | 116 | #endif /* __AA_NET_H */ |
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index ab64c6b5db5a..8e6707c837be 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h | |||
| @@ -155,6 +155,9 @@ struct aa_profile { | |||
| 155 | 155 | ||
| 156 | struct aa_rlimit rlimits; | 156 | struct aa_rlimit rlimits; |
| 157 | 157 | ||
| 158 | int secmark_count; | ||
| 159 | struct aa_secmark *secmark; | ||
| 160 | |||
| 158 | struct aa_loaddata *rawdata; | 161 | struct aa_loaddata *rawdata; |
| 159 | unsigned char *hash; | 162 | unsigned char *hash; |
| 160 | char *dirname; | 163 | char *dirname; |
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h index dee6fa3b6081..fa2062711b63 100644 --- a/security/apparmor/include/secid.h +++ b/security/apparmor/include/secid.h | |||
| @@ -22,6 +22,9 @@ struct aa_label; | |||
| 22 | /* secid value that will not be allocated */ | 22 | /* secid value that will not be allocated */ |
| 23 | #define AA_SECID_INVALID 0 | 23 | #define AA_SECID_INVALID 0 |
| 24 | 24 | ||
| 25 | /* secid value that matches any other secid */ | ||
| 26 | #define AA_SECID_WILDCARD 1 | ||
| 27 | |||
| 25 | struct aa_label *aa_secid_to_label(u32 secid); | 28 | struct aa_label *aa_secid_to_label(u32 secid); |
| 26 | int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | 29 | int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); |
| 27 | int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); | 30 | int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); |
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 974affe50531..76491e7f4177 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c | |||
| @@ -90,10 +90,12 @@ const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, | |||
| 90 | const char *end = fqname + n; | 90 | const char *end = fqname + n; |
| 91 | const char *name = skipn_spaces(fqname, n); | 91 | const char *name = skipn_spaces(fqname, n); |
| 92 | 92 | ||
| 93 | if (!name) | ||
| 94 | return NULL; | ||
| 95 | *ns_name = NULL; | 93 | *ns_name = NULL; |
| 96 | *ns_len = 0; | 94 | *ns_len = 0; |
| 95 | |||
| 96 | if (!name) | ||
| 97 | return NULL; | ||
| 98 | |||
| 97 | if (name[0] == ':') { | 99 | if (name[0] == ':') { |
| 98 | char *split = strnchr(&name[1], end - &name[1], ':'); | 100 | char *split = strnchr(&name[1], end - &name[1], ':'); |
| 99 | *ns_name = skipn_spaces(&name[1], end - &name[1]); | 101 | *ns_name = skipn_spaces(&name[1], end - &name[1]); |
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index aa35939443c4..42446a216f3b 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #include <linux/sysctl.h> | 23 | #include <linux/sysctl.h> |
| 24 | #include <linux/audit.h> | 24 | #include <linux/audit.h> |
| 25 | #include <linux/user_namespace.h> | 25 | #include <linux/user_namespace.h> |
| 26 | #include <linux/netfilter_ipv4.h> | ||
| 27 | #include <linux/netfilter_ipv6.h> | ||
| 26 | #include <net/sock.h> | 28 | #include <net/sock.h> |
| 27 | 29 | ||
| 28 | #include "include/apparmor.h" | 30 | #include "include/apparmor.h" |
| @@ -114,13 +116,13 @@ static int apparmor_ptrace_access_check(struct task_struct *child, | |||
| 114 | struct aa_label *tracer, *tracee; | 116 | struct aa_label *tracer, *tracee; |
| 115 | int error; | 117 | int error; |
| 116 | 118 | ||
| 117 | tracer = begin_current_label_crit_section(); | 119 | tracer = __begin_current_label_crit_section(); |
| 118 | tracee = aa_get_task_label(child); | 120 | tracee = aa_get_task_label(child); |
| 119 | error = aa_may_ptrace(tracer, tracee, | 121 | error = aa_may_ptrace(tracer, tracee, |
| 120 | (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ | 122 | (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ |
| 121 | : AA_PTRACE_TRACE); | 123 | : AA_PTRACE_TRACE); |
| 122 | aa_put_label(tracee); | 124 | aa_put_label(tracee); |
| 123 | end_current_label_crit_section(tracer); | 125 | __end_current_label_crit_section(tracer); |
| 124 | 126 | ||
| 125 | return error; | 127 | return error; |
| 126 | } | 128 | } |
| @@ -130,11 +132,11 @@ static int apparmor_ptrace_traceme(struct task_struct *parent) | |||
| 130 | struct aa_label *tracer, *tracee; | 132 | struct aa_label *tracer, *tracee; |
| 131 | int error; | 133 | int error; |
| 132 | 134 | ||
| 133 | tracee = begin_current_label_crit_section(); | 135 | tracee = __begin_current_label_crit_section(); |
| 134 | tracer = aa_get_task_label(parent); | 136 | tracer = aa_get_task_label(parent); |
| 135 | error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); | 137 | error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); |
| 136 | aa_put_label(tracer); | 138 | aa_put_label(tracer); |
| 137 | end_current_label_crit_section(tracee); | 139 | __end_current_label_crit_section(tracee); |
| 138 | 140 | ||
| 139 | return error; | 141 | return error; |
| 140 | } | 142 | } |
| @@ -1020,6 +1022,7 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) | |||
| 1020 | return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); | 1022 | return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); |
| 1021 | } | 1023 | } |
| 1022 | 1024 | ||
| 1025 | #ifdef CONFIG_NETWORK_SECMARK | ||
| 1023 | /** | 1026 | /** |
| 1024 | * apparmor_socket_sock_recv_skb - check perms before associating skb to sk | 1027 | * apparmor_socket_sock_recv_skb - check perms before associating skb to sk |
| 1025 | * | 1028 | * |
| @@ -1030,8 +1033,15 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) | |||
| 1030 | */ | 1033 | */ |
| 1031 | static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | 1034 | static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 1032 | { | 1035 | { |
| 1033 | return 0; | 1036 | struct aa_sk_ctx *ctx = SK_CTX(sk); |
| 1037 | |||
| 1038 | if (!skb->secmark) | ||
| 1039 | return 0; | ||
| 1040 | |||
| 1041 | return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE, | ||
| 1042 | skb->secmark, sk); | ||
| 1034 | } | 1043 | } |
| 1044 | #endif | ||
| 1035 | 1045 | ||
| 1036 | 1046 | ||
| 1037 | static struct aa_label *sk_peer_label(struct sock *sk) | 1047 | static struct aa_label *sk_peer_label(struct sock *sk) |
| @@ -1126,6 +1136,20 @@ static void apparmor_sock_graft(struct sock *sk, struct socket *parent) | |||
| 1126 | ctx->label = aa_get_current_label(); | 1136 | ctx->label = aa_get_current_label(); |
| 1127 | } | 1137 | } |
| 1128 | 1138 | ||
| 1139 | #ifdef CONFIG_NETWORK_SECMARK | ||
| 1140 | static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb, | ||
| 1141 | struct request_sock *req) | ||
| 1142 | { | ||
| 1143 | struct aa_sk_ctx *ctx = SK_CTX(sk); | ||
| 1144 | |||
| 1145 | if (!skb->secmark) | ||
| 1146 | return 0; | ||
| 1147 | |||
| 1148 | return apparmor_secmark_check(ctx->label, OP_CONNECT, AA_MAY_CONNECT, | ||
| 1149 | skb->secmark, sk); | ||
| 1150 | } | ||
| 1151 | #endif | ||
| 1152 | |||
| 1129 | static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { | 1153 | static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { |
| 1130 | LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), | 1154 | LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), |
| 1131 | LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), | 1155 | LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), |
| @@ -1177,12 +1201,17 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { | |||
| 1177 | LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), | 1201 | LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), |
| 1178 | LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), | 1202 | LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), |
| 1179 | LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), | 1203 | LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), |
| 1204 | #ifdef CONFIG_NETWORK_SECMARK | ||
| 1180 | LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), | 1205 | LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), |
| 1206 | #endif | ||
| 1181 | LSM_HOOK_INIT(socket_getpeersec_stream, | 1207 | LSM_HOOK_INIT(socket_getpeersec_stream, |
| 1182 | apparmor_socket_getpeersec_stream), | 1208 | apparmor_socket_getpeersec_stream), |
| 1183 | LSM_HOOK_INIT(socket_getpeersec_dgram, | 1209 | LSM_HOOK_INIT(socket_getpeersec_dgram, |
| 1184 | apparmor_socket_getpeersec_dgram), | 1210 | apparmor_socket_getpeersec_dgram), |
| 1185 | LSM_HOOK_INIT(sock_graft, apparmor_sock_graft), | 1211 | LSM_HOOK_INIT(sock_graft, apparmor_sock_graft), |
| 1212 | #ifdef CONFIG_NETWORK_SECMARK | ||
| 1213 | LSM_HOOK_INIT(inet_conn_request, apparmor_inet_conn_request), | ||
| 1214 | #endif | ||
| 1186 | 1215 | ||
| 1187 | LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), | 1216 | LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), |
| 1188 | LSM_HOOK_INIT(cred_free, apparmor_cred_free), | 1217 | LSM_HOOK_INIT(cred_free, apparmor_cred_free), |
| @@ -1538,6 +1567,97 @@ static inline int apparmor_init_sysctl(void) | |||
| 1538 | } | 1567 | } |
| 1539 | #endif /* CONFIG_SYSCTL */ | 1568 | #endif /* CONFIG_SYSCTL */ |
| 1540 | 1569 | ||
| 1570 | #if defined(CONFIG_NETFILTER) && defined(CONFIG_NETWORK_SECMARK) | ||
| 1571 | static unsigned int apparmor_ip_postroute(void *priv, | ||
| 1572 | struct sk_buff *skb, | ||
| 1573 | const struct nf_hook_state *state) | ||
| 1574 | { | ||
| 1575 | struct aa_sk_ctx *ctx; | ||
| 1576 | struct sock *sk; | ||
| 1577 | |||
| 1578 | if (!skb->secmark) | ||
| 1579 | return NF_ACCEPT; | ||
| 1580 | |||
| 1581 | sk = skb_to_full_sk(skb); | ||
| 1582 | if (sk == NULL) | ||
| 1583 | return NF_ACCEPT; | ||
| 1584 | |||
| 1585 | ctx = SK_CTX(sk); | ||
| 1586 | if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND, | ||
| 1587 | skb->secmark, sk)) | ||
| 1588 | return NF_ACCEPT; | ||
| 1589 | |||
| 1590 | return NF_DROP_ERR(-ECONNREFUSED); | ||
| 1591 | |||
| 1592 | } | ||
| 1593 | |||
| 1594 | static unsigned int apparmor_ipv4_postroute(void *priv, | ||
| 1595 | struct sk_buff *skb, | ||
| 1596 | const struct nf_hook_state *state) | ||
| 1597 | { | ||
| 1598 | return apparmor_ip_postroute(priv, skb, state); | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | static unsigned int apparmor_ipv6_postroute(void *priv, | ||
| 1602 | struct sk_buff *skb, | ||
| 1603 | const struct nf_hook_state *state) | ||
| 1604 | { | ||
| 1605 | return apparmor_ip_postroute(priv, skb, state); | ||
| 1606 | } | ||
| 1607 | |||
| 1608 | static const struct nf_hook_ops apparmor_nf_ops[] = { | ||
| 1609 | { | ||
| 1610 | .hook = apparmor_ipv4_postroute, | ||
| 1611 | .pf = NFPROTO_IPV4, | ||
| 1612 | .hooknum = NF_INET_POST_ROUTING, | ||
| 1613 | .priority = NF_IP_PRI_SELINUX_FIRST, | ||
| 1614 | }, | ||
| 1615 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 1616 | { | ||
| 1617 | .hook = apparmor_ipv6_postroute, | ||
| 1618 | .pf = NFPROTO_IPV6, | ||
| 1619 | .hooknum = NF_INET_POST_ROUTING, | ||
| 1620 | .priority = NF_IP6_PRI_SELINUX_FIRST, | ||
| 1621 | }, | ||
| 1622 | #endif | ||
| 1623 | }; | ||
| 1624 | |||
| 1625 | static int __net_init apparmor_nf_register(struct net *net) | ||
| 1626 | { | ||
| 1627 | int ret; | ||
| 1628 | |||
| 1629 | ret = nf_register_net_hooks(net, apparmor_nf_ops, | ||
| 1630 | ARRAY_SIZE(apparmor_nf_ops)); | ||
| 1631 | return ret; | ||
| 1632 | } | ||
| 1633 | |||
| 1634 | static void __net_exit apparmor_nf_unregister(struct net *net) | ||
| 1635 | { | ||
| 1636 | nf_unregister_net_hooks(net, apparmor_nf_ops, | ||
| 1637 | ARRAY_SIZE(apparmor_nf_ops)); | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | static struct pernet_operations apparmor_net_ops = { | ||
| 1641 | .init = apparmor_nf_register, | ||
| 1642 | .exit = apparmor_nf_unregister, | ||
| 1643 | }; | ||
| 1644 | |||
| 1645 | static int __init apparmor_nf_ip_init(void) | ||
| 1646 | { | ||
| 1647 | int err; | ||
| 1648 | |||
| 1649 | if (!apparmor_enabled) | ||
| 1650 | return 0; | ||
| 1651 | |||
| 1652 | err = register_pernet_subsys(&apparmor_net_ops); | ||
| 1653 | if (err) | ||
| 1654 | panic("Apparmor: register_pernet_subsys: error %d\n", err); | ||
| 1655 | |||
| 1656 | return 0; | ||
| 1657 | } | ||
| 1658 | __initcall(apparmor_nf_ip_init); | ||
| 1659 | #endif | ||
| 1660 | |||
| 1541 | static int __init apparmor_init(void) | 1661 | static int __init apparmor_init(void) |
| 1542 | { | 1662 | { |
| 1543 | int error; | 1663 | int error; |
diff --git a/security/apparmor/net.c b/security/apparmor/net.c index bb24cfa0a164..c07fde444792 100644 --- a/security/apparmor/net.c +++ b/security/apparmor/net.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include "include/label.h" | 18 | #include "include/label.h" |
| 19 | #include "include/net.h" | 19 | #include "include/net.h" |
| 20 | #include "include/policy.h" | 20 | #include "include/policy.h" |
| 21 | #include "include/secid.h" | ||
| 21 | 22 | ||
| 22 | #include "net_names.h" | 23 | #include "net_names.h" |
| 23 | 24 | ||
| @@ -146,17 +147,20 @@ int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family, | |||
| 146 | static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, | 147 | static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request, |
| 147 | struct sock *sk) | 148 | struct sock *sk) |
| 148 | { | 149 | { |
| 149 | struct aa_profile *profile; | 150 | int error = 0; |
| 150 | DEFINE_AUDIT_SK(sa, op, sk); | ||
| 151 | 151 | ||
| 152 | AA_BUG(!label); | 152 | AA_BUG(!label); |
| 153 | AA_BUG(!sk); | 153 | AA_BUG(!sk); |
| 154 | 154 | ||
| 155 | if (unconfined(label)) | 155 | if (!unconfined(label)) { |
| 156 | return 0; | 156 | struct aa_profile *profile; |
| 157 | DEFINE_AUDIT_SK(sa, op, sk); | ||
| 157 | 158 | ||
| 158 | return fn_for_each_confined(label, profile, | 159 | error = fn_for_each_confined(label, profile, |
| 159 | aa_profile_af_sk_perm(profile, &sa, request, sk)); | 160 | aa_profile_af_sk_perm(profile, &sa, request, sk)); |
| 161 | } | ||
| 162 | |||
| 163 | return error; | ||
| 160 | } | 164 | } |
| 161 | 165 | ||
| 162 | int aa_sk_perm(const char *op, u32 request, struct sock *sk) | 166 | int aa_sk_perm(const char *op, u32 request, struct sock *sk) |
| @@ -185,3 +189,70 @@ int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request, | |||
| 185 | 189 | ||
| 186 | return aa_label_sk_perm(label, op, request, sock->sk); | 190 | return aa_label_sk_perm(label, op, request, sock->sk); |
| 187 | } | 191 | } |
| 192 | |||
| 193 | #ifdef CONFIG_NETWORK_SECMARK | ||
| 194 | static int apparmor_secmark_init(struct aa_secmark *secmark) | ||
| 195 | { | ||
| 196 | struct aa_label *label; | ||
| 197 | |||
| 198 | if (secmark->label[0] == '*') { | ||
| 199 | secmark->secid = AA_SECID_WILDCARD; | ||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | label = aa_label_strn_parse(&root_ns->unconfined->label, | ||
| 204 | secmark->label, strlen(secmark->label), | ||
| 205 | GFP_ATOMIC, false, false); | ||
| 206 | |||
| 207 | if (IS_ERR(label)) | ||
| 208 | return PTR_ERR(label); | ||
| 209 | |||
| 210 | secmark->secid = label->secid; | ||
| 211 | |||
| 212 | return 0; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid, | ||
| 216 | struct common_audit_data *sa, struct sock *sk) | ||
| 217 | { | ||
| 218 | int i, ret; | ||
| 219 | struct aa_perms perms = { }; | ||
| 220 | |||
| 221 | if (profile->secmark_count == 0) | ||
| 222 | return 0; | ||
| 223 | |||
| 224 | for (i = 0; i < profile->secmark_count; i++) { | ||
| 225 | if (!profile->secmark[i].secid) { | ||
| 226 | ret = apparmor_secmark_init(&profile->secmark[i]); | ||
| 227 | if (ret) | ||
| 228 | return ret; | ||
| 229 | } | ||
| 230 | |||
| 231 | if (profile->secmark[i].secid == secid || | ||
| 232 | profile->secmark[i].secid == AA_SECID_WILDCARD) { | ||
| 233 | if (profile->secmark[i].deny) | ||
| 234 | perms.deny = ALL_PERMS_MASK; | ||
| 235 | else | ||
| 236 | perms.allow = ALL_PERMS_MASK; | ||
| 237 | |||
| 238 | if (profile->secmark[i].audit) | ||
| 239 | perms.audit = ALL_PERMS_MASK; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | aa_apply_modes_to_perms(profile, &perms); | ||
| 244 | |||
| 245 | return aa_check_perms(profile, &perms, request, sa, audit_net_cb); | ||
| 246 | } | ||
| 247 | |||
| 248 | int apparmor_secmark_check(struct aa_label *label, char *op, u32 request, | ||
| 249 | u32 secid, struct sock *sk) | ||
| 250 | { | ||
| 251 | struct aa_profile *profile; | ||
| 252 | DEFINE_AUDIT_SK(sa, op, sk); | ||
| 253 | |||
| 254 | return fn_for_each_confined(label, profile, | ||
| 255 | aa_secmark_perm(profile, request, secid, | ||
| 256 | &sa, sk)); | ||
| 257 | } | ||
| 258 | #endif | ||
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 1590e2de4e84..df9c5890a878 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
| @@ -231,6 +231,9 @@ void aa_free_profile(struct aa_profile *profile) | |||
| 231 | for (i = 0; i < profile->xattr_count; i++) | 231 | for (i = 0; i < profile->xattr_count; i++) |
| 232 | kzfree(profile->xattrs[i]); | 232 | kzfree(profile->xattrs[i]); |
| 233 | kzfree(profile->xattrs); | 233 | kzfree(profile->xattrs); |
| 234 | for (i = 0; i < profile->secmark_count; i++) | ||
| 235 | kzfree(profile->secmark[i].label); | ||
| 236 | kzfree(profile->secmark); | ||
| 234 | kzfree(profile->dirname); | 237 | kzfree(profile->dirname); |
| 235 | aa_put_dfa(profile->xmatch); | 238 | aa_put_dfa(profile->xmatch); |
| 236 | aa_put_dfa(profile->policy.dfa); | 239 | aa_put_dfa(profile->policy.dfa); |
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 21cb384d712a..379682e2a8d5 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c | |||
| @@ -292,6 +292,19 @@ fail: | |||
| 292 | return 0; | 292 | return 0; |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | static bool unpack_u8(struct aa_ext *e, u8 *data, const char *name) | ||
| 296 | { | ||
| 297 | if (unpack_nameX(e, AA_U8, name)) { | ||
| 298 | if (!inbounds(e, sizeof(u8))) | ||
| 299 | return 0; | ||
| 300 | if (data) | ||
| 301 | *data = get_unaligned((u8 *)e->pos); | ||
| 302 | e->pos += sizeof(u8); | ||
| 303 | return 1; | ||
| 304 | } | ||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 295 | static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) | 308 | static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) |
| 296 | { | 309 | { |
| 297 | if (unpack_nameX(e, AA_U32, name)) { | 310 | if (unpack_nameX(e, AA_U32, name)) { |
| @@ -529,6 +542,49 @@ fail: | |||
| 529 | return 0; | 542 | return 0; |
| 530 | } | 543 | } |
| 531 | 544 | ||
| 545 | static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) | ||
| 546 | { | ||
| 547 | void *pos = e->pos; | ||
| 548 | int i, size; | ||
| 549 | |||
| 550 | if (unpack_nameX(e, AA_STRUCT, "secmark")) { | ||
| 551 | size = unpack_array(e, NULL); | ||
| 552 | |||
| 553 | profile->secmark = kcalloc(size, sizeof(struct aa_secmark), | ||
| 554 | GFP_KERNEL); | ||
| 555 | if (!profile->secmark) | ||
| 556 | goto fail; | ||
| 557 | |||
| 558 | profile->secmark_count = size; | ||
| 559 | |||
| 560 | for (i = 0; i < size; i++) { | ||
| 561 | if (!unpack_u8(e, &profile->secmark[i].audit, NULL)) | ||
| 562 | goto fail; | ||
| 563 | if (!unpack_u8(e, &profile->secmark[i].deny, NULL)) | ||
| 564 | goto fail; | ||
| 565 | if (!unpack_strdup(e, &profile->secmark[i].label, NULL)) | ||
| 566 | goto fail; | ||
| 567 | } | ||
| 568 | if (!unpack_nameX(e, AA_ARRAYEND, NULL)) | ||
| 569 | goto fail; | ||
| 570 | if (!unpack_nameX(e, AA_STRUCTEND, NULL)) | ||
| 571 | goto fail; | ||
| 572 | } | ||
| 573 | |||
| 574 | return 1; | ||
| 575 | |||
| 576 | fail: | ||
| 577 | if (profile->secmark) { | ||
| 578 | for (i = 0; i < size; i++) | ||
| 579 | kfree(profile->secmark[i].label); | ||
| 580 | kfree(profile->secmark); | ||
| 581 | profile->secmark_count = 0; | ||
| 582 | } | ||
| 583 | |||
| 584 | e->pos = pos; | ||
| 585 | return 0; | ||
| 586 | } | ||
| 587 | |||
| 532 | static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) | 588 | static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile) |
| 533 | { | 589 | { |
| 534 | void *pos = e->pos; | 590 | void *pos = e->pos; |
| @@ -727,6 +783,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) | |||
| 727 | goto fail; | 783 | goto fail; |
| 728 | } | 784 | } |
| 729 | 785 | ||
| 786 | if (!unpack_secmark(e, profile)) { | ||
| 787 | info = "failed to unpack profile secmark rules"; | ||
| 788 | goto fail; | ||
| 789 | } | ||
| 790 | |||
| 730 | if (unpack_nameX(e, AA_STRUCT, "policydb")) { | 791 | if (unpack_nameX(e, AA_STRUCT, "policydb")) { |
| 731 | /* generic policy dfa - optional and may be NULL */ | 792 | /* generic policy dfa - optional and may be NULL */ |
| 732 | info = "failed to unpack policydb"; | 793 | info = "failed to unpack policydb"; |
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c index 4ccec1bcf6f5..05373d9a3d6a 100644 --- a/security/apparmor/secid.c +++ b/security/apparmor/secid.c | |||
| @@ -32,8 +32,7 @@ | |||
| 32 | * secids - do not pin labels with a refcount. They rely on the label | 32 | * secids - do not pin labels with a refcount. They rely on the label |
| 33 | * properly updating/freeing them | 33 | * properly updating/freeing them |
| 34 | */ | 34 | */ |
| 35 | 35 | #define AA_FIRST_SECID 2 | |
| 36 | #define AA_FIRST_SECID 1 | ||
| 37 | 36 | ||
| 38 | static DEFINE_IDR(aa_secids); | 37 | static DEFINE_IDR(aa_secids); |
| 39 | static DEFINE_SPINLOCK(secid_lock); | 38 | static DEFINE_SPINLOCK(secid_lock); |
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index fcd965f1d69e..9be76c808fcc 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c | |||
| @@ -146,53 +146,22 @@ static int apply_constraint_to_size(struct snd_pcm_hw_params *params, | |||
| 146 | struct snd_interval *s = hw_param_interval(params, rule->var); | 146 | struct snd_interval *s = hw_param_interval(params, rule->var); |
| 147 | const struct snd_interval *r = | 147 | const struct snd_interval *r = |
| 148 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); | 148 | hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE); |
| 149 | struct snd_interval t = { | 149 | struct snd_interval t = {0}; |
| 150 | .min = s->min, .max = s->max, .integer = 1, | 150 | unsigned int step = 0; |
| 151 | }; | ||
| 152 | int i; | 151 | int i; |
| 153 | 152 | ||
| 154 | for (i = 0; i < CIP_SFC_COUNT; ++i) { | 153 | for (i = 0; i < CIP_SFC_COUNT; ++i) { |
| 155 | unsigned int rate = amdtp_rate_table[i]; | 154 | if (snd_interval_test(r, amdtp_rate_table[i])) |
| 156 | unsigned int step = amdtp_syt_intervals[i]; | 155 | step = max(step, amdtp_syt_intervals[i]); |
| 157 | |||
| 158 | if (!snd_interval_test(r, rate)) | ||
| 159 | continue; | ||
| 160 | |||
| 161 | t.min = roundup(t.min, step); | ||
| 162 | t.max = rounddown(t.max, step); | ||
| 163 | } | 156 | } |
| 164 | 157 | ||
| 165 | if (snd_interval_checkempty(&t)) | 158 | t.min = roundup(s->min, step); |
| 166 | return -EINVAL; | 159 | t.max = rounddown(s->max, step); |
| 160 | t.integer = 1; | ||
| 167 | 161 | ||
| 168 | return snd_interval_refine(s, &t); | 162 | return snd_interval_refine(s, &t); |
| 169 | } | 163 | } |
| 170 | 164 | ||
| 171 | static int apply_constraint_to_rate(struct snd_pcm_hw_params *params, | ||
| 172 | struct snd_pcm_hw_rule *rule) | ||
| 173 | { | ||
| 174 | struct snd_interval *r = | ||
| 175 | hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); | ||
| 176 | const struct snd_interval *s = hw_param_interval_c(params, rule->deps[0]); | ||
| 177 | struct snd_interval t = { | ||
| 178 | .min = UINT_MAX, .max = 0, .integer = 1, | ||
| 179 | }; | ||
| 180 | int i; | ||
| 181 | |||
| 182 | for (i = 0; i < CIP_SFC_COUNT; ++i) { | ||
| 183 | unsigned int step = amdtp_syt_intervals[i]; | ||
| 184 | unsigned int rate = amdtp_rate_table[i]; | ||
| 185 | |||
| 186 | if (s->min % step || s->max % step) | ||
| 187 | continue; | ||
| 188 | |||
| 189 | t.min = min(t.min, rate); | ||
| 190 | t.max = max(t.max, rate); | ||
| 191 | } | ||
| 192 | |||
| 193 | return snd_interval_refine(r, &t); | ||
| 194 | } | ||
| 195 | |||
| 196 | /** | 165 | /** |
| 197 | * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream | 166 | * amdtp_stream_add_pcm_hw_constraints - add hw constraints for PCM substream |
| 198 | * @s: the AMDTP stream, which must be initialized. | 167 | * @s: the AMDTP stream, which must be initialized. |
| @@ -250,24 +219,16 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s, | |||
| 250 | */ | 219 | */ |
| 251 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | 220 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, |
| 252 | apply_constraint_to_size, NULL, | 221 | apply_constraint_to_size, NULL, |
| 222 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, | ||
| 253 | SNDRV_PCM_HW_PARAM_RATE, -1); | 223 | SNDRV_PCM_HW_PARAM_RATE, -1); |
| 254 | if (err < 0) | 224 | if (err < 0) |
| 255 | goto end; | 225 | goto end; |
| 256 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
| 257 | apply_constraint_to_rate, NULL, | ||
| 258 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, -1); | ||
| 259 | if (err < 0) | ||
| 260 | goto end; | ||
| 261 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | 226 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, |
| 262 | apply_constraint_to_size, NULL, | 227 | apply_constraint_to_size, NULL, |
| 228 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, | ||
| 263 | SNDRV_PCM_HW_PARAM_RATE, -1); | 229 | SNDRV_PCM_HW_PARAM_RATE, -1); |
| 264 | if (err < 0) | 230 | if (err < 0) |
| 265 | goto end; | 231 | goto end; |
| 266 | err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, | ||
| 267 | apply_constraint_to_rate, NULL, | ||
| 268 | SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1); | ||
| 269 | if (err < 0) | ||
| 270 | goto end; | ||
| 271 | end: | 232 | end: |
| 272 | return err; | 233 | return err; |
| 273 | } | 234 | } |
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c index 0f6dbcffe711..ed50b222d36e 100644 --- a/sound/firewire/dice/dice.c +++ b/sound/firewire/dice/dice.c | |||
| @@ -240,8 +240,8 @@ static void dice_remove(struct fw_unit *unit) | |||
| 240 | cancel_delayed_work_sync(&dice->dwork); | 240 | cancel_delayed_work_sync(&dice->dwork); |
| 241 | 241 | ||
| 242 | if (dice->registered) { | 242 | if (dice->registered) { |
| 243 | /* No need to wait for releasing card object in this context. */ | 243 | // Block till all of ALSA character devices are released. |
| 244 | snd_card_free_when_closed(dice->card); | 244 | snd_card_free(dice->card); |
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | mutex_destroy(&dice->mutex); | 247 | mutex_destroy(&dice->mutex); |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 04402c14cb23..9847b669cf3c 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
| @@ -582,7 +582,7 @@ | |||
| 582 | #define SPI_PL_BIT_R_R (2<<7) /* right channel = right */ | 582 | #define SPI_PL_BIT_R_R (2<<7) /* right channel = right */ |
| 583 | #define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */ | 583 | #define SPI_PL_BIT_R_C (3<<7) /* right channel = (L+R)/2 */ |
| 584 | #define SPI_IZD_REG 2 | 584 | #define SPI_IZD_REG 2 |
| 585 | #define SPI_IZD_BIT (1<<4) /* infinite zero detect */ | 585 | #define SPI_IZD_BIT (0<<4) /* infinite zero detect */ |
| 586 | 586 | ||
| 587 | #define SPI_FMT_REG 3 | 587 | #define SPI_FMT_REG 3 |
| 588 | #define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */ | 588 | #define SPI_FMT_BIT_RJ (0<<0) /* right justified mode */ |
diff --git a/tools/testing/selftests/powerpc/cache_shape/Makefile b/tools/testing/selftests/powerpc/cache_shape/Makefile index ede4d3dae750..689f6c8ebcd8 100644 --- a/tools/testing/selftests/powerpc/cache_shape/Makefile +++ b/tools/testing/selftests/powerpc/cache_shape/Makefile | |||
| @@ -1,12 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | TEST_PROGS := cache_shape | 2 | TEST_GEN_PROGS := cache_shape |
| 3 | |||
| 4 | all: $(TEST_PROGS) | ||
| 5 | |||
| 6 | $(TEST_PROGS): ../harness.c ../utils.c | ||
| 7 | 3 | ||
| 8 | top_srcdir = ../../../../.. | 4 | top_srcdir = ../../../../.. |
| 9 | include ../../lib.mk | 5 | include ../../lib.mk |
| 10 | 6 | ||
| 11 | clean: | 7 | $(TEST_GEN_PROGS): ../harness.c ../utils.c |
| 12 | rm -f $(TEST_PROGS) *.o | ||
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile index bd5dfa509272..23f4caf48ffc 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile +++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile | |||
| @@ -5,6 +5,9 @@ noarg: | |||
| 5 | # The EBB handler is 64-bit code and everything links against it | 5 | # The EBB handler is 64-bit code and everything links against it |
| 6 | CFLAGS += -m64 | 6 | CFLAGS += -m64 |
| 7 | 7 | ||
| 8 | # Toolchains may build PIE by default which breaks the assembly | ||
| 9 | LDFLAGS += -no-pie | ||
| 10 | |||
| 8 | TEST_GEN_PROGS := reg_access_test event_attributes_test cycles_test \ | 11 | TEST_GEN_PROGS := reg_access_test event_attributes_test cycles_test \ |
| 9 | cycles_with_freeze_test pmc56_overflow_test \ | 12 | cycles_with_freeze_test pmc56_overflow_test \ |
| 10 | ebb_vs_cpu_event_test cpu_event_vs_ebb_test \ | 13 | ebb_vs_cpu_event_test cpu_event_vs_ebb_test \ |
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 9b35ca8e8f13..8d3f006c98cc 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ | 2 | TEST_GEN_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ |
| 3 | ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ | 3 | ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ |
| 4 | ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \ | 4 | ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \ |
| 5 | perf-hwbreak ptrace-syscall | 5 | perf-hwbreak ptrace-syscall |
| @@ -7,14 +7,9 @@ TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ | |||
| 7 | top_srcdir = ../../../../.. | 7 | top_srcdir = ../../../../.. |
| 8 | include ../../lib.mk | 8 | include ../../lib.mk |
| 9 | 9 | ||
| 10 | all: $(TEST_PROGS) | ||
| 11 | |||
| 12 | CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie | 10 | CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie |
| 13 | 11 | ||
| 14 | ptrace-pkey core-pkey: child.h | 12 | $(OUTPUT)/ptrace-pkey $(OUTPUT)/core-pkey: child.h |
| 15 | ptrace-pkey core-pkey: LDLIBS += -pthread | 13 | $(OUTPUT)/ptrace-pkey $(OUTPUT)/core-pkey: LDLIBS += -pthread |
| 16 | |||
| 17 | $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h | ||
| 18 | 14 | ||
| 19 | clean: | 15 | $(TEST_GEN_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h |
| 20 | rm -f $(TEST_PROGS) *.o | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c index 327fa943c7f3..dbdffa2e2c82 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-tm-spd-gpr.c | |||
| @@ -67,8 +67,8 @@ trans: | |||
| 67 | "3: ;" | 67 | "3: ;" |
| 68 | : [res] "=r" (result), [texasr] "=r" (texasr) | 68 | : [res] "=r" (result), [texasr] "=r" (texasr) |
| 69 | : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4), | 69 | : [gpr_1]"i"(GPR_1), [gpr_2]"i"(GPR_2), [gpr_4]"i"(GPR_4), |
| 70 | [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "r" (&a), | 70 | [sprn_texasr] "i" (SPRN_TEXASR), [flt_1] "b" (&a), |
| 71 | [flt_2] "r" (&b), [flt_4] "r" (&d) | 71 | [flt_4] "b" (&d) |
| 72 | : "memory", "r5", "r6", "r7", | 72 | : "memory", "r5", "r6", "r7", |
| 73 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 73 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
| 74 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 74 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
diff --git a/tools/testing/selftests/powerpc/security/Makefile b/tools/testing/selftests/powerpc/security/Makefile index 44690f1bb26a..85861c46b445 100644 --- a/tools/testing/selftests/powerpc/security/Makefile +++ b/tools/testing/selftests/powerpc/security/Makefile | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0+ | 1 | # SPDX-License-Identifier: GPL-2.0+ |
| 2 | 2 | ||
| 3 | TEST_GEN_PROGS := rfi_flush | 3 | TEST_GEN_PROGS := rfi_flush |
| 4 | top_srcdir = ../../../../.. | ||
| 4 | 5 | ||
| 5 | CFLAGS += -I../../../../../usr/include | 6 | CFLAGS += -I../../../../../usr/include |
| 6 | 7 | ||
diff --git a/tools/testing/selftests/powerpc/security/rfi_flush.c b/tools/testing/selftests/powerpc/security/rfi_flush.c index 564ed45bbf73..0a7d0afb26b8 100644 --- a/tools/testing/selftests/powerpc/security/rfi_flush.c +++ b/tools/testing/selftests/powerpc/security/rfi_flush.c | |||
| @@ -49,6 +49,7 @@ int rfi_flush_test(void) | |||
| 49 | struct perf_event_read v; | 49 | struct perf_event_read v; |
| 50 | __u64 l1d_misses_total = 0; | 50 | __u64 l1d_misses_total = 0; |
| 51 | unsigned long iterations = 100000, zero_size = 24 * 1024; | 51 | unsigned long iterations = 100000, zero_size = 24 * 1024; |
| 52 | unsigned long l1d_misses_expected; | ||
| 52 | int rfi_flush_org, rfi_flush; | 53 | int rfi_flush_org, rfi_flush; |
| 53 | 54 | ||
| 54 | SKIP_IF(geteuid() != 0); | 55 | SKIP_IF(geteuid() != 0); |
| @@ -71,6 +72,12 @@ int rfi_flush_test(void) | |||
| 71 | 72 | ||
| 72 | iter = repetitions; | 73 | iter = repetitions; |
| 73 | 74 | ||
| 75 | /* | ||
| 76 | * We expect to see l1d miss for each cacheline access when rfi_flush | ||
| 77 | * is set. Allow a small variation on this. | ||
| 78 | */ | ||
| 79 | l1d_misses_expected = iterations * (zero_size / CACHELINE_SIZE - 2); | ||
| 80 | |||
| 74 | again: | 81 | again: |
| 75 | FAIL_IF(perf_event_reset(fd)); | 82 | FAIL_IF(perf_event_reset(fd)); |
| 76 | 83 | ||
| @@ -78,10 +85,9 @@ again: | |||
| 78 | 85 | ||
| 79 | FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v)); | 86 | FAIL_IF(read(fd, &v, sizeof(v)) != sizeof(v)); |
| 80 | 87 | ||
| 81 | /* Expect at least zero_size/CACHELINE_SIZE misses per iteration */ | 88 | if (rfi_flush && v.l1d_misses >= l1d_misses_expected) |
| 82 | if (v.l1d_misses >= (iterations * zero_size / CACHELINE_SIZE) && rfi_flush) | ||
| 83 | passes++; | 89 | passes++; |
| 84 | else if (v.l1d_misses < iterations && !rfi_flush) | 90 | else if (!rfi_flush && v.l1d_misses < (l1d_misses_expected / 2)) |
| 85 | passes++; | 91 | passes++; |
| 86 | 92 | ||
| 87 | l1d_misses_total += v.l1d_misses; | 93 | l1d_misses_total += v.l1d_misses; |
| @@ -92,13 +98,15 @@ again: | |||
| 92 | if (passes < repetitions) { | 98 | if (passes < repetitions) { |
| 93 | printf("FAIL (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d failures]\n", | 99 | printf("FAIL (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d failures]\n", |
| 94 | rfi_flush, l1d_misses_total, rfi_flush ? '<' : '>', | 100 | rfi_flush, l1d_misses_total, rfi_flush ? '<' : '>', |
| 95 | rfi_flush ? (repetitions * iterations * zero_size / CACHELINE_SIZE) : iterations, | 101 | rfi_flush ? repetitions * l1d_misses_expected : |
| 102 | repetitions * l1d_misses_expected / 2, | ||
| 96 | repetitions - passes, repetitions); | 103 | repetitions - passes, repetitions); |
| 97 | rc = 1; | 104 | rc = 1; |
| 98 | } else | 105 | } else |
| 99 | printf("PASS (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d pass]\n", | 106 | printf("PASS (L1D misses with rfi_flush=%d: %llu %c %lu) [%d/%d pass]\n", |
| 100 | rfi_flush, l1d_misses_total, rfi_flush ? '>' : '<', | 107 | rfi_flush, l1d_misses_total, rfi_flush ? '>' : '<', |
| 101 | rfi_flush ? (repetitions * iterations * zero_size / CACHELINE_SIZE) : iterations, | 108 | rfi_flush ? repetitions * l1d_misses_expected : |
| 109 | repetitions * l1d_misses_expected / 2, | ||
| 102 | passes, repetitions); | 110 | passes, repetitions); |
| 103 | 111 | ||
| 104 | if (rfi_flush == rfi_flush_org) { | 112 | if (rfi_flush == rfi_flush_org) { |
diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile index 1fca25c6ace0..209a958dca12 100644 --- a/tools/testing/selftests/powerpc/signal/Makefile +++ b/tools/testing/selftests/powerpc/signal/Makefile | |||
| @@ -1,15 +1,10 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | TEST_PROGS := signal signal_tm | 2 | TEST_GEN_PROGS := signal signal_tm |
| 3 | |||
| 4 | all: $(TEST_PROGS) | ||
| 5 | |||
| 6 | $(TEST_PROGS): ../harness.c ../utils.c signal.S | ||
| 7 | 3 | ||
| 8 | CFLAGS += -maltivec | 4 | CFLAGS += -maltivec |
| 9 | signal_tm: CFLAGS += -mhtm | 5 | $(OUTPUT)/signal_tm: CFLAGS += -mhtm |
| 10 | 6 | ||
| 11 | top_srcdir = ../../../../.. | 7 | top_srcdir = ../../../../.. |
| 12 | include ../../lib.mk | 8 | include ../../lib.mk |
| 13 | 9 | ||
| 14 | clean: | 10 | $(TEST_GEN_PROGS): ../harness.c ../utils.c signal.S |
| 15 | rm -f $(TEST_PROGS) *.o | ||
diff --git a/tools/testing/selftests/powerpc/switch_endian/Makefile b/tools/testing/selftests/powerpc/switch_endian/Makefile index fcd2dcb8972b..bdc081afedb0 100644 --- a/tools/testing/selftests/powerpc/switch_endian/Makefile +++ b/tools/testing/selftests/powerpc/switch_endian/Makefile | |||
| @@ -8,6 +8,7 @@ EXTRA_CLEAN = $(OUTPUT)/*.o $(OUTPUT)/check-reversed.S | |||
| 8 | top_srcdir = ../../../../.. | 8 | top_srcdir = ../../../../.. |
| 9 | include ../../lib.mk | 9 | include ../../lib.mk |
| 10 | 10 | ||
| 11 | $(OUTPUT)/switch_endian_test: ASFLAGS += -I $(OUTPUT) | ||
| 11 | $(OUTPUT)/switch_endian_test: $(OUTPUT)/check-reversed.S | 12 | $(OUTPUT)/switch_endian_test: $(OUTPUT)/check-reversed.S |
| 12 | 13 | ||
| 13 | $(OUTPUT)/check-reversed.o: $(OUTPUT)/check.o | 14 | $(OUTPUT)/check-reversed.o: $(OUTPUT)/check.o |
diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c index 43c342845be0..ed62f4153d3e 100644 --- a/tools/testing/selftests/powerpc/utils.c +++ b/tools/testing/selftests/powerpc/utils.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include "utils.h" | 25 | #include "utils.h" |
| 26 | 26 | ||
| 27 | static char auxv[4096]; | 27 | static char auxv[4096]; |
| 28 | extern unsigned int dscr_insn[]; | ||
| 29 | 28 | ||
| 30 | int read_auxv(char *buf, ssize_t buf_size) | 29 | int read_auxv(char *buf, ssize_t buf_size) |
| 31 | { | 30 | { |
| @@ -247,7 +246,8 @@ static void sigill_handler(int signr, siginfo_t *info, void *unused) | |||
| 247 | ucontext_t *ctx = (ucontext_t *)unused; | 246 | ucontext_t *ctx = (ucontext_t *)unused; |
| 248 | unsigned long *pc = &UCONTEXT_NIA(ctx); | 247 | unsigned long *pc = &UCONTEXT_NIA(ctx); |
| 249 | 248 | ||
| 250 | if (*pc == (unsigned long)&dscr_insn) { | 249 | /* mtspr 3,RS to check for move to DSCR below */ |
| 250 | if ((*((unsigned int *)*pc) & 0xfc1fffff) == 0x7c0303a6) { | ||
| 251 | if (!warned++) | 251 | if (!warned++) |
| 252 | printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n"); | 252 | printf("WARNING: Skipping over dscr setup. Consider running 'ppc64_cpu --dscr=1' manually.\n"); |
| 253 | *pc += 4; | 253 | *pc += 4; |
| @@ -271,5 +271,5 @@ void set_dscr(unsigned long val) | |||
| 271 | init = 1; | 271 | init = 1; |
| 272 | } | 272 | } |
| 273 | 273 | ||
| 274 | asm volatile("dscr_insn: mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); | 274 | asm volatile("mtspr %1,%0" : : "r" (val), "i" (SPRN_DSCR)); |
| 275 | } | 275 | } |
