diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 4fa822cb561e..68f846fef91f 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2580,6 +2580,8 @@ mds=off [X86] tsx_async_abort=off [X86] kvm.nx_huge_pages=off [X86] + no_entry_flush [PPC] + no_uaccess_flush [PPC] Exceptions: This does not have any effect on @@ -2890,6 +2892,8 @@ noefi Disable EFI runtime services support. + no_entry_flush [PPC] Don't flush the L1-D cache when entering the kernel. + noexec [IA-64] noexec [X86] @@ -2939,6 +2943,9 @@ nospec_store_bypass_disable [HW] Disable all mitigations for the Speculative Store Bypass vulnerability + no_uaccess_flush + [PPC] Don't flush the L1-D cache after accessing user data. + noxsave [BUGS=X86] Disables x86 extended register state save and restore using xsave. The kernel will fallback to enabling legacy floating-point and sse state. @@ -5023,6 +5030,7 @@ device); j = NO_REPORT_LUNS (don't use report luns command, uas only); + k = NO_SAME (do not use WRITE_SAME, uas only) l = NOT_LOCKABLE (don't try to lock and unlock ejectable media, not on uas); m = MAX_SECTORS_64 (don't transfer more diff --git a/Documentation/device-mapper/dm-integrity.txt b/Documentation/device-mapper/dm-integrity.txt index 297251b0d2d5..bf6af2ade0a6 100644 --- a/Documentation/device-mapper/dm-integrity.txt +++ b/Documentation/device-mapper/dm-integrity.txt @@ -146,6 +146,13 @@ block_size:number Supported values are 512, 1024, 2048 and 4096 bytes. If not specified the default block size is 512 bytes. +legacy_recalculate + Allow recalculating of volumes with HMAC keys. This is disabled by + default for security reasons - an attacker could modify the volume, + set recalc_sector to zero, and the kernel would not detect the + modification. + + The journal mode (D/J), buffer_sectors, journal_watermark, commit_time can be changed when reloading the target (load an inactive table and swap the tables with suspend and resume). The other arguments should not be changed diff --git a/Documentation/devicetree/bindings b/Documentation/devicetree/bindings deleted file mode 120000 index 2977badf1905..000000000000 --- a/Documentation/devicetree/bindings +++ /dev/null @@ -1 +0,0 @@ -../../arch/arm64/boot/dts/vendor/bindings \ No newline at end of file diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt index d412b236a9d6..7cf7143921a1 100644 --- a/Documentation/filesystems/seq_file.txt +++ b/Documentation/filesystems/seq_file.txt @@ -192,6 +192,12 @@ between the calls to start() and stop(), so holding a lock during that time is a reasonable thing to do. The seq_file code will also avoid taking any other locks while the iterator is active. +The iterater value returned by start() or next() is guaranteed to be +passed to a subsequent next() or stop() call. This allows resources +such as locks that were taken to be reliably released. There is *no* +guarantee that the iterator will be passed to show(), though in practice +it often will be. + Formatted output diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index a1426cabcef1..2e38fafc1b63 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -211,12 +211,10 @@ Other notes: is 4096. - show() methods should return the number of bytes printed into the - buffer. This is the return value of scnprintf(). + buffer. -- show() must not use snprintf() when formatting the value to be - returned to user space. If you can guarantee that an overflow - will never happen you can use sprintf() otherwise you must use - scnprintf(). +- show() should only use sysfs_emit() or sysfs_emit_at() when formatting + the value to be returned to user space. - store() should return the number of bytes used from the buffer. If the entire buffer has been used, just return the count argument. diff --git a/Makefile b/Makefile index 0a08e206a6eb..adf9e3346af4 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 19 -SUBLEVEL = 113 +SUBLEVEL = 189 EXTRAVERSION = NAME = "People's Front" @@ -366,7 +366,7 @@ HOSTCC = gcc HOSTCXX = g++ endif KBUILD_HOSTCFLAGS := -Wall -Wmissing-prototypes -Wstrict-prototypes -O3 \ - -fomit-frame-pointer -std=gnu89 -pipe $(HOST_LFS_CFLAGS) \ + -fomit-frame-pointer -pipe -std=gnu89 $(HOST_LFS_CFLAGS) \ $(HOSTCFLAGS) KBUILD_HOSTCXXFLAGS := -O3 $(HOST_LFS_CFLAGS) $(HOSTCXXFLAGS) KBUILD_HOSTLDFLAGS := $(HOST_LFS_LDFLAGS) $(HOSTLDFLAGS) @@ -400,19 +400,23 @@ YACC = bison AWK = awk GENKSYMS = scripts/genksyms/genksyms INSTALLKERNEL := installkernel -DEPMOD = /sbin/depmod +DEPMOD = depmod PERL = perl PYTHON = python PYTHON2 = python2 PYTHON3 = python3 CHECK = sparse +# Use the wrapper for the compiler. This wrapper scans for new +# warnings and causes the build to stop upon encountering them +CC = $(PYTHON) $(srctree)/scripts/gcc-wrapper.py $(REAL_CC) + CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ -Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF) NOSTDINC_FLAGS = CFLAGS_MODULE = AFLAGS_MODULE = -LDFLAGS_MODULE = +LDFLAGS_MODULE = --strip-debug CFLAGS_KERNEL = AFLAGS_KERNEL = LDFLAGS_vmlinux = @@ -438,7 +442,7 @@ KBUILD_AFLAGS := -D__ASSEMBLY__ KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -pipe \ -fno-strict-aliasing -fno-common -fshort-wchar \ -Werror-implicit-function-declaration \ - -Wno-format-security \ + -Werror=return-type -Wno-format-security \ -std=gnu89 KBUILD_CPPFLAGS := -D__KERNEL__ KBUILD_AFLAGS_KERNEL := @@ -633,6 +637,15 @@ ifdef CONFIG_LTO_CLANG LLVM_AR := llvm-ar LLVM_NM := llvm-nm export LLVM_AR LLVM_NM +LDFLAGS += --plugin-opt=O3 \ + -mllvm -polly \ + -mllvm -polly-run-dce \ + -mllvm -polly-run-inliner \ + -mllvm -polly-opt-fusion=max \ + -mllvm -polly-ast-use-context \ + -mllvm -polly-detect-keep-going \ + -mllvm -polly-vectorizer=stripmine \ + -mllvm -polly-invariant-load-hoisting endif # The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default @@ -686,16 +699,44 @@ KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE -KBUILD_CFLAGS += -Os +KBUILD_CFLAGS += -Os +else +ifdef CONFIG_PROFILE_ALL_BRANCHES +KBUILD_CFLAGS += -O3 $(call cc-disable-warning,maybe-uninitialized,) else KBUILD_CFLAGS += -O3 -ifeq ($(cc-name),clang) -KBUILD_CFLAGS += -O3 +endif endif ifeq ($(cc-name),clang) KBUILD_CFLAGS += -O3 -KBUILD_CFLAGS += -mcpu=cortex-a55+crypto+crc -march=armv8.2-a+crc+crypto -endif +KBUILD_AFLAGS += -O3 +KBUILD_LDFLAGS += -O3 +KBUILD_CFLAGS += -mllvm -polly \ + -mllvm -polly-run-dce \ + -mllvm -polly-run-inliner \ + -mllvm -polly-opt-fusion=max \ + -mllvm -polly-ast-use-context \ + -mllvm -polly-detect-keep-going \ + -mllvm -polly-vectorizer=stripmine \ + -mllvm -polly-invariant-load-hoisting +KBUILD_AFLAGS += -mllvm -polly \ + -mllvm -polly-run-dce \ + -mllvm -polly-run-inliner \ + -mllvm -polly-opt-fusion=max \ + -mllvm -polly-ast-use-context \ + -mllvm -polly-detect-keep-going \ + -mllvm -polly-vectorizer=stripmine \ + -mllvm -polly-invariant-load-hoisting +KBUILD_LDFLAGS += -mllvm -polly \ + -mllvm -polly-run-dce \ + -mllvm -polly-run-inliner \ + -mllvm -polly-opt-fusion=max \ + -mllvm -polly-ast-use-context \ + -mllvm -polly-detect-keep-going \ + -mllvm -polly-vectorizer=stripmine \ + -mllvm -polly-invariant-load-hoisting +KBUILD_CFLAGS += -mcpu=cortex-a55 -mtune=cortex-a55 -march=armv8.2-a+crc+crypto +KBUILD_AFLAGS += -mcpu=cortex-a55 -mtune=cortex-a55 -march=armv8.2-a+crc+crypto endif # Tell gcc to never replace conditional load with a non-conditional one @@ -732,14 +773,6 @@ stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong KBUILD_CFLAGS += $(stackp-flags-y) ifeq ($(cc-name),clang) -ifneq ($(CROSS_COMPILE),) -CLANG_TRIPLE ?= $(CROSS_COMPILE) -CLANG_TARGET := --target=$(notdir $(CLANG_TRIPLE:%-=%)) -GCC_TOOLCHAIN := $(realpath $(dir $(shell which $(LD)))/..) -endif -ifneq ($(GCC_TOOLCHAIN),) -CLANG_GCC_TC := --gcc-toolchain=$(GCC_TOOLCHAIN) -endif KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) -meabi gnu KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) @@ -754,11 +787,13 @@ KBUILD_CFLAGS += $(call cc-option, -mllvm -disable-struct-const-merge) # Quiet clang warning: comparison of unsigned expression < 0 is always false KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) + +ifdef CONFIG_MODULES # CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the # source of a reference will be _MergedGlobals and not on of the whitelisted names. # See modpost pattern 2 KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,) -KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior) +endif else # These warnings generated too much noise in a regular build. @@ -804,8 +839,11 @@ KBUILD_CFLAGS += $(call cc-option, -gsplit-dwarf, -g) else KBUILD_CFLAGS += -g endif +ifneq ($(LLVM_IAS),1) KBUILD_AFLAGS += -Wa,-gdwarf-2 endif +endif + ifdef CONFIG_DEBUG_INFO_DWARF4 KBUILD_CFLAGS += $(call cc-option, -gdwarf-4,) endif @@ -865,13 +903,10 @@ lto-clang-flags := -flto endif lto-clang-flags += -fvisibility=default $(call cc-option, -fsplit-lto-unit) -# Limit inlining across translation units to reduce binary size -LD_FLAGS_LTO_CLANG := -mllvm -import-instr-limit=5 - KBUILD_LDFLAGS += $(LD_FLAGS_LTO_CLANG) KBUILD_LDFLAGS_MODULE += $(LD_FLAGS_LTO_CLANG) -KBUILD_LDFLAGS_MODULE += -T scripts/module-lto.lds +KBUILD_LDFLAGS_MODULE += -T $(srctree)/scripts/module-lto.lds # allow disabling only clang LTO where needed DISABLE_LTO_CLANG := -fno-lto @@ -957,9 +992,6 @@ KBUILD_CFLAGS += $(call cc-option,-fmerge-constants) # Make sure -fstack-check isn't enabled (like gentoo apparently did) KBUILD_CFLAGS += $(call cc-option,-fno-stack-check,) -# conserve stack if available -KBUILD_CFLAGS += $(call cc-option,-fconserve-stack) - # disallow errors like 'EXPORT_GPL(foo);' with missing header KBUILD_CFLAGS += $(call cc-option,-Werror=implicit-int) @@ -978,12 +1010,6 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=designated-init) # change __FILE__ to the relative path from the srctree KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=) -# ensure -fcf-protection is disabled when using retpoline as it is -# incompatible with -mindirect-branch=thunk-extern -ifdef CONFIG_RETPOLINE -KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) -endif - # use the deterministic mode of AR if available KBUILD_ARFLAGS := $(call ar-option,D) @@ -1160,8 +1186,8 @@ endif autoksyms_h := $(if $(CONFIG_TRIM_UNUSED_KSYMS), include/generated/autoksyms.h) quiet_cmd_autoksyms_h = GEN $@ - cmd_autoksyms_h = mkdir -p $(dir $@); \ - $(CONFIG_SHELL) $(srctree)/scripts/gen_autoksyms.sh $@ + cmd_autoksyms_h = mkdir -p $(dir $@); $(CONFIG_SHELL) \ + $(srctree)/scripts/gen_autoksyms.sh $@ $(autoksyms_h): $(call cmd,autoksyms_h) @@ -1908,4 +1934,5 @@ FORCE: # Declare the contents of the PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) -endif + + diff --git a/arch/Kconfig b/arch/Kconfig index 8a5149f875fe..aa9190dcd132 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -360,6 +360,9 @@ config HAVE_PERF_USER_STACK_DUMP config HAVE_ARCH_JUMP_LABEL bool +config HAVE_ARCH_JUMP_LABEL_RELATIVE + bool + config HAVE_RCU_TABLE_FREE bool @@ -488,11 +491,11 @@ config LTO config ARCH_SUPPORTS_LTO_CLANG bool help - An architecture should select this option if it supports: + An architecture should select this option it supports: - compiling with clang, - compiling inline assembly with clang's integrated assembler, - - and linking with LLD. - + - and linking with either lld or GNU gold w/ LLVMgold. + config ARCH_SUPPORTS_THINLTO bool help @@ -519,8 +522,9 @@ config LTO_CLANG depends on ARCH_SUPPORTS_LTO_CLANG depends on !FTRACE_MCOUNT_RECORD || HAVE_C_RECORDMCOUNT depends on !KASAN - depends on CC_IS_CLANG && LD_IS_LLD select LTO + select THIN_ARCHIVES + select LD_DEAD_CODE_DATA_ELIMINATION help This option enables clang's Link Time Optimization (LTO), which allows the compiler to optimize the kernel globally at link time. If you @@ -528,8 +532,9 @@ config LTO_CLANG files, and the actual compilation from IR occurs at the LTO link step, which may take several minutes. - If you select this option, you must compile the kernel with clang and - LLD. + If you select this option, you must compile the kernel with clang >= + 5.0 (make CC=clang) and GNU gold from binutils >= 2.27, and have the + LLVMgold plug-in in LD_LIBRARY_PATH. endchoice @@ -638,6 +643,11 @@ config HAVE_IRQ_TIME_ACCOUNTING Archs need to ensure they use a high enough resolution clock to support irq time accounting and then call enable_sched_clock_irqtime(). +config HAVE_MOVE_PMD + bool + help + Archs that select this are able to move page tables at the PMD level. + config HAVE_ARCH_TRANSPARENT_HUGEPAGE bool @@ -943,6 +953,16 @@ config STRICT_MODULE_RWX config ARCH_HAS_PHYS_TO_DMA bool +config ARCH_HAS_REFCOUNT_FULL + bool + select ARCH_HAS_REFCOUNT + help + An architecture selects this when the optimized refcount_t + implementation it provides covers all the cases that + CONFIG_REFCOUNT_FULL covers as well, in which case it makes no + sense to even offer CONFIG_REFCOUNT_FULL as a user selectable + option. + config ARCH_HAS_REFCOUNT bool help @@ -956,7 +976,7 @@ config ARCH_HAS_REFCOUNT against bugs in reference counts. config REFCOUNT_FULL - bool "Perform full reference count validation at the expense of speed" + bool "Perform full reference count validation at the expense of speed" if !ARCH_HAS_REFCOUNT_FULL help Enabling this switches the refcounting infrastructure from a fast unchecked atomic_t implementation to a fully state checked @@ -982,6 +1002,20 @@ config HAVE_ARCH_PREL32_RELOCATIONS architectures, and don't require runtime relocation on relocatable kernels. +# Select if the architecture has support for applying RELR relocations. +config ARCH_HAS_RELR + bool + +config RELR + bool "Use RELR relocation packing" + depends on ARCH_HAS_RELR && TOOLS_SUPPORT_RELR + default y + help + Store the kernel's dynamic relocations in the RELR relocation packing + format. Requires a compatible linker (LLD supports this feature), as + well as compatible NM and OBJCOPY utilities (llvm-nm and llvm-objcopy + are compatible). + config PANIC_ON_REFCOUNT_ERROR bool "Kernel panic on refcount error detection" depends on REFCOUNT_FULL @@ -1010,3 +1044,4 @@ source "kernel/gcov/Kconfig" source "scripts/gcc-plugins/Kconfig" endmenu + diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 16e6cc22e25c..99c55f015ce8 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -91,14 +91,9 @@ libs-y += arch/arc/lib/ $(LIBGCC) boot := arch/arc/boot -#default target for make without any arguments. -KBUILD_IMAGE := $(boot)/bootpImage - -all: bootpImage -bootpImage: vmlinux - -boot_targets += uImage uImage.bin uImage.gz +boot_targets := uImage uImage.bin uImage.gz uImage.lzma +PHONY += $(boot_targets) $(boot_targets): vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h index 09ddddf71cc5..a70fef79c405 100644 --- a/arch/arc/include/asm/page.h +++ b/arch/arc/include/asm/page.h @@ -13,6 +13,7 @@ #ifndef __ASSEMBLY__ #define clear_page(paddr) memset((paddr), 0, PAGE_SIZE) +#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) #define copy_page(to, from) memcpy((to), (from), PAGE_SIZE) struct vm_area_struct; diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index 48685445002e..da243420bcb5 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -99,7 +99,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs, sizeof(sf->uc.uc_mcontext.regs.scratch)); err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t)); - return err; + return err ? -EFAULT : 0; } static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) @@ -113,7 +113,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) &(sf->uc.uc_mcontext.regs.scratch), sizeof(sf->uc.uc_mcontext.regs.scratch)); if (err) - return err; + return -EFAULT; set_current_blocked(&set); regs->bta = uregs.scratch.bta; diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index 0fed32b95923..a211e87aa6d9 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c @@ -41,15 +41,15 @@ #ifdef CONFIG_ARC_DW2_UNWIND -static void seed_unwind_frame_info(struct task_struct *tsk, - struct pt_regs *regs, - struct unwind_frame_info *frame_info) +static int +seed_unwind_frame_info(struct task_struct *tsk, struct pt_regs *regs, + struct unwind_frame_info *frame_info) { /* * synchronous unwinding (e.g. dump_stack) * - uses current values of SP and friends */ - if (tsk == NULL && regs == NULL) { + if (regs == NULL && (tsk == NULL || tsk == current)) { unsigned long fp, sp, blink, ret; frame_info->task = current; @@ -68,11 +68,15 @@ static void seed_unwind_frame_info(struct task_struct *tsk, frame_info->call_frame = 0; } else if (regs == NULL) { /* - * Asynchronous unwinding of sleeping task - * - Gets SP etc from task's pt_regs (saved bottom of kernel - * mode stack of task) + * Asynchronous unwinding of a likely sleeping task + * - first ensure it is actually sleeping + * - if so, it will be in __switch_to, kernel mode SP of task + * is safe-kept and BLINK at a well known location in there */ + if (tsk->state == TASK_RUNNING) + return -1; + frame_info->task = tsk; frame_info->regs.r27 = TSK_K_FP(tsk); @@ -106,6 +110,8 @@ static void seed_unwind_frame_info(struct task_struct *tsk, frame_info->regs.r63 = regs->ret; frame_info->call_frame = 0; } + + return 0; } #endif @@ -119,7 +125,8 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs, unsigned int address; struct unwind_frame_info frame_info; - seed_unwind_frame_info(tsk, regs, &frame_info); + if (seed_unwind_frame_info(tsk, regs, &frame_info)) + return 0; while (1) { address = UNW_PC(&frame_info); diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index e205bbbe2794..69e661f574a0 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -1090,9 +1090,9 @@ __armv4_mmu_cache_off: __armv7_mmu_cache_off: mrc p15, 0, r0, c1, c0 #ifdef CONFIG_MMU - bic r0, r0, #0x000d + bic r0, r0, #0x0005 #else - bic r0, r0, #0x000c + bic r0, r0, #0x0004 #endif mcr p15, 0, r0, c1, c0 @ turn MMU and cache off mov r12, lr diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi index d3dd6a16e70a..e321acaf35d6 100644 --- a/arch/arm/boot/dts/am33xx.dtsi +++ b/arch/arm/boot/dts/am33xx.dtsi @@ -39,6 +39,9 @@ ethernet1 = &cpsw_emac1; spi0 = &spi0; spi1 = &spi1; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; }; cpus { diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts index 768b6c5d2129..fde4c302f08e 100644 --- a/arch/arm/boot/dts/armada-385-turris-omnia.dts +++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts @@ -236,6 +236,7 @@ status = "okay"; compatible = "ethernet-phy-id0141.0DD1", "ethernet-phy-ieee802.3-c22"; reg = <1>; + marvell,reg-init = <3 18 0 0x4985>; /* irq is connected to &pcawan pin 7 */ }; diff --git a/arch/arm/boot/dts/armada-388-helios4.dts b/arch/arm/boot/dts/armada-388-helios4.dts index 705adfa8c680..a94758090fb0 100644 --- a/arch/arm/boot/dts/armada-388-helios4.dts +++ b/arch/arm/boot/dts/armada-388-helios4.dts @@ -70,6 +70,9 @@ system-leds { compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&helios_system_led_pins>; + status-led { label = "helios4:green:status"; gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; @@ -86,6 +89,9 @@ io-leds { compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&helios_io_led_pins>; + sata1-led { label = "helios4:green:ata1"; gpios = <&gpio1 17 GPIO_ACTIVE_LOW>; @@ -121,11 +127,15 @@ fan1: j10-pwm { compatible = "pwm-fan"; pwms = <&gpio1 9 40000>; /* Target freq:25 kHz */ + pinctrl-names = "default"; + pinctrl-0 = <&helios_fan1_pins>; }; fan2: j17-pwm { compatible = "pwm-fan"; pwms = <&gpio1 23 40000>; /* Target freq:25 kHz */ + pinctrl-names = "default"; + pinctrl-0 = <&helios_fan2_pins>; }; usb2_phy: usb2-phy { @@ -291,16 +301,22 @@ "mpp39", "mpp40"; marvell,function = "sd0"; }; - helios_led_pins: helios-led-pins { - marvell,pins = "mpp24", "mpp25", - "mpp49", "mpp50", + helios_system_led_pins: helios-system-led-pins { + marvell,pins = "mpp24", "mpp25"; + marvell,function = "gpio"; + }; + helios_io_led_pins: helios-io-led-pins { + marvell,pins = "mpp49", "mpp50", "mpp52", "mpp53", "mpp54"; marvell,function = "gpio"; }; - helios_fan_pins: helios-fan-pins { - marvell,pins = "mpp41", "mpp43", - "mpp48", "mpp55"; + helios_fan1_pins: helios_fan1_pins { + marvell,pins = "mpp41", "mpp43"; + marvell,function = "gpio"; + }; + helios_fan2_pins: helios_fan2_pins { + marvell,pins = "mpp48", "mpp55"; marvell,function = "gpio"; }; microsom_spi1_cs_pins: spi1-cs-pins { diff --git a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi index 3e7d093d7a9a..966d9a6c40fc 100644 --- a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi +++ b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi @@ -266,11 +266,6 @@ reg = <0x11000 0x100>; }; -&i2c1 { - compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c"; - reg = <0x11100 0x100>; -}; - &mpic { reg = <0x20a00 0x2d0>, <0x21070 0x58>; }; diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts index 22dade6393d0..d1dbe3b6ad5a 100644 --- a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts +++ b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts @@ -22,9 +22,9 @@ #size-cells = <1>; ranges; - vga_memory: framebuffer@7f000000 { + vga_memory: framebuffer@9f000000 { no-map; - reg = <0x7f000000 0x01000000>; + reg = <0x9f000000 0x01000000>; /* 16M */ }; }; diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi index 69f6b9d2e7e7..2af093759143 100644 --- a/arch/arm/boot/dts/aspeed-g4.dtsi +++ b/arch/arm/boot/dts/aspeed-g4.dtsi @@ -312,6 +312,7 @@ compatible = "aspeed,ast2400-ibt-bmc"; reg = <0xc0 0x18>; interrupts = <8>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi index f2e1015d75ab..bcd57e6c51e5 100644 --- a/arch/arm/boot/dts/aspeed-g5.dtsi +++ b/arch/arm/boot/dts/aspeed-g5.dtsi @@ -372,6 +372,7 @@ compatible = "aspeed,ast2500-ibt-bmc"; reg = <0xc0 0x18>; interrupts = <8>; + clocks = <&syscon ASPEED_CLK_GATE_LCLK>; status = "disabled"; }; }; diff --git a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi index cf0087b4c9e1..ea02a51c71e2 100644 --- a/arch/arm/boot/dts/at91-sama5d27_som1.dtsi +++ b/arch/arm/boot/dts/at91-sama5d27_som1.dtsi @@ -67,8 +67,8 @@ pinctrl-0 = <&pinctrl_macb0_default>; phy-mode = "rmii"; - ethernet-phy@0 { - reg = <0x0>; + ethernet-phy@7 { + reg = <0x7>; interrupt-parent = <&pioA>; interrupts = ; pinctrl-names = "default"; diff --git a/arch/arm/boot/dts/at91-sama5d3_xplained.dts b/arch/arm/boot/dts/at91-sama5d3_xplained.dts index 02c1d2958d78..74440dad4335 100644 --- a/arch/arm/boot/dts/at91-sama5d3_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d3_xplained.dts @@ -243,6 +243,11 @@ atmel,pins = ; /* PE9, conflicts with A9 */ }; + pinctrl_usb_default: usb_default { + atmel,pins = + ; + }; }; }; }; @@ -260,6 +265,8 @@ &pioE 3 GPIO_ACTIVE_LOW &pioE 4 GPIO_ACTIVE_LOW >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_default>; status = "okay"; }; diff --git a/arch/arm/boot/dts/at91-sama5d4_xplained.dts b/arch/arm/boot/dts/at91-sama5d4_xplained.dts index 7d554b9ab27f..e998d72d8b10 100644 --- a/arch/arm/boot/dts/at91-sama5d4_xplained.dts +++ b/arch/arm/boot/dts/at91-sama5d4_xplained.dts @@ -170,6 +170,11 @@ atmel,pins = ; }; + pinctrl_usb_default: usb_default { + atmel,pins = + ; + }; pinctrl_key_gpio: key_gpio_0 { atmel,pins = ; @@ -195,6 +200,8 @@ &pioE 11 GPIO_ACTIVE_HIGH &pioE 14 GPIO_ACTIVE_HIGH >; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usb_default>; status = "okay"; }; diff --git a/arch/arm/boot/dts/at91sam9rl.dtsi b/arch/arm/boot/dts/at91sam9rl.dtsi index ad495f5a5790..cdf016232fb7 100644 --- a/arch/arm/boot/dts/at91sam9rl.dtsi +++ b/arch/arm/boot/dts/at91sam9rl.dtsi @@ -277,23 +277,26 @@ atmel,adc-use-res = "highres"; trigger0 { - trigger-name = "timer-counter-0"; + trigger-name = "external-rising"; trigger-value = <0x1>; + trigger-external; }; + trigger1 { - trigger-name = "timer-counter-1"; - trigger-value = <0x3>; + trigger-name = "external-falling"; + trigger-value = <0x2>; + trigger-external; }; trigger2 { - trigger-name = "timer-counter-2"; - trigger-value = <0x5>; + trigger-name = "external-any"; + trigger-value = <0x3>; + trigger-external; }; trigger3 { - trigger-name = "external"; - trigger-value = <0x13>; - trigger-external; + trigger-name = "continuous"; + trigger-value = <0x6>; }; }; diff --git a/arch/arm/boot/dts/dra76x.dtsi b/arch/arm/boot/dts/dra76x.dtsi index 216e1d1a69c7..473d6721b788 100644 --- a/arch/arm/boot/dts/dra76x.dtsi +++ b/arch/arm/boot/dts/dra76x.dtsi @@ -35,8 +35,8 @@ interrupts = , ; interrupt-names = "int0", "int1"; - clocks = <&mcan_clk>, <&l3_iclk_div>; - clock-names = "cclk", "hclk"; + clocks = <&l3_iclk_div>, <&mcan_clk>; + clock-names = "hclk", "cclk"; bosch,mram-cfg = <0x0 0 0 32 0 0 1 1>; }; }; diff --git a/arch/arm/boot/dts/exynos3250-artik5.dtsi b/arch/arm/boot/dts/exynos3250-artik5.dtsi index 7c22cbf6f3d4..6e30db644c83 100644 --- a/arch/arm/boot/dts/exynos3250-artik5.dtsi +++ b/arch/arm/boot/dts/exynos3250-artik5.dtsi @@ -68,7 +68,7 @@ s2mps14_pmic@66 { compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx3>; - interrupts = <5 IRQ_TYPE_NONE>; + interrupts = <5 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s2mps14_irq>; reg = <0x66>; diff --git a/arch/arm/boot/dts/exynos3250-monk.dts b/arch/arm/boot/dts/exynos3250-monk.dts index 6ffedf4ed9f2..d343dc13ceec 100644 --- a/arch/arm/boot/dts/exynos3250-monk.dts +++ b/arch/arm/boot/dts/exynos3250-monk.dts @@ -188,7 +188,7 @@ s2mps14_pmic@66 { compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx0>; - interrupts = <7 IRQ_TYPE_NONE>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; reg = <0x66>; wakeup-source; diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts index 2a6b828c01b7..29df4cfa9165 100644 --- a/arch/arm/boot/dts/exynos3250-rinato.dts +++ b/arch/arm/boot/dts/exynos3250-rinato.dts @@ -253,7 +253,7 @@ s2mps14_pmic@66 { compatible = "samsung,s2mps14-pmic"; interrupt-parent = <&gpx0>; - interrupts = <7 IRQ_TYPE_NONE>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; reg = <0x66>; wakeup-source; diff --git a/arch/arm/boot/dts/exynos5250-spring.dts b/arch/arm/boot/dts/exynos5250-spring.dts index 3d501926c227..2355c5316484 100644 --- a/arch/arm/boot/dts/exynos5250-spring.dts +++ b/arch/arm/boot/dts/exynos5250-spring.dts @@ -108,7 +108,7 @@ compatible = "samsung,s5m8767-pmic"; reg = <0x66>; interrupt-parent = <&gpx3>; - interrupts = <2 IRQ_TYPE_NONE>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s5m8767_irq &s5m8767_dvs &s5m8767_ds>; wakeup-source; diff --git a/arch/arm/boot/dts/exynos5410-odroidxu.dts b/arch/arm/boot/dts/exynos5410-odroidxu.dts index a2046f5f998c..840a854ee838 100644 --- a/arch/arm/boot/dts/exynos5410-odroidxu.dts +++ b/arch/arm/boot/dts/exynos5410-odroidxu.dts @@ -324,6 +324,8 @@ regulator-name = "vddq_lcd"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + /* Supplies also GPK and GPJ */ + regulator-always-on; }; ldo8_reg: LDO8 { @@ -626,11 +628,11 @@ }; &usbdrd_dwc3_0 { - dr_mode = "host"; + dr_mode = "peripheral"; }; &usbdrd_dwc3_1 { - dr_mode = "peripheral"; + dr_mode = "host"; }; &usbdrd3_0 { diff --git a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi index 369a8a7f2105..481ee99aa9c9 100644 --- a/arch/arm/boot/dts/exynos5410-pinctrl.dtsi +++ b/arch/arm/boot/dts/exynos5410-pinctrl.dtsi @@ -560,6 +560,34 @@ interrupt-controller; #interrupt-cells = <2>; }; + + usb3_1_oc: usb3-1-oc { + samsung,pins = "gpk2-4", "gpk2-5"; + samsung,pin-function = ; + samsung,pin-pud = ; + samsung,pin-drv = ; + }; + + usb3_1_vbusctrl: usb3-1-vbusctrl { + samsung,pins = "gpk2-6", "gpk2-7"; + samsung,pin-function = ; + samsung,pin-pud = ; + samsung,pin-drv = ; + }; + + usb3_0_oc: usb3-0-oc { + samsung,pins = "gpk3-0", "gpk3-1"; + samsung,pin-function = ; + samsung,pin-pud = ; + samsung,pin-drv = ; + }; + + usb3_0_vbusctrl: usb3-0-vbusctrl { + samsung,pins = "gpk3-2", "gpk3-3"; + samsung,pin-function = ; + samsung,pin-pud = ; + samsung,pin-drv = ; + }; }; &pinctrl_2 { diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi index 57fc9c949e54..95b794b1ea62 100644 --- a/arch/arm/boot/dts/exynos5410.dtsi +++ b/arch/arm/boot/dts/exynos5410.dtsi @@ -392,6 +392,8 @@ &usbdrd3_0 { clocks = <&clock CLK_USBD300>; clock-names = "usbdrd30"; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_0_oc>, <&usb3_0_vbusctrl>; }; &usbdrd_phy0 { @@ -403,6 +405,8 @@ &usbdrd3_1 { clocks = <&clock CLK_USBD301>; clock-names = "usbdrd30"; + pinctrl-names = "default"; + pinctrl-0 = <&usb3_1_oc>, <&usb3_1_vbusctrl>; }; &usbdrd_dwc3_1 { diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index a370857beac0..fbaca74cbaea 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -84,7 +84,7 @@ reg = <0x66>; interrupt-parent = <&gpx3>; - interrupts = <2 IRQ_TYPE_EDGE_FALLING>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s2mps11_irq>; diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi index d476ba0f07b6..ba7187a74be3 100644 --- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi +++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi @@ -136,7 +136,7 @@ samsung,s2mps11-acokb-ground; interrupt-parent = <&gpx0>; - interrupts = <4 IRQ_TYPE_EDGE_FALLING>; + interrupts = <4 IRQ_TYPE_LEVEL_LOW>; pinctrl-names = "default"; pinctrl-0 = <&s2mps11_irq>; diff --git a/arch/arm/boot/dts/imx50-evk.dts b/arch/arm/boot/dts/imx50-evk.dts index a25da415cb02..907339bc81e5 100644 --- a/arch/arm/boot/dts/imx50-evk.dts +++ b/arch/arm/boot/dts/imx50-evk.dts @@ -59,7 +59,7 @@ MX50_PAD_CSPI_MISO__CSPI_MISO 0x00 MX50_PAD_CSPI_MOSI__CSPI_MOSI 0x00 MX50_PAD_CSPI_SS0__GPIO4_11 0xc4 - MX50_PAD_ECSPI1_MOSI__CSPI_SS1 0xf4 + MX50_PAD_ECSPI1_MOSI__GPIO4_13 0x84 >; }; diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi index b8044681006c..2df4694c0d3b 100644 --- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi +++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi @@ -278,7 +278,7 @@ /* VDD_AUD_1P8: Audio codec */ reg_aud_1p8v: ldo3 { - regulator-name = "vdd1p8"; + regulator-name = "vdd1p8a"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-boot-on; diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi index fe4e89d773f5..9499d113b139 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi @@ -423,6 +423,7 @@ pinctrl-0 = <&pinctrl_usdhc2>; cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + vmmc-supply = <&vdd_sd1_reg>; status = "disabled"; }; @@ -432,5 +433,6 @@ &pinctrl_usdhc3_cdwp>; cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; + vmmc-supply = <&vdd_sd0_reg>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi index 4f27861bbb32..4cc9858f7ff8 100644 --- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi +++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi @@ -97,7 +97,7 @@ &fec { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_enet>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; status = "okay"; }; diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi index 9ad3df11db0d..abef034987a2 100644 --- a/arch/arm/boot/dts/lpc32xx.dtsi +++ b/arch/arm/boot/dts/lpc32xx.dtsi @@ -323,9 +323,6 @@ clocks = <&xtal_32k>, <&xtal>; clock-names = "xtal_32k", "xtal"; - - assigned-clocks = <&clk LPC32XX_CLK_HCLK_PLL>; - assigned-clock-rates = <208000000>; }; }; diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index 4043ecb38016..0c8fcfb292bf 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -23,6 +23,9 @@ i2c0 = &i2c1; i2c1 = &i2c2; i2c2 = &i2c3; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts index 19d02df8d8a5..70fd28120c27 100644 --- a/arch/arm/boot/dts/omap4-panda-es.dts +++ b/arch/arm/boot/dts/omap4-panda-es.dts @@ -49,7 +49,7 @@ button_pins: pinmux_button_pins { pinctrl-single,pins = < - OMAP4_IOPAD(0x11b, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */ + OMAP4_IOPAD(0x0fc, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */ >; }; }; diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 8f907c235b02..046e77024567 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -25,6 +25,11 @@ i2c1 = &i2c2; i2c2 = &i2c3; i2c3 = &i2c4; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; + mmc3 = &mmc4; + mmc4 = &mmc5; serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; diff --git a/arch/arm/boot/dts/omap443x.dtsi b/arch/arm/boot/dts/omap443x.dtsi index 86b9caf461df..6e320efd9fc1 100644 --- a/arch/arm/boot/dts/omap443x.dtsi +++ b/arch/arm/boot/dts/omap443x.dtsi @@ -33,10 +33,12 @@ }; ocp { + /* 4430 has only gpio_86 tshut and no talert interrupt */ bandgap: bandgap@4a002260 { reg = <0x4a002260 0x4 0x4a00232C 0x4>; compatible = "ti,omap4430-bandgap"; + gpios = <&gpio3 22 GPIO_ACTIVE_HIGH>; #thermal-sensor-cells = <0>; }; diff --git a/arch/arm/boot/dts/omap44xx-clocks.dtsi b/arch/arm/boot/dts/omap44xx-clocks.dtsi index 279ff2f419df..c654588f9e8c 100644 --- a/arch/arm/boot/dts/omap44xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap44xx-clocks.dtsi @@ -773,14 +773,6 @@ ti,max-div = <2>; }; - sha2md5_fck: sha2md5_fck@15c8 { - #clock-cells = <0>; - compatible = "ti,gate-clock"; - clocks = <&l3_div_ck>; - ti,bit-shift = <1>; - reg = <0x15c8>; - }; - usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 { #clock-cells = <0>; compatible = "ti,gate-clock"; diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index 3c0bafe0fb05..cf66c374de4f 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -26,6 +26,11 @@ i2c2 = &i2c3; i2c3 = &i2c4; i2c4 = &i2c5; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; + mmc3 = &mmc4; + mmc4 = &mmc5; serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; diff --git a/arch/arm/boot/dts/picoxcell-pc3x2.dtsi b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi index a1266cf8776c..8362c6a3bcd3 100644 --- a/arch/arm/boot/dts/picoxcell-pc3x2.dtsi +++ b/arch/arm/boot/dts/picoxcell-pc3x2.dtsi @@ -54,18 +54,21 @@ emac: gem@30000 { compatible = "cadence,gem"; reg = <0x30000 0x10000>; + interrupt-parent = <&vic0>; interrupts = <31>; }; dmac1: dmac@40000 { compatible = "snps,dw-dmac"; reg = <0x40000 0x10000>; + interrupt-parent = <&vic0>; interrupts = <25>; }; dmac2: dmac@50000 { compatible = "snps,dw-dmac"; reg = <0x50000 0x10000>; + interrupt-parent = <&vic0>; interrupts = <26>; }; @@ -243,6 +246,7 @@ axi2pico@c0000000 { compatible = "picochip,axi2pico-pc3x2"; reg = <0xc0000000 0x10000>; + interrupt-parent = <&vic0>; interrupts = <13 14 15 16 17 18 19 20 21>; }; }; diff --git a/arch/arm/boot/dts/sama5d2.dtsi b/arch/arm/boot/dts/sama5d2.dtsi index b405992eb601..d856c16d0015 100644 --- a/arch/arm/boot/dts/sama5d2.dtsi +++ b/arch/arm/boot/dts/sama5d2.dtsi @@ -1247,6 +1247,7 @@ clocks = <&securam_clk>; #address-cells = <1>; #size-cells = <1>; + no-memory-wc; ranges = <0 0xf8044000 0x1420>; }; @@ -1297,7 +1298,7 @@ can0: can@f8054000 { compatible = "bosch,m_can"; - reg = <0xf8054000 0x4000>, <0x210000 0x4000>; + reg = <0xf8054000 0x4000>, <0x210000 0x1c00>; reg-names = "m_can", "message_ram"; interrupts = <56 IRQ_TYPE_LEVEL_HIGH 7>, <64 IRQ_TYPE_LEVEL_HIGH 7>; @@ -1490,7 +1491,7 @@ can1: can@fc050000 { compatible = "bosch,m_can"; - reg = <0xfc050000 0x4000>, <0x210000 0x4000>; + reg = <0xfc050000 0x4000>, <0x210000 0x3800>; reg-names = "m_can", "message_ram"; interrupts = <57 IRQ_TYPE_LEVEL_HIGH 7>, <65 IRQ_TYPE_LEVEL_HIGH 7>; @@ -1500,7 +1501,7 @@ assigned-clocks = <&can1_gclk>; assigned-clock-parents = <&utmi>; assigned-clock-rates = <40000000>; - bosch,mram-cfg = <0x1100 0 0 64 0 0 32 32>; + bosch,mram-cfg = <0x1c00 0 0 64 0 0 32 32>; status = "disabled"; }; diff --git a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts b/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts index f250b20af493..9be1c4a3d95f 100644 --- a/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts +++ b/arch/arm/boot/dts/sun8i-a83t-bananapi-m3.dts @@ -131,7 +131,7 @@ pinctrl-0 = <&emac_rgmii_pins>; phy-supply = <®_sw>; phy-handle = <&rgmii_phy>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; allwinner,rx-delay-ps = <700>; allwinner,tx-delay-ps = <700>; status = "okay"; diff --git a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts b/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts index 7e74ba83f809..75396993195d 100644 --- a/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts +++ b/arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts @@ -168,7 +168,7 @@ pinctrl-0 = <&emac_rgmii_pins>; phy-supply = <®_dldo4>; phy-handle = <&rgmii_phy>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts index 71fb73208939..babf4cf1b2f6 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc-plus.dts @@ -53,11 +53,6 @@ }; }; -&emac { - /* LEDs changed to active high on the plus */ - /delete-property/ allwinner,leds-active-low; -}; - &mmc1 { vmmc-supply = <®_vcc3v3>; bus-width = <4>; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts index 6dbf7b2e0c13..b6ca45d18e51 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus2e.dts @@ -67,7 +67,7 @@ pinctrl-0 = <&emac_rgmii_pins>; phy-supply = <®_gmac_3v3>; phy-handle = <&ext_rgmii_phy>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts index b2a773a718e1..5e5223a48ac7 100644 --- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts +++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts @@ -121,7 +121,7 @@ pinctrl-names = "default"; pinctrl-0 = <&gmac_rgmii_pins>; phy-handle = <&phy1>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-supply = <®_dc1sw>; status = "okay"; }; diff --git a/arch/arm/boot/dts/sun8i-v3s.dtsi b/arch/arm/boot/dts/sun8i-v3s.dtsi index 92fcb756a08a..97cac6d63692 100644 --- a/arch/arm/boot/dts/sun8i-v3s.dtsi +++ b/arch/arm/boot/dts/sun8i-v3s.dtsi @@ -419,7 +419,7 @@ gic: interrupt-controller@1c81000 { compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic"; reg = <0x01c81000 0x1000>, - <0x01c82000 0x1000>, + <0x01c82000 0x2000>, <0x01c84000 0x2000>, <0x01c86000 0x2000>; interrupt-controller; diff --git a/arch/arm/configs/vendor/msm8937-perf_defconfig b/arch/arm/configs/vendor/msm8937-perf_defconfig new file mode 100644 index 000000000000..437a96d260be --- /dev/null +++ b/arch/arm/configs/vendor/msm8937-perf_defconfig @@ -0,0 +1,663 @@ +CONFIG_LOCALVERSION="-perf" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_SCHED_CORE_CTL=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_FHANDLE is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_QM215=y +CONFIG_ARCH_MSM8917=y +# CONFIG_VDSO is not set +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_HIGHMEM=y +CONFIG_SECCOMP=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_ENERGY_MODEL=y +CONFIG_MSM_TZ_LOG=y +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_NEON=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_AES_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_ARCH_MMAP_RND_BITS=16 +CONFIG_PANIC_ON_REFCOUNT_ERROR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_IOSCHED_BFQ=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_INTERFACE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPGRE_DEMUX=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_OWNER=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_BPF=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_DNS_RESOLVER=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_BT=y +# CONFIG_BT_BREDR is not set +# CONFIG_BT_LE is not set +CONFIG_MSM_BT_POWER=y +CONFIG_BTFM_SLIM_WCN3990=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_CRDA_SUPPORT is not set +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y +CONFIG_FPR_FPC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_SCSI_UFS_CRYPTO_QTI=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y +CONFIG_DM_BOW=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +# CONFIG_NET_VENDOR_AMAZON is not set +CONFIG_MSM_RMNET_BAM=y +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPTP=y +CONFIG_PPPOL2TP=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_RTL8152=y +CONFIG_USB_USBNET=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM_HS=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_MSM_SMD_PKT=y +CONFIG_DIAG_CHAR=y +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_PINCTRL_MSM8937=y +CONFIG_PINCTRL_MSM8917=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_QPNP_SMB5=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_SMB1355_SLAVE_CHARGER=y +CONFIG_QPNP_QG=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_MFD_I2C_PMIC=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_PROXY_CONSUMER=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_QPNP_LCDB=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_MSM_VIDC_3X_GOVERNORS=y +CONFIG_MSM_VIDC_3X_V4L2=y +CONFIG_MSM_CAMERA=y +CONFIG_MSMB_CAMERA=y +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF_V2=y +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_FB=y +CONFIG_FB_MSM=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_SONY=y +CONFIG_USB_HIDDEV=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CI13XXX_MSM=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_RMNET_BAM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_TYPEC=y +CONFIG_MMC=y +# CONFIG_PWRSEQ_EMMC is not set +# CONFIG_PWRSEQ_SIMPLE is not set +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_IPC_LOGGING=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_CQHCI_CRYPTO=y +CONFIG_MMC_CQHCI_CRYPTO_QTI=y +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_QPNP_FLASH_V2=y +CONFIG_LEDS_QPNP_VIBRATOR_LDO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_EDAC=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_ION_POOL_AUTO_REFILL=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y +CONFIG_RNDIS_IPA=y +CONFIG_USB_BAM=y +CONFIG_MDSS_PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SDM_GCC_429W=y +CONFIG_SDM_DEBUGCC_429W=y +CONFIG_CLOCK_CPU_SDM=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_MSM_RPM_SMD=y +CONFIG_QCOM_CPUSS_DUMP=y +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_QCOM_DCC_V2=y +CONFIG_MSM_CORE_HANG_DETECT=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_GLINK=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_QTEE_SHM_BRIDGE=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_QTI_CRYPTO_COMMON=y +CONFIG_QTI_CRYPTO_TZ=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_IIO=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_QCOM_SHOW_RESUME_IRQ=y +CONFIG_QCOM_MPM=y +CONFIG_RAS=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y +CONFIG_QCOM_QFPROM=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SENSORS_SSC=y +CONFIG_QCOM_KGSL=y +CONFIG_LEGACY_ENERGY_MODEL_DT=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_PAGESPAN=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y +CONFIG_STATIC_USERMODEHELPER_PATH="" +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZ4=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=2048 +CONFIG_DEBUG_FS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_WQ_WATCHDOG=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_IPC_LOGGING=y +# CONFIG_FTRACE is not set +CONFIG_LKDTM=m +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_REMOTE_ETM=y diff --git a/arch/arm/configs/vendor/msm8937_32go-perf_defconfig b/arch/arm/configs/vendor/msm8937_32go-perf_defconfig index b5070161ecbc..0836d7e42dc2 100644 --- a/arch/arm/configs/vendor/msm8937_32go-perf_defconfig +++ b/arch/arm/configs/vendor/msm8937_32go-perf_defconfig @@ -280,6 +280,7 @@ CONFIG_SCSI_UFS_CRYPTO_QTI=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y +CONFIG_DM_DEFAULT_KEY=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y @@ -290,6 +291,7 @@ CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y # CONFIG_NET_VENDOR_AMAZON is not set +CONFIG_MSM_RMNET_BAM=y # CONFIG_NET_VENDOR_EZCHIP is not set # CONFIG_NET_VENDOR_HISILICON is not set # CONFIG_NET_VENDOR_MARVELL is not set @@ -421,6 +423,8 @@ CONFIG_OV12830=y CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y CONFIG_MSMB_JPEG=y CONFIG_MSM_FD=y +CONFIG_RADIO_IRIS=y +CONFIG_RADIO_IRIS_TRANSPORT=y CONFIG_FB=y CONFIG_FB_MSM=y CONFIG_FB_MSM_MDSS=y @@ -520,6 +524,7 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_IPA=y CONFIG_RMNET_IPA=y CONFIG_RNDIS_IPA=y +CONFIG_USB_BAM=y CONFIG_MDSS_PLL=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_SDM_GCC_429W=y @@ -548,8 +553,10 @@ CONFIG_QCOM_SMP2P=y CONFIG_QCOM_SMSM=y CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_TZ_SMMU=y CONFIG_MSM_SUBSYSTEM_RESTART=y CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_QCOM_DCC_V2=y @@ -566,6 +573,7 @@ CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_PERFORMANCE=y CONFIG_QTI_CRYPTO_COMMON=y CONFIG_QTI_CRYPTO_TZ=y +CONFIG_MSM_BAM_DMUX=y CONFIG_WCNSS_CORE=y CONFIG_WCNSS_CORE_PRONTO=y CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y diff --git a/arch/arm/configs/vendor/msm8937_32go_defconfig b/arch/arm/configs/vendor/msm8937_32go_defconfig index 433e6853d1be..4a8b685369bb 100644 --- a/arch/arm/configs/vendor/msm8937_32go_defconfig +++ b/arch/arm/configs/vendor/msm8937_32go_defconfig @@ -285,6 +285,7 @@ CONFIG_SCSI_UFS_CRYPTO_QTI=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y +CONFIG_DM_DEFAULT_KEY=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y @@ -295,6 +296,7 @@ CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y # CONFIG_NET_VENDOR_AMAZON is not set +CONFIG_MSM_RMNET_BAM=y # CONFIG_NET_VENDOR_EZCHIP is not set # CONFIG_NET_VENDOR_HISILICON is not set # CONFIG_NET_VENDOR_MARVELL is not set @@ -427,6 +429,8 @@ CONFIG_OV12830=y CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y CONFIG_MSMB_JPEG=y CONFIG_MSM_FD=y +CONFIG_RADIO_IRIS=y +CONFIG_RADIO_IRIS_TRANSPORT=y CONFIG_FB=y CONFIG_FB_VIRTUAL=y CONFIG_FB_MSM=y @@ -528,6 +532,7 @@ CONFIG_SPS_SUPPORT_NDP_BAM=y CONFIG_IPA=y CONFIG_RMNET_IPA=y CONFIG_RNDIS_IPA=y +CONFIG_USB_BAM=y CONFIG_MDSS_PLL=y CONFIG_QCOM_CLK_SMD_RPM=y CONFIG_SDM_GCC_429W=y @@ -558,8 +563,10 @@ CONFIG_QCOM_SMP2P=y CONFIG_QCOM_SMSM=y CONFIG_MSM_PIL_MSS_QDSP6V5=y CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_TZ_SMMU=y CONFIG_MSM_SUBSYSTEM_RESTART=y CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_QCOM_DCC_V2=y @@ -576,6 +583,7 @@ CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_PERFORMANCE=y CONFIG_QTI_CRYPTO_COMMON=y CONFIG_QTI_CRYPTO_TZ=y +CONFIG_MSM_BAM_DMUX=y CONFIG_WCNSS_CORE=y CONFIG_WCNSS_CORE_PRONTO=y CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y diff --git a/arch/arm/configs/vendor/msm8937_defconfig b/arch/arm/configs/vendor/msm8937_defconfig new file mode 100644 index 000000000000..4810de5044dd --- /dev/null +++ b/arch/arm/configs/vendor/msm8937_defconfig @@ -0,0 +1,719 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_BLK_CGROUP=y +CONFIG_DEBUG_BLK_CGROUP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_DEBUG=y +CONFIG_SCHED_CORE_CTL=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_FHANDLE is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_QM215=y +CONFIG_ARCH_MSM8917=y +# CONFIG_VDSO is not set +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_ARM_PSCI=y +CONFIG_HIGHMEM=y +CONFIG_SECCOMP=y +CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y +CONFIG_CPU_IDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_DEBUG=y +CONFIG_ENERGY_MODEL=y +CONFIG_MSM_TZ_LOG=y +CONFIG_ARM_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM_NEON=y +CONFIG_CRYPTO_SHA2_ARM_CE=y +CONFIG_CRYPTO_AES_ARM_BS=y +CONFIG_CRYPTO_AES_ARM_CE=y +CONFIG_CRYPTO_GHASH_ARM_CE=y +CONFIG_OPROFILE=m +CONFIG_KPROBES=y +CONFIG_ARCH_MMAP_RND_BITS=16 +CONFIG_PANIC_ON_REFCOUNT_ERROR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_IOSCHED_BFQ=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_INTERFACE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPGRE_DEMUX=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_OWNER=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_BPF=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_DNS_RESOLVER=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_BT=y +# CONFIG_BT_BREDR is not set +# CONFIG_BT_LE is not set +CONFIG_MSM_BT_POWER=y +CONFIG_BTFM_SLIM_WCN3990=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_CRDA_SUPPORT is not set +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y +CONFIG_FPR_FPC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFSHCD_CMD_LOGGING=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_SCSI_UFS_CRYPTO_QTI=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y +CONFIG_DM_BOW=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +# CONFIG_NET_VENDOR_AMAZON is not set +CONFIG_MSM_RMNET_BAM=y +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPTP=y +CONFIG_PPPOL2TP=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_RTL8152=y +CONFIG_USB_USBNET=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_MSM_HS=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_MSM_SMD_PKT=y +CONFIG_DIAG_CHAR=y +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_PINCTRL_MSM8937=y +CONFIG_PINCTRL_MSM8917=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QPNP_SMB5=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_SMB1355_SLAVE_CHARGER=y +CONFIG_QPNP_QG=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_MFD_I2C_PMIC=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_PROXY_CONSUMER=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_QPNP_LCDB=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_MSM_VIDC_3X_GOVERNORS=y +CONFIG_MSM_VIDC_3X_V4L2=y +CONFIG_MSM_CAMERA=y +CONFIG_MSM_CAMERA_DEBUG=y +CONFIG_MSMB_CAMERA=y +CONFIG_MSMB_CAMERA_DEBUG=y +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF_V2=y +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_FB=y +CONFIG_FB_VIRTUAL=y +CONFIG_FB_MSM=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_SONY=y +CONFIG_USB_HIDDEV=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CI13XXX_MSM=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_RMNET_BAM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_TYPEC=y +CONFIG_MMC=y +# CONFIG_PWRSEQ_EMMC is not set +# CONFIG_PWRSEQ_SIMPLE is not set +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_IPC_LOGGING=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_CQHCI_CRYPTO=y +CONFIG_MMC_CQHCI_CRYPTO_QTI=y +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_QPNP_FLASH_V2=y +CONFIG_LEDS_QPNP_VIBRATOR_LDO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_EDAC=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_ION_POOL_AUTO_REFILL=y +CONFIG_MSM_EXT_DISPLAY=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y +CONFIG_RNDIS_IPA=y +CONFIG_USB_BAM=y +CONFIG_MDSS_PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SDM_GCC_429W=y +CONFIG_SDM_DEBUGCC_429W=y +CONFIG_CLOCK_CPU_SDM=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_TESTS=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_MSM_RPM_SMD=y +CONFIG_QCOM_CPUSS_DUMP=y +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_QCOM_DCC_V2=y +CONFIG_MSM_CORE_HANG_DETECT=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_GLINK=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_QTEE_SHM_BRIDGE=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_QTI_CRYPTO_COMMON=y +CONFIG_QTI_CRYPTO_TZ=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_IIO=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_QCOM_SHOW_RESUME_IRQ=y +CONFIG_QCOM_MPM=y +CONFIG_RAS=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y +CONFIG_QCOM_QFPROM=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SENSORS_SSC=y +CONFIG_QCOM_KGSL=y +CONFIG_LEGACY_ENERGY_MODEL_DT=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_CHECK_FS=y +CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_SDCARD_FS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_PAGESPAN=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y +CONFIG_STATIC_USERMODEHELPER_PATH="" +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_LZ4=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y +CONFIG_DEBUG_MODULE_LOAD_INFO=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=2048 +CONFIG_PAGE_OWNER=y +CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_SLUB_DEBUG_PANIC_ON=y +CONFIG_DEBUG_PANIC_ON_OOM=y +CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_PAGE_POISONING=y +CONFIG_PAGE_POISONING_ENABLE_DEFAULT=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_WORK=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_WQ_WATCHDOG=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_SCHED_BUG=y +CONFIG_PANIC_ON_RT_THROTTLING=y +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_NOTIFIERS=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_IPC_LOGGING=y +CONFIG_QCOM_RTB=y +CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_PREEMPTIRQ_EVENTS=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_PREEMPT_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LKDTM=y +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_MEMTEST=y +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_PANIC_ON_DATA_CORRUPTION=y +CONFIG_DEBUG_USER=y +CONFIG_FORCE_PAGES=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_REMOTE_ETM=y diff --git a/arch/arm/include/asm/kexec-internal.h b/arch/arm/include/asm/kexec-internal.h new file mode 100644 index 000000000000..ecc2322db7aa --- /dev/null +++ b/arch/arm/include/asm/kexec-internal.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ARM_KEXEC_INTERNAL_H +#define _ARM_KEXEC_INTERNAL_H + +struct kexec_relocate_data { + unsigned long kexec_start_address; + unsigned long kexec_indirection_page; + unsigned long kexec_mach_type; + unsigned long kexec_r2; +}; + +#endif diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h index 82290f212d8e..e1eb662e0f9e 100644 --- a/arch/arm/include/asm/kprobes.h +++ b/arch/arm/include/asm/kprobes.h @@ -52,20 +52,20 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, void *data); /* optinsn template addresses */ -extern __visible kprobe_opcode_t optprobe_template_entry; -extern __visible kprobe_opcode_t optprobe_template_val; -extern __visible kprobe_opcode_t optprobe_template_call; -extern __visible kprobe_opcode_t optprobe_template_end; -extern __visible kprobe_opcode_t optprobe_template_sub_sp; -extern __visible kprobe_opcode_t optprobe_template_add_sp; -extern __visible kprobe_opcode_t optprobe_template_restore_begin; -extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn; -extern __visible kprobe_opcode_t optprobe_template_restore_end; +extern __visible kprobe_opcode_t optprobe_template_entry[]; +extern __visible kprobe_opcode_t optprobe_template_val[]; +extern __visible kprobe_opcode_t optprobe_template_call[]; +extern __visible kprobe_opcode_t optprobe_template_end[]; +extern __visible kprobe_opcode_t optprobe_template_sub_sp[]; +extern __visible kprobe_opcode_t optprobe_template_add_sp[]; +extern __visible kprobe_opcode_t optprobe_template_restore_begin[]; +extern __visible kprobe_opcode_t optprobe_template_restore_orig_insn[]; +extern __visible kprobe_opcode_t optprobe_template_restore_end[]; #define MAX_OPTIMIZED_LENGTH 4 #define MAX_OPTINSN_SIZE \ - ((unsigned long)&optprobe_template_end - \ - (unsigned long)&optprobe_template_entry) + ((unsigned long)optprobe_template_end - \ + (unsigned long)optprobe_template_entry) #define RELATIVEJUMP_SIZE 4 struct arch_optimized_insn { diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 3968d6c22455..ae85f67a6352 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -18,6 +18,7 @@ #include #endif #include +#include #include #include #include @@ -189,5 +190,9 @@ int main(void) DEFINE(MPU_RGN_PRBAR, offsetof(struct mpu_rgn, prbar)); DEFINE(MPU_RGN_PRLAR, offsetof(struct mpu_rgn, prlar)); #endif + DEFINE(KEXEC_START_ADDR, offsetof(struct kexec_relocate_data, kexec_start_address)); + DEFINE(KEXEC_INDIR_PAGE, offsetof(struct kexec_relocate_data, kexec_indirection_page)); + DEFINE(KEXEC_MACH_TYPE, offsetof(struct kexec_relocate_data, kexec_mach_type)); + DEFINE(KEXEC_R2, offsetof(struct kexec_relocate_data, kexec_r2)); return 0; } diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 6b1148cafffd..90add5ded3f1 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -674,12 +674,8 @@ ARM_BE8(rev16 ip, ip) ldrcc r7, [r4], #4 @ use branch for delay slot bcc 1b bx lr -#else -#ifdef CONFIG_CPU_ENDIAN_BE8 - moveq r0, #0x00004000 @ set bit 22, mov to mvn instruction #else moveq r0, #0x400000 @ set bit 22, mov to mvn instruction -#endif b 2f 1: ldr ip, [r7, r3] #ifdef CONFIG_CPU_ENDIAN_BE8 @@ -688,7 +684,7 @@ ARM_BE8(rev16 ip, ip) tst ip, #0x000f0000 @ check the rotation field orrne ip, ip, r6, lsl #24 @ mask in offset bits 31-24 biceq ip, ip, #0x00004000 @ clear bit 22 - orreq ip, ip, r0 @ mask in offset bits 7-0 + orreq ip, ip, r0, ror #8 @ mask in offset bits 7-0 #else bic ip, ip, #0x000000ff tst ip, #0xf00 @ check the rotation field diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index 76300f3813e8..734adeb42df8 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -24,11 +25,6 @@ extern void relocate_new_kernel(void); extern const unsigned int relocate_new_kernel_size; -extern unsigned long kexec_start_address; -extern unsigned long kexec_indirection_page; -extern unsigned long kexec_mach_type; -extern unsigned long kexec_boot_atags; - static atomic_t waiting_for_crash_ipi; /* @@ -161,6 +157,7 @@ void (*kexec_reinit)(void); void machine_kexec(struct kimage *image) { unsigned long page_list, reboot_entry_phys; + struct kexec_relocate_data *data; void (*reboot_entry)(void); void *reboot_code_buffer; @@ -176,18 +173,17 @@ void machine_kexec(struct kimage *image) reboot_code_buffer = page_address(image->control_code_page); - /* Prepare parameters for reboot_code_buffer*/ - set_kernel_text_rw(); - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->arch.kernel_r2; - /* copy our kernel relocation code to the control code page */ reboot_entry = fncpy(reboot_code_buffer, &relocate_new_kernel, relocate_new_kernel_size); + data = reboot_code_buffer + relocate_new_kernel_size; + data->kexec_start_address = image->start; + data->kexec_indirection_page = page_list; + data->kexec_mach_type = machine_arch_type; + data->kexec_r2 = image->arch.kernel_r2; + /* get the identity mapping physical address for the reboot code */ reboot_entry_phys = virt_to_idmap(reboot_entry); diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index 7eaa2ae7aff5..5e15b5912cb0 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -5,14 +5,16 @@ #include #include +#include #include .align 3 /* not needed for this code, but keeps fncpy() happy */ ENTRY(relocate_new_kernel) - ldr r0,kexec_indirection_page - ldr r1,kexec_start_address + adr r7, relocate_new_kernel_end + ldr r0, [r7, #KEXEC_INDIR_PAGE] + ldr r1, [r7, #KEXEC_START_ADDR] /* * If there is no indirection page (we are doing crashdumps) @@ -57,34 +59,16 @@ ENTRY(relocate_new_kernel) 2: /* Jump to relocated kernel */ - mov lr,r1 - mov r0,#0 - ldr r1,kexec_mach_type - ldr r2,kexec_boot_atags - ARM( ret lr ) - THUMB( bx lr ) - - .align - - .globl kexec_start_address -kexec_start_address: - .long 0x0 - - .globl kexec_indirection_page -kexec_indirection_page: - .long 0x0 - - .globl kexec_mach_type -kexec_mach_type: - .long 0x0 - - /* phy addr of the atags for the new kernel */ - .globl kexec_boot_atags -kexec_boot_atags: - .long 0x0 + mov lr, r1 + mov r0, #0 + ldr r1, [r7, #KEXEC_MACH_TYPE] + ldr r2, [r7, #KEXEC_R2] + ARM( ret lr ) + THUMB( bx lr ) ENDPROC(relocate_new_kernel) + .align 3 relocate_new_kernel_end: .globl relocate_new_kernel_size diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index b908382b69ff..1c01358b9b6d 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -697,18 +697,20 @@ struct page *get_signal_page(void) addr = page_address(page); + /* Poison the entire page */ + memset32(addr, __opcode_to_mem_arm(0xe7fddef1), + PAGE_SIZE / sizeof(u32)); + /* Give the signal return code some randomness */ offset = 0x200 + (get_random_int() & 0x7fc); signal_return_offset = offset; - /* - * Copy signal return handlers into the vector page, and - * set sigreturn to be a pointer to these. - */ + /* Copy signal return handlers into the page */ memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes)); - ptr = (unsigned long)addr + offset; - flush_icache_range(ptr, ptr + sizeof(sigreturn_codes)); + /* Flush out all instructions in this page */ + ptr = (unsigned long)addr; + flush_icache_range(ptr, ptr + PAGE_SIZE); return page; } diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c index 0b2fd7e2e9b4..90b1e9be430e 100644 --- a/arch/arm/mach-footbridge/cats-pci.c +++ b/arch/arm/mach-footbridge/cats-pci.c @@ -15,14 +15,14 @@ #include /* cats host-specific stuff */ -static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; +static int irqmap_cats[] = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin) { return 0; } -static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { if (dev->irq >= 255) return -1; /* not a valid interrupt. */ diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c index 16d71bac0061..2d1f822700a1 100644 --- a/arch/arm/mach-footbridge/dc21285.c +++ b/arch/arm/mach-footbridge/dc21285.c @@ -69,15 +69,15 @@ dc21285_read_config(struct pci_bus *bus, unsigned int devfn, int where, if (addr) switch (size) { case 1: - asm("ldrb %0, [%1, %2]" + asm volatile("ldrb %0, [%1, %2]" : "=r" (v) : "r" (addr), "r" (where) : "cc"); break; case 2: - asm("ldrh %0, [%1, %2]" + asm volatile("ldrh %0, [%1, %2]" : "=r" (v) : "r" (addr), "r" (where) : "cc"); break; case 4: - asm("ldr %0, [%1, %2]" + asm volatile("ldr %0, [%1, %2]" : "=r" (v) : "r" (addr), "r" (where) : "cc"); break; } @@ -103,17 +103,17 @@ dc21285_write_config(struct pci_bus *bus, unsigned int devfn, int where, if (addr) switch (size) { case 1: - asm("strb %0, [%1, %2]" + asm volatile("strb %0, [%1, %2]" : : "r" (value), "r" (addr), "r" (where) : "cc"); break; case 2: - asm("strh %0, [%1, %2]" + asm volatile("strh %0, [%1, %2]" : : "r" (value), "r" (addr), "r" (where) : "cc"); break; case 4: - asm("str %0, [%1, %2]" + asm volatile("str %0, [%1, %2]" : : "r" (value), "r" (addr), "r" (where) : "cc"); break; diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c index 6f28aaa9ca79..c3f280d08fa7 100644 --- a/arch/arm/mach-footbridge/ebsa285-pci.c +++ b/arch/arm/mach-footbridge/ebsa285-pci.c @@ -14,9 +14,9 @@ #include #include -static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; +static int irqmap_ebsa285[] = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; -static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { if (dev->vendor == PCI_VENDOR_ID_CONTAQ && dev->device == PCI_DEVICE_ID_CONTAQ_82C693) diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c index 9473aa0305e5..e8304392074b 100644 --- a/arch/arm/mach-footbridge/netwinder-pci.c +++ b/arch/arm/mach-footbridge/netwinder-pci.c @@ -18,7 +18,7 @@ * We now use the slot ID instead of the device identifiers to select * which interrupt is routed where. */ -static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { switch (slot) { case 0: /* host bridge */ diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c index 4391e433a4b2..9d19aa98a663 100644 --- a/arch/arm/mach-footbridge/personal-pci.c +++ b/arch/arm/mach-footbridge/personal-pci.c @@ -14,13 +14,12 @@ #include #include -static int irqmap_personal_server[] __initdata = { +static int irqmap_personal_server[] = { IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0, IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI }; -static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot, - u8 pin) +static int personal_server_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { unsigned char line; diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S index 7d84b617af48..99d2e296082c 100644 --- a/arch/arm/mach-imx/suspend-imx6.S +++ b/arch/arm/mach-imx/suspend-imx6.S @@ -73,6 +73,7 @@ #define MX6Q_CCM_CCR 0x0 .align 3 + .arm .macro sync_l2_cache diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c index 84613abf35a3..79ff5b953431 100644 --- a/arch/arm/mach-keystone/keystone.c +++ b/arch/arm/mach-keystone/keystone.c @@ -65,7 +65,7 @@ static void __init keystone_init(void) static long long __init keystone_pv_fixup(void) { long long offset; - phys_addr_t mem_start, mem_end; + u64 mem_start, mem_end; mem_start = memblock_start_of_DRAM(); mem_end = memblock_end_of_DRAM(); @@ -78,7 +78,7 @@ static long long __init keystone_pv_fixup(void) if (mem_start < KEYSTONE_HIGH_PHYS_START || mem_end > KEYSTONE_HIGH_PHYS_END) { pr_crit("Invalid address space for memory (%08llx-%08llx)\n", - (u64)mem_start, (u64)mem_end); + mem_start, mem_end); return 0; } diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 41c7b905980a..23e8146b9b32 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -239,10 +239,12 @@ static int _omap_device_notifier_call(struct notifier_block *nb, break; case BUS_NOTIFY_BIND_DRIVER: od = to_omap_device(pdev); - if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) && - pm_runtime_status_suspended(dev)) { + if (od) { od->_driver_status = BUS_NOTIFY_BIND_DRIVER; - pm_runtime_set_active(dev); + if (od->_state == OMAP_DEVICE_STATE_ENABLED && + pm_runtime_status_suspended(dev)) { + pm_runtime_set_active(dev); + } } break; case BUS_NOTIFY_ADD_DEVICE: diff --git a/arch/arm/mach-shmobile/pm-rmobile.c b/arch/arm/mach-shmobile/pm-rmobile.c index e348bcfe389d..cb8b02a1abe2 100644 --- a/arch/arm/mach-shmobile/pm-rmobile.c +++ b/arch/arm/mach-shmobile/pm-rmobile.c @@ -330,6 +330,7 @@ static int __init rmobile_init_pm_domains(void) pmd = of_get_child_by_name(np, "pm-domains"); if (!pmd) { + iounmap(base); pr_warn("%pOF lacks pm-domains node\n", np); continue; } diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c index de4b0e932f22..aa08b8cb0152 100644 --- a/arch/arm/mach-sunxi/sunxi.c +++ b/arch/arm/mach-sunxi/sunxi.c @@ -66,6 +66,7 @@ static const char * const sun8i_board_dt_compat[] = { "allwinner,sun8i-h2-plus", "allwinner,sun8i-h3", "allwinner,sun8i-r40", + "allwinner,sun8i-v3", "allwinner,sun8i-v3s", NULL, }; diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c index 0dc23fc227ed..cf08cb726767 100644 --- a/arch/arm/probes/kprobes/opt-arm.c +++ b/arch/arm/probes/kprobes/opt-arm.c @@ -98,21 +98,21 @@ asm ( "optprobe_template_end:\n"); #define TMPL_VAL_IDX \ - ((unsigned long *)&optprobe_template_val - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_val - (unsigned long *)optprobe_template_entry) #define TMPL_CALL_IDX \ - ((unsigned long *)&optprobe_template_call - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_call - (unsigned long *)optprobe_template_entry) #define TMPL_END_IDX \ - ((unsigned long *)&optprobe_template_end - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_end - (unsigned long *)optprobe_template_entry) #define TMPL_ADD_SP \ - ((unsigned long *)&optprobe_template_add_sp - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_add_sp - (unsigned long *)optprobe_template_entry) #define TMPL_SUB_SP \ - ((unsigned long *)&optprobe_template_sub_sp - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_sub_sp - (unsigned long *)optprobe_template_entry) #define TMPL_RESTORE_BEGIN \ - ((unsigned long *)&optprobe_template_restore_begin - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_restore_begin - (unsigned long *)optprobe_template_entry) #define TMPL_RESTORE_ORIGN_INSN \ - ((unsigned long *)&optprobe_template_restore_orig_insn - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_restore_orig_insn - (unsigned long *)optprobe_template_entry) #define TMPL_RESTORE_END \ - ((unsigned long *)&optprobe_template_restore_end - (unsigned long *)&optprobe_template_entry) + ((unsigned long *)optprobe_template_restore_end - (unsigned long *)optprobe_template_entry) /* * ARM can always optimize an instruction when using ARM ISA, except @@ -247,7 +247,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or } /* Copy arch-dep-instance from template. */ - memcpy(code, (unsigned long *)&optprobe_template_entry, + memcpy(code, (unsigned long *)optprobe_template_entry, TMPL_END_IDX * sizeof(kprobe_opcode_t)); /* Adjust buffer according to instruction. */ diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c index bf992264060e..b1b7b51c938c 100644 --- a/arch/arm/probes/uprobes/core.c +++ b/arch/arm/probes/uprobes/core.c @@ -207,7 +207,7 @@ unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) static struct undef_hook uprobes_arm_break_hook = { .instr_mask = 0x0fffffff, .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff), - .cpsr_mask = MODE_MASK, + .cpsr_mask = (PSR_T_BIT | MODE_MASK), .cpsr_val = USR_MODE, .fn = uprobe_trap_handler, }; @@ -215,7 +215,7 @@ static struct undef_hook uprobes_arm_break_hook = { static struct undef_hook uprobes_arm_ss_hook = { .instr_mask = 0x0fffffff, .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff), - .cpsr_mask = MODE_MASK, + .cpsr_mask = (PSR_T_BIT | MODE_MASK), .cpsr_val = USR_MODE, .fn = uprobe_trap_handler, }; diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c index 07060e5b5864..dd946c77e801 100644 --- a/arch/arm/xen/enlighten.c +++ b/arch/arm/xen/enlighten.c @@ -404,8 +404,6 @@ static int __init xen_guest_init(void) return -ENOMEM; } gnttab_init(); - if (!xen_initial_domain()) - xenbus_probe(NULL); /* * Making sure board specific code will not set up ops for diff --git a/arch/arm/xen/p2m.c b/arch/arm/xen/p2m.c index 0641ba54ab62..8a8a388549e7 100644 --- a/arch/arm/xen/p2m.c +++ b/arch/arm/xen/p2m.c @@ -91,10 +91,39 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, int i; for (i = 0; i < count; i++) { + struct gnttab_unmap_grant_ref unmap; + int rc; + if (map_ops[i].status) continue; - set_phys_to_machine(map_ops[i].host_addr >> XEN_PAGE_SHIFT, - map_ops[i].dev_bus_addr >> XEN_PAGE_SHIFT); + if (likely(set_phys_to_machine(map_ops[i].host_addr >> XEN_PAGE_SHIFT, + map_ops[i].dev_bus_addr >> XEN_PAGE_SHIFT))) + continue; + + /* + * Signal an error for this slot. This in turn requires + * immediate unmapping. + */ + map_ops[i].status = GNTST_general_error; + unmap.host_addr = map_ops[i].host_addr, + unmap.handle = map_ops[i].handle; + map_ops[i].handle = ~0; + if (map_ops[i].flags & GNTMAP_device_map) + unmap.dev_bus_addr = map_ops[i].dev_bus_addr; + else + unmap.dev_bus_addr = 0; + + /* + * Pre-populate the status field, to be recognizable in + * the log message below. + */ + unmap.status = 1; + + rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, + &unmap, 1); + if (rc || unmap.status != GNTST_okay) + pr_err_once("gnttab unmap failed: rc=%d st=%d\n", + rc, unmap.status); } return 0; diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 36671df21df5..daf61aae8cf3 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -20,6 +20,7 @@ config ARM64 select ARCH_HAS_KCOV select ARCH_HAS_MEMBARRIER_SYNC_CORE select ARCH_HAS_PTE_SPECIAL + select ARCH_HAS_REFCOUNT_FULL select ARCH_HAS_SET_MEMORY select ARCH_HAS_SG_CHAIN select ARCH_HAS_STRICT_KERNEL_RWX @@ -78,6 +79,7 @@ config ARM64 select CLONE_BACKWARDS select COMMON_CLK select CPU_PM if (SUSPEND || CPU_IDLE) + select CRC32 select DCACHE_WORD_ACCESS select DMA_DIRECT_OPS select EDAC_SUPPORT @@ -103,12 +105,14 @@ config ARM64 select GENERIC_GETTIMEOFDAY select HANDLE_DOMAIN_IRQ select HARDIRQS_SW_RESEND + select HAVE_MOVE_PMD select HAVE_ACPI_APEI if (ACPI && EFI) select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_BITREVERSE select HAVE_ARCH_HUGE_VMAP select HAVE_ARCH_JUMP_LABEL + select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48) select HAVE_ARCH_KASAN_SW_TAGS if HAVE_ARCH_KASAN select HAVE_ARCH_KGDB @@ -141,8 +145,10 @@ config ARM64 select HAVE_IRQ_TIME_ACCOUNTING select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZ4 + select HAVE_LD_DEAD_CODE_DATA_ELIMINATION select HAVE_MEMBLOCK select HAVE_MEMBLOCK_NODE_MAP if NUMA + select HAVE_MOVE_PMD select HAVE_NMI select HAVE_PATA_PLATFORM select HAVE_PERF_EVENTS @@ -177,6 +183,34 @@ config ARM64 select THREAD_INFO_IN_TASK select ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT select USER_STACKTRACE_SUPPORT + select ARCH_INLINE_SPIN_TRYLOCK + select ARCH_INLINE_SPIN_TRYLOCK_BH + select ARCH_INLINE_SPIN_LOCK + select ARCH_INLINE_SPIN_LOCK_BH + select ARCH_INLINE_SPIN_LOCK_IRQ + select ARCH_INLINE_SPIN_LOCK_IRQSAVE + select ARCH_INLINE_SPIN_UNLOCK + select ARCH_INLINE_SPIN_UNLOCK_BH + select ARCH_INLINE_SPIN_UNLOCK_IRQ + select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE + select ARCH_INLINE_READ_TRYLOCK + select ARCH_INLINE_READ_LOCK + select ARCH_INLINE_READ_LOCK_BH + select ARCH_INLINE_READ_LOCK_IRQ + select ARCH_INLINE_READ_LOCK_IRQSAVE + select ARCH_INLINE_READ_UNLOCK + select ARCH_INLINE_READ_UNLOCK_BH + select ARCH_INLINE_READ_UNLOCK_IRQ + select ARCH_INLINE_READ_UNLOCK_IRQRESTORE + select ARCH_INLINE_WRITE_TRYLOCK + select ARCH_INLINE_WRITE_LOCK + select ARCH_INLINE_WRITE_LOCK_BH + select ARCH_INLINE_WRITE_LOCK_IRQ + select ARCH_INLINE_WRITE_LOCK_IRQSAVE + select ARCH_INLINE_WRITE_UNLOCK + select ARCH_INLINE_WRITE_UNLOCK_BH + select ARCH_INLINE_WRITE_UNLOCK_IRQ + select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE help ARM 64-bit (AArch64) Linux support. @@ -806,6 +840,27 @@ config NR_CPUS # These have to remain sorted largest to smallest default "64" +config LITTLE_CPU_MASK + int "Bitmask of available LITTLE CPUs" + help + This is a bitmask specifying which of the CPUs are LITTLE in a + heterogeneous system. Use 0 if you are unsure, which just results in + this storing the bitmask of all available CPUs. + +config BIG_CPU_MASK + int "Bitmask of available big CPUs" + help + This is a bitmask specifying which of the CPUs are big in a + heterogeneous system. Use 0 if you are unsure, which just results in + this storing the bitmask of all available CPUs. + +config PRIME_CPU_MASK + int "Bitmask of available prime CPUs" + help + This is a bitmask specifying which of the CPUs are prime in a + heterogeneous system. Use 0 if you are unsure, which just results in + this storing the bitmask of all available CPUs. + config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" select GENERIC_IRQ_MIGRATION @@ -1142,7 +1197,7 @@ config ARM64_TAGGED_ADDR_ABI config COMPAT_VDSO bool "Enable vDSO for 32-bit applications" - depends on !CPU_BIG_ENDIAN && "$(CROSS_COMPILE_COMPAT)" != "" + depends on !CPU_BIG_ENDIAN select GENERIC_COMPAT_VDSO default y help diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index ddb607140f7c..3aedffd56dad 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -10,7 +10,7 @@ # # Copyright (C) 1995-2001 by Russell King -LDFLAGS_vmlinux :=--no-undefined -X -z norelro +LDFLAGS_vmlinux :=--no-undefined -X CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) GZFLAGS :=-9 @@ -18,8 +18,15 @@ ifeq ($(CONFIG_RELOCATABLE), y) # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour # for relative relocs, since this leads to better Image compression # with the relocation offsets always being zero. -LDFLAGS_vmlinux += -shared -Bsymbolic -z notext \ +LDFLAGS_vmlinux += -Bsymbolic -z notext \ $(call ld-option, --no-apply-dynamic-relocs) + +# Pass -pie for lld to minimize image size +ifeq ($(CONFIG_LD_IS_LLD), y) +LDFLAGS_vmlinux += -pie -z norelro +else +LDFLAGS_vmlinux += -shared +endif endif ifeq ($(CONFIG_ARM64_ERRATUM_843419),y) @@ -51,6 +58,11 @@ endif ifeq ($(cc-name),clang) KBUILD_CFLAGS += -mno-implicit-float +ifeq ($(CONFIG_ARCH_KONA), y) +KBUILD_CFLAGS += -mcpu=cortex-a55 +KBUILD_AFLAGS += -mcpu=cortex-a55 +KBUILD_LDFLAGS += -mllvm -mcpu=cortex-a55 +endif else KBUILD_CFLAGS += -mgeneral-regs-only endif @@ -72,17 +84,21 @@ CHECKFLAGS += -D__AARCH64EB__ AS += -EB # Prefer the baremetal ELF build target, but not all toolchains include # it so fall back to the standard linux version if needed. -KBUILD_LDFLAGS += -EB $(call ld-option, -maarch64elfb, -maarch64linuxb) +KBUILD_LDFLAGS += -EB $(call ld-option, -maarch64elfb, -maarch64linuxb -z norelro) UTS_MACHINE := aarch64_be else KBUILD_CPPFLAGS += -mlittle-endian CHECKFLAGS += -D__AARCH64EL__ AS += -EL # Same as above, prefer ELF but fall back to linux target if needed. -KBUILD_LDFLAGS += -EL $(call ld-option, -maarch64elf, -maarch64linux) +KBUILD_LDFLAGS += -EL $(call ld-option, -maarch64elf, -maarch64linux -z norelro) UTS_MACHINE := aarch64 endif +ifeq ($(CONFIG_LD_IS_LLD), y) +KBUILD_LDFLAGS += -z norelro +endif + CHECKFLAGS += -D__aarch64__ ifeq ($(CONFIG_ARM64_MODULE_PLTS),y) @@ -183,6 +199,7 @@ Image.gz-dtb: vmlinux scripts dtbs Image.gz PHONY += vdso_install vdso_install: $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso $@ + $(Q)$(MAKE) $(build)=arch/arm64/kernel/vdso32 $@ # We use MRPROPER_FILES and CLEAN_FILES now archclean: diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 254262de63ad..529a44cbbbcb 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -16,7 +16,6 @@ subdir-y += lg subdir-y += marvell subdir-y += mediatek subdir-y += nvidia -subdir-y += qcom subdir-y += realtek subdir-y += renesas subdir-y += rockchip diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts index 094cfed13df9..13ce24e922ee 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts @@ -97,7 +97,7 @@ &emac { pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; phy-handle = <&ext_rgmii_phy>; phy-supply = <®_dc1sw>; status = "okay"; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts index d5b6e8159a33..5d0905f0f1c1 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-plus.dts @@ -52,7 +52,7 @@ &emac { pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; - phy-mode = "rgmii"; + phy-mode = "rgmii-txid"; phy-handle = <&ext_rgmii_phy>; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts index 897e60cbe38d..ecb3e10c85e0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts @@ -67,8 +67,6 @@ }; &ehci0 { - phys = <&usbphy 0>; - phy-names = "usb"; status = "okay"; }; @@ -107,6 +105,7 @@ pinctrl-0 = <&mmc2_pins>; vmmc-supply = <®_dcdc1>; vqmmc-supply = <®_eldo1>; + max-frequency = <200000000>; bus-width = <8>; non-removable; cap-mmc-hw-reset; @@ -115,8 +114,6 @@ }; &ohci0 { - phys = <&usbphy 0>; - phy-names = "usb"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi index 6723b8695e0b..ca39084fddc0 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi @@ -51,7 +51,6 @@ pinctrl-names = "default"; pinctrl-0 = <&mmc0_pins>; vmmc-supply = <®_dcdc1>; - non-removable; disable-wp; bus-width = <4>; cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index 7abc4ea30541..30cc2e83a288 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi @@ -264,7 +264,7 @@ resets = <&ccu RST_BUS_MMC2>; reset-names = "ahb"; interrupts = ; - max-frequency = <200000000>; + max-frequency = <150000000>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -312,6 +312,8 @@ <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>, <&ccu RST_BUS_EHCI0>; + phys = <&usbphy 0>; + phy-names = "usb"; status = "disabled"; }; @@ -322,6 +324,8 @@ clocks = <&ccu CLK_BUS_OHCI0>, <&ccu CLK_USB_OHCI0>; resets = <&ccu RST_BUS_OHCI0>; + phys = <&usbphy 0>; + phy-names = "usb"; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts index 3e0d5a9c096d..5fbfa76daae2 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts @@ -157,7 +157,7 @@ pinctrl-0 = <&emac_rgmii_pins>; phy-supply = <®_gmac_3v3>; phy-handle = <&ext_rgmii_phy>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts index b75ca4d7d001..7a30211d59ef 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-prime.dts @@ -164,7 +164,7 @@ pinctrl-0 = <&emac_rgmii_pins>; phy-supply = <®_gmac_3v3>; phy-handle = <&ext_rgmii_phy>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts index bdf7c6c5983c..30fa9302a4dc 100644 --- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts +++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts @@ -399,7 +399,7 @@ #size-cells = <1>; compatible = "winbond,w25q16", "jedec,spi-nor"; reg = <0>; - spi-max-frequency = <3000000>; + spi-max-frequency = <104000000>; }; }; diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi index a1e3194b7483..d64f97d97c35 100644 --- a/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi @@ -378,7 +378,7 @@ s2mps13-pmic@66 { compatible = "samsung,s2mps13-pmic"; interrupt-parent = <&gpa0>; - interrupts = <7 IRQ_TYPE_NONE>; + interrupts = <7 IRQ_TYPE_LEVEL_LOW>; reg = <0x66>; samsung,s2mps11-wrstbi-ground; diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts index d991eae5202f..2ba62118ae90 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -85,7 +85,7 @@ s2mps15_pmic@66 { compatible = "samsung,s2mps15-pmic"; reg = <0x66>; - interrupts = <2 IRQ_TYPE_NONE>; + interrupts = <2 IRQ_TYPE_LEVEL_LOW>; interrupt-parent = <&gpa0>; pinctrl-names = "default"; pinctrl-0 = <&pmic_irq>; diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi index 31b1a606cb66..5c5e57026c27 100644 --- a/arch/arm64/boot/dts/exynos/exynos7.dtsi +++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi @@ -62,8 +62,10 @@ }; psci { - compatible = "arm,psci-0.2"; + compatible = "arm,psci"; method = "smc"; + cpu_off = <0x84000002>; + cpu_on = <0xC4000003>; }; soc: soc { @@ -494,13 +496,6 @@ pmu_system_controller: system-controller@105c0000 { compatible = "samsung,exynos7-pmu", "syscon"; reg = <0x105c0000 0x5000>; - - reboot: syscon-reboot { - compatible = "syscon-reboot"; - regmap = <&pmu_system_controller>; - offset = <0x0400>; - mask = <0x1>; - }; }; rtc: rtc@10590000 { @@ -638,3 +633,4 @@ }; #include "exynos7-pinctrl.dtsi" +#include "arm/exynos-syscon-restart.dtsi" diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi index 5da732f82fa0..712264e4e26e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi @@ -177,6 +177,7 @@ ranges = <0x0 0x00 0x1700000 0x100000>; reg = <0x00 0x1700000 0x0 0x100000>; interrupts = ; + dma-coherent; sec_jr0: jr@10000 { compatible = "fsl,sec-v5.4-job-ring", diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi index b9c0f2de8f12..3ec60e33f299 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi @@ -237,6 +237,7 @@ ranges = <0x0 0x00 0x1700000 0x100000>; reg = <0x00 0x1700000 0x0 0x100000>; interrupts = <0 75 0x4>; + dma-coherent; sec_jr0: jr@10000 { compatible = "fsl,sec-v5.4-job-ring", diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi index de6af453a6e1..3452971a8e1c 100644 --- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi @@ -243,6 +243,7 @@ ranges = <0x0 0x00 0x1700000 0x100000>; reg = <0x00 0x1700000 0x0 0x100000>; interrupts = ; + dma-coherent; sec_jr0: jr@10000 { compatible = "fsl,sec-v5.4-job-ring", @@ -303,7 +304,7 @@ dcfg: dcfg@1ee0000 { compatible = "fsl,ls1046a-dcfg", "syscon"; - reg = <0x0 0x1ee0000 0x0 0x10000>; + reg = <0x0 0x1ee0000 0x0 0x1000>; big-endian; }; diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi index de2c47bdbe64..2bcee994898a 100644 --- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi @@ -641,6 +641,8 @@ clocks = <&pericfg CLK_PERI_MSDC30_1_PD>, <&topckgen CLK_TOP_AXI_SEL>; clock-names = "source", "hclk"; + resets = <&pericfg MT7622_PERI_MSDC1_SW_RST>; + reset-names = "hrst"; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi index 6597c0894137..4eecf3b02468 100644 --- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi +++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi @@ -826,6 +826,7 @@ <&tegra_car 128>, /* hda2hdmi */ <&tegra_car 111>; /* hda2codec_2x */ reset-names = "hda", "hda2hdmi", "hda2codec_2x"; + power-domains = <&pd_sor>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi index 2c5193ae2027..ba42c6239922 100644 --- a/arch/arm64/boot/dts/qcom/msm8916.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi @@ -64,7 +64,7 @@ no-map; }; - reserved@8668000 { + reserved@86680000 { reg = <0x0 0x86680000 0x0 0x80000>; no-map; }; @@ -77,7 +77,7 @@ qcom,client-id = <1>; }; - rfsa@867e00000 { + rfsa@867e0000 { reg = <0x0 0x867e0000 0x0 0x20000>; no-map; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts index 91061d9cf78b..5b1ece4a68d6 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-roc-cc.dts @@ -255,6 +255,7 @@ }; &usb20_otg { + dr_mode = "host"; status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 92186edefeb9..6be7c67584ba 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -1085,8 +1085,8 @@ uart0 { uart0_xfer: uart0-xfer { - rockchip,pins = <1 RK_PB1 1 &pcfg_pull_up>, - <1 RK_PB0 1 &pcfg_pull_none>; + rockchip,pins = <1 RK_PB1 1 &pcfg_pull_none>, + <1 RK_PB0 1 &pcfg_pull_up>; }; uart0_cts: uart0-cts { @@ -1104,8 +1104,8 @@ uart1 { uart1_xfer: uart1-xfer { - rockchip,pins = <3 RK_PA4 4 &pcfg_pull_up>, - <3 RK_PA6 4 &pcfg_pull_none>; + rockchip,pins = <3 RK_PA4 4 &pcfg_pull_none>, + <3 RK_PA6 4 &pcfg_pull_up>; }; uart1_cts: uart1-cts { @@ -1123,15 +1123,15 @@ uart2-0 { uart2m0_xfer: uart2m0-xfer { - rockchip,pins = <1 RK_PA0 2 &pcfg_pull_up>, - <1 RK_PA1 2 &pcfg_pull_none>; + rockchip,pins = <1 RK_PA0 2 &pcfg_pull_none>, + <1 RK_PA1 2 &pcfg_pull_up>; }; }; uart2-1 { uart2m1_xfer: uart2m1-xfer { - rockchip,pins = <2 RK_PA0 1 &pcfg_pull_up>, - <2 RK_PA1 1 &pcfg_pull_none>; + rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>, + <2 RK_PA1 1 &pcfg_pull_up>; }; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi index f14e8c5c41ac..b1c1a88a1c20 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -29,6 +29,9 @@ i2c6 = &i2c6; i2c7 = &i2c7; i2c8 = &i2c8; + mmc0 = &sdio0; + mmc1 = &sdmmc; + mmc2 = &sdhci; serial0 = &uart0; serial1 = &uart1; serial2 = &uart2; @@ -195,6 +198,7 @@ reg = <0x0 0xf8000000 0x0 0x2000000>, <0x0 0xfd000000 0x0 0x1000000>; reg-names = "axi-base", "apb-base"; + device_type = "pci"; #address-cells = <3>; #size-cells = <2>; #interrupt-cells = <1>; @@ -213,7 +217,6 @@ <0 0 0 2 &pcie0_intc 1>, <0 0 0 3 &pcie0_intc 2>, <0 0 0 4 &pcie0_intc 3>; - linux,pci-domain = <0>; max-link-speed = <1>; msi-map = <0x0 &its 0x0 0x1000>; phys = <&pcie_phy 0>, <&pcie_phy 1>, diff --git a/arch/arm64/boot/dts/vendor/bindings/input/qpnp-power-on.txt b/arch/arm64/boot/dts/vendor/bindings/input/qpnp-power-on.txt index 7367934138e8..6c2b66700197 100755 --- a/arch/arm64/boot/dts/vendor/bindings/input/qpnp-power-on.txt +++ b/arch/arm64/boot/dts/vendor/bindings/input/qpnp-power-on.txt @@ -86,8 +86,14 @@ Optional properties: - qcom,shutdown-poweroff-type: Same description as qcom,warm-reset-poweroff- type but this applies for the system shutdown case. -- qcom,kpdpwr-sw-debounce: Boolean property to enable the debounce logic - on the KPDPWR_N rising edge. +- qcom,pon-sw-debounce Boolean property to enable software debouncing + logic for pon input keys. +- qcom,pon-sw-dbc-delay The debounce delay for the power-key interrupt + specified in us. This can be set to any value + as it is handled in software rather than by the + PMIC hardware. Only used if qcom,pon-sw-debounce + is enabled. Defaults to the value of + qcom,pon-dbc-delay if not specified. - qcom,resin-pon-reset: Boolean property which indicates that resin needs to be configured during reset in addition to the primary PON device that is configured diff --git a/arch/arm64/boot/dts/vendor/bindings/net/btusb.txt b/arch/arm64/boot/dts/vendor/bindings/net/btusb.txt index 37d67926dd6d..d883a35641d1 100755 --- a/arch/arm64/boot/dts/vendor/bindings/net/btusb.txt +++ b/arch/arm64/boot/dts/vendor/bindings/net/btusb.txt @@ -35,7 +35,7 @@ Following example uses irq pin number 3 of gpio0 for out of band wake-on-bt: compatible = "usb1286,204e"; reg = <1>; interrupt-parent = <&gpio0>; - interrupt-name = "wakeup"; + interrupt-names = "wakeup"; interrupts = <3 IRQ_TYPE_LEVEL_LOW>; }; }; diff --git a/arch/arm64/boot/dts/vendor/bindings/net/nfc/nxp-nci.txt b/arch/arm64/boot/dts/vendor/bindings/net/nfc/nxp-nci.txt index cfaf88998918..9e4dc510a40a 100755 --- a/arch/arm64/boot/dts/vendor/bindings/net/nfc/nxp-nci.txt +++ b/arch/arm64/boot/dts/vendor/bindings/net/nfc/nxp-nci.txt @@ -25,7 +25,7 @@ Example (for ARM-based BeagleBone with NPC100 NFC controller on I2C2): clock-frequency = <100000>; interrupt-parent = <&gpio1>; - interrupts = <29 GPIO_ACTIVE_HIGH>; + interrupts = <29 IRQ_TYPE_LEVEL_HIGH>; enable-gpios = <&gpio0 30 GPIO_ACTIVE_HIGH>; firmware-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/vendor/bindings/net/nfc/pn544.txt b/arch/arm64/boot/dts/vendor/bindings/net/nfc/pn544.txt index 92f399ec22b8..2bd82562ce8e 100755 --- a/arch/arm64/boot/dts/vendor/bindings/net/nfc/pn544.txt +++ b/arch/arm64/boot/dts/vendor/bindings/net/nfc/pn544.txt @@ -25,7 +25,7 @@ Example (for ARM-based BeagleBone with PN544 on I2C2): clock-frequency = <400000>; interrupt-parent = <&gpio1>; - interrupts = <17 GPIO_ACTIVE_HIGH>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; enable-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; firmware-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; diff --git a/arch/arm64/boot/dts/vendor/qcom/Makefile b/arch/arm64/boot/dts/vendor/qcom/Makefile index 96886289ac48..49dadbe43f86 100755 --- a/arch/arm64/boot/dts/vendor/qcom/Makefile +++ b/arch/arm64/boot/dts/vendor/qcom/Makefile @@ -1,41 +1,10 @@ ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) dtbo-$(CONFIG_ARCH_KONA) += \ - kona-cdp-overlay.dtbo \ - kona-cdp-lcd-overlay.dtbo \ kona-mtp-overlay.dtbo \ - kona-mtp-ws-overlay.dtbo \ - kona-sa-mtp-overlay.dtbo \ - kona-xr-overlay.dtbo \ - umi-sm8250-overlay.dtbo \ - cmi-sm8250-overlay.dtbo \ - lmi-sm8250-overlay.dtbo \ - cas-sm8250-overlay.dtbo \ apollo-sm8250-overlay.dtbo \ - alioth-sm8250-overlay.dtbo \ - kona-rumi-overlay.dtbo \ - kona-qrd-overlay.dtbo \ - kona-xrfusion-overlay.dtbo \ - kona-xrfusion-ult-overlay.dtbo \ - kona-hdk-overlay.dtbo -kona-cdp-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-cdp-lcd-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb kona-mtp-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-mtp-ws-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-sa-mtp-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-xr-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -umi-sm8250-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -cmi-sm8250-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -lmi-sm8250-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -cas-sm8250-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb apollo-sm8250-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -alioth-sm8250-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-xr-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-rumi-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-qrd-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-xrfusion-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-xrfusion-ult-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb -kona-hdk-overlay.dtbo-base := kona.dtb kona-v2.dtb kona-v2.1.dtb else dtb-$(CONFIG_ARCH_KONA) += kona-rumi.dtb \ kona-mtp.dtb \ diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-idp.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-idp.dtsi index 48f40a98c4a5..65ac19946f1e 100755 --- a/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-idp.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-idp.dtsi @@ -118,8 +118,8 @@ &cam_sensor_rear1_reset_active>; pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_rear1_reset_suspend>; - gpios = <&tlmm 21 0>, - <&tlmm 19 0>; + gpios = <&tlmm 19 0>, + <&tlmm 21 0>; gpio-reset = <1>; gpio-req-tbl-num = <0 1>; gpio-req-tbl-flags = <1 0>; @@ -145,8 +145,8 @@ "cam_clk"; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; + rgltr-min-voltage = <1800000 2800000 1056000 0>; + rgltr-max-voltage = <1800000 2800000 1056000 0>; rgltr-load-current = <0 80000 105000 0>; gpio-no-mux = <0>; pinctrl-names = "cam_default", "cam_suspend"; @@ -211,7 +211,7 @@ cell-index = <0>; compatible = "qcom,cam-sensor"; csiphy-sd-index = <0>; - sensor-position-roll = <270>; + sensor-position-roll = <90>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; actuator-src = <&actuator_rear>; @@ -255,7 +255,7 @@ cell-index = <1>; compatible = "qcom,cam-sensor"; csiphy-sd-index = <1>; - sensor-position-roll = <270>; + sensor-position-roll = <90>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; actuator-src = <&actuator_rear_aux>; @@ -278,8 +278,8 @@ &cam_sensor_rear1_reset_active>; pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_rear1_reset_suspend>; - gpios = <&tlmm 21 0>, - <&tlmm 19 0>; + gpios = <&tlmm 19 0>, + <&tlmm 21 0>; gpio-reset = <1>; gpio-req-tbl-num = <0 1>; gpio-req-tbl-flags = <1 0>; @@ -299,9 +299,9 @@ cell-index = <2>; compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; - sensor-position-roll = <270>; + sensor-position-roll = <90>; sensor-position-pitch = <0>; - sensor-position-yaw = <0>; + sensor-position-yaw = <180>; eeprom-src = <&eeprom_front>; cam_vio-supply = <&L7P>; cam_vana-supply = <&L6P>; @@ -311,8 +311,8 @@ "cam_clk"; rgltr-cntrl-support; pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; + rgltr-min-voltage = <1800000 2800000 1056000 0>; + rgltr-max-voltage = <1800000 2800000 1056000 0>; rgltr-load-current = <0 80000 105000 0>; gpio-no-mux = <0>; pinctrl-names = "cam_default", "cam_suspend"; @@ -329,14 +329,10 @@ <&tlmm 66 0>, <&tlmm 67 0>; gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-custom2 = <3>; gpio-req-tbl-num = <0 1>; gpio-req-tbl-flags = <1 0>; gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_CSIMUX_OE0", - "CAM_CSIMUX_SEL0"; + "CAM_RESET2"; sensor-mode = <0>; cci-master = <1>; status = "ok"; @@ -351,7 +347,7 @@ cell-index = <3>; compatible = "qcom,cam-sensor"; csiphy-sd-index = <2>; - sensor-position-roll = <270>; + sensor-position-roll = <90>; sensor-position-pitch = <0>; sensor-position-yaw = <180>; led-flash-src = <&led_flash_rear_aux2>; @@ -382,14 +378,10 @@ <&tlmm 66 0>, <&tlmm 67 0>; gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-custom2 = <3>; gpio-req-tbl-num = <0 1>; gpio-req-tbl-flags = <1 0>; gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3", - "CAM_CSIMUX_OE1", - "CAM_CSIMUX_SEL1"; + "CAM_RESET3"; sensor-mode = <0>; cci-master = <0>; status = "ok"; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-qrd.dtsi deleted file mode 100755 index c6aa60f384ea..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera-sensor-qrd.dtsi +++ /dev/null @@ -1,403 +0,0 @@ -#include -&soc { - led_flash_rear: qcom,camera-flash@0 { - cell-index = <0>; - compatible = "qcom,camera-flash"; - flash-source = <&pmi632_flash0 &pmi632_flash1>; - torch-source = <&pmi632_torch0 &pmi632_torch1>; - switch-source = <&pmi632_switch0 &pmi632_switch0>; - status = "ok"; - }; - - led_flash_rear_aux: qcom,camera-flash@1 { - cell-index = <1>; - compatible = "qcom,camera-flash"; - flash-source = <&pmi632_flash0 &pmi632_flash1>; - torch-source = <&pmi632_torch0 &pmi632_torch1>; - switch-source = <&pmi632_switch0 &pmi632_switch0>; - status = "ok"; - }; - - led_flash_rear_aux2: qcom,camera-flash@2 { - cell-index = <2>; - compatible = "qcom,camera-flash"; - flash-source = <&pmi632_flash0 &pmi632_flash1>; - torch-source = <&pmi632_torch0 &pmi632_torch1>; - switch-source = <&pmi632_switch0 &pmi632_switch0>; - status = "ok"; - }; - - qcom,cam-res-mgr { - compatible = "qcom,cam-res-mgr"; - status = "ok"; - }; -}; - -&cam_cci0 { - actuator_rear: qcom,actuator0 { - cell-index = <0>; - compatible = "qcom,actuator"; - cci-master = <0>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - actuator_rear_aux: qcom,actuator1 { - cell-index = <1>; - compatible = "qcom,actuator"; - cci-master = <1>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - eeprom_rear: qcom,eeprom0 { - cell-index = <0>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_vaf-supply = <&L5P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1050000 0 2800000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_rear0_reset_active>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_rear0_reset_suspend>; - gpios = <&tlmm 20 0>, - <&tlmm 18 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - eeprom_rear_aux: qcom,eeprom1 { - cell-index = <1>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_vaf-supply = <&L5P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1200000 0 2800000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_rear1_reset_active>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_rear1_reset_suspend>; - gpios = <&tlmm 21 0>, - <&tlmm 19 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - eeprom_front: qcom,eeprom2 { - cell-index = <2>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L6P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_front0_reset_active>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_front0_reset_suspend>; - gpios = <&tlmm 27 0>, - <&tlmm 24 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_rear_aux2: qcom,eeprom3 { - cell-index = <3>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L6P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0>; - rgltr-max-voltage = <1800000 2800000 1200000 0>; - rgltr-load-current = <120000 80000 1200000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_rear2_reset_active>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_rear2_reset_suspend>; - gpios = <&tlmm 28 0>, - <&tlmm 65 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - /* Rear*/ - qcom,cam-sensor0 { - cell-index = <0>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <0>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - actuator-src = <&actuator_rear>; - led-flash-src = <&led_flash_rear>; - eeprom-src = <&eeprom_rear>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_vaf-supply = <&L5P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1050000 0 2800000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_rear0_reset_active>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_rear0_reset_suspend>; - gpios = <&tlmm 20 0>, - <&tlmm 18 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - /*Rear Aux*/ - qcom,cam-sensor1 { - cell-index = <1>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <1>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - actuator-src = <&actuator_rear_aux>; - led-flash-src = <&led_flash_rear_aux>; - eeprom-src = <&eeprom_rear_aux>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_vaf-supply = <&L5P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1200000 0 2800000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_rear1_reset_active>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_rear1_reset_suspend>; - gpios = <&tlmm 21 0>, - <&tlmm 19 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - /*Front*/ - qcom,cam-sensor2 { - cell-index = <2>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <2>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - eeprom-src = <&eeprom_front>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L6P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_front0_reset_active - &cam_sensor_csi_mux_oe_active - &cam_sensor_csi_mux_sel_active>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_front0_reset_suspend - &cam_sensor_csi_mux_oe_suspend - &cam_sensor_csi_mux_sel_suspend>; - gpios = <&tlmm 27 0>, - <&tlmm 24 0>, - <&tlmm 66 0>, - <&tlmm 67 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-custom2 = <3>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_CSIMUX_OE0", - "CAM_CSIMUX_SEL0"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - /*Rear Aux2*/ - qcom,cam-sensor3 { - cell-index = <3>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <2>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_rear_aux2>; - eeprom-src = <&eeprom_rear_aux2>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L6P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0>; - rgltr-max-voltage = <1800000 2800000 1200000 0>; - rgltr-load-current = <120000 80000 1200000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_rear2_reset_active - &cam_sensor_csi_mux_oe_active - &cam_sensor_csi_mux_sel_active>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_rear2_reset_suspend - &cam_sensor_csi_mux_oe_suspend - &cam_sensor_csi_mux_sel_suspend>; - gpios = <&tlmm 28 0>, - <&tlmm 65 0>, - <&tlmm 66 0>, - <&tlmm 67 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-custom2 = <3>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3", - "CAM_CSIMUX_OE1", - "CAM_CSIMUX_SEL1"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera.dtsi index 2ff972feb387..23c6041547f9 100755 --- a/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bengal-camera.dtsi @@ -8,7 +8,7 @@ cam_csiphy0: qcom,csiphy0 { cell-index = <0>; - compatible = "qcom,csiphy-v2.0.1", "qcom,csiphy"; + compatible = "qcom,csiphy-v2.0", "qcom,csiphy"; reg = <0x05C52000 0x1000>; reg-names = "csiphy"; reg-cam-base = <0x52000>; @@ -30,16 +30,15 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; clock-rates = <19200000 0 19200000 0>, - <240000000 0 200000000 0>, + <341330000 0 200000000 0>, <341330000 0 200000000 0>, <384000000 0 268800000 0>; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; cam_csiphy1: qcom,csiphy1 { cell-index = <1>; - compatible = "qcom,csiphy-v2.0.1", "qcom,csiphy"; + compatible = "qcom,csiphy-v2.0", "qcom,csiphy"; reg = <0x05C53000 0x1000>; reg-names = "csiphy"; reg-cam-base = <0x53000>; @@ -61,16 +60,15 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; clock-rates = <19200000 0 19200000 0>, - <240000000 0 200000000 0>, + <341330000 0 200000000 0>, <341330000 0 200000000 0>, <384000000 0 268800000 0>; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; cam_csiphy2: qcom,csiphy2 { cell-index = <2>; - compatible = "qcom,csiphy-v2.0.1", "qcom,csiphy"; + compatible = "qcom,csiphy-v2.0", "qcom,csiphy"; reg = <0x05C54000 0x1000>; reg-names = "csiphy"; reg-cam-base = <0x54000>; @@ -92,16 +90,15 @@ clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; clock-rates = <19200000 0 19200000 0>, - <240000000 0 200000000 0>, + <341330000 0 200000000 0>, <341330000 0 200000000 0>, <384000000 0 268800000 0>; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; cam_cci0: qcom,cci0 { cell-index = <0>; - compatible = "qcom,cci-v1.2", "qcom,cci"; + compatible = "qcom,cci"; #address-cells = <1>; #size-cells = <0>; reg = <0x05C1B000 0x1000>; @@ -200,7 +197,8 @@ msm_cam_smmu_tfe { compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0x400 0x000>; + iommus = <&apps_smmu 0x400 0x000>, + <&apps_smmu 0x401 0x000>; qcom,iommu-faults = "non-fatal"; qcom,iommu-dma-addr-pool = <0x7400000 0xd8c00000>; label = "tfe"; @@ -219,7 +217,9 @@ msm_cam_smmu_ope { compatible = "qcom,msm-cam-smmu-cb"; iommus = <&apps_smmu 0x820 0x000>, - <&apps_smmu 0x840 0x000>; + <&apps_smmu 0x821 0x020>, + <&apps_smmu 0x840 0x000>, + <&apps_smmu 0x841 0x000>; qcom,iommu-faults = "non-fatal"; multiple-client-devices; qcom,iommu-dma-addr-pool = <0x7400000 0xd8c00000>; @@ -238,7 +238,8 @@ msm_cam_smmu_cpas_cdm { compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0x800 0x000>; + iommus = <&apps_smmu 0x800 0x000>, + <&apps_smmu 0x801 0x020>; label = "cpas-cdm0"; qcom,iommu-faults = "non-fatal"; qcom,iommu-dma-addr-pool = <0x7400000 0xd8c00000>; @@ -272,8 +273,6 @@ reg = <0x5c11000 0x1000>, <0x5c13000 0x4000>; reg-cam-base = <0x11000 0x13000>; - cam_hw_fuse = , - ; interrupt-names = "cpas_camnoc"; interrupts = ; camnoc-axi-min-ib-bw = <3000000000>; /*Need to be verified*/ @@ -284,42 +283,37 @@ "gcc_camss_top_ahb_clk", "gcc_camss_top_ahb_clk_src", "gcc_camss_axi_clk", - "gcc_camss_axi_clk_src", - "gcc_camss_nrt_axi_clk", - "gcc_camss_rt_axi_clk"; + "gcc_camss_axi_clk_src"; clocks = <&gcc GCC_CAMERA_AHB_CLK>, <&gcc GCC_CAMSS_TOP_AHB_CLK>, <&gcc GCC_CAMSS_TOP_AHB_CLK_SRC>, <&gcc GCC_CAMSS_AXI_CLK>, - <&gcc GCC_CAMSS_AXI_CLK_SRC>, - <&gcc GCC_CAMSS_NRT_AXI_CLK>, - <&gcc GCC_CAMSS_RT_AXI_CLK>; + <&gcc GCC_CAMSS_AXI_CLK_SRC>; src-clock-name = "gcc_camss_axi_clk_src"; clock-rates = - <0 0 0 0 0 0 0>, - <0 0 80000000 0 19200000 0 0>, - <0 0 80000000 0 150000000 0 0>, - <0 0 80000000 0 200000000 0 0>, - <0 0 80000000 0 300000000 0 0>, - <0 0 80000000 0 300000000 0 0>, - <0 0 80000000 0 300000000 0 0>; + <0 0 0 0 0>, + <0 80000000 80000000 19200000 19200000>, + <0 80000000 80000000 150000000 150000000>, + <0 80000000 80000000 200000000 200000000>, + <0 80000000 80000000 300000000 300000000>, + <0 80000000 80000000 300000000 300000000>, + <0 80000000 80000000 300000000 300000000>; clock-cntl-level = "suspend", "minsvs", "lowsvs", "svs", "svs_l1", "nominal", "turbo"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; control-camnoc-axi-clk; camnoc-bus-width = <32>; camnoc-axi-clk-bw-margin-perc = <20>; - qcom,msm-bus,name = "cam_ahb"; - qcom,msm-bus,num-cases = <7>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = + qcom,msm-bus,name = "cam_ahb"; /*Need to verify*/ + qcom,msm-bus,num-cases = <7>; /*Need to verify*/ + qcom,msm-bus,num-paths = <1>; /*Need to verify*/ + qcom,msm-bus,vectors-KBps = /*Need to verify*/ , , + MSM_BUS_SLAVE_CAMERA_CFG 0 76800>, , + MSM_BUS_SLAVE_CAMERA_CFG 0 76800>, , ; traffic-transaction-type = ; - constituent-paths = - ; parent-node = <&level1_nrt0_rd_wr>; }; @@ -437,9 +427,6 @@ traffic-data = ; traffic-transaction-type = ; - constituent-paths = - ; parent-node = <&level1_nrt0_rd_wr>; }; @@ -604,22 +591,23 @@ "cphy_rx_clk_src", "tfe_cphy_rx_clk", "tfe_clk_src", - "tfe_clk"; + "tfe_clk", + "tfe_axi_clk"; clocks = <&gcc GCC_CAMSS_TFE_0_CSID_CLK_SRC>, <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CLK>; + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; clock-rates = - <240000000 0 240000000 0 256000000 0>, - <384000000 0 341333333 0 460800000 0>, - <426400000 0 384000000 0 576000000 0>; + <240000000 240000000 0 240000000 256000000 256000000 150000000>, + <384000000 384000000 0 341333333 460800000 460800000 200000000>, + <426400000 426400000 0 384000000 576000000 576000000 300000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "tfe_csid_clk_src"; clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; @@ -635,18 +623,19 @@ camss-supply = <&gcc_camss_top_gdsc>; clock-names = "tfe_clk_src", - "tfe_clk"; + "tfe_clk", + "tfe_axi_clk"; clocks = <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CLK>; + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; clock-rates = - <256000000 0>, - <460800000 0>, - <576000000 0>; + <256000000 256000000 150000000>, + <460800000 460800000 200000000>, + <576000000 576000000 300000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "tfe_clk_src"; clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; @@ -668,22 +657,23 @@ "cphy_rx_clk_src", "tfe_cphy_rx_clk", "tfe_clk_src", - "tfe_clk"; + "tfe_clk", + "tfe_axi_clk"; clocks = <&gcc GCC_CAMSS_TFE_1_CSID_CLK_SRC>, <&gcc GCC_CAMSS_TFE_1_CSID_CLK>, <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>, <&gcc GCC_CAMSS_TFE_1_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CLK>; + <&gcc GCC_CAMSS_TFE_1_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; clock-rates = - <240000000 0 240000000 0 256000000 0>, - <384000000 0 341333333 0 460800000 0>, - <426400000 0 384000000 0 576000000 0>; + <240000000 240000000 0 240000000 256000000 256000000 150000000>, + <384000000 384000000 0 341333333 460800000 460800000 200000000>, + <426400000 426400000 0 384000000 576000000 576000000 300000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "tfe_csid_clk_src"; clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; @@ -699,18 +689,19 @@ camss-supply = <&gcc_camss_top_gdsc>; clock-names = "tfe_clk_src", - "tfe_clk"; + "tfe_clk", + "tfe_axi_clk"; clocks = <&gcc GCC_CAMSS_TFE_1_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CLK>; + <&gcc GCC_CAMSS_TFE_1_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; clock-rates = - <256000000 0>, - <460800000 0>, - <576000000 0>; + <256000000 256000000 150000000>, + <460800000 460800000 200000000>, + <576000000 576000000 300000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "tfe_clk_src"; clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; @@ -732,22 +723,23 @@ "cphy_rx_clk_src", "tfe_cphy_rx_clk", "tfe_clk_src", - "tfe_clk"; + "tfe_clk", + "tfe_axi_clk"; clocks = <&gcc GCC_CAMSS_TFE_2_CSID_CLK_SRC>, <&gcc GCC_CAMSS_TFE_2_CSID_CLK>, <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, <&gcc GCC_CAMSS_TFE_2_CPHY_RX_CLK>, <&gcc GCC_CAMSS_TFE_2_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_2_CLK>; + <&gcc GCC_CAMSS_TFE_2_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; clock-rates = - <240000000 0 240000000 0 256000000 0>, - <384000000 0 341333333 0 460800000 0>, - <426400000 0 384000000 0 576000000 0>; + <240000000 240000000 0 240000000 256000000 256000000 150000000>, + <384000000 384000000 0 341333333 460800000 460800000 200000000>, + <426400000 426400000 0 384000000 576000000 576000000 300000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "tfe_csid_clk_src"; clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; @@ -763,18 +755,19 @@ camss-supply = <&gcc_camss_top_gdsc>; clock-names = "tfe_clk_src", - "tfe_clk"; + "tfe_clk", + "tfe_axi_clk"; clocks = <&gcc GCC_CAMSS_TFE_2_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_2_CLK>; + <&gcc GCC_CAMSS_TFE_2_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; clock-rates = - <256000000 0>, - <460800000 0>, - <576000000 0>; + <256000000 256000000 150000000>, + <460800000 460800000 200000000>, + <576000000 576000000 300000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "tfe_clk_src"; clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; @@ -789,16 +782,14 @@ camss-supply = <&gcc_camss_top_gdsc>; clock-names = "cphy_rx_clk_src", - "tfe_0_cphy_rx_clk", - "gcc_camss_cphy_0_clk"; + "tfe_0_cphy_rx_clk"; clocks = <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, - <&gcc GCC_CAMSS_CPHY_0_CLK>; + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>; clock-rates = - <240000000 0 0>, - <341333333 0 0>, - <384000000 0 0>; + <240000000 240000000>, + <341333333 341333333>, + <384000000 384000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "cphy_rx_clk_src"; clock-control-debugfs = "false"; @@ -816,16 +807,14 @@ camss-supply = <&gcc_camss_top_gdsc>; clock-names = "cphy_rx_clk_src", - "tfe_1_cphy_rx_clk", - "gcc_camss_cphy_1_clk"; + "tfe_1_cphy_rx_clk"; clocks = <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>, - <&gcc GCC_CAMSS_CPHY_1_CLK>; + <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>; clock-rates = - <240000000 0 0>, - <341333333 0 0>, - <384000000 0 0>; + <240000000 240000000>, + <341333333 341333333>, + <384000000 384000000>; clock-cntl-level = "svs", "svs_l1", "turbo"; src-clock-name = "cphy_rx_clk_src"; clock-control-debugfs = "false"; @@ -870,13 +859,12 @@ <&gcc GCC_CAMSS_OPE_CLK_SRC>, <&gcc GCC_CAMSS_OPE_CLK>; clock-rates = - <171428571 200000000 0>, - <171428571 266600000 0>, - <240000000 465000000 0>, - <240000000 576000000 0>; + <171428571 200000000 200000000>, + <171428571 266600000 266600000>, + <240000000 465000000 465000000>, + <240000000 580000000 580000000>; clock-cntl-level = "svs", "svs_l1", "nominal", "turbo"; src-clock-name = "ope_clk_src"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; status = "ok"; }; }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cci.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cci.txt new file mode 100755 index 000000000000..59651a354157 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cci.txt @@ -0,0 +1,817 @@ +* Qualcomm Technologies, Inc. MSM CCI + +CCI (Camera Control Interface) is module that is use for camera sensor module +I2C communication. + +======================= +Required Node Structure +======================= +The camera CCI node must be described in two levels of device nodes. The +first level describe the overall CCI node structure. Second level nodes +describe camera sensor submodule nodes which is using CCI for +i2c communication. + +====================================== +First Level Node - CCI device +====================================== + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cci". + +- cell-index: cci hardware core index + Usage: required + Value type: + Definition: Should specify the Hardware index id. + +- reg + Usage: required + Value type: + Definition: offset and length of the register set + for the device for the cci operating in + compatible mode. + +- reg-names + Usage: required + Value type: + Definition: Should specify relevant names to each + reg property defined. + +- interrupts + Usage: required + Value type: + Definition: Interrupt associated with CCI HW. + +- interrupt-names + Usage: required + Value type: + Definition: Name of the interrupt. + +- gpios + Usage: required + Value type: + Definition: should specify the gpios to be used for the CCI. + +- gpio-req-tbl-num + Usage: required + Value type: + Definition: should specify the gpio table index. + +- gpio-req-tbl-flags + Usage: required + Value type: + Definition: should specify the gpio functions. + +- gpio-req-tbl-label + Usage: required + Value type: + Definition: should specify the gpio labels in + gpio-req-tbl-num property (in the same order) + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for CCI HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clock rates in Hz for CCI HW. + +- clock-cntl-level + Usage: required + Value type: + Definition: All different clock level node can support. + +- clocks + Usage: required + Value type: + Definition: all clock phandle and source clocks. + +- src-clock-name + Usage: required + Value type: + Definition: name for the source clock. + +- regulator-names + Usage: required + Value type: + Definition: name of the voltage regulators required for the device. + +- gdscr-supply + Usage: required + Value type: + Definition: should contain gdsr regulator used for cci clocks. + +- mmagic-supply + Usage: optional + Value type: + Definition: should contain mmagic regulator used for mmagic clocks. + +========================= +CCI clock settings +========================= +- I2c speed settings (*) + Usage: required + Definition: List of i2c rates for CCI HW. + - i2c_freq_100Khz + Definition: qcom,i2c_standard_mode - node should contain clock settings for + 100Khz + - i2c_freq_400Khz + Definition: qcom,i2c_fast_mode - node should contain clock settings for + 400Khz + - i2c_freq_custom + Definition: qcom,i2c_custom_mode - node can contain clock settings for + frequencies other than 100Khz and 400Khz which is specific to usecase. + Currently it has settings for 375Khz. + - i2c_freq_1Mhz + Definition: qcom,i2c_fast_plus_mode - node should contain clock + settings for 1Mhz +* if speed settings is not defined the low level driver can use "i2c_freq_custom" +like default + + - hw-thigh + Definition: should contain high period of the SCL clock in terms of CCI clock cycle + - hw-tlow + Definition: should contain high period of the SCL clock in terms of CCI clock cycle + - hw-tsu-sto + Definition: should contain setup time for STOP condition + - hw-tsu-sta + Definition: should contain setup time for Repeated START condition + - hw-thd-dat + Definition: should contain hold time for the data + - hw-thd-sta + Definition: should contain hold time for START condition + - hw-tbuf + Definition: should contain free time between a STOP and a START condition + - hw-scl-stretch-en + Definition: should contain enable or disable clock stretching + - hw-trdhld + Definition: should contain internal hold time for SDA + - hw-tsp + Definition: should contain filtering of glitches + +Example: + + qcom,cci@0xfda0c000 { + cell-index = <0>; + compatible = "qcom,cci"; + reg = <0xfda0c000 0x300>; + reg-names = "cci"; + interrupts = <0 50 0>; + interrupt-names = "cci"; + clock-names = "camnoc_axi_clk", "soc_ahb_clk", + "slow_ahb_src_clk", "cpas_ahb_clk", + "cci_clk", "cci_clk_src"; + clock-rates = <0 0 80000000 0 0 37500000>; + clock-cntl-level = "turbo"; + gpios = <&tlmm 17 0>, + <&tlmm 18 0>, + <&tlmm 19 0>, + <&tlmm 20 0>; + gpio-tbl-num = <0 1 2 3>; + gpio-tbl-flags = <1 1 1 1>; + gpio-tbl-label = "CCI_I2C_DATA0", + "CCI_I2C_CLK0", + "CCI_I2C_DATA1", + "CCI_I2C_CLK1"; + i2c_freq_100Khz: qcom,i2c_standard_mode { + hw-thigh = <78>; + hw-tlow = <114>; + hw-tsu-sto = <28>; + hw-tsu-sta = <28>; + hw-thd-dat = <10>; + hw-thd-sta = <77>; + hw-tbuf = <118>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <1>; + status = "ok"; + }; + i2c_freq_400Khz: qcom,i2c_fast_mode { + hw-thigh = <20>; + hw-tlow = <28>; + hw-tsu-sto = <21>; + hw-tsu-sta = <21>; + hw-thd-dat = <13>; + hw-thd-sta = <18>; + hw-tbuf = <25>; + hw-scl-stretch-en = <0>; + hw-trdhld = <6>; + hw-tsp = <3>; + status = "ok"; + }; + i2c_freq_custom: qcom,i2c_custom_mode { + hw-thigh = <15>; + hw-tlow = <28>; + hw-tsu-sto = <21>; + hw-tsu-sta = <21>; + hw-thd-dat = <13>; + hw-thd-sta = <18>; + hw-tbuf = <25>; + hw-scl-stretch-en = <1>; + hw-trdhld = <6>; + hw-tsp = <3>; + status = "ok"; + }; + i2c_freq_1Mhz: qcom,i2c_fast_plus_mode { + hw-thigh = <16>; + hw-tlow = <22>; + hw-tsu-sto = <17>; + hw-tsu-sta = <18>; + hw-thd-dat = <16>; + hw-thd-sta = <15>; + hw-tbuf = <19>; + hw-scl-stretch-en = <1>; + hw-trdhld = <3>; + hw-tsp = <3>; + cci-clk-src = <37500000>; + status = "ok"; + }; + }; + +======================================= +Second Level Node - CAM SENSOR MODULES +======================================= + +======================================= +CAM SENSOR RESOURCE MANAGER +======================================= +Camera Sensor Resource manager node contains properties of shared camera +sensor resource. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-res-mgr". + +- shared-gpios + Usage: optional + Value type: + Definition: should contain the gpios which are used by two or more + cameras, and these cameras may be opened together. + +- pinctrl-names + Usage: optional + Value type: + Definition: List of names to assign the shared pin state defined in pinctrl device node + +- pinctrl-<0..n> + Usage: optional + Value type: + Definition: Lists phandles each pointing to the pin configuration node within a pin + controller. These pin configurations are installed in the pinctrl device node. + + +============================= +CAMERA IMAGE SENSOR MODULE +============================= +Image sensor node contains properties of camera image sensor + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-sensor". + +- cell-index: cci hardware core index + Usage: required + Value type: + Definition: Should specify the Hardware index id. + +- reg + Usage: required + Value type: + Definition: offset and length of the register set + for the device for the cci operating in + compatible mode. + +- cci-device + Usage: required + Value type: + Definition: should contain i2c device id to be used for this camera + sensor + +- cci-master + Usage: required + Value type: + Definition: should contain i2c master id to be used for this camera + sensor + - 0 -> MASTER 0 + - 1 -> MASTER 1 + +- csiphy-sd-index + Usage: required + Value type: + Definition: should contain csiphy instance that will used to + receive sensor data (0, 1, 2, 3). + +- cam_vdig-supply + Usage: required + Value type: + Definition: should contain regulator from which digital voltage is + supplied + +- cam_vana-supply + Usage: required + Value type: + Definition: should contain regulator from which analog voltage is + supplied + +- cam_vio-supply + Usage: required + Value type: + Definition: should contain regulator from which IO voltage is supplied + +- cam_bob-supply + Usage: optional + Value type: + Definition: should contain regulator from which BoB voltage is supplied + +- regulator-names + Usage: required + Value type: + Definition: should contain names of all regulators needed by this + sensor + +- rgltr-cntrl-support + Usage: required + Value type: + Definition: This property is required if the sw control regulator parameters + e.g. rgltr-min-voltage + +- rgltr-min-voltage + Usage: required + Value type: + Definition: should contain minimum voltage level for regulators mentioned + in regulator-names property (in the same order) + +- rgltr-max-voltage + Usage: required + Value type: + Definition: should contain maximum voltage level for regulators mentioned + in regulator-names property (in the same order) + +- rgltr-load-current + Usage: required + Value type: + Definition: should contain optimum voltage level for regulators mentioned + in regulator-names property (in the same order) + +- sensor-position-roll + Usage: required + Value type: + Definition: should contain sensor rotational angle with respect to axis of + reference. i.e. 0, 90, 180, 360 + +- sensor-position-pitch + Usage: required + Value type: + Definition: should contain sensor rotational angle with respect to axis of + reference. i.e. 0, 90, 180, 360 + +- sensor-position-yaw + Usage: required + Value type: + Definition: should contain sensor rotational angle with respect to axis of + reference. i.e. 0, 90, 180, 360 + +- qcom,secure + Usage: optional + Value type: + Definition: should be enabled to operate the camera in secure mode + +- gpio-no-mux + Usage: optional + Value type: + Definition: should contain field to indicate whether gpio mux table is + available. i.e. 1 if gpio mux is not available, 0 otherwise + +- cam_vaf-supply + Usage: optional + Value type: + Definition: should contain regulator from which AF voltage is supplied + +- pwm-switch + Usage: optional + Value type: + Definition: This property is required for regulator to switch into PWM mode. + +- gpios + Usage: required + Value type: + Definition: should contain phandle to gpio controller node and array of + #gpio-cells specifying specific gpio (controller specific) + +- gpio-reset + Usage: required + Value type: + Definition: should contain index to gpio used by sensors reset_n + +- gpio-standby + Usage: optional + Value type: + Definition: should contain index to gpio used by sensors standby_n + +- gpio-vio + Usage: optional + Value type: + Definition: should contain index to gpio used by sensors io vreg enable + +- gpio-vana + Usage: optional + Value type: + Definition: should contain index to gpio used by sensors analog vreg enable + +- gpio-vdig + Usage: optional + Value type: + Definition: should contain index to gpio used by sensors digital vreg enable + +- gpio-vaf + Usage: optional + Value type: + Definition: should contain index to gpio used by sensors af vreg enable + +- gpio-af-pwdm + Usage: optional + Value type: + Definition: should contain index to gpio used by sensors af pwdm_n + +- gpio-req-tbl-num + Usage: optional + Value type: + Definition: should contain index to gpios specific to this sensor + +- gpio-req-tbl-flags + Usage: optional + Value type: + Definition: should contain direction of gpios present in + gpio-req-tbl-num property (in the same order) + +- gpio-req-tbl-label + Usage: optional + Value type: + Definition: should contain name of gpios present in + gpio-req-tbl-num property (in the same order) + +- gpio-set-tbl-num + Usage: optional + Value type: + Definition: should contain index of gpios that need to be + configured by msm + +- gpio-set-tbl-flags + Usage: optional + Value type: + Definition: should contain value to be configured for the gpios + present in gpio-set-tbl-num property (in the same order) + +- gpio-set-tbl-delay + Usage: optional + Value type: + Definition: should contain amount of delay after configuring + gpios as specified in gpio_set_tbl_flags property (in the same order) + +- actuator-src + Usage: optional + Value type: + Definition: if auto focus is supported by this sensor, this + property should contain phandle of respective actuator node + +- led-flash-src + Usage: optional + Value type: + Definition: if LED flash is supported by this sensor, this + property should contain phandle of respective LED flash node + +- qcom,vdd-cx-supply + Usage: optional + Value type: + Definition: should contain regulator from which cx voltage is supplied + +- qcom,vdd-cx-name + Usage: optional + Value type: + Definition: should contain names of cx regulator + +- eeprom-src + Usage: optional + Value type: + Definition: if eeprom memory is supported by this sensor, this + property should contain phandle of respective eeprom nodes + +- ois-src + Usage: optional + Value type: + Definition: if optical image stabilization is supported by this sensor, + this property should contain phandle of respective ois node + +- ir-led-src + Usage: optional + Value type: + Definition: if ir led is supported by this sensor, this property + should contain phandle of respective ir-led node + +- qcom,ir-cut-src + Usage: optional + Value type: + Definition: if ir cut is supported by this sensor, this property + should contain phandle of respective ir-cut node + +- qcom,special-support-sensors + Usage: required + Value type: + Definition: if only some special sensors are supported + on this board, add sensor name in this property. + +- use-shared-clk + Usage: optional + Value type: + Definition: It is booloean property. This property is required + if the clk is shared clk between different sensor and ois, if this + device need to be opened together. + +- clock-rates + Usage: required + Value type: + Definition: clock rate in Hz. + +- clock-cntl-level + Usage: required + Value type: + Definition: All different clock level node can support. + +- clock-cntl-support + Usage: optional + Value type: + Definition: Says whether clock control support is present or not + +- clocks + Usage: required + Value type: + Definition: all clock phandle and source clocks. + +- clock-control + Usage: optional + Value type: + Definition: The valid fields are "NO_SET_RATE", "INIT_RATE" and + "SET_RATE". "NO_SET_RATE" the corresponding clock is enabled without setting + the rate assuming some other driver has already set it to appropriate rate. + "INIT_RATE" clock rate is not queried assuming some other driver has set + the clock rate and ispif will set the the clock to this rate. + "SET_RATE" clock is enabled and the rate is set to the value specified + in the property clock-rates. + +============================= +ACTUATOR MODULE +============================= + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,actuator". + +- cell-index: cci hardware core index + Usage: required + Value type: + Definition: Should specify the Hardware index id. + +- reg + Usage: required + Value type: + Definition: offset and length of the register set + for the device for the cci operating in + compatible mode. + +- cci-device + Usage: required + Value type: + Definition: should contain i2c device id to be used for this camera + sensor + +- cci-master + Usage: required + Value type: + Definition: should contain i2c master id to be used for this camera + sensor + - 0 -> MASTER 0 + - 1 -> MASTER 1 + +- cam_vaf-supply + Usage: required + Value type: + Definition: should contain regulator from which AF voltage is supplied + +- regulator-names + Usage: required + Value type: + Definition: should contain names of all regulators needed by this + actuator. i.e. "cam_vaf" + +- rgltr-cntrl-support + Usage: optional + Value type: + Definition: It is booloean property. This property is required + if the code and regulator control parameters e.g. rgltr-min-voltage + +- rgltr-min-voltage + Usage: optional + Value type: + Definition: should contain minimum voltage level in mcrovolts + for regulators mentioned in regulator-names property (in the same order) + +- rgltr-max-voltage + Usage: optional + Value type: + Definition: should contain maximum voltage level in mcrovolts + for regulators mentioned in regulator-names property (in the same order) + +- rgltr-load-current + Usage: optional + Value type: + Definition: should contain the maximum current in microamps + required from the regulators mentioned in the regulator-names property + (in the same order). + +============================= +OIS MODULE +============================= + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,ois". + +- cell-index: cci hardware core index + Usage: required + Value type: + Definition: Should specify the Hardware index id. + +- reg + Usage: required + Value type: + Definition: offset and length of the register set + for the device for the cci operating in + compatible mode. + +- cci-device + Usage: required + Value type: + Definition: should contain i2c device id to be used for this camera + sensor + +- cci-master + Usage: required + Value type: + Definition: should contain i2c master id to be used for this camera + sensor + - 0 -> MASTER 0 + - 1 -> MASTER 1 + +- cam_vaf-supply + Usage: required + Value type: + Definition: should contain regulator from which AF voltage is supplied + +- regulator-names + Usage: required + Value type: + Definition: should contain names of all regulators needed by this + actuator. i.e. "cam_vaf" + +- rgltr-cntrl-support + Usage: optional + Value type: + Definition: It is booloean property. This property is required + if the code and regulator control parameters e.g. rgltr-min-voltage + +- rgltr-min-voltage + Usage: optional + Value type: + Definition: should contain minimum voltage level in mcrovolts + for regulators mentioned in regulator-names property (in the same order) + +- rgltr-max-voltage + Usage: optional + Value type: + Definition: should contain maximum voltage level in mcrovolts + for regulators mentioned in regulator-names property (in the same order) + +- rgltr-load-current + Usage: optional + Value type: + Definition: should contain the maximum current in microamps + required from the regulators mentioned in the regulator-names property + (in the same order). + +- use-shared-clk + Usage: optional + Value type: + Definition: This property is required if the clk is shared clk between different + sensor and ois, if this device need to be opened together. + +Example: +&soc { + led_flash0: qcom,camera-flash@0 { + cell-index = <0>; + compatible = "qcom,camera-flash"; + flash-source = <&pmi8994_flash0 &pmi8994_flash1>; + torch-source = <&pmi8998_torch0 &pmi8998_torch1>; + switch-source = <&pmi8998_switch>; + status = "ok"; + }; +}; + +&cam_cci0 { + actuator0: qcom,actuator@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,actuator"; + cci-device = <0>; + cci-master = <0>; + cam_vaf-supply = <&pmi8998_bob>; + regulator-names = "cam_vaf"; + rgltr-cntrl-support; + rgltr-min-voltage = <2800000>; + rgltr-max-voltage = <2800000>; + rgltr-load-current = <100000>; + }; + + ois0: qcom,ois@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,ois"; + cci-device = <0>; + cci-master = <0>; + cam_vaf-supply = <&pmi8998_bob>; + regulator-names = "cam_vaf"; + rgltr-cntrl-support; + rgltr-min-voltage = <2800000>; + rgltr-max-voltage = <2800000>; + rgltr-load-current = <100000>; + }; + + qcom,cam-res-mgr { + compatible = "qcom,cam-res-mgr"; + status = "ok"; + shared-gpios = <18 19>; + pinctrl-names = "cam_res_mgr_default", "cam_res_mgr_suspend"; + pinctrl-0 = <&cam_shared_clk_active &cam_res_mgr_active>; + pinctrl-1 = <&cam_shared_clk_suspend &cam_res_mgr_suspend>; + }; + + qcom,cam-sensor@0 { + cell-index = <0>; + compatible = "qcom,camera"; + reg = <0x0>; + csiphy-sd-index = <0>; + sensor-position-roll = <90>; + sensor-position-pitch = <0>; + sensor-position-yaw = <180>; + secure = <1>; + led-flash-src = <&led_flash0>; + actuator-src = <&actuator0>; + ois-src = <&ois0>; + eeprom-src = <&eeprom0>; + cam_vdig-supply = <&pm8009_l2>; + cam_vio-supply = <&pm8009l_l1>; + cam_vana-supply = <&pm8009l_l5>; + cam_bob-supply = <&pm8150l_bob>; + cam_clk-supply = <&tital_top_gdsc>; + regulator-names = "cam_vio", "cam_vana", "cam_vdig", + "cam_clk", "cam_bob"; + rgltr-cntrl-support; + pwm-switch; + rgltr-min-voltage = <0 2800000 1200000 0 3008000>; + rgltr-max-voltage = <0 2800000 1200000 0 4000000>; + rgltr-load-current = <0 80000 1200000 0 2000000>; + gpio-no-mux = <0>; + pinctrl-names = "cam_default", "cam_suspend"; + pinctrl-0 = <&cam_sensor_mclk0_active + &cam_sensor_rear_active>; + pinctrl-1 = <&cam_sensor_mclk0_suspend + &cam_sensor_rear_suspend>; + gpios = <&tlmm 13 0>, + <&tlmm 80 0>, + <&tlmm 79 0>; + gpio-reset = <1>; + gpio-standby = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK0", + "CAM_RESET0", + "CAM_VANA"; + sensor-position = <0>; + sensor-mode = <0>; + cci-device = <0>; + cci-master = <0>; + status = "ok"; + use-shared-clk; + clocks = <&clock_mmss clk_mclk0_clk_src>, + <&clock_mmss clk_camss_mclk0_clk>; + clock-names = "cam_src_clk", "cam_clk"; + clock-cntl-leveli = "turbo"; + clock-rates = <24000000>; + }; +}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cdm.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cdm.txt new file mode 100755 index 000000000000..a407bd656a0b --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cdm.txt @@ -0,0 +1,157 @@ +* Qualcomm Technologies, Inc. MSM Camera CDM + +CDM (Camera Data Mover) is module intended to provide means for fast programming +camera registers and lookup tables. + +======================= +Required Node Structure +======================= +CDM Interface node takes care of the handling has HW nodes and provide interface +for camera clients. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-cdm-intf". + +- label + Usage: required + Value type: + Definition: Should be "cam-cdm-intf". + +- num-hw-cdm + Usage: required + Value type: + Definition: Number of supported HW blocks. + +- cdm-client-names + Usage: required + Value type: + Definition: List of Clients supported by CDM interface. + +Example: + qcom,cam-cdm-intf { + compatible = "qcom,cam-cdm-intf"; + label = "cam-cdm-intf"; + num-hw-cdm = <1>; + cdm-client-names = "vfe", + "jpeg-dma", + "jpeg", + "fd"; + }; + +======================= +Required Node Structure +======================= +CDM HW node provides interface for camera clients through +to CDM interface node. + +- cell-index + Usage: required + Value type: + Definition: Node instance number. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam170-cpas-cdm0", "qcom,cam480-cpas-cdm0", + "qcom,cam480-cpas-cdm1", "qcom,cam480-cpas-cdm2", "qcom,cam-cpas-cdm1_0", + "qcom,cam-cpas-cdm1_1", "qcom,cam-cpas-cdm1_2", "qcom,cam-ife-cdm1_2", + "qcom,cam-cpas-cdm2_0" or "qcom,cam-ope-cdm2_0" + +- label + Usage: required + Value type: + Definition: Should be "cpas-cdm". + +- reg-names + Usage: required + Value type: + Definition: Name of the register resources. + +- reg + Usage: required + Value type: + Definition: Register values. + +- reg-cam-base + Usage: required + Value type: + Definition: Offset of the register space compared to + to Camera base register space. + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: optional + Value type: + Definition: Interrupt associated with CDM HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for CDM HW. + +- camss-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for CDM HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for CDM HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- cdm-client-names + Usage: required + Value type: + Definition: List of Clients supported by CDM HW node. + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels. + Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo. + +Example: + qcom,cpas-cdm0@ac48000 { + cell-index = <0>; + compatible = "qcom,cam170-cpas-cdm0"; + label = "cpas-cdm0"; + reg = <0xac48000 0x1000>; + reg-names = "cpas-cdm"; + interrupts = <0 461 0>; + interrupt-names = "cpas-cdm"; + regulator-names = "camss"; + camss-supply = <&titan_top_gdsc>; + clock-names = "soc_ahb_clk", + "titan_top_ahb_clk", + "cam_axi_clk", + "camcc_slow_ahb_clk_src", + "cpas_top_ahb_clk", + "camnoc_axi_clk"; + clocks = <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>; + qcom,clock-rates = <0 80000000 80000000 80000000 80000000 80000000>; + cdm-client-names = "ife"; + clock-cntl-level = "turbo"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cpas.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cpas.txt new file mode 100755 index 000000000000..c18b74391c18 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-cpas.txt @@ -0,0 +1,406 @@ +* Qualcomm Technologies, Inc. MSM Camera CPAS + +The MSM camera CPAS device provides dependency definitions for +enabling Camera CPAS HW and provides the Client definitions +for all HW blocks that use CPAS driver for BW voting. These +definitions consist of various properties that define the list +of clients supported, AHB, AXI master-slave IDs used for BW +voting. + +======================= +Required Node Structure +======================= +The camera CPAS device must be described in five levels. The first level has +general description of cpas including compatibility, interrupts, power info +etc. +The second level deals with information related to CPAS clients and how +the BW should be calculated. For simplicity in BW vote consolidation, the +grouping of granular votes pertaining to CPAS clients is represented as nodes +at four CAMNOC levels. The nodes at a particular level have some common +properties such as traffic merge type which indicates whether the votes at a +node have to be summed up, sum divided by two or taken max of all. CAMNOC Level +zero node usually represents granular vote info for clients. CAMNOC Level one +represents nodes which are clubbed together by arbiter in CAMNOC diagram. CAMNOC +Level two represents consolidated read and write nodes for RT and NRT paths. +CAMNOC Level three provides axi port information and these have nodes where all +paths from clients eventually converge according to their properties. This +includes master-slave IDs, ab, ib values for mnoc, camnoc bus interface + +================================== +First Level Node - CAM CPAS device +================================== +- cell-index + Usage: required + Value type: + Definition: Node instance number. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-cpas". + +- label + Usage: required + Value type: + Definition: Should be "cpas". + +- arch-compat + Usage: required + Value type: + Definition: Should be "cpas_top" or "camss_top". + +- reg-names + Usage: required + Value type: + Definition: Name of the register resources. + +- reg + Usage: required + Value type: + Definition: Register values. + +- reg-cam-base + Usage: required + Value type: + Definition: Offset of the register space compared to + to Camera base register space. + +- cam_hw_fuse + Usage: optional + Value type: + Definition: List of fuse based features and respective + fuse info. + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: optional + Value type: + Definition: Interrupt associated with CAMNOC HW. + +- qcom,cpas-hw-ver + Usage: required + Value type: + Definition: CAM HW Version information. + +- camnoc-axi-min-ib-bw + Usage: optional + Value type: + Definition: Min camnoc axi bw for the given target. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for CPAS HW. + +- camss-vdd-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for CPAS HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for CPAS HW. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels. + Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo. + +- control-camnoc-axi-clk + Usage: optional + Value type: + Definition: Bool property specifying whether to control camnoc axi + clock from cpas driver. + +- camnoc-bus-width + Usage: required if control-camnoc-axi-clk is enabled + Value type: + Definition: camnoc bus width. + +- camnoc-axi-clk-bw-margin-perc + Usage: optional + Value type: + Definition: Percentage value to be added to camnoc bw while calculating + camnoc axi clock frequency. + +- qcom,msm-bus,name +- qcom,msm-bus,num-cases +- qcom,msm-bus,num-paths +- qcom,msm-bus,vectors-KBps + Please refer Documentation/devicetree/bindings/arm/msm/msm_bus.txt + for the properties above. + +- vdd-corners + Usage: required + Value type: + Definition: List of vdd corners to map for ahb level. + +- vdd-corner-ahb-mapping + Usage: required + Value type: + Definition: List of ahb level strings corresponds to vdd-corners. + Supported strings: suspend, svs, nominal, turbo + +- client-id-based + Usage: required + Value type: + Definition: Bool property specifying whether CPAS clients are ID based. + +- client-names + Usage: required + Value type: + Definition: List of Clients supported by CPAS. + +- client-bus-camnoc-based + Usage: optional + Value type: + Definition: Bool property specifying whether Clients are connected + through CAMNOC for AXI access. + +=================================================================== +Third Level Node - CAMNOC Level nodes +=================================================================== +- level-index + Usage: required + Value type: + Definition: Number representing level index for ndoes at current CAMNOC level + +- camnoc-max-needed + Usage: optional + Value type: + Definition: Bool property for all votes at current level to be taken maximum + for CAMNOC BW calculation. + +=================================================================== +Fourth Level Node - Generic CAMNOC node properties +=================================================================== +- cell-index + Usage: required + Value type: + Definition: Unique index of node to be used by CPAS driver. + +- node-name + Usage: required + Value type: + Definition: Unique name representing this node. + +- path-data-type + Usage: required if a CAMNOC Level 0 Node + Value type: + Definition: Type of path data for a specific client. + Supported : CAM_CPAS_PATH_DATA_IFE_LINEAR, CAM_CPAS_PATH_DATA_ALL, etc. + Please refer dt-bindings/msm/msm-camera.h for all supported + definitions. + +- path-transaction-type + Usage: required if a CAMNOC Level 0 Node + Value type: + Definition: Type of path transaction for a specific client. + Supported : CAM_CPAS_TRANSACTION_READ, CAM_CPAS_TRANSACTION_WRITE + +- client-name + Usage: required if a CAMNOC Level 0 Node + Value type: + Definition: Name of the client with above properties. + Supported : From "client-names" property in CPAS node + +- constituent-paths + Usage: optional, applicable only to CAMNOC Level 0 Nodes + Value type: + Definition: List of constituents of path data type of current node. + Supported : CAM_CPAS_PATH_DATA_IFE_VID, CAM_CPAS_PATH_DATA_IFE_DISP, etc. + Please refer dt-bindings/msm/msm-camera.h for all supported + definitions. + +- traffic-merge-type + Usage: required if NOT a CAMNOC Level 0 Node + Value type: + Definition: Type of traffic merge for that node. + Supported : CAM_CPAS_TRAFFIC_MERGE_SUM, CAM_CPAS_TRAFFIC_MERGE_SUM_INTERLEAVE. + +- parent-node + Usage: required for all except CAMNOC Level 3 Nodes + Value type: + Definition: Parent node of this node. Parent node must be at least + one level above the current level. + +- bus-width-factor + Usage: optional + Value type: + Definition: For bus width factor consideration in CAMNOC BW calculation + +- qcom,axi-port-name + Usage: required at CAMNOC Level 3 + Value type: + Definition: Name of the AXI Port. + +- ib-bw-voting-needed + Usage: optional + Value type: + Definition: Bool property indicating axi port requires instantaneous bandwidth + +=================================================================== +Fifth Level Node - CAM AXI Bus Properties +=================================================================== +- qcom,msm-bus,name +- qcom,msm-bus,num-cases +- qcom,msm-bus,num-paths +- qcom,msm-bus,vectors-KBps + Please refer Documentation/devicetree/bindings/arm/msm/msm_bus.txt + for the properties above. + +- qcom,msm-bus-vector-dyn-vote + Usage: optional + Value type: + Definition: Bool property specifying whether this bus client + is dynamic vote based. + +Example: + + qcom,cam-cpas@ac40000 { + cell-index = <0>; + compatible = "qcom,cam-cpas"; + label = "cpas"; + arch-compat = "cpas_top"; + status = "ok"; + reg-names = "cam_cpas_top", "cam_camnoc"; + reg = <0xac40000 0x1000>, + <0xac42000 0x5000>; + reg-cam-base = <0x40000 0x42000>; + cam_hw_fuse = , + ; + interrupt-names = "cpas_camnoc"; + interrupts = <0 459 0>; + qcom,cpas-hw-ver = <0x170100>; /* Titan v170 v1.0.0 */ + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = "gcc_ahb_clk", + "gcc_axi_clk", + "soc_ahb_clk", + "cpas_ahb_clk", + "slow_ahb_clk_src", + "camnoc_axi_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>; + src-clock-name = "slow_ahb_clk_src"; + clock-rates = <0 0 0 0 80000000 0>; + clock-cntl-level = "turbo"; + control-camnoc-axi-clk; + camnoc-bus-width = <32>; + camnoc-axi-clk-bw-margin-perc = <10>; + qcom,msm-bus,name = "cam_ahb"; + qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + , + , + ; + client-id-based; + client-names = + "csiphy0", "csiphy1", "csiphy2", "csiphy3", + "csiphy4", "csiphy5", "cci0", "cci1", + "csid0", "csid1", "csid2", "csid3", + "csid4", "csid5", "csid6", + "ife0", "ife1", "ife2", "ife3", "custom0", + "ipe0", "cam-cdm-intf0", "cpas-cdm0", "cpas-cdm1", + "cpas-cdm2", + "bps0", "icp0", "jpeg-dma0", "jpeg-enc0", + "fd0"; + + camera-bus-nodes { + level3-nodes { + level-index = <3>; + level3_rt0_rd_wr_sum: level3-rt0-rd-wr-sum { + cell-index = <0>; + node-name = "level3-rt0-rd-wr-sum"; + traffic-merge-type = + ; + qcom,axi-port-name = "cam_hf_0"; + ib-bw-voting-needed; + qcom,axi-port-mnoc { + qcom,msm-bus,name = + "cam_hf_0_mnoc"; + qcom,msm-bus-vector-dyn-vote; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + , + ; + }; + }; + }; + level2-nodes { + level-index = <2>; + camnoc-max-needed; + level2_rt0_wr: level2-rt0-wr { + cell-index = <3>; + node-name = "level2-rt0-wr"; + parent-node = <&level3_rt0_rd_wr_sum>; + traffic-merge-type = + ; + }; + }; + level1-nodes { + level-index = <1>; + camnoc-max-needed; + level1_rt0_wr0: level1-rt0-wr0 { + cell-index = <8>; + node-name = "level1-rt0-wr0"; + parent-node = <&level2_rt0_wr>; + traffic-merge-type = + ; + }; + }; + level0-nodes { + level-index = <0>; + ife0_ubwc_stats_wr: ife0-ubwc-stats-wr { + cell-index = <16>; + node-name = "ife0-ubwc-stats-wr"; + client-name = "ife0"; + traffic-data = + ; + traffic-transaction-type = + ; + constituent-paths = + ; + parent-node = <&level1_rt0_wr0>; + }; + }; + }; + }; + diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-csiphy.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-csiphy.txt new file mode 100755 index 000000000000..f67f4ef7986a --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-csiphy.txt @@ -0,0 +1,117 @@ +* Qualcomm Technologies, Inc. MSM CSI Phy + +======================= +Required Node Structure +======================= +The camera CSIPHY node must be described in First level of device nodes. The +first level describe the overall CSIPHY node structure. + +====================================== +First Level Node - CSIPHY device +====================================== + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,csiphy-v1.0", + "qcom,csiphy-v1.1", "qcom,csiphy-v1.2", "qcom,csiphy-v1.2.1", + "qcom,csiphy-v1.2.2", "qcom,csiphy-v2.0", "qcom,csiphy". + +- cell-index: csiphy hardware core index + Usage: required + Value type: + Definition: Should specify the Hardware index id. + +- reg + Usage: required + Value type: + Definition: offset and length of the register set + for the device for the csiphy operating in + compatible mode. + +- reg-names + Usage: required + Value type: + Definition: Should specify relevant names to each + reg property defined. + +- reg-cam-base + Usage: required + Value type: + Definition: offset of CSIPHY in camera hw block + +- interrupts + Usage: required + Value type: + Definition: Interrupt associated with CCI HW. + +- interrupt-names + Usage: required + Value type: + Definition: Name of the interrupt. + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for CSIPHY HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clock rates in Hz for CSIPHY HW. + +- clock-cntl-level + Usage: required + Value type: + Definition: All different clock level node can support. + +- clocks + Usage: required + Value type: + Definition: all clock phandle and source clocks. + +- regulator-names + Usage: required + Value type: + Definition: name of the voltage regulators required for the device. + +- gdscr-supply + Usage: required + Value type: + Definition: should contain gdsr regulator used for CSIPHY clocks. + +- mipi-csi-vdd-supply + Usage: required + Value type: + Definition: should contain phandle for mipi-csi-vdd regulator used for + CSIPHY device. + +- csi-vdd-voltage + Usage: required + Value type: + Definition: should contain required voltage for csi-vdd supply for CSIPHY. + +Example: + +qcom,csiphy@ac65000 { + cell-index = <0>; + compatible = "qcom,csiphy-v1.0", "qcom,csiphy"; + reg = <0xac65000 0x200>; + reg-cam-base = <0x65000>; + reg-names = "csiphy"; + interrupts = <0 477 0>; + interrupt-names = "csiphy"; + regulator-names = "gdscr", "refgen"; + mipi-csi-vdd-supply = <&pm8998_l1>; + csi-vdd-voltage = <1200000>; + gdscr-supply = <&titan_top_gdsc>; + clocks = <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&clock_camcc CAM_CC_CSIPHY0_CLK>, + <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", "csiphy0_clk", + "csi0phytimer_clk_src", "csi0phytimer_clk"; + clock-rates = <400000000 0 300000000 0>; + clock-cntl-level = "turbo"; + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-custom-hw.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-custom-hw.txt new file mode 100755 index 000000000000..61125d0c8087 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-custom-hw.txt @@ -0,0 +1,28 @@ +* Qualcomm Technologies, Inc. MSM Camera Custom HW + +Camera Custom device provides the definitions for enabling +the custom hardware. It also provides the functions for the client +to control the Custom hardware. + +======================= +Required Node Structure +======================= +The Custom device is described in one level of the device node. + +====================================== +First Level Node - CAM Custom device +====================================== +Required properties: +- compatible + Usage: required + Value type: + Definition: Should specify the compatibility string for matching the + driver. e.g. "qcom,cam_custom_hw_sub_mod". + +Example: + + qcom,cam-custom-hw { + compatible = "qcom,cam_custom_hw_sub_mod"; + arch-compat = "custom"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-custom.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-custom.txt new file mode 100755 index 000000000000..8c5cc6148c5b --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-custom.txt @@ -0,0 +1,31 @@ +* Qualcomm Technologies, Inc. MSM Camera Custom + +The MSM camera Custom driver provides the definitions for enabling +the Camera custom hadware. It provides the functions for the Client to +control the custom hardware. + +======================= +Required Node Structure +======================= +The camera Custom device is described in one level of device node. + +================================== +First Level Node - CAM CUSTOM device +================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-custom". + +- arch-compat + Usage: required + Value type: + Definition: Should be "custom". + +Example: + + qcom,cam-custom { + compatible = "qcom,cam-custom"; + arch-compat = "custom"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-eeprom.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-eeprom.txt new file mode 100755 index 000000000000..d77f337a9e3c --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-eeprom.txt @@ -0,0 +1,503 @@ +* Qualcomm Technologies, Inc. MSM EEPROM + +EEPROM is a one time programmed(OTP) device that stores the calibration data +use for camera sensor. It may either be integrated in the sensor module or in +the sensor itself. As a result, the power, clock and GPIOs may be the same as +the camera sensor. The following describes the page block map, power supply, +clock, GPIO and power on sequence properties of the EEPROM device. + +======================================================= +Required Node Structure if probe happens from userspace +======================================================= +The EEPROM device is described in one level of the device node. + +====================================== +First Level Node - CAM EEPROM device +====================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,eeprom". + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg + Usage: required + Value type: + Definition: Register values. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for EEPROM HW. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- rgltr-cntrl-support + Usage: required + Value type: + Definition: This property specifies if the regulator control is supported + e.g. rgltr-min-voltage. + +- rgltr-min-voltage + Usage: required + Value type: + Definition: should contain minimum voltage level for regulators + mentioned in regulator-names property. + +- rgltr-max-voltage + Usage: required + Value type: + Definition: should contain maximum voltage level for regulators + mentioned in regulator-names property. + +- rgltr-load-current + Usage: required + Value type: + Definition: should contain the maximum current in microamps required for + the regulators mentioned in regulator-names property. + +- gpio-no-mux + Usage: required + Value type: + Definition: should specify the gpio mux type. + +- gpios + Usage: required + Value type: + Definition: should specify the gpios to be used for the eeprom. + +- gpio-reset + Usage: required + Value type: + Definition: should specify the reset gpio index. + +- gpio-standby + Usage: required + Value type: + Definition: should specify the standby gpio index. + +- gpio-req-tbl-num + Usage: required + Value type: + Definition: should specify the gpio table index. + +- gpio-req-tbl-flags + Usage: required + Value type: + Definition: should specify the gpio functions. + +- gpio-req-tbl-label + Usage: required + Value type: + Definition: should specify the gpio labels. + +- sensor-position + Usage: required + Value type: + Definition: should contain the mount angle of the camera sensor. + +- cci-device + Usage: required + Value type: + Definition: should contain i2c device id to be used for this camera + sensor + +- cci-master + Usage: required + Value type: + Definition: should contain i2c master id to be used for this camera + sensor. + +- sensor-mode + Usage: required + Value type: + Definition: should contain sensor mode supported. + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for EEPROM HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for EEPROM HW. + +- clock-cntl-level + Usage: required + Value type: + Definition: says what all different clock levels eeprom node has. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +Example: + + eeprom0: qcom,eeprom@0 { + cell-index = <0>; + reg = <0x0>; + compatible = "qcom,eeprom"; + cam_vdig-supply = <&pm8998_l5>; + cam_vio-supply = <&pm8998_lvs1>; + regulator-names = "cam_vdig", "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 0>; + rgltr-max-voltage = <1200000 0>; + rgltr-load-current = <0 80000 105000 0>; + gpio-no-mux = <0>; + gpios = <&msmgpio 26 0>, + <&msmgpio 37 0>, + <&msmgpio 36 0>; + gpio-reset = <1>; + gpio-standby = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET1", + "CAM_STANDBY"; + sensor-position = <0>; + sensor-mode = <0>; + cci-device = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; + clock-names = "cam_clk"; + clock-cntl-level = "turbo"; + clock-rates = <24000000>; + }; + +======================================================= +Required Node Structure if probe happens from kernel +======================================================= +The EEPROM device is described in one level of the device node. + +====================================== +First Level Node - CAM EEPROM device +====================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,eeprom". + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg + Usage: required + Value type: + Definition: Register values. + +- qcom,eeprom-name + Usage: required + Value type: + Definition: Name of the EEPROM HW. + +- qcom,slave-addr + Usage: required + Value type: + Definition: Slave address of the EEPROM HW. + +- qcom,num-blocks + Usage: required + Value type: + Definition: Total block number that eeprom contains. + +- qcom,pageX + Usage: required + Value type: + Definition: List of values specifying page size, start address, + address type, data, data type, delay in ms. + size 0 stand for non-paged. + +- qcom,pollX + Usage: required + Value type: + Definition: List of values specifying poll size, poll reg address, + address type, data, data type, delay in ms. + size 0 stand for not used. + +- qcom,memX + Usage: required + Value type: + Definition: List of values specifying memory size, start address, + address type, data, data type, delay in ms. + size 0 stand for not used. + +- qcom,saddrX + Usage: required + Value type: + Definition: property should specify the slave address for block (%d). + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for EEPROM HW. + +- qcom,cmm-data-support + Usage: required + Value type: + Definition: Camera MultiModule data capability flag.. + +- qcom,cmm-data-compressed + Usage: required + Value type: + Definition: Camera MultiModule data compression flag. + +- qcom,cmm-data-offset + Usage: required + Value type: + Definition: Camera MultiModule data start offset. + +- qcom,cmm-data-size + Usage: required + Value type: + Definition: Camera MultiModule data size. + +- qcom,cam-power-seq-type + Usage: required + Value type: + Definition: should specify the power on sequence types. + +- qcom,cam-power-seq-val + Usage: required + Value type: + Definition: should specify the power on sequence values. + +- qcom,cam-power-seq-cfg-val + Usage: required + Value type: + Definition: should specify the power on sequence config values. + +- qcom,cam-power-seq-delay + Usage: required + Value type: + Definition: should specify the power on sequence delay time in ms. + +- spiop-read + Usage: required + Value type: + Definition: this array provides SPI read operation related data. + +- spiop-readseq + Usage: required + Value type: + Definition: this array provides SPI read sequence operation realted data. + +- spiop-queryid + Usage: required + Value type: + Definition: this array provides SPI query eeprom id operation related data. + +- spiop-pprog: + Usage: required + Value type: + Definition: this array provides SPI page program operation related data. + +- spiop-wenable + Usage: required + Value type: + Definition: this array provides SPI write enable operation related data. + +- spiop-readst + Usage: required + Value type: + Definition: this array provides SPI read destination operation related data. + +- spiop-erase + Usage: required + Value type: + Definition: this array provides SPI erase operation related data. + +- eeprom-idx + Usage: required + Value type: + Definition: this array provides eeprom id realted data. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- rgltr-cntrl-support + Usage: required + Value type: + Definition: This property specifies if the regulator control is supported + e.g. rgltr-min-voltage. + +- rgltr-min-voltage + Usage: required + Value type: + Definition: should contain minimum voltage level for regulators + mentioned in regulator-names property. + +- rgltr-max-voltage + Usage: required + Value type: + Definition: should contain maximum voltage level for regulators + mentioned in regulator-names property. + +- rgltr-load-current + Usage: required + Value type: + Definition: should contain the maximum current in microamps required for + the regulators mentioned in regulator-names property. + +- gpio-no-mux + Usage: required + Value type: + Definition: should specify the gpio mux type. + +- gpios + Usage: required + Value type: + Definition: should specify the gpios to be used for the eeprom. + +- gpio-reset + Usage: required + Value type: + Definition: should specify the reset gpio index. + +- gpio-standby + Usage: required + Value type: + Definition: should specify the standby gpio index. + +- gpio-req-tbl-num + Usage: required + Value type: + Definition: should specify the gpio table index. + +- gpio-req-tbl-flags + Usage: required + Value type: + Definition: should specify the gpio functions. + +- gpio-req-tbl-label + Usage: required + Value type: + Definition: should specify the gpio labels. + +- sensor-position + Usage: required + Value type: + Definition: should contain the mount angle of the camera sensor. + +- cci-device + Usage: required + Value type: + Definition: should contain i2c device id to be used for this camera + sensor + +- cci-master + Usage: required + Value type: + Definition: should contain i2c master id to be used for this camera + sensor. + +- sensor-mode + Usage: required + Value type: + Definition: should contain sensor mode supported. + +- clock-cntl-level + Usage: required + Value type: + Definition: says what all different clock levels eeprom node has. + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for EEPROM HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for EEPROM HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +Example: + + eeprom0: qcom,eeprom@0 { + cell-index = <0>; + reg = <0x0>; + qcom,eeprom-name = "msm_eeprom"; + eeprom-id0 = <0xF8 0x15>; + eeprom-id1 = <0xEF 0x15>; + eeprom-id2 = <0xC2 0x36>; + eeprom-id3 = <0xC8 0x15>; + compatible = "qcom,eeprom"; + qcom,slave-addr = <0x60>; + qcom,num-blocks = <2>; + qcom,page0 = <1 0x100 2 0x01 1 1>; + qcom,poll0 = <0 0x0 2 0 1 1>; + qcom,mem0 = <0 0x0 2 0 1 0>; + qcom,page1 = <1 0x0200 2 0x8 1 1>; + qcom,pageen1 = <1 0x0202 2 0x01 1 10>; + qcom,poll1 = <0 0x0 2 0 1 1>; + qcom,mem1 = <32 0x3000 2 0 1 0>; + qcom,saddr1 = <0x62>; + qcom,cmm-data-support; + qcom,cmm-data-compressed; + qcom,cmm-data-offset = <0>; + qcom,cmm-data-size = <0>; + spiop-read = <0x03 3 0 0 0>; + spiop-readseq = <0x03 3 0 0 0>; + spiop-queryid = <0x90 3 0 0 0>; + spiop-pprog = <0x02 3 0 3 100>; + spiop-wenable = <0x06 0 0 0 0>; + spiop-readst = <0x05 0 0 0 0>; + spiop-erase = <0x20 3 0 10 100>; + qcom,cam-power-seq-type = "sensor_vreg", + "sensor_vreg", "sensor_clk", + "sensor_gpio", "sensor_gpio"; + qcom,cam-power-seq-val = "cam_vdig", + "cam_vio", "sensor_cam_mclk", + "sensor_gpio_reset", + "sensor_gpio_standby"; + qcom,cam-power-seq-cfg-val = <1 1 24000000 1 1>; + qcom,cam-power-seq-delay = <1 1 5 5 10>; + cam_vdig-supply = <&pm8998_l5>; + cam_vio-supply = <&pm8998_lvs1>; + regulator-names = "cam_vdig", "cam_vio"; + rgltr-cntrl-support; + rgltr-min-voltage = <1200000 0>; + rgltr-max-voltage = <1200000 0>; + rgltr-load-current = <0 80000 105000 0>; + qcom,gpio-no-mux = <0>; + gpios = <&msmgpio 26 0>, + <&msmgpio 37 0>, + <&msmgpio 36 0>; + gpio-reset = <1>; + gpio-standby = <2>; + gpio-req-tbl-num = <0 1 2>; + gpio-req-tbl-flags = <1 0 0>; + gpio-req-tbl-label = "CAMIF_MCLK", + "CAM_RESET1", + "CAM_STANDBY"; + sensor-position = <0>; + sensor-mode = <0>; + cci-device = <0>; + cci-master = <0>; + status = "ok"; + clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; + clock-cntl-level = "turbo"; + clock-names = "cam_clk"; + clock-rates = <24000000>; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-fd.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-fd.txt new file mode 100755 index 000000000000..51b0babaa709 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-fd.txt @@ -0,0 +1,154 @@ +* Qualcomm Technologies, Inc. MSM Camera FD + +The MSM camera Face Detection device provides dependency definitions +for enabling Camera FD HW. MSM camera FD is implemented in multiple +device nodes. The root FD device node has properties defined to hint +the driver about the FD HW nodes available during the probe sequence. +Each node has multiple properties defined for interrupts, clocks and +regulators. + +======================= +Required Node Structure +======================= +FD root interface node takes care of the handling Face Detection high level +driver handling and controls underlying FD hardware present. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-fd". + +- compat-hw-name + Usage: required + Value type: + Definition: Should be "qcom,fd". + +- num-fd + Usage: required + Value type: + Definition: Number of supported FD HW blocks. + +Example: + qcom,cam-fd { + compatible = "qcom,cam-fd"; + compat-hw-name = "qcom,fd"; + num-fd = <1>; + }; + +======================= +Required Node Structure +======================= +FD Node provides interface for Face Detection hardware driver +about the device register map, interrupt map, clocks, regulators. + +- cell-index + Usage: required + Value type: + Definition: Node instance number. + +- compatible + Usage: required + Value type: + Definition: Should be one of "qcom,fd41", "qcom,fd501", + "qcom,fd600". + +- reg-names + Usage: optional + Value type: + Definition: Name of the register resources. + +- reg + Usage: optional + Value type: + Definition: Register values. + +- reg-cam-base + Usage: optional + Value type: + Definition: Offset of the register space compared to + to Camera base register space. + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: optional + Value type: + Definition: Interrupt line associated with FD HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for FD HW. + +- camss-vdd-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for FD HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks required for FD HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels. + Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo. + +Examples: + cam_fd: qcom,fd@ac5a000 { + cell-index = <0>; + compatible = "qcom,fd600"; + reg-names = "fd_core", "fd_wrapper"; + reg = <0xac5a000 0x1000>, + <0xac5b000 0x400>; + reg-cam-base = <0x5a000 0x5b000>; + interrupt-names = "fd"; + interrupts = <0 462 0>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = "gcc_ahb_clk", + "gcc_axi_clk", + "soc_ahb_clk", + "cpas_ahb_clk", + "camnoc_axi_clk", + "fd_core_clk_src", + "fd_core_clk", + "fd_core_uar_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, + <&clock_camcc CAM_CC_FD_CORE_CLK_SRC>, + <&clock_camcc CAM_CC_FD_CORE_CLK>, + <&clock_camcc CAM_CC_FD_CORE_UAR_CLK>; + src-clock-name = "fd_core_clk_src"; + clock-cntl-level = "svs"; + clock-rates = <0 0 0 0 0 400000000 0 0>; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-icp.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-icp.txt new file mode 100755 index 000000000000..e22e1f99f670 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-icp.txt @@ -0,0 +1,287 @@ +* Qualcomm Technologies, Inc. MSM Camera ICP + +The MSM camera ICP devices are implemented multiple device nodes. +The root icp device node has properties defined to hint the driver +about the number of A5,IPE and BPS nodes available during the +probe sequence. Each node has multiple properties defined +for interrupts, clocks and regulators. + +======================= +Required Node Structure +======================= +ICP root interface node takes care of the handling account for number +of A5, IPE and BPS devices present on the hardware. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-icp". + +- compat-hw-name + Usage: required + Value type: + Definition: Should be "qcom,a5" or "qcom,ipe0" or "qcom,ipe1" or "qcom,bps". + +- num-a5 + Usage: required + Value type: + Definition: Number of supported A5 processors. + +- num-ipe + Usage: required + Value type: + Definition: Number of supported IPE HW blocks. + +- num-bps + Usage: required + Value type: + Definition: Number of supported BPS HW blocks. + +Example: + qcom,cam-icp { + compatible = "qcom,cam-icp"; + compat-hw-name = "qcom,a5", "qcom,ipe0", "qcom,ipe1", "qcom,bps"; + num-a5 = <1>; + num-ipe = <2>; + num-bps = <1>; + status = "ok"; + }; + +======================= +Required Node Structure +======================= +A5/IPE/BPS Node's provides interface for Image Control Processor driver +about the A5 register map, interrupt map, clocks, regulators +and name of firmware image. + +- cell-index + Usage: required + Value type: + Definition: Node instance number. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-a5" or "qcom,cam-ipe" or "qcom,cam-bps". + +- reg-names + Usage: optional + Value type: + Definition: Name of the register resources. + +- reg + Usage: optional + Value type: + Definition: Register values. + +- reg-cam-base + Usage: optional + Value type: + Definition: Register values. + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: optional + Value type: + Definition: Interrupt associated with CDM HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for CDM HW. + +- camss-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for CDM HW. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for CDM HW. + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels. + Supported strings: lowsvs, svs, svs_l1, nominal, turbo. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- fw_name + Usage: optional + Value type: + Definition: Name of firmware image. + +- ubwc-ipe-fetch-cfg + Usage: required + Value type: + Definition: UBWC IPE fetch configuration based on DDR device type. + +- ubwc-ipe-write-cfg + Usage: required + Value type: + Definition: UBWC IPE write configuration based on DDR device type. + +- ubwc-bps-fetch-cfg + Usage: required + Value type: + Definition: UBWC BPS fetch configuration based on DDR device type. + +- ubwc-bps-write-cfg + Usage: required + Value type: + Definition: UBWC BPS write configuration based on DDR device type. + +- ubwc-cfg + Usage: optional + Value type: + Definition: UBWC configuration, this is mandatory if above + ipe/bps ubwc properties are not used. + +Examples: +a5: qcom,a5@ac00000 { + cell-index = <0>; + compatible = "qcom,cam-a5"; + reg = <0xac00000 0x6000>, + <0xac10000 0x8000>, + <0xac18000 0x3000>; + reg-names = "a5_qgic", "a5_sierra", "a5_csr"; + interrupts = <0 463 0>; + interrupt-names = "a5"; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = "gcc_cam_ahb_clk", + "gcc_cam_axi_clk", + "soc_ahb_clk", + "cpas_ahb_clk", + "camnoc_axi_clk", + "icp_apb_clk", + "icp_atb_clk", + "icp_clk", + "icp_clk_src", + "icp_cti_clk", + "icp_ts_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, + <&clock_camcc CAM_CC_ICP_APB_CLK>, + <&clock_camcc CAM_CC_ICP_ATB_CLK>, + <&clock_camcc CAM_CC_ICP_CLK>, + <&clock_camcc CAM_CC_ICP_CLK_SRC>, + <&clock_camcc CAM_CC_ICP_CTI_CLK>, + <&clock_camcc CAM_CC_ICP_TS_CLK>; + + clock-rates = <0 0 0 80000000 0 0 0 0 600000000 0 0>; + clock-cntl-level = "turbo"; + fw_name = "CAMERA_ICP.elf"; + /* "ubwc-cfg" is not used, even if defined the new property + tags will be priortized. If the new properties are not used + please specify "ubwc-cfg" in that case */ + ubwc-ipe-fetch-cfg = <0x707b 0x7083>; + ubwc-ipe-write-cfg = <0x161ef 0x1620f>; + ubwc-bps-fetch-cfg = <0x707b 0x7083> + ubwc-bps-write-cfg = <0x161ef 0x1620f>; + +qcom,ipe0 { + cell-index = <0>; + compatible = "qcom,cam-ipe"; + regulator-names = "ipe0-vdd"; + ipe0-vdd-supply = <&ipe_0_gdsc>; + clock-names = "ipe_0_ahb_clk", + "ipe_0_areg_clk", + "ipe_0_axi_clk", + "ipe_0_clk", + "ipe_0_clk_src"; + src-clock-name = "ipe_0_clk_src"; + clocks = <&clock_camcc CAM_CC_IPE_0_AHB_CLK>, + <&clock_camcc CAM_CC_IPE_0_AREG_CLK>, + <&clock_camcc CAM_CC_IPE_0_AXI_CLK>, + <&clock_camcc CAM_CC_IPE_0_CLK>, + <&clock_camcc CAM_CC_IPE_0_CLK_SRC>; + + clock-rates = <0 0 0 0 240000000>, + <0 0 0 0 404000000>, + <0 0 0 0 480000000>, + <0 0 0 0 538000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; +}; + +qcom,ipe1 { + cell-index = <1>; + compatible = "qcom,cam-ipe"; + regulator-names = "ipe1-vdd"; + ipe1-vdd-supply = <&ipe_1_gdsc>; + clock-names = "ipe_1_ahb_clk", + "ipe_1_areg_clk", + "ipe_1_axi_clk", + "ipe_1_clk", + "ipe_1_clk_src"; + src-clock-name = "ipe_1_clk_src"; + clocks = <&clock_camcc CAM_CC_IPE_1_AHB_CLK>, + <&clock_camcc CAM_CC_IPE_1_AREG_CLK>, + <&clock_camcc CAM_CC_IPE_1_AXI_CLK>, + <&clock_camcc CAM_CC_IPE_1_CLK>, + <&clock_camcc CAM_CC_IPE_1_CLK_SRC>; + + clock-rates = <0 0 0 0 240000000>, + <0 0 0 0 404000000>, + <0 0 0 0 480000000>, + <0 0 0 0 538000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; +}; + +bps: qcom,bps { + cell-index = <0>; + compatible = "qcom,cam-bps"; + regulator-names = "bps-vdd"; + bps-vdd-supply = <&bps_gdsc>; + clock-names = "bps_ahb_clk", + "bps_areg_clk", + "bps_axi_clk", + "bps_clk", + "bps_clk_src"; + src-clock-name = "bps_clk_src"; + clocks = <&clock_camcc CAM_CC_BPS_AHB_CLK>, + <&clock_camcc CAM_CC_BPS_AREG_CLK>, + <&clock_camcc CAM_CC_BPS_AXI_CLK>, + <&clock_camcc CAM_CC_BPS_CLK>, + <&clock_camcc CAM_CC_BPS_CLK_SRC>; + + clock-rates = <0 0 0 0 200000000>, + <0 0 0 0 404000000>, + <0 0 0 0 480000000>, + <0 0 0 0 600000000>, + <0 0 0 0 600000000>; + clock-cntl-level = "lowsvs", "svs", + "svs_l1", "nominal", "turbo"; +}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-ife-csid.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-ife-csid.txt new file mode 100755 index 000000000000..ecff78ee1b27 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-ife-csid.txt @@ -0,0 +1,121 @@ +* Qualcomm Technologies, Inc. MSM Camera IFE CSID + +Camera IFE CSID device provides the definitions for enabling +the IFE CSID hardware. It also provides the functions for the client +to control the IFE CSID hardware. + +======================= +Required Node Structure +======================= +The IFE CSID device is described in one level of the device node. + +====================================== +First Level Node - CAM IFE CSID device +====================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,csid170", "qcom,csid175", "qcom,csid175_200", + "qcom,csid480", "qcom,csid-lite170", "qcom,csid-lite175", + "qcom,csid-lite480" or "qcom,csid-custom480". + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg-names + Usage: required + Value type: + Definition: Should be "csid". + +- reg + Usage: required + Value type: + Definition: Register values. + +- interrupt-names + Usage: Required + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: Required + Value type: + Definition: Interrupt associated with IFE CSID HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for IFE CSID HW. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for IFE CSID HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for IFE CSID HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- clock-cntl-level + Usage: required + Value type: + Definition: All different clock level node can support. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +Example: + + qcom,csid0@acb3000 { + cell-index = <0>; + compatible = "qcom,csid480"; + reg = <0xacb3000 0x1000>; + reg-names = "csid"; + interrupts = <0 464 0>; + interrupt-names = "csid"; + vdd-names = "camss", "ife0"; + camss-supply = <&titan_top_gdsc>; + ife0-supply = <&ife_0_gdsc>; + clock-names = "soc_ahb_clk", + "cpas_ahb_clk", + "slow_ahb_clk_src", + "ife_clk", + "ife_clk_src", + "ife_csid_clk", + "ife_csid_clk_src", + "ife_cphy_rx_clk", + "cphy_rx_clk_src"; + clocks = <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CLK>, + <&clock_camcc CAM_CC_IFE_0_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CSID_CLK>, + <&clock_camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CPHY_RX_CLK>, + <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>; + clock-rates = <0 0 80000000 0 320000000 0 384000000 0 384000000>; + src-clock-name = "ife_csid_clk_src"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-isp.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-isp.txt new file mode 100755 index 000000000000..801c3feae3d7 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-isp.txt @@ -0,0 +1,36 @@ +* Qualcomm Technologies, Inc. MSM Camera ISP + +The MSM camera ISP driver provides the definitions for enabling +the Camera ISP hadware. It provides the functions for the Client to +control the ISP hardware. + +======================= +Required Node Structure +======================= +The camera ISP device is described in one level of device node. + +================================== +First Level Node - CAM ISP device +================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-isp". + +- arch-compat + Usage: required + Value type: + Definition: Should be "vfe", "ife" or "tfe". + +- ubwc-static-cfg + Usage: optional + Value type: + Definition: IFE UBWC static configuration based on DDR device type. + +Example: + + qcom,cam-isp { + compatible = "qcom,cam-isp"; + arch-compat = "ife"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-jpeg.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-jpeg.txt new file mode 100755 index 000000000000..73e99b25cd8f --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-jpeg.txt @@ -0,0 +1,186 @@ +* Qualcomm Technologies, Inc. MSM Camera JPEG + +The MSM camera JPEG devices are implemented multiple device nodes. +The root JPEG device node has properties defined to hint the driver +about the number of Encoder and DMA nodes available during the +probe sequence. Each node has multiple properties defined +for interrupts, clocks and regulators. + +======================= +Required Node Structure +======================= +JPEG root interface node takes care of the handling account for number +of Encoder and DMA devices present on the hardware. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-jpeg". + +- compat-hw-name + Usage: required + Value type: + Definition: Should be "qcom,jpegenc" or "qcom,jpegdma". + +- num-jpeg-enc + Usage: required + Value type: + Definition: Number of supported Encoder HW blocks. + +- num-jpeg-dma + Usage: required + Value type: + Definition: Number of supported DMA HW blocks. + +Example: + qcom,cam-jpeg { + compatible = "qcom,cam-jpeg"; + compat-hw-name = "qcom,jpegenc", + "qcom,jpegdma"; + num-jpeg-enc = <1>; + num-jpeg-dma = <1>; + status = "ok"; + }; + + +======================= +Required Node Structure +======================= +Encoder/DMA Nodes provide interface for JPEG driver about +the device register map, interrupt map, clocks and regulators. + +- cell-index + Usage: required + Value type: + Definition: Node instance number. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam_jpeg_enc". + +- reg-names + Usage: optional + Value type: + Definition: Name of the register resources. + +- reg + Usage: optional + Value type: + Definition: Register values. + +- reg-cam-base + Usage: optional + Value type: + Definition: Offset of the register space compared to + to Camera base register space. + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: optional + Value type: + Definition: Interrupt associated with JPEG HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for JPEG HW. + +- camss-vdd-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for JPEG HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for JPEG HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels. + Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo. + +Examples: + cam_jpeg_enc: qcom,jpegenc@ac4e000 { + cell-index = <0>; + compatible = "qcom,cam_jpeg_enc"; + reg-names = "jpege_hw"; + reg = <0xac4e000 0x4000>; + reg-cam-base = <0x4e000>; + interrupt-names = "jpeg"; + interrupts = <0 474 0>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = "camera_ahb", + "camera_axi", + "soc_ahb_clk", + "cpas_ahb_clk", + "camnoc_axi_clk", + "jpegenc_clk_src", + "jpegenc_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, + <&clock_camcc CAM_CC_JPEG_CLK_SRC>, + <&clock_camcc CAM_CC_JPEG_CLK>; + + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "jpegenc_clk_src"; + clock-cntl-level = "nominal"; + status = "ok"; + }; + + cam_jpeg_dma: qcom,jpegdma@0xac52000{ + cell-index = <0>; + compatible = "qcom,cam_jpeg_dma"; + reg-names = "jpegdma_hw"; + reg = <0xac52000 0x4000>; + reg-cam-base = <0x52000>; + interrupt-names = "jpegdma"; + interrupts = <0 475 0>; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + clock-names = "camera_ahb", + "camera_axi", + "soc_ahb_clk", + "cpas_ahb_clk", + "camnoc_axi_clk", + "jpegdma_clk_src", + "jpegdma_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, + <&clock_camcc CAM_CC_JPEG_CLK_SRC>, + <&clock_camcc CAM_CC_JPEG_CLK>; + + clock-rates = <0 0 0 0 0 600000000 0>; + src-clock-name = "jpegdma_clk_src"; + clock-cntl-level = "nominal"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-lrme.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-lrme.txt new file mode 100755 index 000000000000..409be3f08de4 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-lrme.txt @@ -0,0 +1,148 @@ +* Qualcomm Technologies, Inc. MSM Camera LRME + +The MSM camera Low Resolution Motion Estimation device provides dependency +definitions for enabling Camera LRME HW. MSM camera LRME is implemented in +multiple device nodes. The root LRME device node has properties defined to +hint the driver about the LRME HW nodes available during the probe sequence. +Each node has multiple properties defined for interrupts, clocks and +regulators. + +======================= +Required Node Structure +======================= +LRME root interface node takes care of the handling LRME high level +driver handling and controls underlying LRME hardware present. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-lrme" + +- compat-hw-name + Usage: required + Value type: + Definition: Should be "qcom,lrme" + +- num-lrme + Usage: required + Value type: + Definition: Number of supported LRME HW blocks + +Example: + qcom,cam-lrme { + compatible = "qcom,cam-lrme"; + compat-hw-name = "qcom,lrme"; + num-lrme = <1>; + }; + +======================= +Required Node Structure +======================= +LRME Node provides interface for Low Resolution Motion Estimation hardware +driver about the device register map, interrupt map, clocks, regulators. + +- cell-index + Usage: required + Value type: + Definition: Node instance number + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,lrme" + +- reg-names + Usage: optional + Value type: + Definition: Name of the register resources + +- reg + Usage: optional + Value type: + Definition: Register values + +- reg-cam-base + Usage: optional + Value type: + Definition: Offset of the register space compared to + to Camera base register space + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt + +- interrupts + Usage: optional + Value type: + Definition: Interrupt line associated with LRME HW + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for LRME HW + +- camss-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names" + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for LRME HW + +- clocks + Usage: required + Value type: + Definition: List of clocks required for LRME HW + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels + Supported strings: minsvs, lowsvs, svs, svs_l1, nominal, turbo + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name + +Examples: + cam_lrme: qcom,lrme@ac6b000 { + cell-index = <0>; + compatible = "qcom,lrme"; + reg-names = "lrme"; + reg = <0xac6b000 0xa00>; + reg-cam-base = <0x6b000>; + interrupt-names = "lrme"; + interrupts = <0 476 0>; + regulator-names = "camss"; + camss-supply = <&titan_top_gdsc>; + clock-names = "camera_ahb", + "camera_axi", + "soc_ahb_clk", + "cpas_ahb_clk", + "camnoc_axi_clk", + "lrme_clk_src", + "lrme_clk"; + clocks = <&clock_gcc GCC_CAMERA_AHB_CLK>, + <&clock_gcc GCC_CAMERA_AXI_CLK>, + <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, + <&clock_camcc CAM_CC_LRME_CLK_SRC>, + <&clock_camcc CAM_CC_LRME_CLK>; + clock-rates = <0 0 0 0 0 0 0>, + <0 0 0 0 0 19200000 19200000>, + <0 0 0 0 0 19200000 19200000>, + <0 0 0 0 0 19200000 19200000>; + clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; + src-clock-name = "lrme_core_clk_src"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-ope.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-ope.txt new file mode 100755 index 000000000000..fdd6c5e980f1 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-ope.txt @@ -0,0 +1,168 @@ +* Qualcomm Technologies, Inc. MSM Camera OPE + +The ope device node has properties defined to hint the driver +about the number of OPE nodes available during the +probe sequence. Each node has multiple properties defined +for interrupts, clocks and regulators. + +======================= +Required Node Structure +======================= +OPE root interface node takes care of the handling account for number +of OPE devices present on the hardware. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,cam-ope". + +- compat-hw-name + Usage: required + Value type: + Definition: Should be "qcom,ope". + +- num-ope + Usage: required + Value type: + Definition: Number of supported OPE HW blocks. + +Example: + qcom,cam-ope { + compatible = "qcom,cam-ope"; + compat-hw-name = "qcom,ope"; + num-ope = <2>; + status = "ok"; + }; + +======================= +Required Node Structure +======================= +OPE Node provides interface for Image Control Processor driver +about the OPE register map, interrupt map, clocks, regulators. + +- cell-index + Usage: required + Value type: + Definition: Node instance number. + +- compatible + Usage: required + Value type: + Definition: Should be "qcom,ope". + +- reg-names + Usage: optional + Value type: + Definition: Name of the register resources. + +- reg + Usage: optional + Value type: + Definition: Register values. + +- reg-cam-base + Usage: optional + Value type: + Definition: Register values. + +- interrupt-names + Usage: optional + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: optional + Value type: + Definition: Interrupt associated with OPE HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for OPE HW. + +- camss-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed + in "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for CDM HW. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for CDM HW. + +- clock-cntl-level + Usage: required + Value type: + Definition: List of strings corresponds clock-rates levels. + Supported strings: lowsvs, svs, svs_l1, nominal, turbo. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +Examples: +qcom,cam-ope { + compatible = "qcom,cam-ope"; + compat-hw-name = "qcom,ope"; + num-ope = <1>; + status = "ok"; +}; + +ope: qcom,ope@ac00000 { + cell-index = <0>; + compatible = "qcom,ope"; + reg = + <0x42000 0x400>, + <0x42400 0x200>, + <0x42600 0x200>, + <0x42800 0x4400>, + <0x46c00 0x190>, + <0x46d90 0x1270>; + reg-names = + "ope_cdm", + "ope_top", + "ope_qos", + "ope_pp", + "ope_bus_rd", + "ope_bus_wr"; + reg-cam-base = <0x42000 0x42400 0x42600 0x42800 0x46c00 0x46d90>; + interrupts = ; + interrupt-names = "ope"; + regulator-names = "camss-vdd"; + camss-vdd-supply = <&gcc_camss_top_gdsc>; + clock-names = + "ope_ahb_clk_src", + "ope_ahb_clk", + "ope_clk_src", + "ope_clk"; + clocks = + <&gcc GCC_CAMSS_OPE_AHB_CLK_SRC>, + <&gcc GCC_CAMSS_OPE_AHB_CLK>, + <&gcc GCC_CAMSS_OPE_CLK_SRC>, + <&gcc GCC_CAMSS_OPE_CLK>; + + clock-rates = + <200000000 0 480000000 0>, + <400000000 0 600000000 0>; + + clock-cntl-level = "svs", "turbo"; + src-clock-name = "ope_clk_src"; + status = "ok"; +}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-smmu.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-smmu.txt new file mode 100755 index 000000000000..eca2bd82ec79 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-smmu.txt @@ -0,0 +1,142 @@ +* Qualcomm Technologies, Inc. MSM Camera SMMU + +The MSM camera SMMU device provides SMMU context bank definitions +for all HW blocks that need to map IOVA to physical memory. These +definitions consist of various properties that define how the +IOVA address space is laid out for each HW block in the camera +subsystem. + +======================= +Required Node Structure +======================= +The camera SMMU device must be described in three levels of device nodes. The +first level describes the overall SMMU device. Within it, second level nodes +describe individual context banks that map different stream ids. There can +also be second level nodes describing firmware device nodes. Each HW block +such as IFE, ICP maps into these second level device nodes. All context bank +specific properties that define how the IOVA is laid out is contained within +third level device nodes within the second level device nodes. + +During the kernel initialization all the devices are probed recursively and +a device pointer is created for each context bank keeping track of the IOVA +mapping information. + +Duplicate regions of the same type are not allowed within the same +context bank. All context banks must contain an IO region at the very least. + +================================== +First Level Node - CAM SMMU device +================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,msm-cam-smmu". + +=================================================================== +Second Level Node - CAM SMMU context bank device or firmware device +=================================================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,msm-cam-smmu-cb" or "qcom,msm-cam-smmu-fw-dev". + +- memory-region + Usage: optional + Value type: + Definition: Should specify the phandle of the memory region for firmware. + allocation + +- iommus + Usage: required + Value type: + Definition: first cell is phandle of the iommu, second cell is stream id + and third cell is SMR mask. + +- label + Usage: required + Value type: + Definition: Should specify a string label to identify the context bank. + +- qcom,secure-cb + Usage: optional + Value type: boolean + Definition: Specifies if the context bank is a secure context bank. + +============================================= +Third Level Node - CAM SMMU memory map device +============================================= +- iova-region-name + Usage: required + Value type: + Definition: Should specify a string label to identify the IOVA region. + +- iova-region-start + Usage: required + Value type: + Definition: Should specify start IOVA for region. + +- iova-region-len + Usage: required + Value type: + Definition: Should specify length for IOVA region. + +- iova-region-id + Usage: required + Value type: + Definition: Should specify the numerical identifier for IOVA region. + Allowed values are: 0x00 to 0x03 + - Firmware region: 0x00 + - Shared region: 0x01 + - Scratch region: 0x02 + - IO region: 0x03 + +- iova-granularity + Usage: optional + Value type: + Definition: Should specify IOVA granularity for shared memory region. + +Example: + qcom,cam_smmu@0 { + compatible = "qcom,msm-cam-smmu"; + + msm_cam_smmu_icp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x1078>, + <&apps_smmu 0x1020>, + <&apps_smmu 0x1028>, + <&apps_smmu 0x1040>, + <&apps_smmu 0x1048>, + <&apps_smmu 0x1030>, + <&apps_smmu 0x1050>; + label = "icp"; + icp_iova_mem_map: iova-mem-map { + iova-mem-region-firmware { + /* Firmware region is 5MB */ + iova-region-name = "firmware"; + iova-region-start = <0x0>; + iova-region-len = <0x500000>; + iova-region-id = <0x0>; + status = "ok"; + }; + + iova-mem-region-shared { + /* Shared region is 100MB long */ + iova-region-name = "shared"; + iova-region-start = <0x7400000>; + iova-region-len = <0x6400000>; + iova-region-id = <0x1>; + iova-granularity = <0x15>; + status = "ok"; + }; + + iova-mem-region-io { + /* IO region is approximately 3.5 GB */ + iova-region-name = "io"; + iova-region-start = <0xd800000>; + iova-region-len = <0xd2800000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tfe-csid.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tfe-csid.txt new file mode 100755 index 000000000000..73a4b7bc069b --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tfe-csid.txt @@ -0,0 +1,123 @@ +* Qualcomm Technologies, Inc. MSM Camera TFE CSID + +Camera TFE CSID device provides the definitions for enabling +the TFE CSID hardware. It also provides the functions for the client +to control the TFE CSID hardware. + +======================= +Required Node Structure +======================= +The TFE CSID device is described in one level of the device node. + +====================================== +First Level Node - CAM TFE CSID device +====================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,csid530" + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg-names + Usage: required + Value type: + Definition: Should be "csid". + +- reg + Usage: required + Value type: + Definition: Register values. + +- interrupt-names + Usage: Required + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: Required + Value type: + Definition: Interrupt associated with TFE CSID HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for TFE CSID HW. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for TFE CSID HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for TFE CSID HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- clock-cntl-level + Usage: required + Value type: + Definition: All different clock level node can support. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +Example: + + qcom,tfe_csid0@5c6e000 { + cell-index = <0>; + compatible = "qcom,csid530"; + reg-names = reg-names = "csid", "top", "camnoc"; + reg = <0x5c6e000 0x5000>, + <0x5c11000 0x1000>, + <0x5c13000 0x4000>; + interrupt-names = "csid0"; + interrupts = ; + regulator-names = "camss"; + camss-supply = <&gcc_camss_top_gdsc>; + clock-names = + "tfe_csid_clk_src", + "tfe_csid_clk", + "cphy_rx_clk_src", + "tfe_cphy_rx_clk", + "tfe_clk_src", + "tfe_clk", + "tfe_axi_clk"; + clocks = + <&gcc GCC_CAMSS_TFE_0_CSID_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, + <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, + <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; + clock-rates = + <240000000 0 0 0 256000000 0 0>, + <384000000 0 0 0 460800000 0 0>, + <426400000 0 0 0 576000000 0 0>, + clock-cntl-level = "svs", "svs_l1", "turbo"; + src-clock-name = "tfe_csid_clk_src"; + clock-control-debugfs = "true"; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tfe.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tfe.txt new file mode 100755 index 000000000000..8f7c21b97765 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tfe.txt @@ -0,0 +1,142 @@ +* Qualcomm Technologies, Inc. MSM Camera TFE + +Camera TFE device provides the definitions for enabling +the TFE hardware. It also provides the functions for the client +to control the TFE hardware. + +======================= +Required Node Structure +======================= +The TFE device is described in one level of the device node. + +====================================== +First Level Node - CAM TFE device +====================================== +Required properties: +- compatible + Usage: required + Value type: + Definition: Should specify the compatibility string for matching the + driver. e.g. "qcom,tfe530" + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg-names + Usage: required + Value type: + Definition: Should specify the name of the register block. + +- reg + Usage: required + Value type: + Definition: Register values. + +- interrupt-names + Usage: Required + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: Required + Value type: + Definition: Interrupt associated with TFE HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for TFE HW. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for TFE HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for TFE HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +Optional properties: +- clock-names-option + Usage: optional + Value type: + Definition: Optional clock names. + +- clocks-option + Usage: required if clock-names-option defined + Value type: + Definition: List of optinal clocks used for TFE HW. + +- clock-rates-option + Usage: required if clock-names-option defined + Value type: + Definition: List of clocks rates for optional clocks. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +- qcom,cam-cx-ipeak: + Usage: optional + Value type: + phandle - phandle of CX Ipeak device node + bit - Every bit corresponds to a client of CX Ipeak + Definition: CX Ipeak is a mitigation scheme which throttles camera frequency + if all the clients are running at their respective threshold + frequencies to limit CX peak current. + driver in the relevant register. + +- scl-clk-names: + Usage: optional + Value type: + Definition: Scalable clock names to identify which clocks needs to update + along with source clock. + +Example: + cam_tfe0: qcom,tfe0@5c6e000{ + cell-index = <0>; + compatible = "qcom,tfe530"; + reg-names = "tfe0"; + reg = <0x5c6e000 0x5000>; + reg-cam-base = <0x6e000>; + interrupt-names = "tfe0"; + interrupts = ; + regulator-names = "camss"; + camss-supply = <&gcc_camss_top_gdsc>; + clock-names = + "tfe_clk_src", + "tfe_clk", + "tfe_axi_clk"; + clocks = + <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CLK>, + <&gcc GCC_CAMSS_AXI_CLK>; + clock-rates = + <256000000 0 150000000>, + <460800000 0 200000000>, + <576000000 0 300000000>; + clock-cntl-level = "svs", "svs_l1", "turbo"; + src-clock-name = "tfe_clk_src"; + clock-control-debugfs = "true"; + status = "ok"; + }; \ No newline at end of file diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tpg.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tpg.txt new file mode 100755 index 000000000000..0e34d93ad576 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-tpg.txt @@ -0,0 +1,113 @@ +* Qualcomm Technologies, Inc. MSM Camera TPG + +Camera TPG device provides the definitions for enabling +the TPG hardware. It also provides the functions for the client +to control the TPG hardware. + +======================= +Required Node Structure +======================= +The TPG device is described in one level of the device node. + +====================================== +First Level Node - CAM TPG device +====================================== +Required properties: +- compatible + Usage: required + Value type: + Definition: Should specify the compatibility string for matching the + driver. e.g. "qcom,tpgv1" + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg-names + Usage: required + Value type: + Definition: Should specify the name of the register block. + +- reg + Usage: required + Value type: + Definition: Register values. + +- interrupt-names + Usage: Required + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: Required + Value type: + Definition: Interrupt associated with TFE HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for TFE HW. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for TFE HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for TFE HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +- scl-clk-names: + Usage: optional + Value type: + Definition: Scalable clock names to identify which clocks needs to update + along with source clock. + +Example: + cam_tfe_tpg0: qcom,tpg0@5c66000 { + cell-index = <0>; + compatible = "qcom,tpgv1"; + reg-names = "tpg0", "top"; + reg = <0x5c66000 0x400>, + <0x5c11000 0x1000>; + reg-cam-base = <0x66000 0x11000>; + regulator-names = "camss"; + camss-supply = <&gcc_camss_top_gdsc>; + clock-names = + "cphy_rx_clk_src", + "tfe_0_cphy_rx_clk"; + clocks = + <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, + <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>; + clock-rates = + <240000000 240000000>, + <341333333 341333333>, + <384000000 384000000>; + clock-cntl-level = "svs", "svs_l1", "turbo"; + src-clock-name = "cphy_rx_clk_src"; + clock-control-debugfs = "false"; + status = "ok"; + }; \ No newline at end of file diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-vfe.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-vfe.txt new file mode 100755 index 000000000000..2866d67cf5e2 --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-cam-vfe.txt @@ -0,0 +1,154 @@ +* Qualcomm Technologies, Inc. MSM Camera VFE + +Camera VFE device provides the definitions for enabling +the VFE hardware. It also provides the functions for the client +to control the VFE hardware. + +======================= +Required Node Structure +======================= +The VFE device is described in one level of the device node. + +====================================== +First Level Node - CAM VFE device +====================================== +Required properties: +- compatible + Usage: required + Value type: + Definition: Should specify the compatibility string for matching the + driver. e.g. "qcom,vfe480", "qcom,vfe175", "qcom,vfe170", "qcom,vfe175_130", + "qcom,vfe-lite480", "qcom,vfe-lite175", "qcom,vfe-lite175_130", "qcom,vfe-lite170". + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg-names + Usage: required + Value type: + Definition: Should specify the name of the register block. + +- reg + Usage: required + Value type: + Definition: Register values. + +- interrupt-names + Usage: Required + Value type: + Definition: Name of the interrupt. + +- interrupts + Usage: Required + Value type: + Definition: Interrupt associated with VFE HW. + +- regulator-names + Usage: required + Value type: + Definition: Name of the regulator resources for VFE HW. + +- xxxx-supply + Usage: required + Value type: + Definition: Regulator reference corresponding to the names listed in + "regulator-names". + +- clock-names + Usage: required + Value type: + Definition: List of clock names required for VFE HW. + +- clocks + Usage: required + Value type: + Definition: List of clocks used for VFE HW. + +- clock-rates + Usage: required + Value type: + Definition: List of clocks rates. + +- src-clock-name + Usage: required + Value type: + Definition: Source clock name. + +Optional properties: +- clock-names-option + Usage: optional + Value type: + Definition: Optional clock names. + +- clocks-option + Usage: required if clock-names-option defined + Value type: + Definition: List of optinal clocks used for VFE HW. + +- clock-rates-option + Usage: required if clock-names-option defined + Value type: + Definition: List of clocks rates for optional clocks. + +- clock-control-debugfs + Usage: optional + Value type: + Definition: Enable/Disable clk rate control. + +- qcom,cam-cx-ipeak: + Usage: optional + Value type: + phandle - phandle of CX Ipeak device node + bit - Every bit corresponds to a client of CX Ipeak + Definition: CX Ipeak is a mitigation scheme which throttles camera frequency + if all the clients are running at their respective threshold + frequencies to limit CX peak current. + driver in the relevant register. + +- scl-clk-names: + Usage: optional + Value type: + Definition: Scalable clock names to identify which clocks needs to update + along with source clock. + +Example: + qcom,vfe0@acaf000 { + cell-index = <0>; + compatible = "qcom,vfe480"; + reg-names = "ife"; + reg = <0xacaf000 0x4000>; + interrupts = <0 465 0>; + interrupt-names = "ife"; + vdd-names = "camss-vdd", "ife0-vdd"; + camss-vdd-supply = <&titan_top_gdsc>; + ife0-vdd-supply = <&ife_0_gdsc>; + clock-names = "soc_ahb_clk", + "cpas_ahb_clk", + "slow_ahb_clk_src", + "ife_clk", + "ife_clk_src", + "ife_csid_clk", + "ife_csid_clk_src", + "camnoc_axi_clk", + "ife_axi_clk", + clocks = <&clock_camcc CAM_CC_SOC_AHB_CLK>, + <&clock_camcc CAM_CC_CPAS_AHB_CLK>, + <&clock_camcc CAM_CC_SLOW_AHB_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CLK>, + <&clock_camcc CAM_CC_IFE_0_CLK_SRC>, + <&clock_camcc CAM_CC_IFE_0_CSID_CLK>, + <&clock_camcc CAM_CC_IFE_0_CSID_CLK_SRC>, + <&clock_camcc CAM_CC_CAMNOC_AXI_CLK>, + <&clock_camcc CAM_CC_IFE_0_AXI_CLK>, + clock-rates = <0 0 80000000 0 320000000 0 384000000 0 0 0>; + src-clock-name = "ife_clk_src"; + clock-names-option = "ife_dsp_clk"; + clocks-option = <&clock_camcc CAM_CC_IFE_0_DSP_CLK>; + clock-rates-option = <600000000>; + scl-clk-en; + scl-clk-names = "ife_axi_clk"; + qcom,cam-cx-ipeak = <&cx_ipeak_lm 2>; + status = "ok"; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-camera-flash.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-camera-flash.txt new file mode 100755 index 000000000000..ab81329df08e --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-camera-flash.txt @@ -0,0 +1,132 @@ +* Qualcomm Technologies, Inc. MSM FLASH + +The MSM camera Flash driver provides the definitions for +enabling and disabling LED Torch/Flash by requesting it to +PMIC/I2C/GPIO based hardware. It provides the functions for +the Client to control the Flash hardware. + +======================================================= +Required Node Structure +======================================================= +The Flash device is described in one level of the device node. + +====================================== +First Level Node - CAM FLASH device +====================================== +- compatible + Usage: required + Value type: + Definition: Should be "qcom,camera-flash". + +- cell-index + Usage: required + Value type: + Definition: Should specify the hardware index id. + +- reg + Usage: required + Value type: + Definition: Register values. + +- flash-source + Usage: required + Value type: + Definition: Should contain array of phandles to Flash source nodes. + +- torch-source + Usage: required + Value type: + Definition: Should contain array of phandles to torch source nodes. + +- switch-source + Usage: Optional + Value type: + Definition: Should contain phandle to switch source nodes. + +- slave-id + Usage: optional + Value type: + Definition: should contain i2c slave address, device id address + and expected id read value. + +- cci-master + Usage: optional + Value type: + Definition: should contain i2c master id to be used for this camera + flash. + +- max-current + Usage: optional + Value type: + Definition: Max current in mA supported by flash + +- max-duration + Usage: optional + Value type: + Definition: Max duration in ms flash can glow. + +- wled-flash-support + Usage: optional + Value type: + Definition: To identity wled flash hardware support. + +- gpios + Usage: optional + Value type: + Definition: should specify the gpios to be used for the flash. + +- gpio-req-tbl-num + Usage: optional + Value type: + Definition: should specify the gpio table index. + +- gpio-req-tbl-flags + Usage: optional + Value type: + Definition: should specify the gpio functions. + +- gpio-req-tbl-label + Usage: optional + Value type: + Definition: should specify the gpio labels. + +- gpio-flash-reset + Usage: optional + Value type: + Definition: should contain index to gpio used by flash's "flash reset" pin. + +- gpio-flash-en + Usage: optional + Value type: + Definition: should contain index to gpio used by flash's "flash enable" pin. + +- gpio-flash-now + Usage: optional + Value type: + Definition: should contain index to gpio used by flash's "flash now" pin. + +Example: + +led_flash_rear: qcom,camera-flash@0 { + reg = <0x00 0x00>; + cell-index = <0>; + compatible = "qcom,camera-flash"; + flash-source = <&pmi8998_flash0 &pmi8998_flash1>; + torch-source = <&pmi8998_torch0 &pmi8998_torch1>; + switch-source = <&pmi8998_switch0>; + wled-flash-support; + qcom,slave-id = <0x00 0x00 0x0011>; + qcom,cci-master = <0>; + gpios = <&msmgpio 23 0>, + <&msmgpio 24 0>; + <&msmgpio 25 0>; + qcom,gpio-flash-reset = <0>; + qcom,gpio-flash-en = <0>; + qcom,gpio-flash-now = <1>; + qcom,gpio-req-tbl-num = <0 1>; + qcom,gpio-req-tbl-flags = <0 0>; + qcom,gpio-req-tbl-label = "FLASH_EN", + "FLASH_NOW"; + qcom,max-current = <1500>; + qcom,max-duration = <1200>; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-camera.txt b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-camera.txt new file mode 100755 index 000000000000..04548caa330b --- /dev/null +++ b/arch/arm64/boot/dts/vendor/qcom/camera/bindings/msm-camera.txt @@ -0,0 +1,13 @@ +* Qualcomm Technologies, Inc. MSM Camera + +Required properties: +- compatible : + - "qcom,cam-req-mgr" +- qcom,sensor-manual-probe : specify if sensor probes at kernel boot time or user driven + +Example: + + qcom,cam-req-mgr { + compatible = "qcom,cam-req-mgr"; + qcom,sensor-manual-probe; + }; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera-sensor-rb5.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera-sensor-rb5.dtsi deleted file mode 100755 index 261a7fe65f11..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera-sensor-rb5.dtsi +++ /dev/null @@ -1,278 +0,0 @@ -&soc { - qcom,cam-res-mgr { - compatible = "qcom,cam-res-mgr"; - status = "ok"; - }; -}; - -&tlmm { - cam_sensor_active_gmsl: cam_sensor_active_gmsl { - /* RESET */ - mux { - pins = "gpio99"; - function = "gpio"; - }; - - config { - pins = "gpio99"; - bias-pull-up; - drive-strength = <2>; /* 2 MA */ - output-high; - }; - }; - - cam_sensor_suspend_gmsl: cam_sensor_suspend_gmsl { - /* RESET */ - mux { - pins = "gpio99"; - function = "gpio"; - }; - - config { - pins = "gpio99"; - bias-pull-down; /* PULL DOWN */ - drive-strength = <2>; /* 2 MA */ - output-low; - }; - }; -}; - -&cam_cci0 { - qcom,cam-sensor0 { - cell-index = <0>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <0>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_vio-supply = <&pm8009_l7>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 0>; - rgltr-max-voltage = <1800000 0>; - rgltr-load-current = <120000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 94 0>, - <&tlmm 93 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor1 { - cell-index = <1>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <1>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_vio-supply = <&pm8009_l7>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 0>; - rgltr-max-voltage = <1800000 0>; - rgltr-load-current = <120000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 95 0>, - <&tlmm 92 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor3 { - cell-index = <3>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <0>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_vio-supply = <&pm8009_l7>; - cam_bob-supply = <&pm8150a_bob>; - cam_vana-supply = <&pm8009_l5>; - cam_vdig-supply = <&pm8009_l1>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1104000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1104000 0 3960000>; - rgltr-load-current = <120000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 94 0>, - <&tlmm 93 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor4 { - cell-index = <4>; - status = "disable"; - }; - - qcom,cam-sensor5 { - cell-index = <5>; - status = "disable"; - }; -}; - -&cam_cci1 { - qcom,cam-sensor2 { - cell-index = <2>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <2>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - cam_vio-supply = <&pm8009_l7>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 0>; - rgltr-max-voltage = <1800000 0>; - rgltr-load-current = <120000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; - gpios = <&tlmm 96 0>, - <&tlmm 78 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor4 { - cell-index = <4>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <4>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - cam_vio-supply = <&pm8009_l7>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 0>; - rgltr-max-voltage = <1800000 0>; - rgltr-load-current = <120000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_gmsl>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_gmsl>; - gpios = <&tlmm 94 0>, - <&tlmm 99 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET4"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor5 { - cell-index = <5>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <4>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - cam_vio-supply = <&pm8009_l7>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 0>; - rgltr-max-voltage = <1800000 0>; - rgltr-load-current = <120000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_gmsl>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_gmsl>; - gpios = <&tlmm 94 0>, - <&tlmm 99 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET4"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera-sensor-xr.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera-sensor-xr.dtsi deleted file mode 100755 index c0cb17b1319c..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera-sensor-xr.dtsi +++ /dev/null @@ -1,687 +0,0 @@ -#include - -&soc { - led_flash_rear: qcom,camera-flash0 { - cell-index = <0>; - compatible = "qcom,camera-flash"; - flash-source = <&pm8150l_flash0 &pm8150l_flash1>; - torch-source = <&pm8150l_torch0 &pm8150l_torch1>; - switch-source = <&pm8150l_switch2>; - status = "ok"; - }; - - led_flash_rear_aux: qcom,camera-flash1 { - cell-index = <1>; - compatible = "qcom,camera-flash"; - flash-source = <&pm8150l_flash0 &pm8150l_flash1>; - torch-source = <&pm8150l_torch0 &pm8150l_torch1>; - switch-source = <&pm8150l_switch2>; - status = "ok"; - }; - - led_flash_triple_rear: qcom,camera-flash@4 { - cell-index = <4>; - compatible = "qcom,camera-flash"; - flash-source = <&pm8150l_flash0 &pm8150l_flash1>; - torch-source = <&pm8150l_torch0 &pm8150l_torch1>; - switch-source = <&pm8150l_switch2>; - status = "ok"; - }; - - led_flash_triple_rear_aux: qcom,camera-flash@5 { - cell-index = <5>; - compatible = "qcom,camera-flash"; - flash-source = <&pm8150l_flash0 &pm8150l_flash1>; - torch-source = <&pm8150l_torch0 &pm8150l_torch1>; - switch-source = <&pm8150l_switch2>; - status = "ok"; - }; - - led_flash_triple_rear_aux2: qcom,camera-flash@6 { - cell-index = <6>; - compatible = "qcom,camera-flash"; - flash-source = <&pm8150l_flash0 &pm8150l_flash1>; - torch-source = <&pm8150l_torch0 &pm8150l_torch1>; - switch-source = <&pm8150l_switch2>; - status = "ok"; - }; - - qcom,cam-res-mgr { - compatible = "qcom,cam-res-mgr"; - status = "ok"; - shared-gpios = <84 83 82 114 145>; - pinctrl-names = "cam_res_mgr_default", "cam_res_mgr_suspend"; - pinctrl-0 = <&cam_sensor_6dof_vana_active - &cam_sensor_6dof_vdig_active - &cam_sensor_6dof_vio_active - &cam_sensor_active_6 - &cam_sensor_et_vio_active>; - pinctrl-1 = <&cam_sensor_6dof_vana_suspend - &cam_sensor_6dof_vdig_suspend - &cam_sensor_6dof_vio_suspend - &cam_sensor_suspend_6 - &cam_sensor_et_vio_suspend>; - }; -}; - -&cam_cci0 { - actuator_rear: qcom,actuator0 { - cell-index = <0>; - compatible = "qcom,actuator"; - cci-master = <0>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2856000>; - rgltr-max-voltage = <3104000>; - rgltr-load-current = <100000>; - }; - - actuator_rear_aux: qcom,actuator1 { - cell-index = <1>; - compatible = "qcom,actuator"; - cci-master = <1>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2856000>; - rgltr-max-voltage = <3104000>; - rgltr-load-current = <100000>; - }; - - actuator_triple_wide: qcom,actuator4 { - cell-index = <4>; - compatible = "qcom,actuator"; - cci-master = <0>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2856000>; - rgltr-max-voltage = <3104000>; - rgltr-load-current = <100000>; - }; - - actuator_triple_tele: qcom,actuator5 { - cell-index = <5>; - compatible = "qcom,actuator"; - cci-master = <1>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2856000>; - rgltr-max-voltage = <3104000>; - rgltr-load-current = <100000>; - }; - - eeprom_rear: qcom,eeprom0 { - cell-index = <0>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l5>; - cam_vdig-supply = <&pm8009_l1>; - cam_clk-supply = <&titan_top_gdsc>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1104000 0 2856000>; - rgltr-max-voltage = <1800000 3000000 1104000 0 3104000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 94 0>, - <&tlmm 93 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-position = <0>; - sensor-mode = <0>; - cci-master = <0>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_rear_aux: qcom,eeprom1 { - cell-index = <1>; - compatible = "qcom,eeprom"; - cam_vdig-supply = <&pm8009_l2>; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l6>; - cam_clk-supply = <&titan_top_gdsc>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1200000 0 2856000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3104000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 95 0>, - <&tlmm 92 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1"; - sensor-position = <0>; - sensor-mode = <0>; - cci-master = <1>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_wide: qcom,eeprom4 { - cell-index = <4>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l5>; - cam_vdig-supply = <&pm8009_l1>; - cam_clk-supply = <&titan_top_gdsc>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1104000 0 2856000>; - rgltr-max-voltage = <1800000 3000000 1104000 0 3104000>; - rgltr-load-current = <120000 80000 1200000 0 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 94 0>, - <&tlmm 93 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-position = <0>; - sensor-mode = <0>; - cci-master = <0>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_tele: qcom,eeprom5 { - cell-index = <5>; - compatible = "qcom,eeprom"; - cam_vdig-supply = <&pm8009_l2>; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l6>; - cam_clk-supply = <&titan_top_gdsc>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1200000 0 2856000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3104000>; - rgltr-load-current = <120000 80000 1200000 0 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 95 0>, - <&tlmm 92 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1"; - sensor-position = <0>; - sensor-mode = <0>; - cci-master = <0>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - /* RGB Left (Master) */ - qcom,cam-sensor2 { - cell-index = <2>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <2>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - eeprom-src = <&eeprom_front>; - cam_vio-supply = <&pm8009_l7>; - cam_bob-supply = <&pm8150a_bob>; - cam_vana-supply = <&pm8009_l6>; - cam_vdig-supply = <&pm8009_l2>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3960000>; - rgltr-load-current = <600000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rgbleft>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rgbleft>; - gpios = <&tlmm 96 0>, - <&tlmm 78 0>, - <&tlmm 117 0>, - <&tlmm 116 0>, - <&tlmm 115 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-vio = <3>; - gpio-vdig = <4>; - gpio-req-tbl-num = <0 1 2 3 4>; - gpio-req-tbl-flags = <1 0 0 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_VANA2", - "CAM_VIO2", - "CAM_VDIG2"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - /* RGB Right(Slave) */ - qcom,cam-sensor3 { - cell-index = <3>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <3>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - cam_vio-supply = <&pm8009_l7>; - cam_bob-supply = <&pm8150a_bob>; - cam_vana-supply = <&pm8009_l6>; - cam_vdig-supply = <&pm8009_l2>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3960000>; - rgltr-load-current = <600000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_rgbright>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_rgbright>; - gpios = <&tlmm 97 0>, - <&tlmm 109 0>, - <&tlmm 117 0>, - <&tlmm 116 0>, - <&tlmm 115 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-vio = <3>; - gpio-vdig = <4>; - gpio-req-tbl-num = <0 1 2 3 4>; - gpio-req-tbl-flags = <1 0 0 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3", - "CAM_VANA3", - "CAM_VIO3", - "CAM_VDIG3"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - /* 6DOF Left (Slave) */ - qcom,cam-sensor4 { - cell-index = <4>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <4>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_vio-supply = <&pm8009_l7>; - cam_bob-supply = <&pm8150a_bob>; - cam_vana-supply = <&pm8009_l6>; - cam_vdig-supply = <&pm8009_l2>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3960000>; - rgltr-load-current = <6000000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk4_active - &cam_sensor_active_6dofright>; - pinctrl-1 = <&cam_sensor_mclk4_suspend - &cam_sensor_suspend_6dofright>; - gpios = <&tlmm 98 0>, - <&tlmm 131 0>, - <&tlmm 84 0>, - <&tlmm 83 0>, - <&tlmm 82 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-vio = <3>; - gpio-vdig = <4>; - gpio-req-tbl-num = <0 1 2 3 4>; - gpio-req-tbl-flags = <1 0 0 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK4", - "CAM_RESET4", - "CAM_VANA4", - "CAM_VIO4", - "CAM_VDIG4"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK4_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - /* 6DOF Right (Master) */ - qcom,cam-sensor5 { - cell-index = <5>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <5>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_bob-supply = <&pm8150a_bob>; - cam_vdig-supply = <&pm8009_l2>; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l6>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3960000>; - rgltr-load-current = <6000000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk5_active - &cam_sensor_active_6dofleft>; - pinctrl-1 = <&cam_sensor_mclk5_suspend - &cam_sensor_suspend_6dofleft>; - gpios = <&tlmm 99 0>, - <&tlmm 130 0>, - <&tlmm 84 0>, - <&tlmm 83 0>, - <&tlmm 82 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-vio = <3>; - gpio-vdig = <4>; - gpio-req-tbl-num = <0 1 2 3 4>; - gpio-req-tbl-flags = <1 0 0 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK5", - "CAM_RESET5", - "CAM_VANA5", - "CAM_VIO5", - "CAM_VDIG5"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK5_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - -}; - -&cam_cci1 { - actuator_triple_uw: qcom,actuator6 { - cell-index = <6>; - compatible = "qcom,actuator"; - cci-master = <0>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2856000>; - rgltr-max-voltage = <3104000>; - rgltr-load-current = <100000>; - }; - - eeprom_front: qcom,eeprom2 { - cell-index = <2>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l6>; - cam_vdig-supply = <&pm8009_l3>; - cam_clk-supply = <&titan_top_gdsc>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0 2856000>; - rgltr-max-voltage = <1800000 3000000 1056000 0 3104000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; - gpios = <&tlmm 96 0>, - <&tlmm 78 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-position = <1>; - sensor-mode = <0>; - cci-master = <0>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_uw: qcom,eeprom6 { - cell-index = <6>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l6>; - cam_vdig-supply = <&pm8009_l3>; - cam_clk-supply = <&titan_top_gdsc>; - cam_vaf-supply = <&pm8150a_l7>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0 2856000>; - rgltr-max-voltage = <1800000 3000000 1056000 0 3104000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rst2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rst2>; - gpios = <&tlmm 96 0>, - <&tlmm 78 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-position = <1>; - sensor-mode = <0>; - cci-master = <0>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_tof: qcom,eeprom3 { - cell-index = <3>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&pm8009_l7>; - cam_vdig-supply = <&vreg_tof>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - rgltr-min-voltage = <0 3600000 0>; - rgltr-max-voltage = <0 3600000 0>; - rgltr-load-current = <180000 120000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_3>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_3>; - gpios = <&tlmm 97 0>, - <&tlmm 109 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3"; - sensor-position = <1>; - sensor-mode = <0>; - cci-master = <1>; - status = "disabled"; - clocks = <&clock_camcc CAM_CC_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - /* ET LEFT (Master) */ - qcom,cam-sensor0 { - cell-index = <0>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <0>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_vio-supply = <&pm8009_l7>; - cam_bob-supply = <&pm8150a_bob>; - cam_vana-supply = <&pm8009_l6>; - cam_vdig-supply = <&pm8009_l1>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1104000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1104000 0 3960000>; - rgltr-load-current = <600000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_etleft>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_etleft>; - gpios = <&tlmm 94 0>, - <&tlmm 93 0>, - <&tlmm 114 0>, - <&tlmm 145 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-vio = <3>; - gpio-req-tbl-num = <0 1 2 3>; - gpio-req-tbl-flags = <1 0 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0", - "CAM_VANA0", - "CAM_VIO0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - /* ET RIGHT (Left) */ - qcom,cam-sensor1 { - cell-index = <1>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <1>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - cam_bob-supply = <&pm8150a_bob>; - cam_vdig-supply = <&pm8009_l2>; - cam_vio-supply = <&pm8009_l7>; - cam_vana-supply = <&pm8009_l6>; - cam_clk-supply = <&titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_bob"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 3008000>; - rgltr-max-voltage = <1800000 3000000 1200000 0 3960000>; - rgltr-load-current = <600000 80000 1200000 0 2000000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_etright>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_etright>; - gpios = <&tlmm 95 0>, - <&tlmm 92 0>, - <&tlmm 114 0>, - <&tlmm 145 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-vio = <3>; - gpio-req-tbl-num = <0 1 2 3>; - gpio-req-tbl-flags = <1 0 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1", - "CAM_VANA1", - "CAM_VIO1"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&clock_camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - -}; - diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera.dtsi index 11dc66d57e63..6a9054786a40 100755 --- a/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/camera/kona-camera.dtsi @@ -260,7 +260,7 @@ hw-thd-dat = <16>; hw-thd-sta = <15>; hw-tbuf = <24>; - hw-scl-stretch-en = <0>; + hw-scl-stretch-en = <1>; hw-trdhld = <3>; hw-tsp = <3>; cci-clk-src = <37500000>; @@ -353,7 +353,7 @@ hw-thd-dat = <16>; hw-thd-sta = <15>; hw-tbuf = <24>; - hw-scl-stretch-en = <0>; + hw-scl-stretch-en = <1>; hw-trdhld = <3>; hw-tsp = <3>; cci-clk-src = <37500000>; @@ -430,7 +430,7 @@ <&apps_smmu 0x2420 0x400>, <&apps_smmu 0x2421 0x400>; label = "icp"; - qcom,iommu-dma-addr-pool = <0x10c00000 0xee300000>; + qcom,iommu-dma-addr-pool = <0x17600000 0xe7900000>; iova-region-discard = <0xdff00000 0x300000>; icp_iova_mem_map: iova-mem-map { iova-mem-region-firmware { @@ -443,10 +443,10 @@ }; iova-mem-region-shared { - /* Shared region is 150MB long */ + /* Shared region is 268MB long */ iova-region-name = "shared"; iova-region-start = <0x7400000>; - iova-region-len = <0x9600000>; + iova-region-len = <0x10000000>; iova-region-id = <0x1>; status = "ok"; }; @@ -454,7 +454,7 @@ iova-mem-region-secondary-heap { /* Secondary heap region is 1MB long */ iova-region-name = "secheap"; - iova-region-start = <0x10a00000>; + iova-region-start = <0x17400000>; iova-region-len = <0x100000>; iova-region-id = <0x4>; status = "ok"; @@ -463,8 +463,8 @@ iova-mem-region-io { /* IO region is approximately 3.7 GB */ iova-region-name = "io"; - iova-region-start = <0x10c00000>; - iova-region-len = <0xee300000>; + iova-region-start = <0x17600000>; + iova-region-len = <0xe7900000>; iova-region-id = <0x3>; iova-region-discard = <0xdff00000 0x300000>; status = "ok"; @@ -473,7 +473,7 @@ iova-mem-qdss-region { /* QDSS region is appropriate 1MB */ iova-region-name = "qdss"; - iova-region-start = <0x10b00000>; + iova-region-start = <0x17500000>; iova-region-len = <0x100000>; iova-region-id = <0x5>; qdss-phy-addr = <0x16790000>; @@ -1437,11 +1437,11 @@ camss-supply = <&titan_top_gdsc>; clock-names = "ife_csid_clk_src", + "ife_lite_ahb", "ife_csid_clk", "cphy_rx_clk_src", "ife_cphy_rx_clk", "ife_clk_src", - "ife_lite_ahb", "ife_clk"; clocks = <&clock_camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera-sensor-cdp.dtsi deleted file mode 100755 index 1bb08daa1d83..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera-sensor-cdp.dtsi +++ /dev/null @@ -1,421 +0,0 @@ -#include - -&soc { - led_flash_triple_rear: qcom,camera-flash@4 { - cell-index = <4>; - reg = <0x04 0x00>; - compatible = "qcom,camera-flash"; - flash-source = <&pm6150l_flash0 &pm6150l_flash1>; - torch-source = <&pm6150l_torch0 &pm6150l_torch1>; - switch-source = <&pm6150l_switch2>; - }; - - led_flash_triple_rear_aux: qcom,camera-flash@5 { - cell-index = <5>; - reg = <0x05 0x00>; - compatible = "qcom,camera-flash"; - flash-source = <&pm6150l_flash0 &pm6150l_flash1>; - torch-source = <&pm6150l_torch0 &pm6150l_torch1>; - switch-source = <&pm6150l_switch2>; - }; - - led_flash_triple_rear_aux2: qcom,camera-flash@6 { - cell-index = <6>; - reg = <0x06 0x00>; - compatible = "qcom,camera-flash"; - flash-source = <&pm6150l_flash0 &pm6150l_flash1>; - torch-source = <&pm6150l_torch0 &pm6150l_torch1>; - switch-source = <&pm6150l_switch2>; - }; - - qcom,cam-res-mgr { - compatible = "qcom,cam-res-mgr"; - status = "ok"; - }; -}; - -&cam_cci0 { - actuator_triple_rear: qcom,actuator@4 { - cell-index = <4>; - reg = <0x4>; - compatible = "qcom,actuator"; - cci-device = <0>; - cci-master = <0>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - actuator_triple_rear_aux: qcom,actuator@5 { - cell-index = <5>; - reg = <0x5>; - compatible = "qcom,actuator"; - cci-device = <0>; - cci-master = <1>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - eeprom_triple_rear: qcom,eeprom@4 { - cell-index = <4>; - reg = <4>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2904000 1104000 0 2800000>; - rgltr-max-voltage = <1800000 2904000 1104000 0 2800000>; - rgltr-load-current = <0 80000 105000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 29 0>, - <&tlmm 34 0>, - <&tlmm 50 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK4", - "CAM_RESET4", - "CAM_VANA4"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_rear_aux: qcom,eeprom@5 { - cell-index = <5>; - reg = <5>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-load-current = <0 2000000 105000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 30 0>, - <&tlmm 35 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK5", - "CAM_RESET5"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@4 { - cell-index = <4>; - compatible = "qcom,cam-sensor"; - reg = <0x4>; - csiphy-sd-index = <0>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_triple_rear>; - actuator-src = <&actuator_triple_rear>; - eeprom-src = <&eeprom_triple_rear>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_v_custom1-supply = <&S2A>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_v_custom1"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2904000 1104000 0 2096000>; - rgltr-max-voltage = <1800000 2904000 1104000 0 2096000>; - rgltr-load-current = <0 80000 105000 0 80000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 29 0>, - <&tlmm 34 0>, - <&tlmm 50 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK4", - "CAM_RESET4", - "CAM_VANA4"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@5 { - cell-index = <5>; - compatible = "qcom,cam-sensor"; - reg = <0x5>; - csiphy-sd-index = <1>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_triple_rear_aux>; - actuator-src = <&actuator_triple_rear_aux>; - eeprom-src = <&eeprom_triple_rear_aux>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 2000000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 30 0>, - <&tlmm 35 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK5", - "CAM_RESET5"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; -}; - -&cam_cci1 { - actuator_triple_rear_aux2: qcom,actuator@6 { - cell-index = <6>; - reg = <0x6>; - compatible = "qcom,actuator"; - cci-device = <1>; - cci-master = <0>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - eeprom_front: qcom,eeprom@2 { - cell-index = <2>; - reg = <0x2>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_front>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_front>; - gpios = <&tlmm 32 0>, - <&tlmm 37 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3"; - sensor-position = <1>; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_rear_aux2: qcom,eeprom@6 { - cell-index = <6>; - reg = <6>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L7P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-load-current = <0 80000 105000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rear_aux2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rear_aux2>; - gpios = <&tlmm 31 0>, - <&tlmm 36 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@2 { - cell-index = <2>; - compatible = "qcom,cam-sensor"; - reg = <0x02>; - csiphy-sd-index = <3>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - eeprom-src = <&eeprom_front>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_front>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_front>; - gpios = <&tlmm 32 0>, - <&tlmm 37 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3"; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@6 { - cell-index = <6>; - compatible = "qcom,cam-sensor"; - reg = <0x06>; - csiphy-sd-index = <2>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_triple_rear_aux2>; - actuator-src = <&actuator_triple_rear_aux2>; - eeprom-src = <&eeprom_triple_rear_aux2>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L7P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rear_aux2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rear_aux2>; - gpios = <&tlmm 31 0>, - <&tlmm 36 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK6", - "CAM_RESET6"; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera-sensor-mtp.dtsi deleted file mode 100755 index 1bb08daa1d83..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera-sensor-mtp.dtsi +++ /dev/null @@ -1,421 +0,0 @@ -#include - -&soc { - led_flash_triple_rear: qcom,camera-flash@4 { - cell-index = <4>; - reg = <0x04 0x00>; - compatible = "qcom,camera-flash"; - flash-source = <&pm6150l_flash0 &pm6150l_flash1>; - torch-source = <&pm6150l_torch0 &pm6150l_torch1>; - switch-source = <&pm6150l_switch2>; - }; - - led_flash_triple_rear_aux: qcom,camera-flash@5 { - cell-index = <5>; - reg = <0x05 0x00>; - compatible = "qcom,camera-flash"; - flash-source = <&pm6150l_flash0 &pm6150l_flash1>; - torch-source = <&pm6150l_torch0 &pm6150l_torch1>; - switch-source = <&pm6150l_switch2>; - }; - - led_flash_triple_rear_aux2: qcom,camera-flash@6 { - cell-index = <6>; - reg = <0x06 0x00>; - compatible = "qcom,camera-flash"; - flash-source = <&pm6150l_flash0 &pm6150l_flash1>; - torch-source = <&pm6150l_torch0 &pm6150l_torch1>; - switch-source = <&pm6150l_switch2>; - }; - - qcom,cam-res-mgr { - compatible = "qcom,cam-res-mgr"; - status = "ok"; - }; -}; - -&cam_cci0 { - actuator_triple_rear: qcom,actuator@4 { - cell-index = <4>; - reg = <0x4>; - compatible = "qcom,actuator"; - cci-device = <0>; - cci-master = <0>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - actuator_triple_rear_aux: qcom,actuator@5 { - cell-index = <5>; - reg = <0x5>; - compatible = "qcom,actuator"; - cci-device = <0>; - cci-master = <1>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - eeprom_triple_rear: qcom,eeprom@4 { - cell-index = <4>; - reg = <4>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2904000 1104000 0 2800000>; - rgltr-max-voltage = <1800000 2904000 1104000 0 2800000>; - rgltr-load-current = <0 80000 105000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 29 0>, - <&tlmm 34 0>, - <&tlmm 50 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK4", - "CAM_RESET4", - "CAM_VANA4"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_rear_aux: qcom,eeprom@5 { - cell-index = <5>; - reg = <5>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-load-current = <0 2000000 105000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 30 0>, - <&tlmm 35 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK5", - "CAM_RESET5"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@4 { - cell-index = <4>; - compatible = "qcom,cam-sensor"; - reg = <0x4>; - csiphy-sd-index = <0>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_triple_rear>; - actuator-src = <&actuator_triple_rear>; - eeprom-src = <&eeprom_triple_rear>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_v_custom1-supply = <&S2A>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_v_custom1"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2904000 1104000 0 2096000>; - rgltr-max-voltage = <1800000 2904000 1104000 0 2096000>; - rgltr-load-current = <0 80000 105000 0 80000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_active_rear>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_suspend_rear>; - gpios = <&tlmm 29 0>, - <&tlmm 34 0>, - <&tlmm 50 0>; - gpio-reset = <1>; - gpio-vana = <2>; - gpio-req-tbl-num = <0 1 2>; - gpio-req-tbl-flags = <1 0 0>; - gpio-req-tbl-label = "CAMIF_MCLK4", - "CAM_RESET4", - "CAM_VANA4"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@5 { - cell-index = <5>; - compatible = "qcom,cam-sensor"; - reg = <0x5>; - csiphy-sd-index = <1>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_triple_rear_aux>; - actuator-src = <&actuator_triple_rear_aux>; - eeprom-src = <&eeprom_triple_rear_aux>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 2000000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_active_rear_aux>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_suspend_rear_aux>; - gpios = <&tlmm 30 0>, - <&tlmm 35 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK5", - "CAM_RESET5"; - sensor-mode = <0>; - cci-device = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; -}; - -&cam_cci1 { - actuator_triple_rear_aux2: qcom,actuator@6 { - cell-index = <6>; - reg = <0x6>; - compatible = "qcom,actuator"; - cci-device = <1>; - cci-master = <0>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - eeprom_front: qcom,eeprom@2 { - cell-index = <2>; - reg = <0x2>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_front>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_front>; - gpios = <&tlmm 32 0>, - <&tlmm 37 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3"; - sensor-position = <1>; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - eeprom_triple_rear_aux2: qcom,eeprom@6 { - cell-index = <6>; - reg = <6>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L7P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1056000 0 2800000>; - rgltr-load-current = <0 80000 105000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rear_aux2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rear_aux2>; - gpios = <&tlmm 31 0>, - <&tlmm 36 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@2 { - cell-index = <2>; - compatible = "qcom,cam-sensor"; - reg = <0x02>; - csiphy-sd-index = <3>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - eeprom-src = <&eeprom_front>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk3_active - &cam_sensor_active_front>; - pinctrl-1 = <&cam_sensor_mclk3_suspend - &cam_sensor_suspend_front>; - gpios = <&tlmm 32 0>, - <&tlmm 37 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK3", - "CAM_RESET3"; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK3_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - qcom,cam-sensor@6 { - cell-index = <6>; - compatible = "qcom,cam-sensor"; - reg = <0x06>; - csiphy-sd-index = <2>; - sensor-position-roll = <90>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - led-flash-src = <&led_flash_triple_rear_aux2>; - actuator-src = <&actuator_triple_rear_aux2>; - eeprom-src = <&eeprom_triple_rear_aux2>; - cam_vio-supply = <&L6P>; - cam_vana-supply = <&L7P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1056000 0>; - rgltr-max-voltage = <1800000 2800000 1056000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_active_rear_aux2>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_suspend_rear_aux2>; - gpios = <&tlmm 31 0>, - <&tlmm 36 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK6", - "CAM_RESET6"; - sensor-mode = <0>; - cci-device = <1>; - cci-master = <0>; - status = "ok"; - clocks = <&camcc CAM_CC_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera.dtsi deleted file mode 100755 index e59eb916a660..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/lagoon-camera.dtsi +++ /dev/null @@ -1,1478 +0,0 @@ -#include - -&soc { - qcom,cam-req-mgr { - compatible = "qcom,cam-req-mgr"; - status = "ok"; - }; - - cam_csiphy0: qcom,csiphy0 { - cell-index = <0>; - compatible = "qcom,csiphy-v1.2.3", "qcom,csiphy"; - reg = <0x0ac65000 0x1000>; - reg-names = "csiphy"; - reg-cam-base = <0x65000>; - interrupts = ; - interrupt-names = "csiphy"; - regulator-names = "gdscr", "refgen", "mipi-csi-vdd1", - "mipi-csi-vdd2"; - gdscr-supply = <&cam_cc_titan_top_gdsc>; - refgen-supply = <&refgen>; - mipi-csi-vdd1-supply = <&L18A>; - mipi-csi-vdd2-supply = <&L22A>; - rgltr-cntrl-support; - rgltr-min-voltage = <0 0 880000 1200000>; - rgltr-max-voltage = <0 0 880000 1200000>; - rgltr-load-current = <0 0 80000 80000>; - clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_CSIPHY0_CLK>, - <&camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, - <&camcc CAM_CC_CSI0PHYTIMER_CLK>; - clock-names = "cphy_rx_clk_src", - "csiphy0_clk", - "csi0phytimer_clk_src", - "csi0phytimer_clk"; - src-clock-name = "csi0phytimer_clk_src"; - clock-cntl-level = "lowsvs", "svs", "svs_l1"; - clock-rates = - <300000000 0 300000000 0>, - <384000000 0 300000000 0>, - <400000000 0 300000000 0>; - status = "ok"; - }; - - cam_csiphy1: qcom,csiphy1 { - cell-index = <1>; - compatible = "qcom,csiphy-v1.2.3", "qcom,csiphy"; - reg = <0xac66000 0x1000>; - reg-names = "csiphy"; - reg-cam-base = <0x66000>; - interrupts = ; - interrupt-names = "csiphy"; - regulator-names = "gdscr", "refgen", "mipi-csi-vdd1", - "mipi-csi-vdd2"; - gdscr-supply = <&cam_cc_titan_top_gdsc>; - refgen-supply = <&refgen>; - mipi-csi-vdd1-supply = <&L18A>; - mipi-csi-vdd2-supply = <&L22A>; - rgltr-cntrl-support; - rgltr-min-voltage = <0 0 880000 1200000>; - rgltr-max-voltage = <0 0 880000 1200000>; - rgltr-load-current = <0 0 80000 80000>; - clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_CSIPHY1_CLK>, - <&camcc CAM_CC_CSI1PHYTIMER_CLK_SRC>, - <&camcc CAM_CC_CSI1PHYTIMER_CLK>; - clock-names = "cphy_rx_clk_src", - "csiphy1_clk", - "csi1phytimer_clk_src", - "csi1phytimer_clk"; - src-clock-name = "csi1phytimer_clk_src"; - clock-cntl-level = "lowsvs", "svs", "svs_l1"; - clock-rates = - <300000000 0 300000000 0>, - <384000000 0 300000000 0>, - <400000000 0 300000000 0>; - status = "ok"; - }; - - cam_csiphy2: qcom,csiphy2 { - cell-index = <2>; - compatible = "qcom,csiphy-v1.2.3", "qcom,csiphy"; - reg = <0xac67000 0x1000>; - reg-names = "csiphy"; - reg-cam-base = <0x67000>; - interrupts = ; - interrupt-names = "csiphy"; - regulator-names = "gdscr", "refgen", "mipi-csi-vdd1", - "mipi-csi-vdd2"; - gdscr-supply = <&cam_cc_titan_top_gdsc>; - refgen-supply = <&refgen>; - mipi-csi-vdd1-supply = <&L18A>; - mipi-csi-vdd2-supply = <&L22A>; - rgltr-cntrl-support; - rgltr-min-voltage = <0 0 880000 1200000>; - rgltr-max-voltage = <0 0 880000 1200000>; - rgltr-load-current = <0 0 80000 80000>; - clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_CSIPHY2_CLK>, - <&camcc CAM_CC_CSI2PHYTIMER_CLK_SRC>, - <&camcc CAM_CC_CSI2PHYTIMER_CLK>; - clock-names = "cphy_rx_clk_src", - "csiphy2_clk", - "csi2phytimer_clk_src", - "csi2phytimer_clk"; - src-clock-name = "csi2phytimer_clk_src"; - clock-cntl-level = "lowsvs", "svs", "svs_l1"; - clock-rates = - <300000000 0 300000000 0>, - <384000000 0 300000000 0>, - <400000000 0 300000000 0>; - status = "ok"; - }; - - cam_csiphy3: qcom,csiphy3 { - cell-index = <3>; - compatible = "qcom,csiphy-v1.2.3", "qcom,csiphy"; - reg = <0xac68000 0x1000>; - reg-names = "csiphy"; - reg-cam-base = <0x68000>; - interrupts = ; - interrupt-names = "csiphy"; - regulator-names = "gdscr", "refgen", "mipi-csi-vdd1", - "mipi-csi-vdd2"; - gdscr-supply = <&cam_cc_titan_top_gdsc>; - refgen-supply = <&refgen>; - mipi-csi-vdd1-supply = <&L18A>; - mipi-csi-vdd2-supply = <&L22A>; - rgltr-cntrl-support; - rgltr-min-voltage = <0 0 880000 1200000>; - rgltr-max-voltage = <0 0 880000 1200000>; - rgltr-load-current = <0 0 80000 80000>; - clocks = <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_CSIPHY3_CLK>, - <&camcc CAM_CC_CSI3PHYTIMER_CLK_SRC>, - <&camcc CAM_CC_CSI3PHYTIMER_CLK>; - clock-names = "cphy_rx_clk_src", - "csiphy3_clk", - "csi3phytimer_clk_src", - "csi3phytimer_clk"; - src-clock-name = "csi3phytimer_clk_src"; - clock-cntl-level = "lowsvs", "svs", "svs_l1"; - clock-rates = - <300000000 0 300000000 0>, - <384000000 0 300000000 0>, - <400000000 0 300000000 0>; - status = "ok"; - }; - - cam_cci0: qcom,cci0 { - cell-index = <0>; - compatible = "qcom,cci"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0xac4a000 0x1000>; - reg-names = "cci"; - reg-cam-base = <0x4a000>; - interrupt-names = "cci"; - interrupts = ; - status = "ok"; - gdscr-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "gdscr"; - clocks = <&camcc CAM_CC_CCI_0_CLK>, - <&camcc CAM_CC_CCI_0_CLK_SRC>; - clock-names = "cci_0_clk", - "cci_0_clk_src"; - src-clock-name = "cci_0_clk_src"; - clock-cntl-level = "lowsvs"; - clock-rates = <0 37500000>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cci0_active &cci1_active>; - pinctrl-1 = <&cci0_suspend &cci1_suspend>; - gpios = <&tlmm 39 0>, - <&tlmm 40 0>, - <&tlmm 41 0>, - <&tlmm 42 0>; - gpio-req-tbl-num = <0 1 2 3>; - gpio-req-tbl-flags = <1 1 1 1>; - gpio-req-tbl-label = "CCI_I2C_DATA0", - "CCI_I2C_CLK0", - "CCI_I2C_DATA1", - "CCI_I2C_CLK1"; - - i2c_freq_100Khz_cci0: qcom,i2c_standard_mode { - hw-thigh = <201>; - hw-tlow = <174>; - hw-tsu-sto = <204>; - hw-tsu-sta = <231>; - hw-thd-dat = <22>; - hw-thd-sta = <162>; - hw-tbuf = <227>; - hw-scl-stretch-en = <0>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_400Khz_cci0: qcom,i2c_fast_mode { - hw-thigh = <38>; - hw-tlow = <56>; - hw-tsu-sto = <40>; - hw-tsu-sta = <40>; - hw-thd-dat = <22>; - hw-thd-sta = <35>; - hw-tbuf = <62>; - hw-scl-stretch-en = <0>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_custom_cci0: qcom,i2c_custom_mode { - hw-thigh = <38>; - hw-tlow = <56>; - hw-tsu-sto = <40>; - hw-tsu-sta = <40>; - hw-thd-dat = <22>; - hw-thd-sta = <35>; - hw-tbuf = <62>; - hw-scl-stretch-en = <1>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_1Mhz_cci0: qcom,i2c_fast_plus_mode { - hw-thigh = <16>; - hw-tlow = <22>; - hw-tsu-sto = <17>; - hw-tsu-sta = <18>; - hw-thd-dat = <16>; - hw-thd-sta = <15>; - hw-tbuf = <24>; - hw-scl-stretch-en = <0>; - hw-trdhld = <3>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - }; - - cam_cci1: qcom,cci1 { - cell-index = <1>; - compatible = "qcom,cci"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0xac4b000 0x1000>; - reg-names = "cci"; - reg-cam-base = <0x4b000>; - interrupt-names = "cci"; - interrupts = ; - status = "ok"; - gdscr-supply = <&cam_cc_titan_top_gdsc>; - regulator-names = "gdscr"; - clocks = <&camcc CAM_CC_CCI_1_CLK>, - <&camcc CAM_CC_CCI_1_CLK_SRC>; - clock-names = "cci_clk", - "cci_1_clk_src"; - src-clock-name = "cci_1_clk_src"; - clock-cntl-level = "lowsvs"; - clock-rates = <0 37500000>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cci2_active>; - pinctrl-1 = <&cci2_suspend>; - gpios = <&tlmm 43 0>, - <&tlmm 44 0>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 1>; - gpio-req-tbl-label = "CCI_I2C_DATA2", - "CCI_I2C_CLK2"; - - i2c_freq_100Khz_cci1: qcom,i2c_standard_mode { - hw-thigh = <201>; - hw-tlow = <174>; - hw-tsu-sto = <204>; - hw-tsu-sta = <231>; - hw-thd-dat = <22>; - hw-thd-sta = <162>; - hw-tbuf = <227>; - hw-scl-stretch-en = <0>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_400Khz_cci1: qcom,i2c_fast_mode { - hw-thigh = <38>; - hw-tlow = <56>; - hw-tsu-sto = <40>; - hw-tsu-sta = <40>; - hw-thd-dat = <22>; - hw-thd-sta = <35>; - hw-tbuf = <62>; - hw-scl-stretch-en = <0>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_custom_cci1: qcom,i2c_custom_mode { - hw-thigh = <38>; - hw-tlow = <56>; - hw-tsu-sto = <40>; - hw-tsu-sta = <40>; - hw-thd-dat = <22>; - hw-thd-sta = <35>; - hw-tbuf = <62>; - hw-scl-stretch-en = <1>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_1Mhz_cci1: qcom,i2c_fast_plus_mode { - hw-thigh = <16>; - hw-tlow = <22>; - hw-tsu-sto = <17>; - hw-tsu-sta = <18>; - hw-thd-dat = <16>; - hw-thd-sta = <15>; - hw-tbuf = <24>; - hw-scl-stretch-en = <0>; - hw-trdhld = <3>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - }; - - qcom,cam_smmu { - compatible = "qcom,msm-cam-smmu"; - status = "ok"; - non-fatal-fault-disabled; - - msm_cam_smmu_lrme { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0xD40 0x20>, - <&apps_smmu 0xD60 0x20>; - label = "lrme"; - lrme_iova_mem_map: iova-mem-map { - iova-mem-region-shared { - /* Shared region is 100MB long */ - iova-region-name = "shared"; - iova-region-start = <0x7400000>; - iova-region-len = <0x6400000>; - iova-region-id = <0x1>; - status = "ok"; - }; - /* IO region is approximately 3.3 GB */ - iova-mem-region-io { - iova-region-name = "io"; - iova-region-start = <0xd800000>; - iova-region-len = <0xd2800000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_ife { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0x820 0xc0>, - <&apps_smmu 0x840 0x0>, - <&apps_smmu 0x860 0xc0>, - <&apps_smmu 0x880 0x0>; - label = "ife"; - ife_iova_mem_map: iova-mem-map { - /* IO region is approximately 3.4 GB */ - iova-mem-region-io { - iova-region-name = "io"; - iova-region-start = <0x7400000>; - iova-region-len = <0xd8c00000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_jpeg { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0xD00 0x20>, - <&apps_smmu 0xD20 0x20>; - label = "jpeg"; - jpeg_iova_mem_map: iova-mem-map { - /* IO region is approximately 3.4 GB */ - iova-mem-region-io { - iova-region-name = "io"; - iova-region-start = <0x7400000>; - iova-region-len = <0xd8c00000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_icp_fw { - compatible = "qcom,msm-cam-smmu-fw-dev"; - label="icp"; - memory-region = <&pil_camera_mem>; - }; - - msm_cam_smmu_icp { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0xCA2 0x0>, - <&apps_smmu 0xCC0 0x20>, - <&apps_smmu 0xCE0 0x20>; - label = "icp"; - icp_iova_mem_map: iova-mem-map { - iova-mem-region-firmware { - /* Firmware region is 5MB */ - iova-region-name = "firmware"; - iova-region-start = <0x0>; - iova-region-len = <0x500000>; - iova-region-id = <0x0>; - status = "ok"; - }; - - iova-mem-region-shared { - /* Shared region is 150MB long */ - iova-region-name = "shared"; - iova-region-start = <0x7400000>; - iova-region-len = <0x9600000>; - iova-region-id = <0x1>; - iova-granularity = <0x15>; - status = "ok"; - }; - - iova-mem-region-secondary-heap { - /* Secondary heap region is 1MB long */ - iova-region-name = "secheap"; - iova-region-start = <0x10A00000>; - iova-region-len = <0x100000>; - iova-region-id = <0x4>; - status = "ok"; - }; - - iova-mem-region-io { - /* IO region is approximately 3 GB */ - iova-region-name = "io"; - iova-region-start = <0x10C00000>; - iova-region-len = <0xCF300000>; - iova-region-id = <0x3>; - status = "ok"; - }; - - iova-mem-qdss-region { - /* qdss region is approximately 1MB */ - iova-region-name = "qdss"; - iova-region-start = <0x10B00000>; - iova-region-len = <0x100000>; - iova-region-id = <0x5>; - qdss-phy-addr = <0x16790000>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_cpas_cdm { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0xC80 0x0>; - label = "cpas-cdm0"; - cpas_cdm_iova_mem_map: iova-mem-map { - iova-mem-region-io { - /* IO region is approximately 3.4 GB */ - iova-region-name = "io"; - iova-region-start = <0x7400000>; - iova-region-len = <0xd8c00000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_secure { - compatible = "qcom,msm-cam-smmu-cb"; - label = "cam-secure"; - qcom,secure-cb; - }; - - }; - - qcom,cam-cdm-intf { - compatible = "qcom,cam-cdm-intf"; - cell-index = <0>; - label = "cam-cdm-intf"; - num-hw-cdm = <1>; - cdm-client-names = "vfe", - "jpegdma", - "jpegenc", - "lrmecdm"; - status = "ok"; - }; - - qcom,cpas-cdm0@ac48000 { - cell-index = <0>; - compatible = "qcom,cam170-cpas-cdm0"; - label = "cpas-cdm"; - reg = <0xac48000 0x1000>; - reg-names = "cpas-cdm"; - reg-cam-base = <0x48000>; - interrupts = ; - interrupt-names = "cpas-cdm"; - regulator-names = "camss"; - camss-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "cam_cc_soc_ahb_clk", - "cam_cc_cpas_ahb_clk", - "cam_cc_camnoc_axi_clk"; - clocks = - <&camcc CAM_CC_SOC_AHB_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_CLK>; - clock-rates = <0 0 0>; - clock-cntl-level = "svs"; - cdm-client-names = "ife"; - status = "ok"; - }; - - qcom,cam-isp { - compatible = "qcom,cam-isp"; - arch-compat = "ife"; - status = "ok"; - }; - - cam_csid0: qcom,csid0@acb3000 { - cell-index = <0>; - compatible = "qcom,csid170_200"; - reg-names = "csid"; - reg = <0xacb3000 0x1000>; - reg-cam-base = <0xb3000>; - interrupt-names = "csid0"; - interrupts = ; - regulator-names = "camss", "ife0"; - camss-supply = <&cam_cc_titan_top_gdsc>; - ife0-supply = <&cam_cc_ife_0_gdsc>; - clock-names = - "ife_csid_clk_src", - "ife_csid_clk", - "cphy_rx_clk_src", - "ife_cphy_rx_clk", - "ife_clk_src", - "ife_clk", - "ife_axi_clk"; - clocks = - <&camcc CAM_CC_IFE_0_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_0_CSID_CLK>, - <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_IFE_0_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_0_CLK_SRC>, - <&camcc CAM_CC_IFE_0_CLK>, - <&camcc CAM_CC_IFE_0_AXI_CLK>; - clock-rates = - <300000000 0 0 0 320000000 0 0>, - <384000000 0 0 0 404000000 0 0>, - <400000000 0 0 0 480000000 0 0>, - <400000000 0 0 0 600000000 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_csid_clk_src"; - status = "ok"; - }; - - cam_vfe0: qcom,vfe0@acaf000 { - cell-index = <0>; - compatible = "qcom,vfe170_150"; - reg-names = "ife"; - reg = <0xacaf000 0x4000>; - reg-cam-base = <0xaf000>; - interrupt-names = "ife0"; - interrupts = ; - regulator-names = "camss", "ife0"; - camss-supply = <&cam_cc_titan_top_gdsc>; - ife0-supply = <&cam_cc_ife_0_gdsc>; - clock-names = - "ife_clk_src", - "ife_clk", - "ife_axi_clk"; - clocks = - <&camcc CAM_CC_IFE_0_CLK_SRC>, - <&camcc CAM_CC_IFE_0_CLK>, - <&camcc CAM_CC_IFE_0_AXI_CLK>; - clock-rates = - <320000000 0 0>, - <404000000 0 0>, - <480000000 0 0>, - <600000000 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_clk_src"; - clock-names-option = "ife_dsp_clk"; - clocks-option = <&camcc CAM_CC_IFE_0_DSP_CLK>; - clock-rates-option = <600000000>; - status = "ok"; - }; - - cam_csid1: qcom,csid1@acba000 { - cell-index = <1>; - compatible = "qcom,csid170_200"; - reg-names = "csid"; - reg = <0xacba000 0x1000>; - reg-cam-base = <0xba000>; - interrupt-names = "csid1"; - interrupts = ; - regulator-names = "camss", "ife1"; - camss-supply = <&cam_cc_titan_top_gdsc>; - ife1-supply = <&cam_cc_ife_1_gdsc>; - clock-names = - "ife_csid_clk_src", - "ife_csid_clk", - "cphy_rx_clk_src", - "ife_cphy_rx_clk", - "ife_clk_src", - "ife_clk", - "ife_axi_clk"; - clocks = - <&camcc CAM_CC_IFE_1_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_1_CSID_CLK>, - <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_IFE_1_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_1_CLK_SRC>, - <&camcc CAM_CC_IFE_1_CLK>, - <&camcc CAM_CC_IFE_1_AXI_CLK>; - clock-rates = - <300000000 0 0 0 320000000 0 0>, - <384000000 0 0 0 404000000 0 0>, - <400000000 0 0 0 480000000 0 0>, - <400000000 0 0 0 600000000 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_csid_clk_src"; - status = "ok"; - }; - - cam_vfe1: qcom,vfe1@acb6000 { - cell-index = <1>; - compatible = "qcom,vfe170_150"; - reg-names = "ife"; - reg = <0xacb6000 0x4000>; - reg-cam-base = <0xb6000>; - interrupt-names = "ife1"; - interrupts = ; - regulator-names = "camss", "ife1"; - camss-supply = <&cam_cc_titan_top_gdsc>; - ife1-supply = <&cam_cc_ife_1_gdsc>; - clock-names = - "ife_clk_src", - "ife_clk", - "ife_axi_clk"; - clocks = - <&camcc CAM_CC_IFE_1_CLK_SRC>, - <&camcc CAM_CC_IFE_1_CLK>, - <&camcc CAM_CC_IFE_1_AXI_CLK>; - clock-rates = - <320000000 0 0>, - <404000000 0 0>, - <480000000 0 0>, - <600000000 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_clk_src"; - clock-names-option = "ife_dsp_clk"; - clocks-option = <&camcc CAM_CC_IFE_1_DSP_CLK>; - clock-rates-option = <600000000>; - status = "ok"; - }; - - cam_csid2: qcom,csid2@acc1000 { - cell-index = <2>; - compatible = "qcom,csid170_200"; - reg-names = "csid2"; - reg = <0xacc1000 0x1000>; - reg-cam-base = <0xc1000>; - interrupt-names = "csid"; - interrupts = ; - regulator-names = "camss", "ife2"; - camss-supply = <&cam_cc_titan_top_gdsc>; - ife2-supply = <&cam_cc_ife_2_gdsc>; - clock-names = - "ife_csid_clk_src", - "ife_csid_clk", - "cphy_rx_clk_src", - "ife_cphy_rx_clk", - "ife_clk_src", - "ife_clk", - "ife_axi_clk"; - clocks = - <&camcc CAM_CC_IFE_2_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_2_CSID_CLK>, - <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_IFE_2_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_2_CLK_SRC>, - <&camcc CAM_CC_IFE_2_CLK>, - <&camcc CAM_CC_IFE_2_AXI_CLK>; - clock-rates = - <300000000 0 0 0 320000000 0 0>, - <384000000 0 0 0 404000000 0 0>, - <400000000 0 0 0 480000000 0 0>, - <400000000 0 0 0 600000000 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_csid_clk_src"; - status = "ok"; - }; - - cam_vfe2: qcom,vfe2@acbd000 { - cell-index = <2>; - compatible = "qcom,vfe170_150"; - reg-names = "ife2"; - reg = <0xacbd000 0x4000>; - reg-cam-base = <0xbd000>; - interrupt-names = "ife"; - interrupts = ; - regulator-names = "camss", "ife2"; - camss-supply = <&cam_cc_titan_top_gdsc>; - ife2-supply = <&cam_cc_ife_2_gdsc>; - clock-names = - "ife_clk_src", - "ife_clk", - "ife_axi_clk"; - clocks = - <&camcc CAM_CC_IFE_2_CLK_SRC>, - <&camcc CAM_CC_IFE_2_CLK>, - <&camcc CAM_CC_IFE_2_AXI_CLK>; - clock-rates = - <320000000 0 0>, - <404000000 0 0>, - <480000000 0 0>, - <600000000 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_clk_src"; - clock-names-option = "ife_dsp_clk"; - clocks-option = <&camcc CAM_CC_IFE_2_DSP_CLK>; - clock-rates-option = <600000000>; - status = "ok"; - }; - - cam_csid_lite: qcom,csid-lite@acc8000 { - cell-index = <3>; - compatible = "qcom,csid-lite170"; - reg-names = "csid-lite"; - reg = <0xacc8000 0x1000>; - reg-cam-base = <0xc8000>; - interrupt-names = "csid-lite"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "ife_csid_clk_src", - "ife_csid_clk", - "cphy_rx_clk_src", - "ife_cphy_rx_clk", - "ife_clk_src", - "ife_clk"; - clocks = - <&camcc CAM_CC_IFE_LITE_CSID_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CSID_CLK>, - <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <300000000 0 0 0 320000000 0>, - <384000000 0 0 0 400000000 0>, - <400000000 0 0 0 480000000 0>, - <400000000 0 0 0 600000000 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_csid_clk_src"; - status = "ok"; - }; - - cam_vfe_lite: qcom,vfe-lite@acc4000 { - cell-index = <3>; - compatible = "qcom,vfe-lite170"; - reg-names = "ife-lite"; - reg = <0xacc4000 0x4000>; - reg-cam-base = <0xc4000>; - interrupt-names = "ife-lite"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "ife_clk_src", - "ife_clk"; - clocks = - <&camcc CAM_CC_IFE_LITE_CLK_SRC>, - <&camcc CAM_CC_IFE_LITE_CLK>; - clock-rates = - <320000000 0>, - <400000000 0>, - <480000000 0>, - <600000000 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - src-clock-name = "ife_clk_src"; - status = "ok"; - }; - - qcom,cam-icp { - compatible = "qcom,cam-icp"; - compat-hw-name = "qcom,a5", - "qcom,ipe0", - "qcom,bps"; - num-a5 = <1>; - num-ipe = <1>; - num-bps = <1>; - status = "ok"; - }; - - cam_a5: qcom,a5@ac00000 { - cell-index = <0>; - compatible = "qcom,cam-a5"; - reg = <0xac00000 0x6000>, - <0xac10000 0x8000>, - <0xac18000 0x3000>; - reg-names = "a5_qgic", "a5_sierra", "a5_csr"; - reg-cam-base = <0x00000 0x10000 0x18000>; - interrupts = ; - interrupt-names = "a5"; - regulator-names = "camss-vdd"; - camss-vdd-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "soc_fast_ahb", - "soc_ahb_clk", - "icp_clk", - "icp_clk_src"; - src-clock-name = "icp_clk_src"; - clocks = - <&camcc CAM_CC_FAST_AHB_CLK_SRC>, - <&camcc CAM_CC_SOC_AHB_CLK>, - <&camcc CAM_CC_ICP_CLK>, - <&camcc CAM_CC_ICP_CLK_SRC>; - - clock-rates = - <100000000 0 0 384000000>, - <200000000 0 0 404000000>, - <300000000 0 0 600000000>, - <404000000 0 0 600000000>, - <404000000 0 0 600000000>; - clock-cntl-level = "lowsvs", "svs", - "svs_l1", "nominal", "turbo"; - fw_name = "CAMERA_ICP.elf"; - ubwc-cfg = <0x73 0x1CF>; - status = "ok"; - }; - - cam_ipe0: qcom,ipe0 { - cell-index = <0>; - compatible = "qcom,cam-ipe"; - reg = <0xac87000 0xa000>; - reg-names = "ipe0_top"; - reg-cam-base = <0x87000>; - regulator-names = "ipe0-vdd"; - ipe0-vdd-supply = <&cam_cc_ipe_0_gdsc>; - clock-names = - "ipe_0_ahb_clk", - "ipe_0_areg_clk", - "ipe_0_axi_clk", - "ipe_0_clk", - "ipe_0_clk_src"; - src-clock-name = "ipe_0_clk_src"; - clocks = <&camcc CAM_CC_IPE_0_AHB_CLK>, - <&camcc CAM_CC_IPE_0_AREG_CLK>, - <&camcc CAM_CC_IPE_0_AXI_CLK>, - <&camcc CAM_CC_IPE_0_CLK>, - <&camcc CAM_CC_IPE_0_CLK_SRC>; - - clock-rates = - <0 0 0 0 240000000>, - <0 0 0 0 320000000>, - <0 0 0 0 404000000>, - <0 0 0 0 538666666>, - <0 0 0 0 600000000>; - clock-cntl-level = "lowsvs", "svs", - "svs_l1", "nominal", "turbo"; - status = "ok"; - }; - - cam_bps: qcom,bps { - cell-index = <0>; - compatible = "qcom,cam-bps"; - reg = <0xac6f000 0x8000>; - reg-names = "bps_top"; - reg-cam-base = <0x6f000>; - regulator-names = "bps-vdd"; - bps-vdd-supply = <&cam_cc_bps_gdsc>; - clock-names = "bps_ahb_clk", - "bps_areg_clk", - "bps_axi_clk", - "bps_clk", - "bps_clk_src"; - src-clock-name = "bps_clk_src"; - clocks = - <&camcc CAM_CC_BPS_AHB_CLK>, - <&camcc CAM_CC_BPS_AREG_CLK>, - <&camcc CAM_CC_BPS_AXI_CLK>, - <&camcc CAM_CC_BPS_CLK>, - <&camcc CAM_CC_BPS_CLK_SRC>; - - clock-rates = - <0 0 0 0 200000000>, - <0 0 0 0 404000000>, - <0 0 0 0 480000000>, - <0 0 0 0 600000000>, - <0 0 0 0 600000000>; - clock-cntl-level = "lowsvs", "svs", - "svs_l1", "nominal", "turbo"; - status = "ok"; - }; - - qcom,cam-jpeg { - compatible = "qcom,cam-jpeg"; - compat-hw-name = "qcom,jpegenc", - "qcom,jpegdma"; - num-jpeg-enc = <1>; - num-jpeg-dma = <1>; - status = "ok"; - }; - - cam_jpeg_enc: qcom,jpegenc@ac4e000 { - cell-index = <0>; - compatible = "qcom,cam_jpeg_enc"; - reg-names = "jpege_hw"; - reg = <0xac4e000 0x4000>; - reg-cam-base = <0x4e000>; - interrupt-names = "jpeg"; - interrupts = ; - regulator-names = "camss-vdd"; - camss-vdd-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "jpegenc_clk_src", - "jpegenc_clk"; - clocks = - <&camcc CAM_CC_JPEG_CLK_SRC>, - <&camcc CAM_CC_JPEG_CLK>; - - clock-rates = - <600000000 0>; - src-clock-name = "jpegenc_clk_src"; - clock-cntl-level = "nominal"; - status = "ok"; - }; - - cam_jpeg_dma: qcom,jpegdma@0xac52000 { - cell-index = <0>; - compatible = "qcom,cam_jpeg_dma"; - reg-names = "jpegdma_hw"; - reg = <0xac52000 0x4000>; - reg-cam-base = <0x52000>; - interrupt-names = "jpegdma"; - interrupts = ; - regulator-names = "camss-vdd"; - camss-vdd-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "jpegdma_clk_src", - "jpegdma_clk"; - clocks = - <&camcc CAM_CC_JPEG_CLK_SRC>, - <&camcc CAM_CC_JPEG_CLK>; - - clock-rates = - <600000000 0>; - src-clock-name = "jpegdma_clk_src"; - clock-cntl-level = "nominal"; - status = "ok"; - }; - - qcom,cam-lrme { - compatible = "qcom,cam-lrme"; - arch-compat = "lrme"; - status = "ok"; - }; - - cam_lrme: qcom,lrme@ac6b000 { - cell-index = <0>; - compatible = "qcom,lrme"; - reg-names = "lrme"; - reg = <0xac6b000 0xa00>; - reg-cam-base = <0x6b000>; - interrupt-names = "lrme"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "lrme_clk_src", - "lrme_clk"; - clocks = - <&camcc CAM_CC_LRME_CLK_SRC>, - <&camcc CAM_CC_LRME_CLK>; - clock-rates = - <200000000 0>, - <269333333 0>, - <323200000 0>, - <404000000 0>, - <404000000 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "nominal", - "turbo"; - src-clock-name = "lrme_clk_src"; - status = "ok"; - }; - - qcom,cam-cpas@ac40000 { - cell-index = <0>; - compatible = "qcom,cam-cpas"; - label = "cpas"; - arch-compat = "cpas_top"; - status = "ok"; - reg-names = "cam_cpas_top", "cam_camnoc", "core_top_csr_tcsr"; - reg = <0xac40000 0x1000>, - <0xac42000 0x4600>, - <0x01fc0000 0x40000>; - reg-cam-base = <0x40000 0x42000 0x0>; - interrupt-names = "cpas_camnoc"; - interrupts = ; - qcom,cpas-hw-ver = <0x170200>; /* Titan v170 v2.0.0 */ - camnoc-axi-min-ib-bw = <3000000000>; - regulator-names = "camss-vdd"; - camss-vdd-supply = <&cam_cc_titan_top_gdsc>; - clock-names = - "gcc_ahb_clk", - "gcc_axi_clk", - "soc_ahb_clk", - "slow_ahb_clk_src", - "cpas_ahb_clk", - "camnoc_axi_clk"; - clocks = - <&gcc GCC_CAMERA_AHB_CLK>, - <&gcc GCC_CAMERA_AXI_CLK>, - <&camcc CAM_CC_SOC_AHB_CLK>, - <&camcc CAM_CC_SLOW_AHB_CLK_SRC>, - <&camcc CAM_CC_CPAS_AHB_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_CLK>; - src-clock-name = "slow_ahb_clk_src"; - clock-rates = - <0 0 0 0 0 0>, - <0 0 0 80000000 0 0>, - <0 0 0 80000000 0 0>, - <0 0 0 80000000 0 0>, - <0 0 0 80000000 0 0>, - <0 0 0 80000000 0 0>; - clock-cntl-level = "suspend", "lowsvs", "svs", - "svs_l1", "nominal", "turbo"; - qcom,msm-bus,name = "cam_ahb"; - qcom,msm-bus,num-cases = <7>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - , - , - , - , - , - ; - vdd-corners = ; - vdd-corner-ahb-mapping = "suspend", - "minsvs", "lowsvs", "svs", "svs_l1", - "nominal", "nominal", "nominal", - "turbo", "turbo"; - client-id-based; - client-names = - "csiphy0", "csiphy1", "csiphy2", "csiphy3", "cci0", - "cci1", "csid0", "csid1", "csid2", "csid3", - "ife0", "ife1", "ife2", "ife3", "ipe0", - "cam-cdm-intf0", "cpas-cdm0", "bps0", - "icp0", "jpeg-dma0", "jpeg-enc0", "lrmecpas0"; - - camera-bus-nodes { - level3-nodes { - level-index = <3>; - level3_rt0_wr_sum: level3-rt0-wr-sum { - cell-index = <0>; - node-name = "level3-rt0-wr-sum"; - traffic-merge-type = - ; - qcom,axi-port-name = "cam_hf_0"; - ib-bw-voting-needed; - qcom,axi-port-mnoc { - qcom,msm-bus,name = - "cam_hf_0_mnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - - qcom,axi-port-camnoc { - qcom,msm-bus,name = - "cam_hf_0_camnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - }; - - level3_nrt0_rd_wr_sum: level3-nrt0-rd-wr-sum { - cell-index = <1>; - node-name = "level3-nrt0-rd-wr-sum"; - traffic-merge-type = - ; - qcom,axi-port-name = "cam_sf_0"; - qcom,axi-port-mnoc { - qcom,msm-bus,name = - "cam_sf_0_mnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - - qcom,axi-port-camnoc { - qcom,msm-bus,name = - "cam_sf_0_camnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - }; - - level3_nrt1_rd_wr_sum: level3-nrt1-rd-wr-sum { - cell-index = <2>; - node-name = "level3-nrt1-rd-wr-sum"; - traffic-merge-type = - ; - qcom,axi-port-name = "cam_sf_icp"; - qcom,axi-port-mnoc { - qcom,msm-bus,name = - "cam_sf_icp_mnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - - qcom,axi-port-camnoc { - qcom,msm-bus,name = - "cam_sf_icp_camnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - }; - }; - - level2-nodes { - level-index = <2>; - level2_rt0_wr: level2-rt0-wr { - cell-index = <3>; - node-name = "level2-rt0-wr"; - parent-node = <&level3_rt0_wr_sum>; - traffic-merge-type = - ; - }; - - level2_nrt0_rd_wr: level2-nrt0-rd-wr { - cell-index = <4>; - node-name = "level2-nrt0-rd-wr"; - parent-node = <&level3_nrt0_rd_wr_sum>; - traffic-merge-type = - ; - }; - - level2_nrt1_rd: level2-nrt1-rd { - cell-index = <5>; - node-name = "level2-nrt1-rd"; - parent-node = <&level3_nrt1_rd_wr_sum>; - traffic-merge-type = - ; - bus-width-factor = <4>; - }; - }; - - level1-nodes { - level-index = <1>; - level1_rt0_wr: level1-rt0-wr { - cell-index = <6>; - node-name = "level1-rt0-wr"; - parent-node = <&level2_rt0_wr>; - traffic-merge-type = - ; - }; - - level1_rt1_wr: level1-rt1-wr { - cell-index = <7>; - node-name = "level1-rt1-wr"; - parent-node = <&level2_rt0_wr>; - traffic-merge-type = - ; - }; - - level1_nrt0_wr: level1-nrt0-wr { - cell-index = <8>; - node-name = "level1-nrt0-wr"; - parent-node = <&level2_nrt0_rd_wr>; - traffic-merge-type = - ; - }; - - level1_nrt0_rd: level1-nrt0-rd { - cell-index = <9>; - node-name = "level1-nrt0-rd"; - parent-node = <&level2_nrt0_rd_wr>; - traffic-merge-type = - ; - }; - }; - - level0-nodes { - level-index = <0>; - - ife0_rdi_all_wr: ife0-rdi-all-wr { - cell-index = <10>; - node-name = "ife0-rdi-all-wr"; - client-name = "ife0"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt0_wr>; - }; - - ife1_rdi_all_wr: ife1-rdi-all-wr { - cell-index = <11>; - node-name = "ife1-rdi-all-wr"; - client-name = "ife1"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt0_wr>; - }; - - ife2_rdi_all_wr: ife2-rdi-all-wr { - cell-index = <12>; - node-name = "ife2-rdi-all-wr"; - client-name = "ife2"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt1_wr>; - }; - - ife3_rdi_all_wr: ife3-rdi-all-wr { - cell-index = <13>; - node-name = "ife3-rdi-all-wr"; - client-name = "ife3"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt1_wr>; - }; - - ife0_pixelall_wr: ife0-pixelall-wr { - cell-index = <14>; - node-name = "ife0-pixelall-wr"; - client-name = "ife0"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt0_wr>; - }; - - ife1_pixelall_wr: ife1-pixelall-wr { - cell-index = <15>; - node-name = "ife1-pixelall-wr"; - client-name = "ife1"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt0_wr>; - }; - - ife2_pixelall_wr: ife2-pixelall-wr { - cell-index = <16>; - node-name = "ife2-pixelall-wr"; - client-name = "ife2"; - traffic-data = - ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt1_wr>; - }; - - bps0_all_wr: bps0-all-wr { - cell-index = <17>; - node-name = "bps0-all-wr"; - client-name = "bps0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level1_nrt0_wr>; - }; - - bps0_all_rd: bps0-all-rd { - cell-index = <18>; - node-name = "bps0-all-rd"; - client-name = "bps0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level1_nrt0_rd>; - }; - - ipe0_all_rd: ipe0-all-rd { - cell-index = <19>; - node-name = "ipe0-all-rd"; - client-name = "ipe0"; - traffic-data = ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_nrt0_rd>; - }; - - ipe0_all_wr: ipe0-all-wr { - cell-index = <20>; - node-name = "ipe0-all-wr"; - client-name = "ipe0"; - traffic-data = ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_nrt0_wr>; - }; - - lrme0_all_rd: lrme0-all-rd { - cell-index = <21>; - node-name = "lrme0-all-rd"; - client-name = "lrmecpas0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level1_nrt0_rd>; - }; - - lrme0_all_wr: lrme0-all-wr { - cell-index = <22>; - node-name = "lrme0-all-wr"; - client-name = "lrmecpas0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level1_nrt0_wr>; - }; - - cpas_cdm0_all_rd: cpas-cdm0-all-rd { - cell-index = <23>; - node-name = "cpas-cdm0-all-rd"; - client-name = "cpas-cdm0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level2_nrt0_rd_wr>; - }; - - jpeg0_all_wr: jpeg0-all-wr { - cell-index = <24>; - node-name = "jpeg0-all-wr"; - client-name = "jpeg-enc0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level2_nrt0_rd_wr>; - }; - - jpeg0_all_rd: jpeg0-all-rd { - cell-index = <25>; - node-name = "jpeg0-all-rd"; - client-name = "jpeg-enc0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level2_nrt0_rd_wr>; - }; - - icp0_all_rd: icp0-all-rd { - cell-index = <26>; - node-name = "icp0-all-rd"; - client-name = "icp0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level2_nrt1_rd>; - }; - }; - }; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/lito-v2-camera.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/lito-v2-camera.dtsi deleted file mode 100755 index 9b292b1bc692..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/lito-v2-camera.dtsi +++ /dev/null @@ -1,16 +0,0 @@ -/* Override CSIPHY version */ -&cam_csiphy0 { - compatible = "qcom,csiphy-v1.2.2.2", "qcom,csiphy"; -}; - -&cam_csiphy1 { - compatible = "qcom,csiphy-v1.2.2.2", "qcom,csiphy"; -}; - -&cam_csiphy2 { - compatible = "qcom,csiphy-v1.2.2.2", "qcom,csiphy"; -}; - -&cam_csiphy3 { - compatible = "qcom,csiphy-v1.2.2.2", "qcom,csiphy"; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/scuba-camera-sensor-idp.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/scuba-camera-sensor-idp.dtsi deleted file mode 100755 index 9d3d8cc43c8b..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/scuba-camera-sensor-idp.dtsi +++ /dev/null @@ -1,313 +0,0 @@ -#include -&soc { - led_flash_rear: qcom,camera-flash@0 { - cell-index = <0>; - compatible = "qcom,camera-flash"; - flash-source = <&pm2250_flash0>; - torch-source = <&pm2250_torch0>; - switch-source = <&pm2250_switch0>; - status = "ok"; - }; - - led_flash_rear_aux: qcom,camera-flash@1 { - cell-index = <1>; - compatible = "qcom,camera-flash"; - flash-source = <&pm2250_flash0>; - torch-source = <&pm2250_torch0>; - switch-source = <&pm2250_switch0>; - status = "ok"; - }; - - qcom,cam-res-mgr { - compatible = "qcom,cam-res-mgr"; - status = "ok"; - }; -}; - -&cam_cci0 { - actuator_rear: qcom,actuator0 { - cell-index = <0>; - compatible = "qcom,actuator"; - cci-master = <0>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - actuator_rear_aux: qcom,actuator1 { - cell-index = <1>; - compatible = "qcom,actuator"; - cci-master = <1>; - cam_vaf-supply = <&L5P>; - regulator-names = "cam_vaf"; - rgltr-cntrl-support; - rgltr-min-voltage = <2800000>; - rgltr-max-voltage = <2800000>; - rgltr-load-current = <100000>; - status = "ok"; - }; - - eeprom_rear: qcom,eeprom0 { - cell-index = <0>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_vaf-supply = <&L5P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1050000 0 2800000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_rear0_reset_active>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_rear0_reset_suspend>; - gpios = <&tlmm 20 0>, - <&tlmm 18 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - eeprom_rear_aux: qcom,eeprom1 { - cell-index = <1>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_vaf-supply = <&L5P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk", "cam_vaf"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0 2800000>; - rgltr-max-voltage = <1800000 2800000 1200000 0 2800000>; - rgltr-load-current = <120000 80000 1200000 0 100000>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_rear1_reset_active>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_rear1_reset_suspend>; - gpios = <&tlmm 21 0>, - <&tlmm 19 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - eeprom_front: qcom,eeprom2 { - cell-index = <2>; - compatible = "qcom,eeprom"; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L6P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_front0_reset_active>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_front0_reset_suspend>; - gpios = <&tlmm 27 0>, - <&tlmm 24 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; - - /* Rear*/ - qcom,cam-sensor0 { - cell-index = <0>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <0>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - actuator-src = <&actuator_rear>; - led-flash-src = <&led_flash_rear>; - eeprom-src = <&eeprom_rear>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L4P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; - rgltr-load-current = <120000 80000 1200000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk0_active - &cam_sensor_rear0_reset_active>; - pinctrl-1 = <&cam_sensor_mclk0_suspend - &cam_sensor_rear0_reset_suspend>; - gpios = <&tlmm 20 0>, - <&tlmm 18 0>; - gpio-reset = <1>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK0", - "CAM_RESET0"; - sensor-mode = <0>; - cci-master = <0>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK0_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - /*Rear Aux*/ - qcom,cam-sensor1 { - cell-index = <1>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <1>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <180>; - actuator-src = <&actuator_rear_aux>; - led-flash-src = <&led_flash_rear_aux>; - eeprom-src = <&eeprom_rear_aux>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L3P>; - cam_vdig-supply = <&L1P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1200000 0>; - rgltr-max-voltage = <1800000 2800000 1200000 0>; - rgltr-load-current = <120000 80000 1200000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk1_active - &cam_sensor_rear1_reset_active - &cam_sensor_csi_mux_oe_active - &cam_sensor_csi_mux_sel_active>; - pinctrl-1 = <&cam_sensor_mclk1_suspend - &cam_sensor_rear1_reset_suspend - &cam_sensor_csi_mux_oe_suspend - &cam_sensor_csi_mux_sel_suspend>; - gpios = <&tlmm 21 0>, - <&tlmm 19 0>, - <&tlmm 113 0>, - <&tlmm 114 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-custom2 = <3>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK1", - "CAM_RESET1", - "CAM_CSIMUX_OE0", - "CAM_CSIMUX_SEL0"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK1_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <19200000>; - }; - - /*Front*/ - qcom,cam-sensor2 { - cell-index = <2>; - compatible = "qcom,cam-sensor"; - csiphy-sd-index = <1>; - sensor-position-roll = <270>; - sensor-position-pitch = <0>; - sensor-position-yaw = <0>; - eeprom-src = <&eeprom_front>; - cam_vio-supply = <&L7P>; - cam_vana-supply = <&L6P>; - cam_vdig-supply = <&L2P>; - cam_clk-supply = <&gcc_camss_top_gdsc>; - regulator-names = "cam_vio", "cam_vana", "cam_vdig", - "cam_clk"; - rgltr-cntrl-support; - pwm-switch; - rgltr-min-voltage = <1800000 2800000 1050000 0>; - rgltr-max-voltage = <1800000 2800000 1050000 0>; - rgltr-load-current = <0 80000 105000 0>; - gpio-no-mux = <0>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_active - &cam_sensor_front0_reset_active - &cam_sensor_csi_mux_oe_active - &cam_sensor_csi_mux_sel_active>; - pinctrl-1 = <&cam_sensor_mclk2_suspend - &cam_sensor_front0_reset_suspend - &cam_sensor_csi_mux_oe_suspend - &cam_sensor_csi_mux_sel_suspend>; - gpios = <&tlmm 27 0>, - <&tlmm 24 0>, - <&tlmm 113 0>, - <&tlmm 114 0>; - gpio-reset = <1>; - gpio-custom1 = <2>; - gpio-custom2 = <3>; - gpio-req-tbl-num = <0 1>; - gpio-req-tbl-flags = <1 0>; - gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_CSIMUX_OE0", - "CAM_CSIMUX_SEL0"; - sensor-mode = <0>; - cci-master = <1>; - status = "ok"; - clocks = <&gcc GCC_CAMSS_MCLK2_CLK>; - clock-names = "cam_clk"; - clock-cntl-level = "turbo"; - clock-rates = <24000000>; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/camera/scuba-camera.dtsi b/arch/arm64/boot/dts/vendor/qcom/camera/scuba-camera.dtsi deleted file mode 100755 index 854c60c82264..000000000000 --- a/arch/arm64/boot/dts/vendor/qcom/camera/scuba-camera.dtsi +++ /dev/null @@ -1,774 +0,0 @@ -#include - -&soc { - qcom,cam-req-mgr { - compatible = "qcom,cam-req-mgr"; - status = "ok"; - }; - - cam_csiphy0: qcom,csiphy0 { - cell-index = <0>; - compatible = "qcom,csiphy-v2.0", "qcom,csiphy"; - reg = <0x05C52000 0x1000>; - reg-names = "csiphy"; - reg-cam-base = <0x52000>; - interrupts = ; - interrupt-names = "csiphy"; - regulator-names = "gdscr"; - gdscr-supply = <&gcc_camss_top_gdsc>; - csi-vdd-voltage = <1200000>; - mipi-csi-vdd-supply = <&L5A>; - clocks = <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_CPHY_0_CLK>, - <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK_SRC>, - <&gcc GCC_CAMSS_CSI0PHYTIMER_CLK>; - clock-names = "cphy_rx_clk_src", - "csiphy0_clk", - "csi0phytimer_clk_src", - "csi0phytimer_clk"; - src-clock-name = "csi0phytimer_clk_src"; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - clock-rates = - <19200000 0 19200000 0>, - <240000000 0 200000000 0>, - <341330000 0 200000000 0>, - <384000000 0 268800000 0>; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; - - cam_csiphy1: qcom,csiphy1 { - cell-index = <1>; - compatible = "qcom,csiphy-v2.0", "qcom,csiphy"; - reg = <0x05C53000 0x1000>; - reg-names = "csiphy"; - reg-cam-base = <0x53000>; - interrupts = ; - interrupt-names = "csiphy"; - regulator-names = "gdscr"; - gdscr-supply = <&gcc_camss_top_gdsc>; - csi-vdd-voltage = <1200000>; - mipi-csi-vdd-supply = <&L5A>; - clocks = <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_CPHY_1_CLK>, - <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK_SRC>, - <&gcc GCC_CAMSS_CSI1PHYTIMER_CLK>; - clock-names = "cphy_rx_clk_src", - "csiphy1_clk", - "csi1phytimer_clk_src", - "csi1phytimer_clk"; - src-clock-name = "csi1phytimer_clk_src"; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - clock-rates = - <19200000 0 19200000 0>, - <240000000 0 200000000 0>, - <341330000 0 200000000 0>, - <384000000 0 268800000 0>; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; - - cam_cci0: qcom,cci0 { - cell-index = <0>; - compatible = "qcom,cci"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x05C1B000 0x1000>; - reg-names = "cci"; - reg-cam-base = <0x1B000>; - interrupt-names = "cci"; - interrupts = ; - status = "ok"; - gdscr-supply = <&gcc_camss_top_gdsc>; - regulator-names = "gdscr"; - clocks = <&gcc GCC_CAMSS_CCI_0_CLK>, - <&gcc GCC_CAMSS_CCI_CLK_SRC>; - clock-names = "cci_0_clk", - "cci_0_clk_src"; - src-clock-name = "cci_0_clk_src"; - clock-cntl-level = "svs"; - clock-rates = <0 37500000>; - pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cci0_active &cci1_active>; - pinctrl-1 = <&cci0_suspend &cci1_suspend>; - gpios = <&tlmm 22 0>, - <&tlmm 23 0>, - <&tlmm 29 0>, - <&tlmm 30 0>; - gpio-req-tbl-num = <0 1 2 3>; - gpio-req-tbl-flags = <1 1 1 1>; - gpio-req-tbl-label = "CCI_I2C_DATA0", - "CCI_I2C_CLK0", - "CCI_I2C_DATA1", - "CCI_I2C_CLK1"; - - i2c_freq_100Khz_cci0: qcom,i2c_standard_mode { - hw-thigh = <201>; - hw-tlow = <174>; - hw-tsu-sto = <204>; - hw-tsu-sta = <231>; - hw-thd-dat = <22>; - hw-thd-sta = <162>; - hw-tbuf = <227>; - hw-scl-stretch-en = <0>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_400Khz_cci0: qcom,i2c_fast_mode { - hw-thigh = <38>; - hw-tlow = <56>; - hw-tsu-sto = <40>; - hw-tsu-sta = <40>; - hw-thd-dat = <22>; - hw-thd-sta = <35>; - hw-tbuf = <62>; - hw-scl-stretch-en = <0>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_custom_cci0: qcom,i2c_custom_mode { - hw-thigh = <38>; - hw-tlow = <56>; - hw-tsu-sto = <40>; - hw-tsu-sta = <40>; - hw-thd-dat = <22>; - hw-thd-sta = <35>; - hw-tbuf = <62>; - hw-scl-stretch-en = <1>; - hw-trdhld = <6>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - - i2c_freq_1Mhz_cci0: qcom,i2c_fast_plus_mode { - hw-thigh = <16>; - hw-tlow = <22>; - hw-tsu-sto = <17>; - hw-tsu-sta = <18>; - hw-thd-dat = <16>; - hw-thd-sta = <15>; - hw-tbuf = <24>; - hw-scl-stretch-en = <0>; - hw-trdhld = <3>; - hw-tsp = <3>; - cci-clk-src = <37500000>; - status = "ok"; - }; - }; - - qcom,cam_smmu { - compatible = "qcom,msm-cam-smmu"; - status = "ok"; - - msm_cam_smmu_tfe { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0x400 0x000>; - qcom,iommu-faults = "non-fatal"; - qcom,iommu-dma-addr-pool = <0x7400000 0xd8c00000>; - label = "tfe"; - tfe_iova_mem_map: iova-mem-map { - /* IO region is approximately 3.4 GB */ - iova-mem-region-io { - iova-region-name = "io"; - iova-region-start = <0x7400000>; - iova-region-len = <0xd8c00000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_ope { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0x820 0x000>, - <&apps_smmu 0x840 0x000>; - qcom,iommu-faults = "non-fatal"; - multiple-client-devices; - qcom,iommu-dma-addr-pool = <0x7400000 0xd8c00000>; - label = "ope", "ope-cdm0"; - ope_iova_mem_map: iova-mem-map { - /* IO region is approximately 3.4 GB */ - iova-mem-region-io { - iova-region-name = "io"; - iova-region-start = <0x7400000>; - iova-region-len = <0xd8c00000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_cpas_cdm { - compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0x800 0x000>; - label = "cpas-cdm0"; - qcom,iommu-faults = "non-fatal"; - qcom,iommu-dma-addr-pool = <0x7400000 0xd8c00000>; - cpas_cdm_iova_mem_map: iova-mem-map { - iova-mem-region-io { - /* IO region is approximately 3.4 GB */ - iova-region-name = "io"; - iova-region-start = <0x7400000>; - iova-region-len = <0xd8c00000>; - iova-region-id = <0x3>; - status = "ok"; - }; - }; - }; - - msm_cam_smmu_secure { - compatible = "qcom,msm-cam-smmu-cb"; - label = "cam-secure"; - qcom,secure-cb; - }; - - }; - - qcom,cam-cpas@5c11000 { - cell-index = <0>; - compatible = "qcom,cam-cpas"; - label = "cpas"; - arch-compat = "cpas_top"; - status = "ok"; - reg-names = "cam_cpas_top", "cam_camnoc"; - reg = <0x5c11000 0x1000>, - <0x5c13000 0x4000>; - reg-cam-base = <0x11000 0x13000>; - interrupt-names = "cpas_camnoc"; - interrupts = ; - camnoc-axi-min-ib-bw = <3000000000>; - regulator-names = "camss-vdd"; - camss-vdd-supply = <&gcc_camss_top_gdsc>; - clock-names = - "gcc_camss_ahb_clk", - "gcc_camss_top_ahb_clk", - "gcc_camss_top_ahb_clk_src", - "gcc_camss_axi_clk", - "gcc_camss_axi_clk_src", - "gcc_camss_nrt_axi_clk", - "gcc_camss_rt_axi_clk"; - clocks = - <&gcc GCC_CAMERA_AHB_CLK>, - <&gcc GCC_CAMSS_TOP_AHB_CLK>, - <&gcc GCC_CAMSS_TOP_AHB_CLK_SRC>, - <&gcc GCC_CAMSS_AXI_CLK>, - <&gcc GCC_CAMSS_AXI_CLK_SRC>, - <&gcc GCC_CAMSS_NRT_AXI_CLK>, - <&gcc GCC_CAMSS_RT_AXI_CLK>; - src-clock-name = "gcc_camss_axi_clk_src"; - clock-rates = - <0 0 0 0 0 0 0>, - <0 0 80000000 0 19200000 0 0>, - <0 0 80000000 0 150000000 0 0>, - <0 0 80000000 0 200000000 0 0>, - <0 0 80000000 0 300000000 0 0>, - <0 0 80000000 0 300000000 0 0>, - <0 0 80000000 0 300000000 0 0>; - clock-cntl-level = "suspend", "minsvs", "lowsvs", "svs", - "svs_l1", "nominal", "turbo"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - control-camnoc-axi-clk; - camnoc-bus-width = <32>; - camnoc-axi-clk-bw-margin-perc = <20>; - qcom,msm-bus,name = "cam_ahb"; - qcom,msm-bus,num-cases = <7>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - , - , - , - , - , - ; - vdd-corners = ; - vdd-corner-ahb-mapping = "suspend", "lowsvs", "lowsvs", - "lowsvs", "lowsvs", "svs", "svs_l1", "svs_l1", - "svs_l1", "nominal", "nominal", "nominal", - "turbo", "turbo"; - client-id-based; - client-names = - "csiphy0", "csiphy1", "cci0", - "csid0", "csid1", "tfe0", - "tfe1", "ope0", "cam-cdm-intf0", - "cpas-cdm0", "ope-cdm0", "tpg0", "tpg1"; - - camera-bus-nodes { - level2-nodes { - level-index = <2>; - level2_rt0_rd_wr_sum: level2-rt0-rd-wr-sum { - cell-index = <0>; - node-name = "level2-rt0-rd-wr-sum"; - traffic-merge-type = - ; - qcom,axi-port-name = "cam_hf_0"; - ib-bw-voting-needed; - qcom,axi-port-mnoc { - qcom,msm-bus,name = - "cam_hf_0_mnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - }; - - level2_nrt0_rd_wr_sum: level2-nrt0-rd-wr-sum { - cell-index = <1>; - node-name = "level2-nrt0-rd-wr-sum"; - traffic-merge-type = - ; - qcom,axi-port-name = "cam_sf_0"; - qcom,axi-port-mnoc { - qcom,msm-bus,name = - "cam_sf_0_mnoc"; - qcom,msm-bus-vector-dyn-vote; - qcom,msm-bus,num-cases = <2>; - qcom,msm-bus,num-paths = <1>; - qcom,msm-bus,vectors-KBps = - , - ; - }; - }; - }; - - level1-nodes { - level-index = <1>; - camnoc-max-needed; - level1_rt0_wr: level1-rt0-wr { - cell-index = <2>; - node-name = "level1-rt0-wr"; - parent-node = <&level2_rt0_rd_wr_sum>; - traffic-merge-type = - ; - }; - - level1_nrt0_rd_wr: level1-nrt0-rd-wr { - cell-index = <3>; - node-name = "level1-nrt0-rd-wr"; - parent-node = <&level2_nrt0_rd_wr_sum>; - traffic-merge-type = - ; - }; - }; - - level0-nodes { - level-index = <0>; - ope0_all_wr: ope0-all-wr { - cell-index = <4>; - node-name = "ope0-all-wr"; - client-name = "ope0"; - traffic-data = ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_nrt0_rd_wr>; - }; - - ope0_all_rd: ope0-all-rd { - cell-index = <5>; - node-name = "ope0-all-rd"; - client-name = "ope0"; - traffic-data = ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_nrt0_rd_wr>; - }; - - tfe0_all_wr: tfe0-all-wr { - cell-index = <6>; - node-name = "tfe0-all-wr"; - client-name = "tfe0"; - traffic-data = ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt0_wr>; - }; - - tfe1_all_wr: tfe1-all-wr { - cell-index = <7>; - node-name = "tfe1-all-wr"; - client-name = "tfe1"; - traffic-data = ; - traffic-transaction-type = - ; - constituent-paths = - ; - parent-node = <&level1_rt0_wr>; - }; - - cpas_cdm0_all_rd: cpas-cdm0-all-rd { - cell-index = <9>; - node-name = "cpas-cdm0-all-rd"; - client-name = "cpas-cdm0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level1_nrt0_rd_wr>; - }; - - ope_cdm0_all_rd: ope-cdm0-all-rd { - cell-index = <10>; - node-name = "ope-cdm0-all-rd"; - client-name = "ope-cdm0"; - traffic-data = ; - traffic-transaction-type = - ; - parent-node = <&level1_nrt0_rd_wr>; - }; - }; - }; - }; - - qcom,cam-cdm-intf { - compatible = "qcom,cam-cdm-intf"; - cell-index = <0>; - label = "cam-cdm-intf"; - num-hw-cdm = <2>; - cdm-client-names = "vfe"; - status = "ok"; - }; - - cam_cpas_cdm: qcom,cpas-cdm0@5c23000 { - cell-index = <0>; - compatible = "qcom,cam-cpas-cdm2_0"; - label = "cpas-cdm"; - reg = <0x5c23000 0x400>; - reg-names = "cpas-cdm0"; - reg-cam-base = <0x23000>; - interrupts = ; - interrupt-names = "cpas-cdm0"; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = "cam_cc_cpas_top_ahb_clk"; - clocks = <&gcc GCC_CAMSS_TOP_AHB_CLK>; - clock-rates = <0>; - clock-cntl-level = "svs"; - cdm-client-names = "tfe0", "tfe1"; - config-fifo; - fifo-depths = <64 64 64 64>; - status = "ok"; - }; - - cam_ope_cdm: qcom,ope-cdm0@5c42000 { - cell-index = <0>; - compatible = "qcom,cam-ope-cdm2_0"; - label = "ope-cdm"; - reg = <0x5c42000 0x400>; - reg-names = "ope-cdm0"; - reg-cam-base = <0x42000>; - interrupts = ; - interrupt-names = "ope-cdm0"; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "ope_ahb_clk", - "ope_clk_src", - "ope_clk"; - clocks = - <&gcc GCC_CAMSS_OPE_AHB_CLK>, - <&gcc GCC_CAMSS_OPE_CLK_SRC>, - <&gcc GCC_CAMSS_OPE_CLK>; - clock-rates = <0 0 0>, - <0 0 0>, - <0 0 0>, - <0 0 0>; - clock-cntl-level = "lowsvs", "svs", "svs_l1", "turbo"; - cdm-client-names = "ope"; - config-fifo; - fifo-depths = <64 64 64 64>; - status = "ok"; - }; - - qcom,cam-isp { - compatible = "qcom,cam-isp"; - arch-compat = "tfe"; - status = "ok"; - }; - - cam_tfe_csid0: qcom,tfe_csid0@5c6e000 { - cell-index = <0>; - compatible = "qcom,csid530"; - reg-names = "csid", "top", "camnoc"; - reg = <0x5c6e000 0x1000>, - <0x5c11000 0x1000>, - <0x5c13000 0x4000>; - reg-cam-base = <0x6e000 0x11000 0x13000>; - interrupt-names = "csid0"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "tfe_csid_clk_src", - "tfe_csid_clk", - "cphy_rx_clk_src", - "tfe_cphy_rx_clk", - "tfe_clk_src", - "tfe_clk"; - clocks = - <&gcc GCC_CAMSS_TFE_0_CSID_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CSID_CLK>, - <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, - <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CLK>; - clock-rates = - <240000000 0 240000000 0 256000000 0>, - <384000000 0 341333333 0 460800000 0>, - <426400000 0 384000000 0 576000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; - src-clock-name = "tfe_csid_clk_src"; - clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; - - cam_tfe0: qcom,tfe0@5c6e000 { - cell-index = <0>; - compatible = "qcom,tfe530"; - reg-names = "tfe0"; - reg = <0x5c6e000 0x5000>; - reg-cam-base = <0x6e000>; - interrupt-names = "tfe0"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "tfe_clk_src", - "tfe_clk"; - clocks = - <&gcc GCC_CAMSS_TFE_0_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CLK>; - clock-rates = - <256000000 0>, - <460800000 0>, - <576000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; - src-clock-name = "tfe_clk_src"; - clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; - - cam_tfe_csid1: qcom,tfe_csid1@5c75000 { - cell-index = <1>; - compatible = "qcom,csid530"; - reg-names = "csid", "top", "camnoc"; - reg = <0x5c75000 0x1000>, - <0x5c11000 0x1000>, - <0x5c13000 0x4000>; - reg-cam-base = <0x75000 0x11000 0x13000>; - interrupt-names = "csid1"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "tfe_csid_clk_src", - "tfe_csid_clk", - "cphy_rx_clk_src", - "tfe_cphy_rx_clk", - "tfe_clk_src", - "tfe_clk"; - clocks = - <&gcc GCC_CAMSS_TFE_1_CSID_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CSID_CLK>, - <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>, - <&gcc GCC_CAMSS_TFE_1_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CLK>; - clock-rates = - <240000000 0 240000000 0 256000000 0>, - <384000000 0 341333333 0 460800000 0>, - <426400000 0 384000000 0 576000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; - src-clock-name = "tfe_csid_clk_src"; - clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; - - cam_tfe1: qcom,tfe1@5c75000 { - cell-index = <1>; - compatible = "qcom,tfe530"; - reg-names = "tfe1"; - reg = <0x5c75000 0x5000>; - reg-cam-base = <0x75000>; - interrupt-names = "tfe1"; - interrupts = ; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "tfe_clk_src", - "tfe_clk"; - clocks = - <&gcc GCC_CAMSS_TFE_1_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CLK>; - clock-rates = - <256000000 0>, - <460800000 0>, - <576000000 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; - src-clock-name = "tfe_clk_src"; - clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; - - cam_tfe_tpg0: qcom,tpg0@5c66000 { - cell-index = <0>; - compatible = "qcom,tpgv1"; - reg-names = "tpg0", "top"; - reg = <0x5c66000 0x400>, - <0x5c11000 0x1000>; - reg-cam-base = <0x66000 0x11000>; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "cphy_rx_clk_src", - "tfe_0_cphy_rx_clk", - "gcc_camss_cphy_0_clk"; - clocks = - <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_0_CPHY_RX_CLK>, - <&gcc GCC_CAMSS_CPHY_0_CLK>; - clock-rates = - <240000000 0 0>, - <341333333 0 0>, - <384000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; - src-clock-name = "cphy_rx_clk_src"; - clock-control-debugfs = "false"; - status = "ok"; - }; - - cam_tfe_tpg1: qcom,tpg0@5c68000 { - cell-index = <1>; - compatible = "qcom,tpgv1"; - reg-names = "tpg0", "top"; - reg = <0x5c68000 0x400>, - <0x5c11000 0x1000>; - reg-cam-base = <0x68000 0x11000>; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "cphy_rx_clk_src", - "tfe_1_cphy_rx_clk", - "gcc_camss_cphy_1_clk"; - clocks = - <&gcc GCC_CAMSS_TFE_CPHY_RX_CLK_SRC>, - <&gcc GCC_CAMSS_TFE_1_CPHY_RX_CLK>, - <&gcc GCC_CAMSS_CPHY_1_CLK>; - clock-rates = - <240000000 0 0>, - <341333333 0 0>, - <384000000 0 0>; - clock-cntl-level = "svs", "svs_l1", "turbo"; - src-clock-name = "cphy_rx_clk_src"; - clock-control-debugfs = "false"; - status = "ok"; - }; - - qcom,cam-ope { - compatible = "qcom,cam-ope"; - compat-hw-name = "qcom,ope"; - num-ope = <1>; - status = "ok"; - }; - - ope: qcom,ope@0x5c42000 { - cell-index = <0>; - compatible = "qcom,ope"; - reg = - <0x5c42000 0x400>, - <0x5c42400 0x200>, - <0x5c42600 0x200>, - <0x5c42800 0x4400>, - <0x5c46c00 0x190>, - <0x5c46d90 0xA00>; - reg-names = - "ope_cdm", - "ope_top", - "ope_qos", - "ope_pp", - "ope_bus_rd", - "ope_bus_wr"; - reg-cam-base = <0x42000 0x42400 0x42600 0x42800 0x46c00 0x46d90>; - interrupts = ; - interrupt-names = "ope"; - regulator-names = "camss"; - camss-supply = <&gcc_camss_top_gdsc>; - clock-names = - "ope_ahb_clk_src", - "ope_ahb_clk", - "ope_clk_src", - "ope_clk"; - clocks = - <&gcc GCC_CAMSS_OPE_AHB_CLK_SRC>, - <&gcc GCC_CAMSS_OPE_AHB_CLK>, - <&gcc GCC_CAMSS_OPE_CLK_SRC>, - <&gcc GCC_CAMSS_OPE_CLK>; - clock-rates = - <171428571 0 200000000 0>, - <171428571 0 266600000 0>, - <240000000 0 465000000 0>, - <240000000 0 580000000 0>; - clock-cntl-level = "svs", "svs_l1", "nominal", "turbo"; - src-clock-name = "ope_clk_src"; - clock-control-debugfs = "true"; - qcom,cam-cx-ipeak = <&cx_ipeak_lm 8>; - status = "ok"; - }; -}; diff --git a/arch/arm64/boot/dts/vendor/qcom/kona-gpu.dtsi b/arch/arm64/boot/dts/vendor/qcom/kona-gpu.dtsi index 12af820076ee..0db3003f4e31 100755 --- a/arch/arm64/boot/dts/vendor/qcom/kona-gpu.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/kona-gpu.dtsi @@ -59,8 +59,6 @@ qcom,idle-timeout = <80>; /* msecs */ - qcom,no-nap; - qcom,highest-bank-bit = <16>; qcom,min-access-length = <32>; @@ -75,8 +73,6 @@ qcom,tzone-name = "gpuss-max-step"; - qcom,pm-qos-active-latency = <44>; - clocks = <&clock_gpucc GPU_CC_CXO_CLK>, <&clock_gcc GCC_DDRSS_GPU_AXI_CLK>, <&clock_gcc GCC_GPU_MEMNOC_GFX_CLK>, diff --git a/arch/arm64/boot/dts/vendor/qcom/kona-v2.dtsi b/arch/arm64/boot/dts/vendor/qcom/kona-v2.dtsi index 8ca5010a1ab7..10784c342a49 100755 --- a/arch/arm64/boot/dts/vendor/qcom/kona-v2.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/kona-v2.dtsi @@ -6,20 +6,44 @@ qcom,msm-id = <356 0x20000>; }; +&CPU0 { + capacity-dmips-mhz = <448>; + dynamic-power-coefficient = <103>; +}; + +&CPU1 { + capacity-dmips-mhz = <448>; + dynamic-power-coefficient = <103>; +}; + +&CPU2 { + capacity-dmips-mhz = <448>; + dynamic-power-coefficient = <103>; +}; + +&CPU3 { + capacity-dmips-mhz = <448>; + dynamic-power-coefficient = <103>; +}; + &CPU4 { - dynamic-power-coefficient = <533>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <340>; }; &CPU5 { - dynamic-power-coefficient = <533>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <340>; }; &CPU6 { - dynamic-power-coefficient = <533>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <340>; }; &CPU7 { - dynamic-power-coefficient = <642>; + capacity-dmips-mhz = <1024>; + dynamic-power-coefficient = <409>; }; &clock_camcc { @@ -390,4 +414,29 @@ , ; interrupt-names = "dcvsh0_int", "dcvsh1_int", "dcvsh2_int"; + + qcom,cpufreq-table-0 = + < 691200>, + <1708800>; + + qcom,cpufreq-table-1 = + < 710400>, + <1286400>, + <1478400>, + <1766400>, + <2054400>, + <2150400>, + <2246400>, + <2342400>, + <2419200>; + + qcom,cpufreq-table-2 = + < 844800>, + <1862400>, + <2073600>, + <2457600>, + <2553600>, + <2649600>, + <2745600>, + <2841600>; }; diff --git a/arch/arm64/boot/dts/vendor/qcom/kona.dtsi b/arch/arm64/boot/dts/vendor/qcom/kona.dtsi index 3497919fe01a..f0f7aeff1d96 100755 --- a/arch/arm64/boot/dts/vendor/qcom/kona.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/kona.dtsi @@ -347,7 +347,7 @@ }; chosen { - bootargs = "rcupdate.rcu_expedited=1 rcu_nocbs=0-7"; + bootargs = "rcu_nocbs=0-7 nodebugmon noirqdebug"; }; firmware: firmware { @@ -510,11 +510,6 @@ label = "cont_splash_region"; }; - disp_rdump_memory: disp_rdump_region@9c000000 { - reg = <0x0 0x9c000000 0x0 0x02400000>; - label = "disp_rdump_region"; - }; - dfps_data_memory: dfps_data_region@9e300000 { reg = <0x0 0x9e300000 0x0 0x0100000>; label = "dfps_data_region"; @@ -580,7 +575,7 @@ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; - size = <0x0 0x2000000>; + size = <0x0 0x8000000>; linux,cma-default; }; @@ -4307,7 +4302,7 @@ compatible = "qcom,msm-hdcp"; }; - mem_dump { + mem_dump: mem_dump { compatible = "qcom,mem-dump"; memory-region = <&dump_mem>; diff --git a/arch/arm64/boot/dts/vendor/qcom/pm8150.dtsi b/arch/arm64/boot/dts/vendor/qcom/pm8150.dtsi index e60f19afba85..16b8af9a737e 100755 --- a/arch/arm64/boot/dts/vendor/qcom/pm8150.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/pm8150.dtsi @@ -27,8 +27,9 @@ <0x0 0x8 0x5 IRQ_TYPE_EDGE_BOTH>; interrupt-names = "kpdpwr", "resin", "kpdpwr-bark", "resin-bark", "kpdpwr-resin-bark"; - qcom,pon-dbc-delay = <15625>; - qcom,kpdpwr-sw-debounce; + qcom,pon-dbc-delay = <62>; + qcom,pon-sw-dbc-delay = <15500>; + qcom,pon-sw-debounce; qcom,system-reset; qcom,store-hard-reset-reason; diff --git a/arch/arm64/boot/dts/vendor/qcom/xiaomi-sm8250-common.dtsi b/arch/arm64/boot/dts/vendor/qcom/xiaomi-sm8250-common.dtsi index 6ec5fa05cb81..cab92a4cdbd8 100755 --- a/arch/arm64/boot/dts/vendor/qcom/xiaomi-sm8250-common.dtsi +++ b/arch/arm64/boot/dts/vendor/qcom/xiaomi-sm8250-common.dtsi @@ -715,3 +715,11 @@ no-map; reg = <0x0 0xb0400000 0x0 0x01000000>; }; + +&dump_mem { + status = "disabled"; +}; + +&mem_dump { + status = "disabled"; +}; diff --git a/arch/arm64/configs/Apollo_defconfig b/arch/arm64/configs/Apollo_defconfig index 7a8091b82a27..473bd2a218fe 100755 --- a/arch/arm64/configs/Apollo_defconfig +++ b/arch/arm64/configs/Apollo_defconfig @@ -26,11 +26,11 @@ CONFIG_SWAP=y # CONFIG_POSIX_MQUEUE is not set CONFIG_CROSS_MEMORY_ATTACH=y # CONFIG_USELIB is not set -CONFIG_AUDIT=y +# CONFIG_AUDIT is not set CONFIG_HAVE_ARCH_AUDITSYSCALL=y -CONFIG_AUDITSYSCALL=y -CONFIG_AUDIT_WATCH=y -CONFIG_AUDIT_TREE=y +# CONFIG_AUDITSYSCALL is not set +# CONFIG_AUDIT_WATCH is not set +# CONFIG_AUDIT_TREE is not set # # IRQ subsystem @@ -102,7 +102,7 @@ CONFIG_RCU_NEED_SEGCBLIST=y CONFIG_RCU_FANOUT=64 CONFIG_RCU_FANOUT_LEAF=16 CONFIG_RCU_FAST_NO_HZ=y -# CONFIG_RCU_BOOST is not set +CONFIG_RCU_BOOST=y CONFIG_RCU_NOCB_CPU=y CONFIG_BUILD_BIN2C=y CONFIG_IKCONFIG=y @@ -144,7 +144,7 @@ CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y # CONFIG_CGROUP_DEBUG is not set CONFIG_SOCK_CGROUP_DATA=y -CONFIG_SCHED_CORE_CTL=y +# CONFIG_SCHED_CORE_CTL is not set # CONFIG_PERF_HUMANTASK is not set CONFIG_NAMESPACES=y CONFIG_UTS_NS=y @@ -152,7 +152,7 @@ CONFIG_UTS_NS=y # CONFIG_PID_NS is not set CONFIG_NET_NS=y # CONFIG_CHECKPOINT_RESTORE is not set -CONFIG_SCHED_AUTOGROUP=y +# CONFIG_SCHED_AUTOGROUP is not set CONFIG_SCHED_TUNE=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set @@ -167,6 +167,8 @@ CONFIG_RD_LZMA=y # CONFIG_RD_LZ4 is not set CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_HAVE_LD_DEAD_CODE_DATA_ELIMINATION=y +CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y CONFIG_SYSCTL=y CONFIG_HAVE_UID16=y CONFIG_SYSCTL_EXCEPTION_TRACE=y @@ -175,7 +177,6 @@ CONFIG_EXPERT=y CONFIG_UID16=y CONFIG_MULTIUSER=y # CONFIG_SGETMASK_SYSCALL is not set -CONFIG_SYSFS_SYSCALL=y # CONFIG_SYSCTL_SYSCALL is not set # CONFIG_FHANDLE is not set CONFIG_POSIX_TIMERS=y @@ -194,9 +195,7 @@ CONFIG_SHMEM=y CONFIG_AIO=y CONFIG_ADVISE_SYSCALLS=y CONFIG_MEMBARRIER=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_BASE_RELATIVE=y +# CONFIG_KALLSYMS is not set CONFIG_BPF_SYSCALL=y CONFIG_BPF_JIT_ALWAYS_ON=y # CONFIG_USERFAULTFD is not set @@ -223,10 +222,9 @@ CONFIG_SLUB=y CONFIG_SLAB_MERGE_DEFAULT=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_SLAB_FREELIST_HARDENED=y -CONFIG_SLUB_CPU_PARTIAL=y +# CONFIG_SLUB_CPU_PARTIAL is not set CONFIG_SYSTEM_DATA_VERIFICATION=y CONFIG_PROFILING=y -CONFIG_TRACEPOINTS=y CONFIG_ARM64=y CONFIG_64BIT=y CONFIG_MMU=y @@ -357,27 +355,26 @@ CONFIG_PCI_MSM_MSI=y # # ARM errata workarounds via the alternatives framework # -CONFIG_ARM64_ERRATUM_826319=y -CONFIG_ARM64_ERRATUM_827319=y -CONFIG_ARM64_ERRATUM_824069=y -CONFIG_ARM64_ERRATUM_819472=y -CONFIG_ARM64_ERRATUM_832075=y -CONFIG_ARM64_ERRATUM_845719=y -CONFIG_ARM64_ERRATUM_843419=y -CONFIG_ARM64_ERRATUM_1024718=y -CONFIG_ARM64_ERRATUM_1188873=y -CONFIG_ARM64_ERRATUM_1463225=y -CONFIG_ARM64_ERRATUM_1542418=y -CONFIG_CAVIUM_ERRATUM_22375=y -CONFIG_CAVIUM_ERRATUM_23154=y -CONFIG_CAVIUM_ERRATUM_27456=y -CONFIG_CAVIUM_ERRATUM_30115=y -CONFIG_QCOM_FALKOR_ERRATUM_1003=y -CONFIG_QCOM_FALKOR_ERRATUM_1009=y -CONFIG_QCOM_QDF2400_ERRATUM_0065=y -CONFIG_SOCIONEXT_SYNQUACER_PREITS=y -CONFIG_HISILICON_ERRATUM_161600802=y -CONFIG_QCOM_FALKOR_ERRATUM_E1041=y +# CONFIG_ARM64_ERRATUM_826319 is not set +# CONFIG_ARM64_ERRATUM_827319 is not set +# CONFIG_ARM64_ERRATUM_824069 is not set +# CONFIG_ARM64_ERRATUM_819472 is not set +# CONFIG_ARM64_ERRATUM_832075 is not set +# CONFIG_ARM64_ERRATUM_845719 is not set +# CONFIG_ARM64_ERRATUM_843419 is not set +# CONFIG_ARM64_ERRATUM_1188873 is not set +# CONFIG_ARM64_ERRATUM_1463225 is not set +# CONFIG_ARM64_ERRATUM_1542419 is not set +# CONFIG_CAVIUM_ERRATUM_22375 is not set +# CONFIG_CAVIUM_ERRATUM_23154 is not set +# CONFIG_CAVIUM_ERRATUM_27456 is not set +# CONFIG_CAVIUM_ERRATUM_30115 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1003 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_1009 is not set +# CONFIG_QCOM_QDF2400_ERRATUM_0065 is not set +# CONFIG_SOCIONEXT_SYNQUACER_PREITS is not set +# CONFIG_HISILICON_ERRATUM_161600802 is not set +# CONFIG_QCOM_FALKOR_ERRATUM_E1041 is not set CONFIG_ARM64_4K_PAGES=y # CONFIG_ARM64_16K_PAGES is not set # CONFIG_ARM64_64K_PAGES is not set @@ -390,6 +387,9 @@ CONFIG_ARM64_PA_BITS=48 CONFIG_SCHED_MC=y # CONFIG_SCHED_SMT is not set CONFIG_NR_CPUS=8 +CONFIG_LITTLE_CPU_MASK=15 +CONFIG_BIG_CPU_MASK=112 +CONFIG_PRIME_CPU_MASK=128 CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y @@ -427,15 +427,15 @@ CONFIG_OKL4_GUEST=y CONFIG_FORCE_MAX_ZONEORDER=11 # CONFIG_UNMAP_KERNEL_AT_EL0 is not set # CONFIG_HARDEN_BRANCH_PREDICTOR is not set -CONFIG_HARDEN_EL2_VECTORS=y +# CONFIG_HARDEN_EL2_VECTORS is not set CONFIG_ARM64_SSBD=y # CONFIG_PRINT_VMEMLAYOUT is not set CONFIG_ARM64_TAGGED_ADDR_ABI=y +CONFIG_COMPAT_VDSO=y CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y -CONFIG_ARM64_SW_TTBR0_PAN=y # # ARMv8.1 architectural features @@ -452,7 +452,6 @@ CONFIG_ARM64_UAO=y # CONFIG_ARM64_PMEM is not set CONFIG_ARM64_RAS_EXTN=y CONFIG_ARM64_SVE=y -CONFIG_ARM64_MODULE_PLTS=y CONFIG_RELOCATABLE=y CONFIG_RANDOMIZE_BASE=y CONFIG_RANDOMIZE_MODULE_REGION_FULL=y @@ -460,13 +459,11 @@ CONFIG_RANDOMIZE_MODULE_REGION_FULL=y # # Boot options # -CONFIG_CMDLINE="ramoops_memreserve=4M" +CONFIG_CMDLINE="ramoops_memreserve=4M quiet" # CONFIG_CMDLINE_FROM_BOOTLOADER is not set CONFIG_CMDLINE_EXTEND=y # CONFIG_CMDLINE_FORCE is not set # CONFIG_EFI is not set -# CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE is not set -# CONFIG_BUILD_ARM64_KERNEL_COMPRESSION_GZIP is not set # CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL is not set CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME="Image.gz-dtb" @@ -476,6 +473,7 @@ CONFIG_KRYO_PMU_WORKAROUND=y CONFIG_BOOT_INFO=y CONFIG_BUILD_ARM64_DT_OVERLAY=y CONFIG_COMPAT=y +CONFIG_KUSER_HELPERS=y # # Power management options @@ -528,19 +526,19 @@ CONFIG_CPU_FREQ_GOV_ATTR_SET=y CONFIG_CPU_FREQ_GOV_COMMON=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_FREQ_TIMES=y -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y -CONFIG_CPU_FREQ_GOV_USERSPACE=y -CONFIG_CPU_FREQ_GOV_ONDEMAND=y -CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y -CONFIG_CPU_BOOST=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +# CONFIG_CPU_BOOST is not set CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDHORIZON=y # # CPU frequency scaling drivers @@ -600,7 +598,7 @@ CONFIG_HWCONF_MANAGER=y # General architecture-dependent options # # CONFIG_KPROBES is not set -# CONFIG_JUMP_LABEL is not set +CONFIG_JUMP_LABEL=y CONFIG_UPROBES=y CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_KPROBES=y @@ -630,19 +628,24 @@ CONFIG_HAVE_ARCH_SECCOMP_FILTER=y CONFIG_SECCOMP_FILTER=y CONFIG_HAVE_STACKPROTECTOR=y CONFIG_CC_HAS_STACKPROTECTOR_NONE=y -CONFIG_STACKPROTECTOR=y -CONFIG_STACKPROTECTOR_STRONG=y +# CONFIG_STACKPROTECTOR is not set +# CONFIG_STACKPROTECTOR_STRONG is not set CONFIG_ARCH_SUPPORTS_LTO_CLANG=y CONFIG_ARCH_SUPPORTS_THINLTO=y -CONFIG_LTO_NONE=y +CONFIG_LTO=y +CONFIG_THINLTO=y +CONFIG_LTO_CLANG=y +# CONFIG_LTO_NONE is not set +# CONFIG_CFI_CLANG is not set CONFIG_ARCH_SUPPORTS_SHADOW_CALL_STACK=y # CONFIG_SHADOW_CALL_STACK is not set CONFIG_HAVE_CONTEXT_TRACKING=y CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_MOVE_PUD=y +CONFIG_HAVE_MOVE_PMD=y CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y CONFIG_HAVE_ARCH_HUGE_VMAP=y -CONFIG_HAVE_MOD_ARCH_SPECIFIC=y CONFIG_MODULES_USE_ELF_RELA=y CONFIG_ARCH_HAS_ELF_RANDOMIZE=y CONFIG_HAVE_ARCH_MMAP_RND_BITS=y @@ -658,11 +661,11 @@ CONFIG_VMAP_STACK=y CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y CONFIG_STRICT_KERNEL_RWX=y CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y -CONFIG_STRICT_MODULE_RWX=y -CONFIG_REFCOUNT_FULL=y CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y CONFIG_PANIC_ON_REFCOUNT_ERROR=y CONFIG_ARCH_HAS_RELR=y +CONFIG_TOOLS_SUPPORT_RELR=y +CONFIG_RELR=y # # GCOV-based kernel profiling @@ -672,22 +675,8 @@ CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y CONFIG_HAVE_GCC_PLUGINS=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_MODVERSIONS=y -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_MODULE_SIG=y -CONFIG_MODULE_SIG_FORCE=y -CONFIG_MODULE_SIG_ALL=y -# CONFIG_MODULE_SIG_SHA1 is not set -# CONFIG_MODULE_SIG_SHA224 is not set -# CONFIG_MODULE_SIG_SHA256 is not set -# CONFIG_MODULE_SIG_SHA384 is not set -CONFIG_MODULE_SIG_SHA512=y -CONFIG_MODULE_SIG_HASH="sha512" -# CONFIG_MODULE_COMPRESS is not set -# CONFIG_TRIM_UNUSED_KSYMS is not set +# CONFIG_MODULES is not set +CONFIG_TRIM_UNUSED_KSYMS=y CONFIG_MODULES_TREE_LOOKUP=y CONFIG_BLOCK=y CONFIG_BLK_SCSI_REQUEST=y @@ -701,7 +690,7 @@ CONFIG_BLK_WBT=y # CONFIG_BLK_CGROUP_IOLATENCY is not set CONFIG_BLK_WBT_SQ=y CONFIG_BLK_WBT_MQ=y -CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_DEBUG_FS is not set # CONFIG_BLK_SED_OPAL is not set CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y @@ -737,18 +726,76 @@ CONFIG_BLK_MQ_PCI=y # CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_MAPLE=y CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_FIOPS=y +CONFIG_IOSCHED_SIO=y +CONFIG_IOSCHED_ZEN=y CONFIG_CFQ_GROUP_IOSCHED=y # CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y +CONFIG_DEFAULT_FIOPS=y # CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEFAULT_IOSCHED="fiops" CONFIG_MQ_IOSCHED_DEADLINE=y CONFIG_MQ_IOSCHED_KYBER=y CONFIG_IOSCHED_BFQ=y CONFIG_BFQ_GROUP_IOSCHED=y CONFIG_ASN1=y -CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_INLINE_SPIN_TRYLOCK=y +CONFIG_ARCH_INLINE_SPIN_TRYLOCK_BH=y +CONFIG_ARCH_INLINE_SPIN_LOCK=y +CONFIG_ARCH_INLINE_SPIN_LOCK_BH=y +CONFIG_ARCH_INLINE_SPIN_LOCK_IRQ=y +CONFIG_ARCH_INLINE_SPIN_LOCK_IRQSAVE=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK_BH=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE=y +CONFIG_ARCH_INLINE_READ_TRYLOCK=y +CONFIG_ARCH_INLINE_READ_LOCK=y +CONFIG_ARCH_INLINE_READ_LOCK_BH=y +CONFIG_ARCH_INLINE_READ_LOCK_IRQ=y +CONFIG_ARCH_INLINE_READ_LOCK_IRQSAVE=y +CONFIG_ARCH_INLINE_READ_UNLOCK=y +CONFIG_ARCH_INLINE_READ_UNLOCK_BH=y +CONFIG_ARCH_INLINE_READ_UNLOCK_IRQ=y +CONFIG_ARCH_INLINE_READ_UNLOCK_IRQRESTORE=y +CONFIG_ARCH_INLINE_WRITE_TRYLOCK=y +CONFIG_ARCH_INLINE_WRITE_LOCK=y +CONFIG_ARCH_INLINE_WRITE_LOCK_BH=y +CONFIG_ARCH_INLINE_WRITE_LOCK_IRQ=y +CONFIG_ARCH_INLINE_WRITE_LOCK_IRQSAVE=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK_BH=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE=y +CONFIG_INLINE_SPIN_TRYLOCK=y +CONFIG_INLINE_SPIN_TRYLOCK_BH=y +CONFIG_INLINE_SPIN_LOCK=y +CONFIG_INLINE_SPIN_LOCK_BH=y +CONFIG_INLINE_SPIN_LOCK_IRQ=y +CONFIG_INLINE_SPIN_LOCK_IRQSAVE=y +CONFIG_INLINE_SPIN_UNLOCK_BH=y +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE=y +CONFIG_INLINE_READ_TRYLOCK=y +CONFIG_INLINE_READ_LOCK=y +CONFIG_INLINE_READ_LOCK_BH=y +CONFIG_INLINE_READ_LOCK_IRQ=y +CONFIG_INLINE_READ_LOCK_IRQSAVE=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_BH=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK_IRQRESTORE=y +CONFIG_INLINE_WRITE_TRYLOCK=y +CONFIG_INLINE_WRITE_LOCK=y +CONFIG_INLINE_WRITE_LOCK_BH=y +CONFIG_INLINE_WRITE_LOCK_IRQ=y +CONFIG_INLINE_WRITE_LOCK_IRQSAVE=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_BH=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE=y CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y CONFIG_MUTEX_SPIN_ON_OWNER=y CONFIG_RWSEM_SPIN_ON_OWNER=y @@ -830,11 +877,11 @@ CONFIG_GENERIC_EARLY_IOREMAP=y CONFIG_BALANCE_ANON_FILE_RECLAIM=y # CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set # CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_VMSTAT_INTERVAL=20 CONFIG_FRAME_VECTOR=y # CONFIG_PERCPU_STATS is not set CONFIG_ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT=y CONFIG_SPECULATIVE_PAGE_FAULT=y -CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y # CONFIG_GUP_BENCHMARK is not set CONFIG_ARCH_HAS_PTE_SPECIAL=y CONFIG_PROCESS_RECLAIM=y @@ -901,6 +948,8 @@ CONFIG_INET_DIAG_DESTROY=y CONFIG_TCP_CONG_BIC=y CONFIG_TCP_CONG_CUBIC=y CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_CORESIGHT_PLACEHOLDER=y +CONFIG_CORESIGHT_AMBA_PLACEHOLDER=y CONFIG_TCP_CONG_HTCP=y CONFIG_TCP_CONG_HSTCP=y CONFIG_TCP_CONG_HYBLA=y @@ -961,10 +1010,10 @@ CONFIG_NETFILTER_FAMILY_BRIDGE=y CONFIG_NETFILTER_FAMILY_ARP=y # CONFIG_NETFILTER_NETLINK_ACCT is not set CONFIG_NETFILTER_NETLINK_QUEUE=y -CONFIG_NETFILTER_NETLINK_LOG=y +# CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NETFILTER_NETLINK_OSF is not set CONFIG_NF_CONNTRACK=y -CONFIG_NF_LOG_COMMON=y +# CONFIG_NF_LOG_COMMON is not set # CONFIG_NF_LOG_NETDEV is not set CONFIG_NETFILTER_CONNCOUNT=y CONFIG_NF_CONNTRACK_MARK=y @@ -1026,11 +1075,11 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=y CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y # CONFIG_NETFILTER_XT_TARGET_LED is not set -CONFIG_NETFILTER_XT_TARGET_LOG=y +# CONFIG_NETFILTER_XT_TARGET_LOG is not set CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_NAT=y CONFIG_NETFILTER_XT_TARGET_NETMAP=y -CONFIG_NETFILTER_XT_TARGET_NFLOG=y +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y CONFIG_NETFILTER_XT_TARGET_NOTRACK=y # CONFIG_NETFILTER_XT_TARGET_RATEEST is not set @@ -1079,7 +1128,7 @@ CONFIG_NETFILTER_XT_MATCH_POLICY=y CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y -CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG is not set # CONFIG_NETFILTER_XT_MATCH_RATEEST is not set # CONFIG_NETFILTER_XT_MATCH_REALM is not set # CONFIG_NETFILTER_XT_MATCH_RECENT is not set @@ -1102,7 +1151,7 @@ CONFIG_NF_SOCKET_IPV4=y CONFIG_NF_TPROXY_IPV4=y CONFIG_NF_DUP_IPV4=y # CONFIG_NF_LOG_ARP is not set -CONFIG_NF_LOG_IPV4=y +# CONFIG_NF_LOG_IPV4 is not set CONFIG_NF_REJECT_IPV4=y CONFIG_NF_NAT_IPV4=y CONFIG_NF_NAT_MASQUERADE_IPV4=y @@ -1138,7 +1187,7 @@ CONFIG_NF_SOCKET_IPV6=y CONFIG_NF_TPROXY_IPV6=y CONFIG_NF_DUP_IPV6=y CONFIG_NF_REJECT_IPV6=y -CONFIG_NF_LOG_IPV6=y +# CONFIG_NF_LOG_IPV6 is not set # CONFIG_NF_NAT_IPV6 is not set CONFIG_IP6_NF_IPTABLES=y # CONFIG_IP6_NF_MATCH_AH is not set @@ -1341,7 +1390,7 @@ CONFIG_BT_HS=y CONFIG_BT_LE=y # CONFIG_BT_LEDS is not set # CONFIG_BT_SELFTEST is not set -CONFIG_BT_DEBUGFS=y +# CONFIG_BT_DEBUGFS is not set # # Bluetooth device drivers @@ -1426,7 +1475,7 @@ CONFIG_FW_LOADER_USER_HELPER=y CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y # CONFIG_FW_CACHE is not set CONFIG_WANT_DEV_COREDUMP=y -CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_ALLOW_DEV_COREDUMP is not set CONFIG_DEV_COREDUMP=y # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set @@ -1574,6 +1623,7 @@ CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_NULL_BLK is not set # CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set CONFIG_ZRAM=y +CONFIG_ZRAM_SIZE_OVERRIDE=1 # CONFIG_ZRAM_DEDUP is not set # CONFIG_ZRAM_WRITEBACK is not set # CONFIG_ZRAM_MEMORY_TRACKING is not set @@ -1641,7 +1691,7 @@ CONFIG_OKL4_USER_VIRQ=y # CONFIG_MOTOR_DRV8846 is not set # CONFIG_HALL_AKM09970 is not set # CONFIG_TEST_IRQ_REQUESTER is not set -CONFIG_WIGIG_SENSING_SPI=m +CONFIG_WIGIG_SENSING_SPI=y CONFIG_QTI_XR_SMRTVWR_MISC=y CONFIG_QTI_MAXIM_FAN_CONTROLLER=y # CONFIG_C2PORT is not set @@ -1730,7 +1780,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y CONFIG_SCSI_CONSTANTS=y -CONFIG_SCSI_LOGGING=y +# CONFIG_SCSI_LOGGING is not set CONFIG_SCSI_SCAN_ASYNC=y # @@ -1940,7 +1990,7 @@ CONFIG_NET_VENDOR_EMULEX=y # CONFIG_BE2NET is not set CONFIG_NET_VENDOR_EZCHIP=y # CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set -CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_NET_VENDOR_HISILICON is not set # CONFIG_HIX5HD2_GMAC is not set # CONFIG_HISI_FEMAC is not set # CONFIG_HIP04_ETH is not set @@ -1953,7 +2003,7 @@ CONFIG_NET_VENDOR_HP=y CONFIG_NET_VENDOR_HUAWEI=y # CONFIG_HINIC is not set CONFIG_NET_VENDOR_I825XX=y -CONFIG_NET_VENDOR_INTEL=y +# CONFIG_NET_VENDOR_INTEL is not set # CONFIG_E100 is not set # CONFIG_E1000 is not set # CONFIG_E1000E is not set @@ -2182,7 +2232,7 @@ CONFIG_WLAN_VENDOR_ATH=y # CONFIG_ATH_DEBUG is not set # CONFIG_ATH5K_PCI is not set # CONFIG_ATH6KL is not set -CONFIG_WIL6210=m +CONFIG_WIL6210=y CONFIG_WIL6210_ISR_COR=y # CONFIG_WIL6210_TRACING is not set CONFIG_WIL6210_PLATFORM_MSM=y @@ -2194,7 +2244,7 @@ CONFIG_WLAN_VENDOR_ATMEL=y CONFIG_WLAN_VENDOR_BROADCOM=y # CONFIG_BRCMFMAC is not set CONFIG_WLAN_VENDOR_CISCO=y -CONFIG_WLAN_VENDOR_INTEL=y +# CONFIG_WLAN_VENDOR_INTEL is not set # CONFIG_IPW2100 is not set # CONFIG_IPW2200 is not set CONFIG_WLAN_VENDOR_INTERSIL=y @@ -2334,7 +2384,7 @@ CONFIG_TABLET_USB_KBTAB=y CONFIG_INPUT_TOUCHSCREEN=y # CONFIG_TOUCHSCREEN_GOODIX_GTX8 is not set CONFIG_TOUCHSCREEN_NT36xxx_HOSTDL_SPI=y -CONFIG_TOUCHSCREEN_NVT_DEBUG_FS=y +# CONFIG_TOUCHSCREEN_NVT_DEBUG_FS is not set CONFIG_TOUCHSCREEN_PROPERTIES=y # CONFIG_TOUCHSCREEN_ADS7846 is not set # CONFIG_TOUCHSCREEN_AD7877 is not set @@ -2505,7 +2555,6 @@ CONFIG_LDISC_AUTOLOAD=y # # Serial drivers # -CONFIG_SERIAL_EARLYCON=y # CONFIG_SERIAL_8250 is not set # @@ -2518,11 +2567,11 @@ CONFIG_SERIAL_EARLYCON=y # CONFIG_SERIAL_MAX310X is not set # CONFIG_SERIAL_UARTLITE is not set CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_SERIAL_JSM is not set # CONFIG_SERIAL_MSM is not set +# CONFIG_SERIAL_MSM_CONSOLE is not set +# CONFIG_SERIAL_MSM_HSL_CONSOLE is not set CONFIG_SERIAL_MSM_GENI=y -CONFIG_SERIAL_MSM_GENI_CONSOLE=y CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING=y # CONFIG_SERIAL_MSM_HS is not set # CONFIG_SERIAL_SCCNXP is not set @@ -2535,7 +2584,6 @@ CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING=y # CONFIG_SERIAL_RP2 is not set # CONFIG_SERIAL_FSL_LPUART is not set # CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set -CONFIG_FASTBOOT_CMD_CTRL_UART=y CONFIG_SERIAL_DEV_BUS=y CONFIG_SERIAL_DEV_CTRL_TTYPORT=y CONFIG_TTY_PRINTK=y @@ -2564,8 +2612,7 @@ CONFIG_DIAGFWD_BRIDGE_CODE=y # CONFIG_MSM_FASTCVPD is not set CONFIG_MSM_ADSPRPC=y # CONFIG_ADSPRPC_DEBUG is not set -CONFIG_MSM_RDBG=m -CONFIG_XLOGCHAR=y +CONFIG_MSM_RDBG=y CONFIG_OKL4_PIPE=y CONFIG_VSERVICES_SERIAL=y CONFIG_VSERVICES_SERIAL_SERVER=y @@ -3297,7 +3344,7 @@ CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_DEV=y CONFIG_VIDEO_V4L2_SUBDEV_API=y CONFIG_VIDEO_V4L2=y -CONFIG_VIDEO_ADV_DEBUG=y +# CONFIG_VIDEO_ADV_DEBUG is not set CONFIG_VIDEO_FIXED_MINOR_RANGES=y CONFIG_V4L2_MEM2MEM_DEV=y CONFIG_DVB_CORE=y @@ -3318,7 +3365,7 @@ CONFIG_MEDIA_USB_SUPPORT=y # CONFIG_USB_VIDEO_CLASS=y CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y -CONFIG_USB_GSPCA=m +CONFIG_USB_GSPCA=y # CONFIG_USB_M5602 is not set # CONFIG_USB_STV06XX is not set # CONFIG_USB_GL860 is not set @@ -3412,12 +3459,12 @@ CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_MSM_CVP_V4L2=y CONFIG_MSM_NPU=y CONFIG_MSM_GLOBAL_SYNX=y -CONFIG_DVB_MPQ=m +CONFIG_DVB_MPQ=y # # Qualcomm Technologies, Inc. Demux device config # -CONFIG_DVB_MPQ_DEMUX=m +CONFIG_DVB_MPQ_DEMUX=y CONFIG_DVB_MPQ_NUM_DMX_DEVICES=4 CONFIG_DVB_MPQ_SW=y # CONFIG_TSPP is not set @@ -3743,7 +3790,7 @@ CONFIG_FB_ARMCLCD=y # CONFIG_FB_SM712 is not set # CONFIG_MSM_DBA is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=m +CONFIG_LCD_CLASS_DEVICE=y # CONFIG_LCD_L4F00242T03 is not set # CONFIG_LCD_LMS283GF05 is not set # CONFIG_LCD_LTV350QV is not set @@ -3783,10 +3830,6 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_DUMMY_CONSOLE_COLUMNS=80 CONFIG_DUMMY_CONSOLE_ROWS=25 # CONFIG_FRAMEBUFFER_CONSOLE is not set -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_TIMER=y @@ -4055,7 +4098,7 @@ CONFIG_HID_GENERIC=y # CONFIG_HID_A4TECH is not set # CONFIG_HID_ACCUTOUCH is not set # CONFIG_HID_ACRUX is not set -CONFIG_HID_APPLE=y +# CONFIG_HID_APPLE is not set # CONFIG_HID_APPLEIR is not set # CONFIG_HID_ASUS is not set # CONFIG_HID_AUREAL is not set @@ -4071,7 +4114,7 @@ CONFIG_HID_APPLE=y # CONFIG_HID_DRAGONRISE is not set # CONFIG_HID_EMS_FF is not set # CONFIG_HID_ELAN is not set -CONFIG_HID_ELECOM=y +# CONFIG_HID_ELECOM is not set # CONFIG_HID_ELO is not set # CONFIG_HID_EZKEY is not set # CONFIG_HID_GEMBIRD is not set @@ -4093,13 +4136,13 @@ CONFIG_HID_ELECOM=y # CONFIG_HID_LED is not set # CONFIG_HID_LENOVO is not set # CONFIG_HID_LOGITECH is not set -CONFIG_HID_MAGICMOUSE=y +# CONFIG_HID_MAGICMOUSE is not set # CONFIG_HID_MAYFLASH is not set # CONFIG_HID_REDRAGON is not set -CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MICROSOFT is not set # CONFIG_HID_MONTEREY is not set CONFIG_HID_MULTITOUCH=y -CONFIG_HID_NINTENDO=y +# CONFIG_HID_NINTENDO is not set # CONFIG_HID_NTI is not set # CONFIG_HID_NTRIG is not set # CONFIG_HID_ORTEK is not set @@ -4107,13 +4150,13 @@ CONFIG_HID_NINTENDO=y # CONFIG_HID_PENMOUNT is not set # CONFIG_HID_PETALYNX is not set # CONFIG_HID_PICOLCD is not set -CONFIG_HID_PLANTRONICS=y +# CONFIG_HID_PLANTRONICS is not set # CONFIG_HID_PRIMAX is not set # CONFIG_HID_RETRODE is not set # CONFIG_HID_ROCCAT is not set # CONFIG_HID_SAITEK is not set # CONFIG_HID_SAMSUNG is not set -CONFIG_HID_SONY=y +# CONFIG_HID_SONY is not set # CONFIG_SONY_FF is not set # CONFIG_HID_SPEEDLINK is not set # CONFIG_HID_STEAM is not set @@ -4134,7 +4177,7 @@ CONFIG_HID_SONY=y # CONFIG_HID_ZYDACRON is not set # CONFIG_HID_SENSOR_HUB is not set # CONFIG_HID_ALPS is not set -CONFIG_HID_QVR=y +# CONFIG_HID_QVR is not set # # USB HID support @@ -4450,19 +4493,16 @@ CONFIG_QPNP_USB_PDPHY=y # CONFIG_USB_LED_TRIG is not set # CONFIG_USB_ULPI_BUS is not set # CONFIG_UWB is not set -CONFIG_PWRSEQ_EMMC=y -CONFIG_PWRSEQ_SIMPLE=y # CONFIG_SDIO_UART is not set # CONFIG_MMC_IPC_LOGGING is not set # # MMC/SD/SDIO Host Controller Drivers # +# CONFIG_MMC is not set # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_ARMMMCI is not set -CONFIG_MMC_SDHCI_IO_ACCESSORS=y # CONFIG_MMC_SDHCI_PCI is not set -CONFIG_MMC_SDHCI_PLTFM=y # CONFIG_MMC_SDHCI_OF_ARASAN is not set # CONFIG_MMC_SDHCI_OF_AT91 is not set # CONFIG_MMC_SDHCI_OF_DWCMSHC is not set @@ -4560,7 +4600,6 @@ CONFIG_EDAC_LEGACY_SYSFS=y CONFIG_EDAC_KRYO_ARM64=y # CONFIG_EDAC_KRYO_ARM64_POLL is not set # CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set -CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y # CONFIG_EDAC_XGENE is not set # CONFIG_EDAC_CORTEX_ARM64 is not set # CONFIG_EDAC_QCOM is not set @@ -4734,7 +4773,7 @@ CONFIG_VIRTIO_MENU=y CONFIG_VSERVICES_SUPPORT=y CONFIG_VSERVICES_CHAR_DEV=y # CONFIG_VSERVICES_DEBUG is not set -CONFIG_VSERVICES_LOCK_DEBUG=y +# CONFIG_VSERVICES_LOCK_DEBUG is not set CONFIG_VSERVICES_SERVER=y CONFIG_VSERVICES_CLIENT=y # CONFIG_VSERVICES_SKELETON_DRIVER is not set @@ -4844,6 +4883,7 @@ CONFIG_ION=y # CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE is not set CONFIG_ION_POOL_AUTO_REFILL=y CONFIG_ION_POOL_FILL_MARK=100 +CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS=y # CONFIG_STAGING_BOARD is not set # CONFIG_LTE_GDM724X is not set # CONFIG_DGNC is not set @@ -4893,7 +4933,7 @@ CONFIG_RNDIS_IPA=y # CONFIG_IPA3_MHI_PROXY is not set CONFIG_IPA3_MHI_PRIME_MANAGER=y CONFIG_IPA_UT=y -CONFIG_MSM_11AD=m +CONFIG_MSM_11AD=y CONFIG_USB_BAM=y CONFIG_QCOM_GENI_SE=y CONFIG_IPA3_REGDUMP=y @@ -5004,10 +5044,10 @@ CONFIG_TIMER_PROBE=y CONFIG_ARM_ARCH_TIMER=y CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y -CONFIG_FSL_ERRATUM_A008585=y -CONFIG_HISILICON_ERRATUM_161010101=y -CONFIG_ARM64_ERRATUM_858921=y -# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_FSL_ERRATUM_A008585 is not set +# CONFIG_HISILICON_ERRATUM_161010101 is not set +# CONFIG_ARM64_ERRATUM_858921 is not set +CONFIG_ARM_ARCH_TIMER_VCT_ACCESS=y # CONFIG_ARM_TIMER_SP804 is not set CONFIG_MAILBOX=y # CONFIG_ARM_MHU is not set @@ -5030,7 +5070,7 @@ CONFIG_IOMMU_IO_PGTABLE_LPAE=y CONFIG_IOMMU_IO_PGTABLE_FAST=y # CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST is not set # CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB is not set -CONFIG_IOMMU_DEBUGFS=y +# CONFIG_IOMMU_DEBUGFS is not set # CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set CONFIG_IOMMU_IOVA=y CONFIG_OF_IOMMU=y @@ -5103,7 +5143,6 @@ CONFIG_QCOM_KONA_LLCC=y # CONFIG_QCOM_LITO_LLCC is not set # CONFIG_QCOM_LAGOON_LLCC is not set # CONFIG_QCOM_SDM845_LLCC is not set -CONFIG_QCOM_LLCC_PERFMON=m CONFIG_QCOM_MDT_LOADER=y CONFIG_QPNP_PBS=y CONFIG_QCOM_QMI_HELPERS=y @@ -5167,21 +5206,17 @@ CONFIG_QTI_SYSTEM_PM=y CONFIG_QCOM_SMCINVOKE=y CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_PM=y -CONFIG_MSM_IDLE_STATS=y -CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 -CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 -CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +# CONFIG_MSM_IDLE_STATS is not set CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 # CONFIG_QTI_L2_REUSE is not set -CONFIG_QTI_RPM_STATS_LOG=y -CONFIG_QTI_DDR_STATS_LOG=y +# CONFIG_QTI_RPM_STATS_LOG is not set +# CONFIG_QTI_DDR_STATS_LOG is not set # CONFIG_MSM_JTAGV8 is not set CONFIG_QTEE_SHM_BRIDGE=y # CONFIG_MEM_SHARE_QMI_SERVICE is not set -CONFIG_MSM_PERFORMANCE=y +# CONFIG_MSM_PERFORMANCE is not set CONFIG_QMP_DEBUGFS_CLIENT=y CONFIG_QCOM_CDSP_RM=y -CONFIG_QCOM_QHEE_ENABLE_MEM_PROTECTION=y # CONFIG_QCOM_CX_IPEAK is not set CONFIG_QTI_CRYPTO_COMMON=y CONFIG_QTI_CRYPTO_TZ=y @@ -5211,6 +5246,11 @@ CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y CONFIG_DEVFREQ_GOV_MEMLAT=y CONFIG_DEVFREQ_GOV_CDSPL3=y +CONFIG_DEVFREQ_BOOST=y +CONFIG_DEVFREQ_INPUT_BOOST_DURATION_MS=64 +CONFIG_DEVFREQ_WAKE_BOOST_DURATION_MS=100 +CONFIG_DEVFREQ_MSM_LLCCBW_DDR_BOOST_FREQ=3879 +CONFIG_DEVFREQ_MSM_CPU_LLCCBW_BOOST_FREQ=9155 # # DEVFREQ Drivers @@ -5660,6 +5700,7 @@ CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_ANDROID_BINDERFS=y +CONFIG_ANDROID_SIMPLE_LMK=y CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder" # CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set CONFIG_BINDER_OPT=y @@ -5831,15 +5872,11 @@ CONFIG_SDCARD_FS=y # CONFIG_QNX6FS_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_PSTORE=y -CONFIG_PSTORE_DEFLATE_COMPRESS=y # CONFIG_PSTORE_LZO_COMPRESS is not set # CONFIG_PSTORE_LZ4_COMPRESS is not set # CONFIG_PSTORE_LZ4HC_COMPRESS is not set # CONFIG_PSTORE_842_COMPRESS is not set # CONFIG_PSTORE_ZSTD_COMPRESS is not set -CONFIG_PSTORE_COMPRESS=y -CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y -CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" CONFIG_PSTORE_CONSOLE=y CONFIG_PSTORE_PMSG=y CONFIG_PSTORE_RAM=y @@ -5938,21 +5975,17 @@ CONFIG_SECURITY_SELINUX_DEVELOP=y CONFIG_SECURITY_SELINUX_AVC_STATS=y CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 CONFIG_SECURITY_SELINUX_SIDTAB_HASH_BITS=9 -CONFIG_SECURITY_SMACK=y +# CONFIG_SECURITY_SMACK is not set # CONFIG_SECURITY_SMACK_BRINGUP is not set # CONFIG_SECURITY_SMACK_NETFILTER is not set # CONFIG_SECURITY_SMACK_APPEND_SIGNALS is not set # CONFIG_SECURITY_TOMOYO is not set -CONFIG_SECURITY_APPARMOR=y -CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=0 -CONFIG_SECURITY_APPARMOR_HASH=y -CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y +# CONFIG_SECURITY_APPARMOR is not set # CONFIG_SECURITY_APPARMOR_DEBUG is not set # CONFIG_SECURITY_LOADPIN is not set # CONFIG_SECURITY_YAMA is not set CONFIG_INTEGRITY=y # CONFIG_INTEGRITY_SIGNATURE is not set -CONFIG_INTEGRITY_AUDIT=y # CONFIG_IMA is not set # CONFIG_EVM is not set CONFIG_DEFAULT_SECURITY_SELINUX=y @@ -6100,7 +6133,8 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_LZO=y # CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set +CONFIG_CRYPTO_LZ4=y +CONFIG_ZRAM_DEFAULT_COMP_ALGORITHM="lz4" # CONFIG_CRYPTO_LZ4HC is not set # CONFIG_CRYPTO_ZSTD is not set @@ -6147,7 +6181,6 @@ CONFIG_SYSTEM_TRUSTED_KEYS="" # CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set # CONFIG_SECONDARY_TRUSTED_KEYRING is not set # CONFIG_SYSTEM_BLACKLIST_KEYRING is not set -CONFIG_BINARY_PRINTF=y # # Library routines @@ -6177,13 +6210,11 @@ CONFIG_CRC32_SLICEBY8=y # CONFIG_CRC7 is not set CONFIG_LIBCRC32C=y CONFIG_CRC8=y -CONFIG_AUDIT_GENERIC=y -CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y -CONFIG_AUDIT_COMPAT_GENERIC=y # CONFIG_RANDOM32_SELFTEST is not set CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y +CONFIG_LZ4_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_LZ4_DECOMPRESS=y # CONFIG_XZ_DEC is not set @@ -6222,10 +6253,15 @@ CONFIG_CLZ_TAB=y CONFIG_MPILIB=y CONFIG_LIBFDT=y CONFIG_OID_REGISTRY=y +CONFIG_HAVE_GENERIC_VDSO=y +CONFIG_GENERIC_GETTIMEOFDAY=y +CONFIG_GENERIC_COMPAT_VDSO=y CONFIG_SG_POOL=y CONFIG_ARCH_HAS_SG_CHAIN=y CONFIG_SBITMAP=y # CONFIG_STRING_SELFTEST is not set +CONFIG_OPTIMIZE_INLINING=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y # # Kernel hacking @@ -6236,7 +6272,7 @@ CONFIG_SBITMAP=y # CONFIG_PRINTK_TIME=y CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 -CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_CONSOLE_LOGLEVEL_QUIET=2 CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_DYNAMIC_DEBUG is not set @@ -6254,7 +6290,7 @@ CONFIG_DEBUG_INFO=y CONFIG_ENABLE_MUST_CHECK=y # CONFIG_FIRE_WATCHDOG is not set # CONFIG_DUMP_ALL_STACKS is not set -CONFIG_FRAME_WARN=4096 +CONFIG_FRAME_WARN=0 # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_READABLE_ASM is not set # CONFIG_UNUSED_SYMBOLS is not set @@ -6278,6 +6314,7 @@ CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_PAGEALLOC is not set # CONFIG_DEBUG_PANIC_ON_OOM is not set # CONFIG_PAGE_POISONING is not set +# CONFIG_SLUB_DEBUG_ON is not set # CONFIG_DEBUG_PAGE_REF is not set # CONFIG_DEBUG_RODATA_TEST is not set # CONFIG_DEBUG_OBJECTS is not set @@ -6314,7 +6351,6 @@ CONFIG_SCHED_DEBUG=y CONFIG_SCHED_INFO=y # CONFIG_PANIC_ON_SCHED_BUG is not set # CONFIG_PANIC_ON_RT_THROTTLING is not set -CONFIG_SCHEDSTATS=y # CONFIG_SCHED_STACK_END_CHECK is not set # CONFIG_DEBUG_TIMEKEEPING is not set # CONFIG_DEBUG_PREEMPT is not set @@ -6362,21 +6398,14 @@ CONFIG_RCU_PANIC_ON_STALL=0 # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_NOP_TRACER=y CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y CONFIG_HAVE_DYNAMIC_FTRACE=y CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_SYSCALL_TRACEPOINTS=y CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACE_CLOCK=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y CONFIG_IPC_LOGGING=y # CONFIG_QCOM_RTB is not set -CONFIG_TRACING=y -CONFIG_GENERIC_TRACER=y CONFIG_TRACING_SUPPORT=y CONFIG_FTRACE=y # CONFIG_FUNCTION_TRACER is not set @@ -6451,26 +6480,27 @@ CONFIG_ARM64_PTDUMP_CORE=y CONFIG_DEBUG_ALIGN_RODATA=y # CONFIG_ARM64_RELOC_TEST is not set # CONFIG_ARM64_STRICT_BREAK_BEFORE_MAKE is not set -CONFIG_CORESIGHT=y -CONFIG_CORESIGHT_LINKS_AND_SINKS=y -CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +# CONFIG_CORESIGHT is not set +# CONFIG_CORESIGHT_LINKS_AND_SINKS is not set +# CONFIG_CORESIGHT_LINK_AND_SINK_TMC is not set # CONFIG_CORESIGHT_CATU is not set # CONFIG_CORESIGHT_SINK_TPIU is not set # CONFIG_CORESIGHT_SINK_ETBV10 is not set # CONFIG_CORESIGHT_SOURCE_ETM4X is not set -CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y -CONFIG_CORESIGHT_STM=y +# CONFIG_CORESIGHT_DYNAMIC_REPLICATOR is not set +# CONFIG_CORESIGHT_STM is not set # CONFIG_CORESIGHT_CPU_DEBUG is not set -CONFIG_CORESIGHT_CTI=y -CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y -CONFIG_CORESIGHT_OST=y -CONFIG_CORESIGHT_TPDA=y -CONFIG_CORESIGHT_TPDM=y +# CONFIG_CORESIGHT_CTI is not set +# CONFIG_CORESIGHT_CTI_SAVE_DISABLE is not set +# CONFIG_CORESIGHT_OST is not set +# CONFIG_CORESIGHT_TPDA is not set +# CONFIG_CORESIGHT_TPDM is not set # CONFIG_CORESIGHT_TPDM_DEFAULT_ENABLE is not set -CONFIG_CORESIGHT_CSR=y -CONFIG_CORESIGHT_HWEVENT=y -CONFIG_CORESIGHT_DUMMY=y -CONFIG_CORESIGHT_REMOTE_ETM=y -CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 -CONFIG_CORESIGHT_TGU=y +# CONFIG_CORESIGHT_CSR is not set +# CONFIG_CORESIGHT_HWEVENT is not set +# CONFIG_CORESIGHT_DUMMY is not set +# CONFIG_CORESIGHT_REMOTE_ETM is not set +# CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE is not set +# CONFIG_CORESIGHT_TGU is not set # CONFIG_CORESIGHT_LINK_LATE_DISABLE is not set + diff --git a/arch/arm64/configs/stock_defconfig b/arch/arm64/configs/stock_defconfig new file mode 100644 index 000000000000..ffe52c0bb970 --- /dev/null +++ b/arch/arm64/configs/stock_defconfig @@ -0,0 +1,6275 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm64 4.19.81 Kernel Configuration +# + +# +# Compiler: clang version 8.0.12 for Android NDK +# +CONFIG_GCC_VERSION=0 +CONFIG_CC_IS_CLANG=y +CONFIG_CLANG_VERSION=80012 +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y +CONFIG_THREAD_INFO_IN_TASK=y + +# +# General setup +# +CONFIG_INIT_ENV_ARG_LIMIT=32 +# CONFIG_COMPILE_TEST is not set +CONFIG_LOCALVERSION="-perf" +CONFIG_MIHW=y +CONFIG_PACKAGE_RUNTIME_INFO=y +CONFIG_LOCALVERSION_AUTO=y +CONFIG_BUILD_SALT="" +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_HAVE_ARCH_AUDITSYSCALL=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_WATCH=y +CONFIG_AUDIT_TREE=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_GENERIC_IRQ_SHOW_LEVEL=y +CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y +CONFIG_GENERIC_IRQ_MIGRATION=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_IRQ_DOMAIN=y +CONFIG_IRQ_DOMAIN_HIERARCHY=y +CONFIG_GENERIC_MSI_IRQ=y +CONFIG_GENERIC_MSI_IRQ_DOMAIN=y +CONFIG_HANDLE_DOMAIN_IRQ=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +# CONFIG_GENERIC_IRQ_DEBUGFS is not set +CONFIG_GENERIC_IRQ_MULTI_HANDLER=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_ARCH_HAS_TICK_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ_COMMON=y +# CONFIG_HZ_PERIODIC is not set +CONFIG_NO_HZ_IDLE=y +# CONFIG_NO_HZ_FULL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_HAVE_SCHED_AVG_IRQ=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +# CONFIG_PSI_DEFAULT_DISABLED is not set +# CONFIG_PSI_FTRACE is not set +CONFIG_CPU_ISOLATION=y + +# +# RCU Subsystem +# +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_EXPERT=y +CONFIG_SRCU=y +CONFIG_TREE_SRCU=y +CONFIG_TASKS_RCU=y +CONFIG_RCU_STALL_COMMON=y +CONFIG_RCU_NEED_SEGCBLIST=y +CONFIG_RCU_FANOUT=64 +CONFIG_RCU_FANOUT_LEAF=16 +CONFIG_RCU_FAST_NO_HZ=y +# CONFIG_RCU_BOOST is not set +CONFIG_RCU_NOCB_CPU=y +CONFIG_BUILD_BIN2C=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_IKHEADERS is not set +CONFIG_LOG_BUF_SHIFT=21 +# CONFIG_CONSOLE_FLUSH_ON_HOTPLUG is not set +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=13 +CONFIG_GENERIC_SCHED_CLOCK=y +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_SUPPORTS_INT128=y +CONFIG_CGROUPS=y +CONFIG_PAGE_COUNTER=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_MEMCG_SWAP_ENABLED=y +CONFIG_MEMCG_KMEM=y +CONFIG_BLK_CGROUP=y +# CONFIG_DEBUG_BLK_CGROUP is not set +CONFIG_CGROUP_WRITEBACK=y +CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set +CONFIG_RT_GROUP_SCHED=y +# CONFIG_CGROUP_PIDS is not set +# CONFIG_CGROUP_RDMA is not set +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_PROC_PID_CPUSET=y +# CONFIG_CGROUP_DEVICE is not set +CONFIG_CGROUP_CPUACCT=y +# CONFIG_CGROUP_PERF is not set +CONFIG_CGROUP_BPF=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_SOCK_CGROUP_DATA=y +CONFIG_SCHED_CORE_CTL=y +# CONFIG_PERF_HUMANTASK is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_NET_NS=y +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_INITRAMFS_FORCE is not set +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_HAVE_UID16=y +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_BPF=y +CONFIG_EXPERT=y +CONFIG_UID16=y +CONFIG_MULTIUSER=y +# CONFIG_SGETMASK_SYSCALL is not set +CONFIG_SYSFS_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set +# CONFIG_FHANDLE is not set +CONFIG_POSIX_TIMERS=y +CONFIG_PRINTK=y +CONFIG_PRINTK_NMI=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_FUTEX_PI=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_ADVISE_SYSCALLS=y +CONFIG_MEMBARRIER=y +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KALLSYMS_BASE_RELATIVE=y +CONFIG_BPF_SYSCALL=y +# CONFIG_USERFAULTFD is not set +CONFIG_ARCH_HAS_MEMBARRIER_SYNC_CORE=y +CONFIG_RSEQ=y +# CONFIG_DEBUG_RSEQ is not set +CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +# CONFIG_PC104 is not set + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_USER_SHARE is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SLUB_MEMCG_SYSFS_ON is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_SLAB_MERGE_DEFAULT=y +CONFIG_SLAB_FREELIST_RANDOM=y +CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_SLUB_CPU_PARTIAL=y +CONFIG_SYSTEM_DATA_VERIFICATION=y +CONFIG_PROFILING=y +CONFIG_TRACEPOINTS=y +CONFIG_ARM64=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_ARM64_PAGE_SHIFT=12 +CONFIG_ARM64_CONT_SHIFT=4 +CONFIG_ARCH_MMAP_RND_BITS_MIN=18 +CONFIG_ARCH_MMAP_RND_BITS_MAX=24 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11 +CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CSUM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_ZONE_DMA32 is not set +CONFIG_HAVE_GENERIC_GUP=y +CONFIG_SMP=y +CONFIG_KERNEL_MODE_NEON=y +CONFIG_FIX_EARLYCON_MEM=y +CONFIG_PGTABLE_LEVELS=3 +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_ARCH_PROC_KCORE_TEXT=y + +# +# Platform selection +# +# CONFIG_ARCH_ACTIONS is not set +# CONFIG_ARCH_SUNXI is not set +# CONFIG_ARCH_ALPINE is not set +# CONFIG_ARCH_BCM2835 is not set +# CONFIG_ARCH_BCM_IPROC is not set +# CONFIG_ARCH_BERLIN is not set +# CONFIG_ARCH_BRCMSTB is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_K3 is not set +# CONFIG_ARCH_LAYERSCAPE is not set +# CONFIG_ARCH_LG1K is not set +# CONFIG_ARCH_HISI is not set +# CONFIG_ARCH_MEDIATEK is not set +# CONFIG_ARCH_MESON is not set +# CONFIG_ARCH_MVEBU is not set +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_KONA=y +# CONFIG_ARCH_LITO is not set +# CONFIG_ARCH_LAGOON is not set +# CONFIG_ARCH_BENGAL is not set +# CONFIG_ARCH_SCUBA is not set +# CONFIG_ARCH_REALTEK is not set +# CONFIG_ARCH_ROCKCHIP is not set +# CONFIG_ARCH_SEATTLE is not set +# CONFIG_ARCH_SYNQUACER is not set +# CONFIG_ARCH_RENESAS is not set +# CONFIG_ARCH_STRATIX10 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_SPRD is not set +# CONFIG_ARCH_THUNDER is not set +# CONFIG_ARCH_THUNDER2 is not set +# CONFIG_ARCH_UNIPHIER is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_XGENE is not set +# CONFIG_ARCH_ZX is not set +# CONFIG_ARCH_ZYNQMP is not set + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_SYSCALL=y +# CONFIG_PCIEPORTBUS is not set +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_QUIRKS=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# PCI controller drivers +# + +# +# Cadence PCIe controllers support +# +# CONFIG_PCIE_CADENCE_HOST is not set +# CONFIG_PCI_FTPCI100 is not set +# CONFIG_PCI_HOST_GENERIC is not set +# CONFIG_PCIE_XILINX is not set +# CONFIG_PCI_XGENE is not set +# CONFIG_PCI_HOST_THUNDER_PEM is not set +# CONFIG_PCI_HOST_THUNDER_ECAM is not set +CONFIG_PCI_MSM=y +CONFIG_PCI_MSM_MSI=y + +# +# DesignWare PCI Core Support +# +# CONFIG_PCIE_DW_PLAT_HOST is not set +# CONFIG_PCI_HISI is not set +# CONFIG_PCIE_QCOM is not set +# CONFIG_PCIE_KIRIN is not set + +# +# PCI Endpoint +# +# CONFIG_PCI_ENDPOINT is not set + +# +# PCI switch controller drivers +# +# CONFIG_PCI_SW_SWITCHTEC is not set + +# +# Kernel Features +# + +# +# ARM errata workarounds via the alternatives framework +# +CONFIG_ARM64_ERRATUM_826319=y +CONFIG_ARM64_ERRATUM_827319=y +CONFIG_ARM64_ERRATUM_824069=y +CONFIG_ARM64_ERRATUM_819472=y +CONFIG_ARM64_ERRATUM_832075=y +CONFIG_ARM64_ERRATUM_845719=y +CONFIG_ARM64_ERRATUM_843419=y +CONFIG_ARM64_ERRATUM_1024718=y +CONFIG_ARM64_ERRATUM_1188873=y +CONFIG_ARM64_ERRATUM_1463225=y +CONFIG_ARM64_ERRATUM_1542418=y +CONFIG_CAVIUM_ERRATUM_22375=y +CONFIG_CAVIUM_ERRATUM_23154=y +CONFIG_CAVIUM_ERRATUM_27456=y +CONFIG_CAVIUM_ERRATUM_30115=y +CONFIG_QCOM_FALKOR_ERRATUM_1003=y +CONFIG_QCOM_FALKOR_ERRATUM_1009=y +CONFIG_QCOM_QDF2400_ERRATUM_0065=y +CONFIG_SOCIONEXT_SYNQUACER_PREITS=y +CONFIG_HISILICON_ERRATUM_161600802=y +CONFIG_QCOM_FALKOR_ERRATUM_E1041=y +CONFIG_ARM64_4K_PAGES=y +# CONFIG_ARM64_16K_PAGES is not set +# CONFIG_ARM64_64K_PAGES is not set +CONFIG_ARM64_VA_BITS_39=y +# CONFIG_ARM64_VA_BITS_48 is not set +CONFIG_ARM64_VA_BITS=39 +CONFIG_ARM64_PA_BITS_48=y +CONFIG_ARM64_PA_BITS=48 +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_NR_CPUS=8 +CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y +CONFIG_ARCH_NR_GPIO=1280 +# CONFIG_NUMA is not set +CONFIG_HOLES_IN_ZONE=y +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_HAVE_ARCH_PFN_VALID=y +CONFIG_HW_PERF_EVENTS=y +CONFIG_SYS_SUPPORTS_HUGETLBFS=y +CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARM64_DMA_USE_IOMMU=y +CONFIG_ARM64_DMA_IOMMU_ALIGNMENT=9 +CONFIG_SECCOMP=y +# CONFIG_PARAVIRT is not set +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_XEN is not set +CONFIG_OKL4_GUEST=y +CONFIG_FORCE_MAX_ZONEORDER=11 +# CONFIG_UNMAP_KERNEL_AT_EL0 is not set +# CONFIG_HARDEN_BRANCH_PREDICTOR is not set +CONFIG_HARDEN_EL2_VECTORS=y +CONFIG_ARM64_SSBD=y +# CONFIG_PRINT_VMEMLAYOUT is not set +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +# CONFIG_ARM64_SW_TTBR0_PAN is not set + +# +# ARMv8.1 architectural features +# +CONFIG_ARM64_HW_AFDBM=y +CONFIG_ARM64_PAN=y +# CONFIG_ARM64_LSE_ATOMICS is not set +# CONFIG_ARM64_VHE is not set + +# +# ARMv8.2 architectural features +# +CONFIG_ARM64_UAO=y +# CONFIG_ARM64_PMEM is not set +CONFIG_ARM64_RAS_EXTN=y +CONFIG_ARM64_SVE=y +CONFIG_ARM64_MODULE_PLTS=y +CONFIG_RELOCATABLE=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_RANDOMIZE_MODULE_REGION_FULL=y + +# +# Boot options +# +CONFIG_CMDLINE="ramoops_memreserve=4M" +# CONFIG_CMDLINE_FROM_BOOTLOADER is not set +CONFIG_CMDLINE_EXTEND=y +# CONFIG_CMDLINE_FORCE is not set +# CONFIG_EFI is not set +# CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE is not set +# CONFIG_BUILD_ARM64_KERNEL_COMPRESSION_GZIP is not set +CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y +CONFIG_KRYO_PMU_WORKAROUND=y +CONFIG_BOOT_INFO=y +# CONFIG_BUILD_ARM64_DT_OVERLAY is not set +CONFIG_COMPAT=y + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_SUSPEND_SKIP_SYNC is not set +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +# CONFIG_PM_AUTOSLEEP is not set +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_PM_CLK=y +CONFIG_PM_GENERIC_DOMAINS=y +# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set +CONFIG_PM_GENERIC_DOMAINS_SLEEP=y +CONFIG_PM_GENERIC_DOMAINS_OF=y +CONFIG_CPU_PM=y +CONFIG_ENERGY_MODEL=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y + +# +# CPU Power Management +# + +# +# CPU Idle +# +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y +# CONFIG_CPU_IDLE_GOV_LADDER is not set +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_DT_IDLE_STATES=y + +# +# ARM CPU Idle Drivers +# +CONFIG_ARM_CPUIDLE=y + +# +# CPU Frequency scaling +# +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y + +# +# CPU frequency scaling drivers +# +# CONFIG_CPUFREQ_DT is not set +# CONFIG_ARM_BIG_LITTLE_CPUFREQ is not set +# CONFIG_ARM_QCOM_CPUFREQ_KRYO is not set +CONFIG_ARM_QCOM_CPUFREQ_HW=y +# CONFIG_ARM_QCOM_CPUFREQ_HW_DEBUG is not set +# CONFIG_CPU_FREQ_MSM is not set +# CONFIG_QORIQ_CPUFREQ is not set + +# +# Firmware Drivers +# +CONFIG_ARM_PSCI_FW=y +# CONFIG_ARM_PSCI_CHECKER is not set +# CONFIG_ARM_SCMI_PROTOCOL is not set +# CONFIG_ARM_SCPI_PROTOCOL is not set +# CONFIG_ARM_SDE_INTERFACE is not set +# CONFIG_FIRMWARE_MEMMAP is not set +# CONFIG_FW_CFG_SYSFS is not set +CONFIG_QCOM_SCM=y +CONFIG_QCOM_SCM_64=y +# CONFIG_QCOM_SCM_DOWNLOAD_MODE_DEFAULT is not set +CONFIG_HAVE_ARM_SMCCC=y +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# Tegra firmware driver +# +CONFIG_MSM_TZ_LOG=y +# CONFIG_VIRTUALIZATION is not set +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA256_ARM64=y +# CONFIG_CRYPTO_SHA512_ARM64 is not set +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +# CONFIG_CRYPTO_SHA512_ARM64_CE is not set +# CONFIG_CRYPTO_SHA3_ARM64 is not set +# CONFIG_CRYPTO_SM3_ARM64_CE is not set +# CONFIG_CRYPTO_SM4_ARM64_CE is not set +CONFIG_CRYPTO_GHASH_ARM64_CE=y +# CONFIG_CRYPTO_CRC32_ARM64_CE is not set +CONFIG_CRYPTO_AES_ARM64=y +CONFIG_CRYPTO_AES_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +# CONFIG_CRYPTO_CHACHA20_NEON is not set +# CONFIG_CRYPTO_AES_ARM64_BS is not set +# CONFIG_FACTORY_BUILD is not set +CONFIG_HWCONF_MANAGER=y + +# +# General architecture-dependent options +# +# CONFIG_KPROBES is not set +CONFIG_UPROBES=y +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_NMI=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_GENERIC_IDLE_POLL_SETUP=y +CONFIG_ARCH_HAS_FORTIFY_SOURCE=y +CONFIG_ARCH_HAS_SET_MEMORY=y +CONFIG_HAVE_ARCH_THREAD_STRUCT_WHITELIST=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_RSEQ=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_HAVE_RCU_TABLE_FREE=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_STACKPROTECTOR=y +CONFIG_CC_HAS_STACKPROTECTOR_NONE=y +CONFIG_STACKPROTECTOR=y +CONFIG_STACKPROTECTOR_STRONG=y +CONFIG_ARCH_SUPPORTS_LTO_CLANG=y +CONFIG_LTO_NONE=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_HAVE_ARCH_HUGE_VMAP=y +CONFIG_HAVE_MOD_ARCH_SPECIFIC=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_ARCH_HAS_ELF_RANDOMIZE=y +CONFIG_HAVE_ARCH_MMAP_RND_BITS=y +CONFIG_ARCH_MMAP_RND_BITS=18 +CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS=y +CONFIG_ARCH_MMAP_RND_COMPAT_BITS=11 +CONFIG_CLONE_BACKWARDS=y +CONFIG_OLD_SIGSUSPEND3=y +CONFIG_COMPAT_OLD_SIGACTION=y +CONFIG_COMPAT_32BIT_TIME=y +CONFIG_HAVE_ARCH_VMAP_STACK=y +CONFIG_VMAP_STACK=y +CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y +CONFIG_STRICT_KERNEL_RWX=y +CONFIG_ARCH_HAS_STRICT_MODULE_RWX=y +CONFIG_STRICT_MODULE_RWX=y +CONFIG_REFCOUNT_FULL=y +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS=y +CONFIG_PANIC_ON_REFCOUNT_ERROR=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y +CONFIG_HAVE_GCC_PLUGINS=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_MODULE_SIG=y +# CONFIG_MODULE_SIG_FORCE is not set +CONFIG_MODULE_SIG_ALL=y +# CONFIG_MODULE_SIG_SHA1 is not set +# CONFIG_MODULE_SIG_SHA224 is not set +# CONFIG_MODULE_SIG_SHA256 is not set +# CONFIG_MODULE_SIG_SHA384 is not set +CONFIG_MODULE_SIG_SHA512=y +CONFIG_MODULE_SIG_HASH="sha512" +# CONFIG_MODULE_COMPRESS is not set +# CONFIG_TRIM_UNUSED_KSYMS is not set +CONFIG_MODULES_TREE_LOOKUP=y +CONFIG_BLOCK=y +CONFIG_BLK_SCSI_REQUEST=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set +# CONFIG_BLK_DEV_ZONED is not set +# CONFIG_BLK_DEV_THROTTLING is not set +# CONFIG_BLK_CMDLINE_PARSER is not set +CONFIG_BLK_WBT=y +# CONFIG_BLK_CGROUP_IOLATENCY is not set +CONFIG_BLK_WBT_SQ=y +CONFIG_BLK_WBT_MQ=y +CONFIG_BLK_DEBUG_FS=y +# CONFIG_BLK_SED_OPAL is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_AIX_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_CMDLINE_PARTITION is not set +CONFIG_BLOCK_COMPAT=y +CONFIG_BLK_MQ_PCI=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_CFQ_GROUP_IOSCHED=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_MQ_IOSCHED_DEADLINE=y +CONFIG_MQ_IOSCHED_KYBER=y +# CONFIG_IOSCHED_BFQ is not set +CONFIG_ASN1=y +CONFIG_UNINLINE_SPIN_UNLOCK=y +CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_RWSEM_SPIN_ON_OWNER=y +CONFIG_LOCK_SPIN_ON_OWNER=y +CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y +CONFIG_QUEUED_SPINLOCKS=y +CONFIG_ARCH_USE_QUEUED_RWLOCKS=y +CONFIG_QUEUED_RWLOCKS=y +CONFIG_RWSEM_PRIO_AWARE=y +CONFIG_ARCH_HAS_SYSCALL_WRAPPER=y +CONFIG_FREEZER=y + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +CONFIG_COMPAT_BINFMT_ELF=y +CONFIG_ELFCORE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_BINFMT_SCRIPT=y +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y + +# +# Memory Management options +# +CONFIG_SELECT_MEMORY_MODEL=y +# CONFIG_FLATMEM_MANUAL is not set +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_NO_BOOTMEM=y +CONFIG_MEMORY_ISOLATION=y +# CONFIG_MEMORY_HOTPLUG is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_COMPACTION=y +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_ARCH_SUPPORTS_MEMORY_FAILURE=y +# CONFIG_MEMORY_FAILURE is not set +# CONFIG_TRANSPARENT_HUGEPAGE is not set +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set +CONFIG_CMA_DEBUGFS=y +# CONFIG_CMA_ALLOW_WRITE_DEBUGFS is not set +CONFIG_CMA_AREAS=16 +# CONFIG_ZPOOL is not set +# CONFIG_ZBUD is not set +CONFIG_ZSMALLOC=y +# CONFIG_PGTABLE_MAPPING is not set +# CONFIG_ZSMALLOC_STAT is not set +CONFIG_GENERIC_EARLY_IOREMAP=y +CONFIG_BALANCE_ANON_FILE_RECLAIM=y +# CONFIG_DEFERRED_STRUCT_PAGE_INIT is not set +# CONFIG_IDLE_PAGE_TRACKING is not set +CONFIG_FRAME_VECTOR=y +# CONFIG_PERCPU_STATS is not set +CONFIG_ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT=y +CONFIG_SPECULATIVE_PAGE_FAULT=y +CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y +# CONFIG_GUP_BENCHMARK is not set +CONFIG_ARCH_HAS_PTE_SPECIAL=y +CONFIG_PROCESS_RECLAIM=y +CONFIG_NET=y +CONFIG_COMPAT_NETLINK_MESSAGES=y +CONFIG_NET_INGRESS=y +CONFIG_NET_EGRESS=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +# CONFIG_TLS is not set +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_INTERFACE=y +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set +# CONFIG_XDP_SOCKETS is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +CONFIG_NET_IPGRE_DEMUX=y +CONFIG_NET_IP_TUNNEL=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=y +CONFIG_NET_UDP_TUNNEL=y +# CONFIG_NET_FOU is not set +# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +# CONFIG_INET_ESP_OFFLOAD is not set +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +CONFIG_INET_UDP_DIAG=y +# CONFIG_INET_RAW_DIAG is not set +CONFIG_INET_DIAG_DESTROY=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +# CONFIG_INET6_ESP_OFFLOAD is not set +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +# CONFIG_IPV6_ILA is not set +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_VTI=y +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IPV6_TUNNEL=y +# CONFIG_IPV6_GRE is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_IPV6_SEG6_LWTUNNEL is not set +# CONFIG_IPV6_SEG6_HMAC is not set +CONFIG_NETLABEL=y +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NETWORK_SECMARK=y +CONFIG_NET_PTP_CLASSIFY=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +CONFIG_NETFILTER_ADVANCED=y +CONFIG_BRIDGE_NETFILTER=m + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_INGRESS=y +CONFIG_NETFILTER_NETLINK=y +CONFIG_NETFILTER_FAMILY_BRIDGE=y +CONFIG_NETFILTER_FAMILY_ARP=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +# CONFIG_NETFILTER_NETLINK_OSF is not set +CONFIG_NF_CONNTRACK=y +CONFIG_NF_LOG_COMMON=y +# CONFIG_NF_LOG_NETDEV is not set +CONFIG_NETFILTER_CONNCOUNT=y +CONFIG_NF_CONNTRACK_MARK=y +CONFIG_NF_CONNTRACK_SECMARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CONNTRACK_LABELS is not set +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_BROADCAST=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +# CONFIG_NF_CONNTRACK_SNMP is not set +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +# CONFIG_NF_CONNTRACK_SIP is not set +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +# CONFIG_NETFILTER_NETLINK_GLUE_CT is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_DCCP=y +CONFIG_NF_NAT_PROTO_UDPLITE=y +CONFIG_NF_NAT_PROTO_SCTP=y +CONFIG_NF_NAT_AMANDA=y +CONFIG_NF_NAT_FTP=y +CONFIG_NF_NAT_IRC=y +CONFIG_NF_NAT_TFTP=y +CONFIG_NF_NAT_REDIRECT=y +# CONFIG_NF_TABLES is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_CT=y +CONFIG_NETFILTER_XT_TARGET_DSCP=y +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_NAT=y +CONFIG_NETFILTER_XT_TARGET_NETMAP=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +CONFIG_NETFILTER_XT_MATCH_BPF=y +# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ECN=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y +# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +CONFIG_NETFILTER_XT_MATCH_OWNER=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_SOCKET_IPV4=y +CONFIG_NF_TPROXY_IPV4=y +CONFIG_NF_DUP_IPV4=y +# CONFIG_NF_LOG_ARP is not set +CONFIG_NF_LOG_IPV4=y +CONFIG_NF_REJECT_IPV4=y +CONFIG_NF_NAT_IPV4=y +CONFIG_NF_NAT_MASQUERADE_IPV4=y +CONFIG_NF_NAT_PROTO_GRE=y +CONFIG_NF_NAT_PPTP=y +CONFIG_NF_NAT_H323=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_SYNPROXY is not set +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_SOCKET_IPV6=y +CONFIG_NF_TPROXY_IPV6=y +CONFIG_NF_DUP_IPV6=y +CONFIG_NF_REJECT_IPV6=y +CONFIG_NF_LOG_IPV6=y +CONFIG_NF_NAT_IPV6=y +CONFIG_NF_NAT_MASQUERADE_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +CONFIG_IP6_NF_MATCH_RPFILTER=y +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_MATCH_SRH is not set +# CONFIG_IP6_NF_TARGET_HL is not set +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +# CONFIG_IP6_NF_TARGET_SYNPROXY is not set +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_SECURITY is not set +CONFIG_IP6_NF_NAT=y +CONFIG_IP6_NF_TARGET_MASQUERADE=y +# CONFIG_IP6_NF_TARGET_NPT is not set +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +# CONFIG_BRIDGE_EBT_T_FILTER is not set +# CONFIG_BRIDGE_EBT_T_NAT is not set +# CONFIG_BRIDGE_EBT_802_3 is not set +# CONFIG_BRIDGE_EBT_AMONG is not set +# CONFIG_BRIDGE_EBT_ARP is not set +# CONFIG_BRIDGE_EBT_IP is not set +# CONFIG_BRIDGE_EBT_IP6 is not set +# CONFIG_BRIDGE_EBT_LIMIT is not set +# CONFIG_BRIDGE_EBT_MARK is not set +# CONFIG_BRIDGE_EBT_PKTTYPE is not set +# CONFIG_BRIDGE_EBT_STP is not set +# CONFIG_BRIDGE_EBT_VLAN is not set +# CONFIG_BRIDGE_EBT_ARPREPLY is not set +# CONFIG_BRIDGE_EBT_DNAT is not set +# CONFIG_BRIDGE_EBT_MARK_T is not set +# CONFIG_BRIDGE_EBT_REDIRECT is not set +# CONFIG_BRIDGE_EBT_SNAT is not set +# CONFIG_BRIDGE_EBT_LOG is not set +# CONFIG_BRIDGE_EBT_NFLOG is not set +# CONFIG_BPFILTER is not set +# CONFIG_IP_DCCP is not set +CONFIG_IP_SCTP=y +# CONFIG_SCTP_DBG_OBJCNT is not set +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set +# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set +CONFIG_SCTP_COOKIE_HMAC_MD5=y +# CONFIG_SCTP_COOKIE_HMAC_SHA1 is not set +CONFIG_INET_SCTP_DIAG=y +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=y +# CONFIG_L2TP_DEBUGFS is not set +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_STP=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_IGMP_SNOOPING=y +CONFIG_HAVE_NET_DSA=y +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_PHONET is not set +# CONFIG_6LOWPAN is not set +# CONFIG_IEEE802154 is not set +CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_MULTIQ=y +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_CBS is not set +# CONFIG_NET_SCH_ETF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +CONFIG_NET_SCH_NETEM=y +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_SKBPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_CODEL is not set +# CONFIG_NET_SCH_FQ_CODEL is not set +# CONFIG_NET_SCH_CAKE is not set +# CONFIG_NET_SCH_FQ is not set +# CONFIG_NET_SCH_HHF is not set +# CONFIG_NET_SCH_PIE is not set +CONFIG_NET_SCH_INGRESS=y +# CONFIG_NET_SCH_PLUG is not set +# CONFIG_NET_SCH_DEFAULT is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=y +# CONFIG_NET_CLS_CGROUP is not set +CONFIG_NET_CLS_BPF=y +# CONFIG_NET_CLS_FLOWER is not set +# CONFIG_NET_CLS_MATCHALL is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +# CONFIG_NET_EMATCH_IPT is not set +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +CONFIG_NET_ACT_GACT=y +# CONFIG_GACT_PROB is not set +CONFIG_NET_ACT_MIRRED=y +# CONFIG_NET_ACT_SAMPLE is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +CONFIG_NET_ACT_SKBEDIT=y +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_ACT_VLAN is not set +# CONFIG_NET_ACT_BPF is not set +# CONFIG_NET_ACT_CONNMARK is not set +# CONFIG_NET_ACT_SKBMOD is not set +# CONFIG_NET_ACT_IFE is not set +# CONFIG_NET_ACT_TUNNEL_KEY is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +# CONFIG_DNS_RESOLVER is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +# CONFIG_VSOCKETS is not set +# CONFIG_NETLINK_DIAG is not set +# CONFIG_MPLS is not set +# CONFIG_NET_NSH is not set +# CONFIG_HSR is not set +# CONFIG_NET_SWITCHDEV is not set +# CONFIG_NET_L3_MASTER_DEV is not set +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +# CONFIG_QRTR_TUN is not set +CONFIG_QRTR_MHI=y +# CONFIG_QRTR_USB is not set +# CONFIG_QRTR_FIFO is not set +# CONFIG_NET_NCSI is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_CGROUP_NET_PRIO is not set +# CONFIG_CGROUP_NET_CLASSID is not set +CONFIG_NET_RX_BUSY_POLL=y +CONFIG_BQL=y +# CONFIG_BPF_JIT is not set +# CONFIG_BPF_STREAM_PARSER is not set +CONFIG_NET_FLOW_LIMIT=y +CONFIG_SOCKEV_NLMCAST=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_NET_DROP_MONITOR is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +CONFIG_BT=y +CONFIG_BT_BREDR=y +# CONFIG_BT_RFCOMM is not set +# CONFIG_BT_BNEP is not set +# CONFIG_BT_HIDP is not set +CONFIG_BT_HS=y +CONFIG_BT_LE=y +# CONFIG_BT_LEDS is not set +# CONFIG_BT_SELFTEST is not set +CONFIG_BT_DEBUGFS=y + +# +# Bluetooth device drivers +# +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +# CONFIG_BT_HCIUART is not set +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +# CONFIG_BT_MTKUART is not set +CONFIG_MSM_BT_POWER=y +CONFIG_BTFM_SLIM=y +# CONFIG_BTFM_SLIM_WCN3990 is not set +CONFIG_BT_SLIM_QCA6390=y +# CONFIG_AF_RXRPC is not set +# CONFIG_AF_KCM is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y +CONFIG_CFG80211=y +CONFIG_NL80211_TESTMODE=y +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_CERTIFICATION_ONUS is not set +CONFIG_CFG80211_REQUIRE_SIGNED_REGDB=y +CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_CFG80211_CRDA_SUPPORT=y +# CONFIG_CFG80211_WEXT is not set +# CONFIG_MAC80211 is not set +CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_NFC_NQ=y +# CONFIG_PSAMPLE is not set +# CONFIG_NET_IFE is not set +# CONFIG_LWTUNNEL is not set +CONFIG_DST_CACHE=y +CONFIG_GRO_CELLS=y +# CONFIG_NET_DEVLINK is not set +CONFIG_MAY_USE_DEVLINK=y +# CONFIG_FAILOVER is not set +CONFIG_HAVE_EBPF_JIT=y + +# +# Device Drivers +# +CONFIG_ARM_AMBA=y + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FIRMWARE_IN_KERNEL=y + +# +# Firmware loader +# +CONFIG_FW_LOADER=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_ALLOW_DEV_COREDUMP=y +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set +# CONFIG_TEST_ASYNC_DRIVER_PROBE is not set +CONFIG_GENERIC_CPU_AUTOPROBE=y +CONFIG_GENERIC_CPU_VULNERABILITIES=y +CONFIG_SOC_BUS=y +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_REGMAP_SPMI=y +CONFIG_REGMAP_MMIO=y +CONFIG_REGMAP_IRQ=y +CONFIG_REGMAP_WCD_IRQ=y +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_DMA_FENCE_TRACE is not set +CONFIG_DMA_CMA=y + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_GENERIC_ARCH_TOPOLOGY=y + +# +# Bus devices +# +# CONFIG_BRCMSTB_GISB_ARB is not set +CONFIG_QCOM_EBI2=y +# CONFIG_SIMPLE_PM_BUS is not set +# CONFIG_VEXPRESS_CONFIG is not set +CONFIG_MHI_BUS=y +CONFIG_MHI_DEBUG=y + +# +# MHI controllers +# +CONFIG_MHI_QCOM=y + +# +# MHI device support +# +CONFIG_MHI_NETDEV=y +CONFIG_MHI_UCI=y +CONFIG_MHI_SATELLITE=y +# CONFIG_CONNECTOR is not set +# CONFIG_GNSS is not set +CONFIG_MTD=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +# CONFIG_MTD_AFS_PARTS is not set +CONFIG_MTD_OF_PARTS=y +# CONFIG_MTD_AR7_PARTS is not set + +# +# Partition parsers +# + +# +# User Modules And Translation Layers +# +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_SM_FTL is not set +CONFIG_MTD_OOPS=y +# CONFIG_MTD_SWAP is not set +# CONFIG_MTD_PARTITIONED_MASTER is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_INTEL_VR_NOR is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_DATAFLASH is not set +# CONFIG_MTD_MCHP23K256 is not set +# CONFIG_MTD_SST25L is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_BLOCK2MTD=y + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOCG3 is not set +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_SPI_NAND is not set + +# +# LPDDR & LPDDR2 PCM memory drivers +# +# CONFIG_MTD_LPDDR is not set +# CONFIG_MTD_SPI_NOR is not set +# CONFIG_MTD_UBI is not set +CONFIG_DTC=y +CONFIG_OF=y +# CONFIG_OF_UNITTEST is not set +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_KOBJ=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_NET=y +CONFIG_OF_MDIO=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_SLIMBUS=y +# CONFIG_OF_OVERLAY is not set +CONFIG_OF_BATTERYDATA=y +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_NULL_BLK is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +CONFIG_ZRAM=y +# CONFIG_ZRAM_DEDUP is not set +# CONFIG_ZRAM_WRITEBACK is not set +# CONFIG_ZRAM_MEMORY_TRACKING is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SKD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=8192 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_RBD is not set +# CONFIG_BLK_DEV_RSXX is not set +CONFIG_VSERVICES_BLOCK_SERVER=y +CONFIG_VSERVICES_BLOCK_CLIENT=y + +# +# NVME Support +# +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_NVME_FC is not set +# CONFIG_NVME_TARGET is not set + +# +# Misc devices +# +CONFIG_SPI_XIAOMI_TP=y +# CONFIG_AD525X_DPOT is not set +# CONFIG_DUMMY_IRQ is not set +# CONFIG_PHANTOM is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_QCOM_COINCELL is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_DS1682 is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_LATTICE_ECP3_CONFIG is not set +# CONFIG_SRAM is not set +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +# CONFIG_PCI_ENDPOINT_TEST is not set +CONFIG_UID_SYS_STATS=y +# CONFIG_UID_SYS_STATS_DEBUG is not set +# CONFIG_MEMORY_STATE_TIME is not set +CONFIG_OKL4_USER_VIRQ=y +# CONFIG_OKL4_RINGBUF is not set +# CONFIG_TEST_IRQ_REQUESTER is not set +CONFIG_QTI_XR_SMRTVWR_MISC=y +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_EEPROM_IDT_89HPESX is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set +# CONFIG_ALTERA_STAPL is not set +CONFIG_XIAOMI_SOLUTION=y +CONFIG_SCHED_USF=y + +# +# Intel MIC & related support +# + +# +# Intel MIC Bus Driver +# + +# +# SCIF Bus Driver +# + +# +# VOP Bus Driver +# + +# +# Intel MIC Host Driver +# + +# +# Intel MIC Card Driver +# + +# +# SCIF Driver +# + +# +# Intel MIC Coprocessor State Management (COSM) Drivers +# + +# +# VOP Driver +# +# CONFIG_GENWQE is not set +# CONFIG_ECHO is not set +# CONFIG_MISC_RTSX_PCI is not set +# CONFIG_MISC_RTSX_USB is not set +# CONFIG_OKL4_USER_VIPC is not set +CONFIG_OKL4_LINK_SHBUF=y +CONFIG_GPIO_TESTING_MODE=y + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +CONFIG_SCSI_MQ_DEFAULT=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_SCSI_ESAS2R is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT3SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_SMARTPQI is not set +CONFIG_SCSI_UFSHCD=y +# CONFIG_SCSI_UFSHCD_PCI is not set +CONFIG_SCSI_UFSHCD_PLATFORM=y +# CONFIG_SCSI_UFS_DWC_TC_PLATFORM is not set +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFS_QCOM_ICE=y +# CONFIG_SCSI_UFSHCD_CMD_LOGGING is not set +# CONFIG_UFSFEATURE is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_SNIC is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_WD719X is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_LOWLEVEL_PCMCIA is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +CONFIG_HAVE_PATA_PLATFORM=y +# CONFIG_ATA is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +# CONFIG_BCACHE is not set +CONFIG_BLK_DEV_DM_BUILTIN=y +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_MQ_DEFAULT is not set +# CONFIG_DM_DEBUG is not set +CONFIG_DM_BUFIO=y +# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set +# CONFIG_DM_UNSTRIPED is not set +CONFIG_DM_CRYPT=y +CONFIG_DM_DEFAULT_KEY=y +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_CACHE is not set +# CONFIG_DM_WRITECACHE is not set +# CONFIG_DM_ERA is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +CONFIG_DM_UEVENT=y +# CONFIG_DM_FLAKEY is not set +CONFIG_DM_VERITY=y +# CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE_128 is not set +CONFIG_DM_VERITY_HASH_PREFETCH_MIN_SIZE=1 +# CONFIG_DM_VERITY_AVB is not set +CONFIG_DM_VERITY_FEC=y +# CONFIG_DM_SWITCH is not set +# CONFIG_DM_LOG_WRITES is not set +# CONFIG_DM_INTEGRITY is not set +# CONFIG_DM_ANDROID_VERITY is not set +# CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED is not set +# CONFIG_DM_BOW is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +CONFIG_NETDEVICES=y +CONFIG_MII=y +CONFIG_NET_CORE=y +CONFIG_BONDING=y +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_IPVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_GENEVE is not set +# CONFIG_GTP is not set +# CONFIG_MACSEC is not set +# CONFIG_NETCONSOLE is not set +CONFIG_TUN=y +# CONFIG_TUN_VNET_CROSS_LE is not set +# CONFIG_VETH is not set +# CONFIG_NLMON is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_AGERE=y +# CONFIG_ET131X is not set +CONFIG_NET_VENDOR_ALACRITECH=y +# CONFIG_SLICOSS is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +# CONFIG_ALTERA_TSE is not set +CONFIG_NET_VENDOR_AMAZON=y +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +# CONFIG_AMD_XGBE is not set +CONFIG_NET_VENDOR_AQUANTIA=y +# CONFIG_AQFWD is not set +CONFIG_NET_VENDOR_ARC=y +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +# CONFIG_ALX is not set +CONFIG_NET_VENDOR_AURORA=y +# CONFIG_AURORA_NB8800 is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BCMGENET is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +# CONFIG_SYSTEMPORT is not set +# CONFIG_BNXT is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +CONFIG_NET_VENDOR_CADENCE=y +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_CAVIUM=y +# CONFIG_THUNDER_NIC_PF is not set +# CONFIG_THUNDER_NIC_VF is not set +# CONFIG_THUNDER_NIC_BGX is not set +# CONFIG_THUNDER_NIC_RGX is not set +CONFIG_CAVIUM_PTP=y +# CONFIG_LIQUIDIO is not set +# CONFIG_LIQUIDIO_VF is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +CONFIG_NET_VENDOR_CORTINA=y +# CONFIG_GEMINI_ETHERNET is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EZCHIP=y +# CONFIG_EZCHIP_NPS_MANAGEMENT_ENET is not set +CONFIG_NET_VENDOR_HISILICON=y +# CONFIG_HIX5HD2_GMAC is not set +# CONFIG_HISI_FEMAC is not set +# CONFIG_HIP04_ETH is not set +# CONFIG_HNS is not set +# CONFIG_HNS_DSAF is not set +# CONFIG_HNS_ENET is not set +# CONFIG_HNS3 is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_HUAWEI=y +# CONFIG_HINIC is not set +CONFIG_NET_VENDOR_I825XX=y +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +# CONFIG_I40E is not set +# CONFIG_I40EVF is not set +# CONFIG_ICE is not set +# CONFIG_FM10K is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +CONFIG_SKY2=y +# CONFIG_SKY2_DEBUG is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX5_CORE is not set +# CONFIG_MLXSW_CORE is not set +# CONFIG_MLXFW is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8842 is not set +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set +# CONFIG_ENCX24J600 is not set +# CONFIG_LAN743X is not set +CONFIG_NET_VENDOR_MICROSEMI=y +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_NETERION=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_NETRONOME=y +# CONFIG_NFP is not set +CONFIG_NET_VENDOR_NI=y +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_ETHOC is not set +CONFIG_NET_VENDOR_PACKET_ENGINES=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_QED is not set +CONFIG_NET_VENDOR_QUALCOMM=y +# CONFIG_QCA7000_SPI is not set +# CONFIG_QCA7000_UART is not set +# CONFIG_QCOM_EMAC is not set +CONFIG_RMNET=y +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RENESAS=y +CONFIG_NET_VENDOR_ROCKER=y +CONFIG_NET_VENDOR_SAMSUNG=y +# CONFIG_SXGBE_ETH is not set +CONFIG_NET_VENDOR_SEEQ=y +CONFIG_NET_VENDOR_SOLARFLARE=y +# CONFIG_SFC is not set +# CONFIG_SFC_FALCON is not set +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_SMC91X is not set +# CONFIG_EPIC100 is not set +CONFIG_SMSC911X=y +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_SOCIONEXT=y +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_SYNOPSYS=y +# CONFIG_DWC_XLGMAC is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TI_CPSW_ALE is not set +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_MDIO_DEVICE=y +CONFIG_MDIO_BUS=y +# CONFIG_MDIO_BCM_UNIMAC is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MDIO_BUS_MUX_GPIO is not set +# CONFIG_MDIO_BUS_MUX_MMIOREG is not set +# CONFIG_MDIO_HISI_FEMAC is not set +# CONFIG_MDIO_MSCC_MIIM is not set +# CONFIG_MDIO_OCTEON is not set +# CONFIG_MDIO_THUNDER is not set +CONFIG_PHYLIB=y +CONFIG_SWPHY=y +# CONFIG_LED_TRIGGER_PHY is not set + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_AQUANTIA_PHY is not set +# CONFIG_AX88796B_PHY is not set +# CONFIG_AT803X_PHY is not set +# CONFIG_BCM7XXX_PHY is not set +# CONFIG_BCM87XX_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_CORTINA_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_DP83822_PHY is not set +# CONFIG_DP83TC811_PHY is not set +# CONFIG_DP83848_PHY is not set +# CONFIG_DP83867_PHY is not set +CONFIG_FIXED_PHY=y +# CONFIG_ICPLUS_PHY is not set +# CONFIG_INTEL_XWAY_PHY is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_MARVELL_10G_PHY is not set +# CONFIG_MICREL_PHY is not set +CONFIG_MICROCHIP_PHY=y +# CONFIG_MICROCHIP_T1_PHY is not set +# CONFIG_MICROSEMI_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_RENESAS_PHY is not set +# CONFIG_ROCKCHIP_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_TERANETICS_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_XILINX_GMII2RGMII is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_MPPE=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPPOE is not set +CONFIG_PPTP=y +CONFIG_PPPOL2TP=y +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_SLIP is not set +CONFIG_SLHC=y +CONFIG_USB_NET_DRIVERS=y +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_RTL8152=y +CONFIG_USB_LAN78XX=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_AX88179_178A=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_HUAWEI_CDC_NCM is not set +# CONFIG_USB_NET_CDC_MBIM is not set +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SR9700 is not set +# CONFIG_USB_NET_SR9800 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=y +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +# CONFIG_USB_NET_RNDIS_HOST is not set +CONFIG_USB_NET_CDC_SUBSET_ENABLE=y +CONFIG_USB_NET_CDC_SUBSET=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +CONFIG_USB_BELKIN=y +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +# CONFIG_USB_NET_QMI_WWAN is not set +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set +# CONFIG_USB_NET_CH9200 is not set +CONFIG_WLAN=y +# CONFIG_WIRELESS_WDS is not set +CONFIG_WLAN_VENDOR_ADMTEK=y +CONFIG_WLAN_VENDOR_ATH=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K_PCI is not set +# CONFIG_ATH6KL is not set +# CONFIG_WIL6210 is not set +CONFIG_WLAN_VENDOR_ATMEL=y +# CONFIG_ATMEL is not set +CONFIG_WLAN_VENDOR_BROADCOM=y +# CONFIG_BRCMFMAC is not set +CONFIG_WLAN_VENDOR_CISCO=y +CONFIG_WLAN_VENDOR_INTEL=y +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +CONFIG_WLAN_VENDOR_INTERSIL=y +# CONFIG_HOSTAP is not set +# CONFIG_HERMES is not set +# CONFIG_PRISM54 is not set +CONFIG_WLAN_VENDOR_MARVELL=y +# CONFIG_LIBERTAS is not set +# CONFIG_MWIFIEX is not set +CONFIG_WLAN_VENDOR_MEDIATEK=y +CONFIG_WLAN_VENDOR_RALINK=y +CONFIG_WLAN_VENDOR_REALTEK=y +CONFIG_WLAN_VENDOR_RSI=y +CONFIG_WLAN_VENDOR_ST=y +CONFIG_WLAN_VENDOR_TI=y +CONFIG_WLAN_VENDOR_ZYDAS=y +# CONFIG_USB_ZD1201 is not set +CONFIG_WLAN_VENDOR_QUANTENNA=y +# CONFIG_QTNFMAC_PEARL_PCIE is not set +# CONFIG_USB_NET_RNDIS_WLAN is not set +# CONFIG_VIRT_WIFI is not set +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_CNSS2=y +CONFIG_CNSS2_DEBUG=y +CONFIG_CNSS2_QMI=y +CONFIG_CNSS_ASYNC=y +CONFIG_BUS_AUTO_SUSPEND=y +# CONFIG_CNSS_QCA6290 is not set +CONFIG_CNSS_QCA6390=y +# CONFIG_CNSS_EMULATION is not set +# CONFIG_CNSS_QCA6490 is not set +CONFIG_CNSS_UTILS=y +CONFIG_CNSS_QMI_SVC=y +CONFIG_CNSS_GENL=y + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_NETDEVSIM is not set +# CONFIG_NET_FAILOVER is not set +# CONFIG_ISDN is not set +# CONFIG_NVM is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_LEDS=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +# CONFIG_INPUT_KEYCOMBO is not set +CONFIG_LAST_TOUCH_EVENTS=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADC is not set +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_DLINK_DIR685 is not set +# CONFIG_KEYBOARD_LKKBD is not set +CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_GPIO_POLLED is not set +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set +# CONFIG_KEYBOARD_MATRIX is not set +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_LM8333 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_TM2_TOUCHKEY is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_CAP11XX is not set +# CONFIG_KEYBOARD_BCM is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +# CONFIG_JOYSTICK_PSXPAD_SPI is not set +# CONFIG_JOYSTICK_PXRC is not set +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=y +CONFIG_TABLET_USB_AIPTEK=y +CONFIG_TABLET_USB_GTCO=y +CONFIG_TABLET_USB_HANWANG=y +CONFIG_TABLET_USB_KBTAB=y +# CONFIG_TABLET_USB_PEGASUS is not set +# CONFIG_TABLET_SERIAL_WACOM4 is not set +CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_GOODIX_GTX8 is not set +CONFIG_TOUCHSCREEN_NT36xxx_HOSTDL_SPI=y +CONFIG_TOUCHSCREEN_NVT_DEBUG_FS=y +CONFIG_TOUCHSCREEN_PROPERTIES=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ADC is not set +# CONFIG_TOUCHSCREEN_AR1021_I2C is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_BU21029 is not set +# CONFIG_TOUCHSCREEN_CHIPONE_ICN8318 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_CYTTSP4_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_EGALAX_SERIAL is not set +# CONFIG_TOUCHSCREEN_EXC3000 is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_GOODIX is not set +# CONFIG_TOUCHSCREEN_HIDEEP is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_S6SY761 is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_EKTF2127 is not set +# CONFIG_TOUCHSCREEN_ELAN is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_WACOM_I2C is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MMS114 is not set +# CONFIG_TOUCHSCREEN_MELFAS_MIP4 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_IMX6UL_TSC is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_EDT_FT5X06 is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_WDT87XX_I2C is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2004 is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_RM_TS is not set +# CONFIG_TOUCHSCREEN_SILEAD is not set +# CONFIG_TOUCHSCREEN_SIS_I2C is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_STMFTS is not set +# CONFIG_TOUCHSCREEN_SUR40 is not set +# CONFIG_TOUCHSCREEN_SURFACE3_SPI is not set +# CONFIG_TOUCHSCREEN_SX8654 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_ZET6223 is not set +# CONFIG_TOUCHSCREEN_ZFORCE is not set +# CONFIG_TOUCHSCREEN_ROHM_BU21023 is not set +CONFIG_TOUCHSCREEN_ST=y +CONFIG_TOUCHSCREEN_ST_I2C="st" +# CONFIG_TOUCHSCREEN_ST_FTS_V521 is not set +CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_DSX is not set +# CONFIG_TOUCHSCREEN_FTS is not set +# CONFIG_INPUT_PRESS_NDT is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_I2C=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_SPI is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_CORE=y +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TOUCH=y +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DEVICE=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_TESTING is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_REFLASH=y +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_RECOVERY=y +# CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_ZEROFLASH is not set +CONFIG_TOUCHSCREEN_SYNAPTICS_TCM_DIAGNOSTICS=y +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_ATMEL_CAPTOUCH is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_E3X0_BUTTON is not set +# CONFIG_INPUT_PM8941_PWRKEY is not set +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +CONFIG_INPUT_QPNP_POWER_ON=y +# CONFIG_INPUT_QTI_HAPTICS is not set +# CONFIG_INPUT_MMA8450 is not set +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_BEEPER is not set +# CONFIG_INPUT_GPIO_DECODER is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set +# CONFIG_INPUT_REGULATOR_HAPTIC is not set +CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_GPIO is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_PWM_BEEPER is not set +# CONFIG_INPUT_PWM_VIBRA is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_IMS_PCU is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_INPUT_SOC_BUTTON_ARRAY is not set +# CONFIG_INPUT_DRV260X_HAPTICS is not set +# CONFIG_INPUT_DRV2665_HAPTICS is not set +# CONFIG_INPUT_DRV2667_HAPTICS is not set +CONFIG_INPUT_AW8697_HAPTIC=y +# CONFIG_RMI4_CORE is not set +CONFIG_INPUT_FINGERPRINT=y +# CONFIG_FINGERPRINT_FPC_FOD is not set +# CONFIG_FINGERPRINT_GOODIX_FOD is not set +# CONFIG_FINGERPRINT_GOODIX_FOD_LMI is not set +CONFIG_FINGERPRINT_GOODIX=y +CONFIG_FINGERPRINT_FPC_TEE=y + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_SERIO_APBPS2 is not set +# CONFIG_SERIO_GPIO_PS2 is not set +# CONFIG_USERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_TTY=y +# CONFIG_VT is not set +CONFIG_TTY_FLUSH_LOCAL_ECHO=y +CONFIG_UNIX98_PTYS=y +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_OKL4_VTTY=y +CONFIG_OKL4_VTTY_CONSOLE=y +CONFIG_LDISC_AUTOLOAD=y +# CONFIG_DEVMEM is not set + +# +# Serial drivers +# +CONFIG_SERIAL_EARLYCON=y +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_AMBA_PL010 is not set +# CONFIG_SERIAL_AMBA_PL011 is not set +# CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST is not set +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX310X is not set +# CONFIG_SERIAL_UARTLITE is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_MSM is not set +CONFIG_SERIAL_MSM_GENI=y +CONFIG_SERIAL_MSM_GENI_CONSOLE=y +CONFIG_SERIAL_MSM_GENI_HALF_SAMPLING=y +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_SC16IS7XX is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set +# CONFIG_SERIAL_ARC is not set +# CONFIG_SERIAL_RP2 is not set +# CONFIG_SERIAL_FSL_LPUART is not set +# CONFIG_SERIAL_CONEXANT_DIGICOLOR is not set +CONFIG_FASTBOOT_CMD_CTRL_UART=y +CONFIG_SERIAL_DEV_BUS=y +CONFIG_SERIAL_DEV_CTRL_TTYPORT=y +CONFIG_TTY_PRINTK=y +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_HW_RANDOM_CAVIUM=y +# CONFIG_APPLICOM is not set + +# +# PCMCIA character devices +# +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_DEVPORT is not set +# CONFIG_XILLYBUS is not set + +# +# Diag Support +# +CONFIG_DIAG_CHAR=y +CONFIG_DIAG_OVER_USB=y +CONFIG_DIAGFWD_BRIDGE_CODE=y +# CONFIG_MSM_FASTCVPD is not set +CONFIG_MSM_ADSPRPC=y +# CONFIG_ADSPRPC_DEBUG is not set +CONFIG_MSM_RDBG=m +CONFIG_XLOGCHAR=y +CONFIG_OKL4_PIPE=y +CONFIG_VSERVICES_SERIAL=y +CONFIG_VSERVICES_SERIAL_SERVER=y +CONFIG_VSERVICES_SERIAL_CLIENT=y +CONFIG_VSERVICES_VTTY_COUNT=8 + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y + +# +# Multiplexer I2C Chip support +# +# CONFIG_I2C_ARB_GPIO_CHALLENGE is not set +# CONFIG_I2C_MUX_GPIO is not set +# CONFIG_I2C_MUX_GPMUX is not set +# CONFIG_I2C_MUX_LTC4306 is not set +# CONFIG_I2C_MUX_PCA9541 is not set +# CONFIG_I2C_MUX_PCA954x is not set +# CONFIG_I2C_MUX_PINCTRL is not set +# CONFIG_I2C_MUX_REG is not set +# CONFIG_I2C_DEMUX_PINCTRL is not set +# CONFIG_I2C_MUX_MLXCPLD is not set +CONFIG_I2C_HELPER_AUTO=y +CONFIG_I2C_ALGOBIT=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_CADENCE is not set +# CONFIG_I2C_CBUS_GPIO is not set +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_EMEV2 is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_NOMADIK is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +CONFIG_I2C_QCOM_GENI=y +# CONFIG_I2C_QUP is not set +# CONFIG_I2C_RK3X is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_THUNDERX is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_ROBOTFUZZ_OSIF is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_SLAVE is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +CONFIG_I3C=y +CONFIG_I3C_MASTER_QCOM_GENI=y +CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y +# CONFIG_SPI_MEM is not set + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_AXI_SPI_ENGINE is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_CADENCE is not set +# CONFIG_SPI_DESIGNWARE is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_FSL_SPI is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PL022 is not set +# CONFIG_SPI_PXA2XX is not set +# CONFIG_SPI_ROCKCHIP is not set +# CONFIG_SPI_QUP is not set +CONFIG_SPI_QCOM_GENI=y +# CONFIG_SPI_SC18IS602 is not set +# CONFIG_SPI_THUNDERX is not set +# CONFIG_SPI_XCOMM is not set +# CONFIG_SPI_XILINX is not set +# CONFIG_SPI_ZYNQMP_GQSPI is not set + +# +# SPI Protocol Masters +# +CONFIG_SPI_SPIDEV=y +# CONFIG_SPI_LOOPBACK_TEST is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPI_SLAVE is not set +CONFIG_SPMI=y +CONFIG_SPMI_MSM_PMIC_ARB=y +CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y +# CONFIG_HSI is not set +CONFIG_PPS=y +# CONFIG_PPS_DEBUG is not set + +# +# PPS clients support +# +# CONFIG_PPS_CLIENT_KTIMER is not set +# CONFIG_PPS_CLIENT_LDISC is not set +# CONFIG_PPS_CLIENT_GPIO is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +CONFIG_PTP_1588_CLOCK=y + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +CONFIG_PINCTRL=y +CONFIG_PINMUX=y +CONFIG_PINCONF=y +CONFIG_GENERIC_PINCONF=y +# CONFIG_DEBUG_PINCTRL is not set +# CONFIG_PINCTRL_AMD is not set +# CONFIG_PINCTRL_MCP23S08 is not set +# CONFIG_PINCTRL_SINGLE is not set +# CONFIG_PINCTRL_SX150X is not set +CONFIG_PINCTRL_MSM=y +# CONFIG_PINCTRL_APQ8064 is not set +# CONFIG_PINCTRL_APQ8084 is not set +# CONFIG_PINCTRL_IPQ4019 is not set +# CONFIG_PINCTRL_IPQ8064 is not set +# CONFIG_PINCTRL_IPQ8074 is not set +# CONFIG_PINCTRL_MSM8660 is not set +# CONFIG_PINCTRL_MSM8960 is not set +# CONFIG_PINCTRL_MDM9615 is not set +# CONFIG_PINCTRL_MSM8X74 is not set +# CONFIG_PINCTRL_MSM8916 is not set +# CONFIG_PINCTRL_MSM8994 is not set +# CONFIG_PINCTRL_MSM8996 is not set +# CONFIG_PINCTRL_MSM8998 is not set +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set +# CONFIG_PINCTRL_SDM845 is not set +CONFIG_PINCTRL_KONA=y +# CONFIG_PINCTRL_LITO is not set +# CONFIG_PINCTRL_LAGOON is not set +# CONFIG_PINCTRL_BENGAL is not set +# CONFIG_PINCTRL_SCUBA is not set +CONFIG_GPIOLIB=y +CONFIG_GPIOLIB_FASTPATH_LIMIT=512 +CONFIG_OF_GPIO=y +CONFIG_GPIOLIB_IRQCHIP=y +# CONFIG_DEBUG_GPIO is not set +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers +# +# CONFIG_GPIO_74XX_MMIO is not set +# CONFIG_GPIO_ALTERA is not set +# CONFIG_GPIO_DWAPB is not set +# CONFIG_GPIO_FTGPIO010 is not set +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_GRGPIO is not set +# CONFIG_GPIO_HLWD is not set +# CONFIG_GPIO_MB86S7X is not set +# CONFIG_GPIO_MOCKUP is not set +# CONFIG_GPIO_PL061 is not set +# CONFIG_GPIO_SYSCON is not set +# CONFIG_GPIO_XGENE is not set +# CONFIG_GPIO_XILINX is not set + +# +# I2C GPIO expanders +# +# CONFIG_GPIO_ADP5588 is not set +# CONFIG_GPIO_ADNP is not set +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_GPIO_PCF857X is not set +# CONFIG_GPIO_TPIC2810 is not set + +# +# MFD GPIO expanders +# + +# +# PCI GPIO expanders +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_PCI_IDIO_16 is not set +# CONFIG_GPIO_PCIE_IDIO_24 is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders +# +# CONFIG_GPIO_74X164 is not set +# CONFIG_GPIO_MAX3191X is not set +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_PISOSR is not set +# CONFIG_GPIO_XRA1403 is not set + +# +# USB GPIO expanders +# +# CONFIG_W1 is not set +# CONFIG_POWER_AVS is not set +CONFIG_POWER_RESET=y +# CONFIG_POWER_RESET_BRCMSTB is not set +# CONFIG_POWER_RESET_GPIO is not set +# CONFIG_POWER_RESET_GPIO_RESTART is not set +# CONFIG_POWER_RESET_MSM is not set +# CONFIG_POWER_RESET_QCOM_PON is not set +# CONFIG_POWER_RESET_LTC2952 is not set +CONFIG_POWER_RESET_QCOM=y +# CONFIG_POWER_RESET_RESTART is not set +CONFIG_POWER_RESET_XGENE=y +CONFIG_POWER_RESET_SYSCON=y +# CONFIG_POWER_RESET_SYSCON_POWEROFF is not set +# CONFIG_SYSCON_REBOOT_MODE is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_GENERIC_ADC_BATTERY is not set +# CONFIG_TEST_POWER is not set +# CONFIG_CHARGER_ADP5061 is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_LEGO_EV3 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_CHARGER_SBS is not set +# CONFIG_MANAGER_SBS is not set +# CONFIG_BATTERY_BQ27XXX is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set +# CONFIG_CHARGER_LTC3651 is not set +# CONFIG_CHARGER_DETECTOR_MAX14656 is not set +# CONFIG_CHARGER_QCOM_SMBB is not set +# CONFIG_CHARGER_BQ2415X is not set +# CONFIG_CHARGER_BQ24190 is not set +# CONFIG_CHARGER_BQ24257 is not set +# CONFIG_CHARGER_BQ24735 is not set +# CONFIG_CHARGER_BQ25890 is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_BATTERY_GAUGE_LTC2941 is not set +# CONFIG_CHARGER_RT9455 is not set +# CONFIG_ARCH_CAS_QCOM is not set + +# +# Qualcomm Technologies, Inc. Charger and Fuel Gauge support +# +CONFIG_QPNP_SMB5=y +# CONFIG_SMB1390_CHARGE_PUMP_PSY is not set +# CONFIG_SMB1398_COMBO_CHARGE_PSY is not set +# CONFIG_SMB1355_SLAVE_CHARGER is not set +CONFIG_QPNP_QNOVO5=y +CONFIG_QPNP_FG_GEN4=y +# CONFIG_QPNP_QG is not set +# CONFIG_FUEL_GAUGE_BQ27Z561 is not set +# CONFIG_HL6111R is not set +# CONFIG_IDT_P9415 is not set +# CONFIG_RX1619_TRIM is not set +# CONFIG_RX_ON_URD is not set +# CONFIG_RX1619 is not set +# CONFIG_LN8282 is not set +# CONFIG_SMB1398_CHARGER is not set + +# +# TI Technologies, Inc. Charger support +# +CONFIG_BQ2597X_CHARGE_PUMP=y +# CONFIG_BQ_PUMP_WIRELESS_CHARGE is not set +CONFIG_BATT_VERIFY_BY_DS28E16=y +CONFIG_ONEWIRE_GPIO=y + +# +# Qualcomm Technologies, Inc. Charger and Fuel Gauge support +# +# CONFIG_QPNP_SMB5_CAS is not set +# CONFIG_CHARGER_BQ25790 is not set +# CONFIG_FUEL_GAUGE_BQ28Z610 is not set +# CONFIG_WATCHDOG_MAX28200 is not set +# CONFIG_CP_MAX77932 is not set +# CONFIG_IDT_P9415_CAS is not set +# CONFIG_RX1619_TRIM_CAS is not set +# CONFIG_RX1619_CAS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7310 is not set +# CONFIG_SENSORS_ADT7410 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ASPEED is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_G762 is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_HIH6130 is not set +# CONFIG_SENSORS_IIO_HWMON is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_POWR1220 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LTC2945 is not set +# CONFIG_SENSORS_LTC2990 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4222 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4260 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_MAX31722 is not set +# CONFIG_SENSORS_MAX6621 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MAX6697 is not set +# CONFIG_SENSORS_MAX31790 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_TC654 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LM95234 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_NCT6683 is not set +# CONFIG_SENSORS_NCT6775 is not set +# CONFIG_SENSORS_NCT7802 is not set +# CONFIG_SENSORS_NCT7904 is not set +# CONFIG_SENSORS_NPCM7XX is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_PWM_FAN is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SHT3x is not set +# CONFIG_SENSORS_SHTC1 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_STTS751 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_ADC128D818 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_INA209 is not set +# CONFIG_SENSORS_INA2XX is not set +# CONFIG_SENSORS_INA3221 is not set +# CONFIG_SENSORS_TC74 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP103 is not set +# CONFIG_SENSORS_TMP108 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83773G is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +CONFIG_THERMAL=y +# CONFIG_THERMAL_STATISTICS is not set +CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0 +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_OF=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set +# CONFIG_THERMAL_GOV_FAIR_SHARE is not set +CONFIG_THERMAL_GOV_STEP_WISE=y +# CONFIG_THERMAL_GOV_BANG_BANG is not set +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set +CONFIG_CPU_THERMAL=y +# CONFIG_CLOCK_THERMAL is not set +CONFIG_DEVFREQ_THERMAL=y +# CONFIG_THERMAL_EMULATION is not set +# CONFIG_QORIQ_THERMAL is not set + +# +# ACPI INT340X thermal drivers +# +CONFIG_QCOM_SPMI_TEMP_ALARM=y +# CONFIG_GENERIC_ADC_THERMAL is not set +CONFIG_THERMAL_TSENS=y + +# +# Qualcomm thermal drivers +# +# CONFIG_QCOM_TSENS is not set +CONFIG_QTI_ADC_TM=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_QMI_SENSOR=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_QTI_THERMAL_LIMITS_DCVS=y +# CONFIG_QTI_AOP_REG_COOLING_DEVICE is not set +# CONFIG_REGULATOR_COOLING_DEVICE is not set +CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y +# CONFIG_QTI_LMH_CPU_VDD_COOLING_DEVICE is not set +CONFIG_QTI_LIMITS_ISENSE_CDSP=y +# CONFIG_QTI_CX_IPEAK_COOLING_DEVICE is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_ACT8945A is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_MFD_AS3722 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_MFD_ATMEL_FLEXCOM is not set +# CONFIG_MFD_ATMEL_HLCDC is not set +# CONFIG_MFD_BCM590XX is not set +# CONFIG_MFD_BD9571MWV is not set +# CONFIG_MFD_AXP20X_I2C is not set +# CONFIG_MFD_CROS_EC is not set +# CONFIG_MFD_MADERA is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_DA9062 is not set +# CONFIG_MFD_DA9063 is not set +# CONFIG_MFD_DA9150 is not set +# CONFIG_MFD_DLN2 is not set +# CONFIG_MFD_MC13XXX_SPI is not set +# CONFIG_MFD_MC13XXX_I2C is not set +# CONFIG_MFD_HI6421_PMIC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_LPC_ICH is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_KEMPLD is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_MAX14577 is not set +# CONFIG_MFD_MAX77620 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX77843 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_MT6397 is not set +# CONFIG_MFD_MENF21BMC is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_CPCAP is not set +# CONFIG_MFD_VIPERBOARD is not set +# CONFIG_MFD_RETU is not set +# CONFIG_MFD_PCF50633 is not set +CONFIG_MFD_I2C_PMIC=y +# CONFIG_MFD_QCOM_RPM is not set +CONFIG_MFD_SPMI_PMIC=y +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_RT5033 is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_RK808 is not set +# CONFIG_MFD_RN5T618 is not set +# CONFIG_MFD_SEC_CORE is not set +# CONFIG_MFD_SI476X_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_SKY81452 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_STMPE is not set +CONFIG_MFD_SYSCON=y +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_MFD_LP3943 is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_TI_LMU is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65086 is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TI_LP873X is not set +# CONFIG_MFD_TI_LP87565 is not set +# CONFIG_MFD_TPS65218 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_WL1273_CORE is not set +# CONFIG_MFD_LM3533 is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_ARIZONA_I2C is not set +# CONFIG_MFD_ARIZONA_SPI is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_ROHM_BD718XX is not set +# CONFIG_RAVE_SP_CORE is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +CONFIG_REGULATOR_PROXY_CONSUMER=y +# CONFIG_REGULATOR_88PG86X is not set +# CONFIG_REGULATOR_ACT8865 is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ANATOP is not set +# CONFIG_REGULATOR_DA9210 is not set +# CONFIG_REGULATOR_DA9211 is not set +# CONFIG_REGULATOR_FAN53555 is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_ISL9305 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_LP8755 is not set +# CONFIG_REGULATOR_LTC3589 is not set +# CONFIG_REGULATOR_LTC3676 is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_MAX8973 is not set +# CONFIG_REGULATOR_MT6311 is not set +# CONFIG_REGULATOR_PFUZE100 is not set +# CONFIG_REGULATOR_PV88060 is not set +# CONFIG_REGULATOR_PV88080 is not set +# CONFIG_REGULATOR_PV88090 is not set +# CONFIG_REGULATOR_PWM is not set +# CONFIG_REGULATOR_QCOM_RPMH is not set +# CONFIG_REGULATOR_QCOM_SPMI is not set +CONFIG_REGULATOR_QPNP_AMOLED=y +# CONFIG_REGULATOR_QPNP_LABIBB is not set +CONFIG_REGULATOR_QPNP_LCDB=y +# CONFIG_REGULATOR_QPNP_OLEDB is not set +# CONFIG_REGULATOR_SY8106A is not set +# CONFIG_REGULATOR_TPS51632 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS65132 is not set +# CONFIG_REGULATOR_TPS6524X is not set +# CONFIG_REGULATOR_VCTRL is not set +CONFIG_REGULATOR_REFGEN=y +CONFIG_REGULATOR_RPMH=y +CONFIG_REGULATOR_STUB=y +CONFIG_REGULATOR_PM8008=y +CONFIG_RC_CORE=y +CONFIG_RC_MAP=y +CONFIG_LIRC=y +# CONFIG_BPF_LIRC_MODE2 is not set +CONFIG_RC_DECODERS=y +# CONFIG_IR_NEC_DECODER is not set +# CONFIG_IR_RC5_DECODER is not set +# CONFIG_IR_RC6_DECODER is not set +# CONFIG_IR_JVC_DECODER is not set +# CONFIG_IR_SONY_DECODER is not set +# CONFIG_IR_SANYO_DECODER is not set +# CONFIG_IR_SHARP_DECODER is not set +# CONFIG_IR_MCE_KBD_DECODER is not set +# CONFIG_IR_XMP_DECODER is not set +# CONFIG_IR_IMON_DECODER is not set +CONFIG_RC_DEVICES=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_HIX5HD2 is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_IMON_RAW is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +CONFIG_IR_SPI=y +# CONFIG_IR_STREAMZAP is not set +# CONFIG_IR_IGORPLUGUSB is not set +# CONFIG_IR_IGUANA is not set +# CONFIG_IR_TTUSBIR is not set +# CONFIG_RC_LOOPBACK is not set +# CONFIG_IR_GPIO_CIR is not set +# CONFIG_IR_GPIO_TX is not set +# CONFIG_IR_PWM_TX is not set +# CONFIG_IR_SERIAL is not set +# CONFIG_IR_SIR is not set +CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# +CONFIG_MEDIA_CAMERA_SUPPORT=y +# CONFIG_MEDIA_ANALOG_TV_SUPPORT is not set +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +# CONFIG_MEDIA_SDR_SUPPORT is not set +# CONFIG_MEDIA_CEC_SUPPORT is not set +CONFIG_MEDIA_CONTROLLER=y +# CONFIG_MEDIA_CONTROLLER_DVB is not set +CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_ADV_DEBUG=y +CONFIG_VIDEO_FIXED_MINOR_RANGES=y +CONFIG_V4L2_MEM2MEM_DEV=y +CONFIG_DVB_CORE=y +# CONFIG_DVB_MMAP is not set +CONFIG_DVB_NET=y +CONFIG_DVB_MAX_ADAPTERS=16 +# CONFIG_DVB_DYNAMIC_MINORS is not set +# CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set +# CONFIG_DVB_ULE_DEBUG is not set + +# +# Media drivers +# +CONFIG_MEDIA_USB_SUPPORT=y + +# +# Webcam devices +# +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=m +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_DTCS033 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STK1135 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TOUPTEK is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +# CONFIG_VIDEO_USBTV is not set + +# +# Analog/digital TV USB devices +# +# CONFIG_VIDEO_AU0828 is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_TM6000 is not set + +# +# Digital TV USB devices +# +# CONFIG_DVB_USB is not set +# CONFIG_DVB_USB_V2 is not set +# CONFIG_DVB_TTUSB_BUDGET is not set +# CONFIG_DVB_TTUSB_DEC is not set +# CONFIG_SMS_USB_DRV is not set +# CONFIG_DVB_B2C2_FLEXCOP_USB is not set +# CONFIG_DVB_AS102 is not set + +# +# Webcam, TV (analog/digital) USB devices +# +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_MEDIA_PCI_SUPPORT is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_VIDEO_CADENCE is not set +# CONFIG_VIDEO_MUX is not set +# CONFIG_VIDEO_QCOM_CAMSS is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_VIDEO_XILINX is not set +# CONFIG_SPECTRA_CAMERA is not set +CONFIG_MSM_CVP_V4L2=y +CONFIG_MSM_NPU=y +CONFIG_MSM_GLOBAL_SYNX=y +CONFIG_DVB_MPQ=m + +# +# Qualcomm Technologies, Inc. Demux device config +# +CONFIG_DVB_MPQ_DEMUX=m +CONFIG_DVB_MPQ_NUM_DMX_DEVICES=4 +CONFIG_DVB_MPQ_TSPP1=y +CONFIG_TSPP=m +CONFIG_VIDEO_V4L2_VIDEOBUF2_CORE=y +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +# CONFIG_V4L_TEST_DRIVERS is not set +# CONFIG_DVB_PLATFORM_DRIVERS is not set + +# +# Qualcomm Technologies, Inc. Demux device config +# + +# +# Qualcomm Technologies, Inc. Demux device config +# + +# +# Supported MMC/SDIO adapters +# +# CONFIG_SMS_SDIO_DRV is not set +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_RADIO_SHARK is not set +# CONFIG_RADIO_SHARK2 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_USB_RAREMONO is not set +# CONFIG_USB_MA901 is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +CONFIG_I2C_RTC6226_QCA=y +# CONFIG_CYPRESS_FIRMWARE is not set +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_V4L2=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_VMALLOC=y + +# +# Media ancillary drivers (tuners, sensors, i2c, spi, frontends) +# +CONFIG_MEDIA_SUBDRV_AUTOSELECT=y +CONFIG_MEDIA_ATTACH=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Audio/Video compression chips +# + +# +# SDR tuner chips +# + +# +# Miscellaneous helper chips +# + +# +# Sensors used on soc_camera driver +# + +# +# Media SPI Adapters +# +# CONFIG_CXD2880_SPI_DRV is not set +CONFIG_MEDIA_TUNER=y +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y + +# +# Multistandard (satellite) frontends +# + +# +# Multistandard (cable + terrestrial) frontends +# + +# +# DVB-S (satellite) frontends +# + +# +# DVB-T (terrestrial) frontends +# + +# +# DVB-C (cable) frontends +# + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# + +# +# ISDB-T (terrestrial) frontends +# + +# +# ISDB-S (satellite) & ISDB-T (terrestrial) frontends +# + +# +# Digital terrestrial only tuners/PLL +# + +# +# SEC control devices for DVB-S +# + +# +# Common Interface (EN50221) controller drivers +# + +# +# Tools to develop new frontends +# + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +CONFIG_DRM=y +CONFIG_DRM_MIPI_DSI=y +# CONFIG_DRM_DP_AUX_CHARDEV is not set +# CONFIG_DRM_DEBUG_MM is not set +# CONFIG_DRM_DEBUG_SELFTEST is not set +CONFIG_DRM_KMS_HELPER=y +# CONFIG_DRM_FBDEV_EMULATION is not set +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +# CONFIG_DRM_DP_CEC is not set + +# +# I2C encoder or helper chips +# +# CONFIG_DRM_I2C_CH7006 is not set +# CONFIG_DRM_I2C_SIL164 is not set +# CONFIG_DRM_I2C_NXP_TDA998X is not set +# CONFIG_DRM_I2C_NXP_TDA9950 is not set +# CONFIG_DRM_HDLCD is not set +# CONFIG_DRM_MALI_DISPLAY is not set +# CONFIG_DRM_RADEON is not set +# CONFIG_DRM_AMDGPU is not set + +# +# ACP (Audio CoProcessor) Configuration +# + +# +# AMD Library routines +# +# CONFIG_DRM_NOUVEAU is not set +# CONFIG_DRM_VGEM is not set +# CONFIG_DRM_VKMS is not set +# CONFIG_DRM_UDL is not set +# CONFIG_DRM_AST is not set +# CONFIG_DRM_MGAG200 is not set +# CONFIG_DRM_CIRRUS_QEMU is not set +# CONFIG_DRM_RCAR_DW_HDMI is not set +# CONFIG_DRM_RCAR_LVDS is not set +# CONFIG_DRM_QXL is not set +# CONFIG_DRM_BOCHS is not set +# CONFIG_DRM_MSM is not set +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +# CONFIG_DRM_PANEL_ARM_VERSATILE is not set +# CONFIG_DRM_PANEL_LVDS is not set +# CONFIG_DRM_PANEL_SIMPLE is not set +# CONFIG_DRM_PANEL_ILITEK_IL9322 is not set +# CONFIG_DRM_PANEL_ILITEK_ILI9881C is not set +# CONFIG_DRM_PANEL_INNOLUX_P079ZCA is not set +# CONFIG_DRM_PANEL_JDI_LT070ME05000 is not set +# CONFIG_DRM_PANEL_SAMSUNG_LD9040 is not set +# CONFIG_DRM_PANEL_LG_LG4573 is not set +# CONFIG_DRM_PANEL_ORISETECH_OTM8009A is not set +# CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00 is not set +# CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN is not set +# CONFIG_DRM_PANEL_RAYDIUM_RM68200 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E3HA2 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03 is not set +# CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0 is not set +# CONFIG_DRM_PANEL_SEIKO_43WVF1G is not set +# CONFIG_DRM_PANEL_SHARP_LQ101R1SX01 is not set +# CONFIG_DRM_PANEL_SHARP_LS043T1LE01 is not set +# CONFIG_DRM_PANEL_SITRONIX_ST7789V is not set +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +# CONFIG_DRM_ANALOGIX_ANX78XX is not set +# CONFIG_DRM_CDNS_DSI is not set +# CONFIG_DRM_DUMB_VGA_DAC is not set +# CONFIG_DRM_LVDS_ENCODER is not set +# CONFIG_DRM_MEGACHIPS_STDPXXXX_GE_B850V3_FW is not set +# CONFIG_DRM_NXP_PTN3460 is not set +# CONFIG_DRM_PARADE_PS8622 is not set +# CONFIG_DRM_SIL_SII8620 is not set +# CONFIG_DRM_SII902X is not set +# CONFIG_DRM_SII9234 is not set +# CONFIG_DRM_THINE_THC63LVD1024 is not set +# CONFIG_DRM_TOSHIBA_TC358767 is not set +# CONFIG_DRM_TI_TFP410 is not set +CONFIG_DRM_LONTIUM_LT9611UXC=y +# CONFIG_DRM_I2C_ADV7511 is not set +# CONFIG_DRM_ARCPGU is not set +# CONFIG_DRM_HISI_HIBMC is not set +# CONFIG_DRM_HISI_KIRIN is not set +# CONFIG_DRM_MXSFB is not set +# CONFIG_DRM_TINYDRM is not set +# CONFIG_DRM_PL111 is not set +# CONFIG_DRM_LEGACY is not set +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y + +# +# Frame buffer Devices +# +CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +CONFIG_FB_CMDLINE=y +CONFIG_FB_NOTIFY=y +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +CONFIG_FB_ARMCLCD=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_OPENCORES is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set +# CONFIG_FB_IBM_GXT4500 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +# CONFIG_FB_SIMPLE is not set +# CONFIG_FB_SSD1307 is not set +# CONFIG_FB_SM712 is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=m +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_ILI922X is not set +# CONFIG_LCD_ILI9320 is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +# CONFIG_LCD_LMS501KF03 is not set +# CONFIG_LCD_HX8357 is not set +# CONFIG_LCD_OTM3225A is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +# CONFIG_BACKLIGHT_PWM is not set +# CONFIG_BACKLIGHT_PM8941_WLED is not set +CONFIG_BACKLIGHT_QCOM_SPMI_WLED=y +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LM3630A is not set +# CONFIG_BACKLIGHT_LM3639 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_GPIO is not set +# CONFIG_BACKLIGHT_LV5207LP is not set +# CONFIG_BACKLIGHT_BD6107 is not set +# CONFIG_BACKLIGHT_ARCXCNN is not set +CONFIG_VIDEOMODE_HELPERS=y +CONFIG_HDMI=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_PCM_ELD=y +CONFIG_SND_PCM_IEC958=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +CONFIG_SND_JACK_INPUT_DEV=y +# CONFIG_SND_OSSEMUL is not set +CONFIG_SND_PCM_TIMER=y +# CONFIG_SND_HRTIMER is not set +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_MAX_CARDS=32 +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_PROC_FS=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_SEQUENCER is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SE6X is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set + +# +# HD-Audio +# +# CONFIG_SND_HDA_INTEL is not set +CONFIG_SND_HDA_PREALLOC_SIZE=64 +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +# CONFIG_SND_USB_HIFACE is not set +# CONFIG_SND_BCD2000 is not set +# CONFIG_SND_USB_POD is not set +# CONFIG_SND_USB_PODHD is not set +# CONFIG_SND_USB_TONEPORT is not set +# CONFIG_SND_USB_VARIAX is not set +CONFIG_SND_USB_AUDIO_QMI=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_COMPRESS=y +# CONFIG_SND_SOC_AMD_ACP is not set +# CONFIG_SND_ATMEL_SOC is not set +# CONFIG_SND_DESIGNWARE_I2S is not set + +# +# SoC Audio for Freescale CPUs +# + +# +# Common SoC Audio options for Freescale CPUs: +# +# CONFIG_SND_SOC_FSL_ASRC is not set +# CONFIG_SND_SOC_FSL_SAI is not set +# CONFIG_SND_SOC_FSL_SSI is not set +# CONFIG_SND_SOC_FSL_SPDIF is not set +# CONFIG_SND_SOC_FSL_ESAI is not set +# CONFIG_SND_SOC_IMX_AUDMUX is not set +# CONFIG_SND_I2S_HI6210_I2S is not set +# CONFIG_SND_SOC_IMG is not set +# CONFIG_SND_SOC_QCOM is not set + +# +# STMicroelectronics STM32 SOC audio support +# +# CONFIG_SND_SOC_XTFPGA_I2S is not set +# CONFIG_ZX_TDM is not set +CONFIG_SND_SOC_I2C_AND_SPI=y + +# +# CODEC drivers +# +# CONFIG_SND_SOC_AC97_CODEC is not set +# CONFIG_SND_SOC_ADAU1701 is not set +# CONFIG_SND_SOC_ADAU1761_I2C is not set +# CONFIG_SND_SOC_ADAU1761_SPI is not set +# CONFIG_SND_SOC_ADAU7002 is not set +# CONFIG_SND_SOC_AK4104 is not set +# CONFIG_SND_SOC_AK4458 is not set +# CONFIG_SND_SOC_AK4554 is not set +# CONFIG_SND_SOC_AK4613 is not set +# CONFIG_SND_SOC_AK4642 is not set +# CONFIG_SND_SOC_AK5386 is not set +# CONFIG_SND_SOC_AK5558 is not set +# CONFIG_SND_SOC_ALC5623 is not set +# CONFIG_SND_SOC_BD28623 is not set +# CONFIG_SND_SOC_BT_SCO is not set +# CONFIG_SND_SOC_CS35L32 is not set +# CONFIG_SND_SOC_CS35L33 is not set +# CONFIG_SND_SOC_CS35L34 is not set +# CONFIG_SND_SOC_CS35L35 is not set +# CONFIG_SND_SOC_CS42L42 is not set +# CONFIG_SND_SOC_CS42L51_I2C is not set +# CONFIG_SND_SOC_CS42L52 is not set +# CONFIG_SND_SOC_CS42L56 is not set +# CONFIG_SND_SOC_CS42L73 is not set +# CONFIG_SND_SOC_CS4265 is not set +# CONFIG_SND_SOC_CS4270 is not set +# CONFIG_SND_SOC_CS4271_I2C is not set +# CONFIG_SND_SOC_CS4271_SPI is not set +# CONFIG_SND_SOC_CS42XX8_I2C is not set +# CONFIG_SND_SOC_CS43130 is not set +# CONFIG_SND_SOC_CS4349 is not set +# CONFIG_SND_SOC_CS53L30 is not set +CONFIG_SND_SOC_HDMI_CODEC=y +# CONFIG_SND_SOC_ES7134 is not set +# CONFIG_SND_SOC_ES7241 is not set +# CONFIG_SND_SOC_ES8316 is not set +# CONFIG_SND_SOC_ES8328_I2C is not set +# CONFIG_SND_SOC_ES8328_SPI is not set +# CONFIG_SND_SOC_GTM601 is not set +# CONFIG_SND_SOC_INNO_RK3036 is not set +# CONFIG_SND_SOC_MAX98504 is not set +# CONFIG_SND_SOC_MAX9867 is not set +# CONFIG_SND_SOC_MAX98927 is not set +# CONFIG_SND_SOC_MAX98373 is not set +# CONFIG_SND_SOC_MAX9860 is not set +# CONFIG_SND_SOC_MSM8916_WCD_ANALOG is not set +# CONFIG_SND_SOC_MSM8916_WCD_DIGITAL is not set +# CONFIG_SND_SOC_PCM1681 is not set +# CONFIG_SND_SOC_PCM1789_I2C is not set +# CONFIG_SND_SOC_PCM179X_I2C is not set +# CONFIG_SND_SOC_PCM179X_SPI is not set +# CONFIG_SND_SOC_PCM186X_I2C is not set +# CONFIG_SND_SOC_PCM186X_SPI is not set +# CONFIG_SND_SOC_PCM3168A_I2C is not set +# CONFIG_SND_SOC_PCM3168A_SPI is not set +# CONFIG_SND_SOC_PCM512x_I2C is not set +# CONFIG_SND_SOC_PCM512x_SPI is not set +# CONFIG_SND_SOC_RT5616 is not set +# CONFIG_SND_SOC_RT5631 is not set +# CONFIG_SND_SOC_SGTL5000 is not set +# CONFIG_SND_SOC_SIMPLE_AMPLIFIER is not set +# CONFIG_SND_SOC_SIRF_AUDIO_CODEC is not set +# CONFIG_SND_SOC_SPDIF is not set +# CONFIG_SND_SOC_SSM2305 is not set +# CONFIG_SND_SOC_SSM2602_SPI is not set +# CONFIG_SND_SOC_SSM2602_I2C is not set +# CONFIG_SND_SOC_SSM4567 is not set +# CONFIG_SND_SOC_STA32X is not set +# CONFIG_SND_SOC_STA350 is not set +# CONFIG_SND_SOC_STI_SAS is not set +# CONFIG_SND_SOC_TAS2552 is not set +# CONFIG_SND_SOC_TAS5086 is not set +# CONFIG_SND_SOC_TAS571X is not set +# CONFIG_SND_SOC_TAS5720 is not set +# CONFIG_SND_SOC_TAS6424 is not set +# CONFIG_SND_SOC_TDA7419 is not set +# CONFIG_SND_SOC_TFA9879 is not set +# CONFIG_SND_SOC_TLV320AIC23_I2C is not set +# CONFIG_SND_SOC_TLV320AIC23_SPI is not set +# CONFIG_SND_SOC_TLV320AIC31XX is not set +# CONFIG_SND_SOC_TLV320AIC32X4_I2C is not set +# CONFIG_SND_SOC_TLV320AIC32X4_SPI is not set +# CONFIG_SND_SOC_TLV320AIC3X is not set +# CONFIG_SND_SOC_TS3A227E is not set +# CONFIG_SND_SOC_TSCS42XX is not set +# CONFIG_SND_SOC_TSCS454 is not set +# CONFIG_SND_SOC_WM8510 is not set +# CONFIG_SND_SOC_WM8523 is not set +# CONFIG_SND_SOC_WM8524 is not set +# CONFIG_SND_SOC_WM8580 is not set +# CONFIG_SND_SOC_WM8711 is not set +# CONFIG_SND_SOC_WM8728 is not set +# CONFIG_SND_SOC_WM8731 is not set +# CONFIG_SND_SOC_WM8737 is not set +# CONFIG_SND_SOC_WM8741 is not set +# CONFIG_SND_SOC_WM8750 is not set +# CONFIG_SND_SOC_WM8753 is not set +# CONFIG_SND_SOC_WM8770 is not set +# CONFIG_SND_SOC_WM8776 is not set +# CONFIG_SND_SOC_WM8782 is not set +# CONFIG_SND_SOC_WM8804_I2C is not set +# CONFIG_SND_SOC_WM8804_SPI is not set +# CONFIG_SND_SOC_WM8903 is not set +# CONFIG_SND_SOC_WM8960 is not set +# CONFIG_SND_SOC_WM8962 is not set +# CONFIG_SND_SOC_WM8974 is not set +# CONFIG_SND_SOC_WM8978 is not set +# CONFIG_SND_SOC_WM8985 is not set +# CONFIG_SND_SOC_ZX_AUD96P22 is not set +# CONFIG_SND_SOC_MAX9759 is not set +# CONFIG_SND_SOC_MT6351 is not set +# CONFIG_SND_SOC_NAU8540 is not set +# CONFIG_SND_SOC_NAU8810 is not set +# CONFIG_SND_SOC_NAU8824 is not set +# CONFIG_SND_SOC_TPA6130A2 is not set +# CONFIG_SND_SIMPLE_CARD is not set +# CONFIG_SND_SIMPLE_SCU_CARD is not set +# CONFIG_SND_AUDIO_GRAPH_CARD is not set +# CONFIG_SND_AUDIO_GRAPH_SCU_CARD is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +CONFIG_UHID=y +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +# CONFIG_HID_A4TECH is not set +# CONFIG_HID_ACCUTOUCH is not set +# CONFIG_HID_ACRUX is not set +CONFIG_HID_APPLE=y +# CONFIG_HID_APPLEIR is not set +# CONFIG_HID_ASUS is not set +# CONFIG_HID_AUREAL is not set +# CONFIG_HID_BELKIN is not set +# CONFIG_HID_BETOP_FF is not set +# CONFIG_HID_CHERRY is not set +# CONFIG_HID_CHICONY is not set +# CONFIG_HID_CORSAIR is not set +# CONFIG_HID_COUGAR is not set +# CONFIG_HID_PRODIKEYS is not set +# CONFIG_HID_CMEDIA is not set +# CONFIG_HID_CYPRESS is not set +# CONFIG_HID_DRAGONRISE is not set +# CONFIG_HID_EMS_FF is not set +# CONFIG_HID_ELAN is not set +CONFIG_HID_ELECOM=y +# CONFIG_HID_ELO is not set +# CONFIG_HID_EZKEY is not set +# CONFIG_HID_GEMBIRD is not set +# CONFIG_HID_GFRM is not set +# CONFIG_HID_HOLTEK is not set +# CONFIG_HID_GOOGLE_HAMMER is not set +# CONFIG_HID_GT683R is not set +# CONFIG_HID_KEYTOUCH is not set +# CONFIG_HID_KYE is not set +# CONFIG_HID_UCLOGIC is not set +# CONFIG_HID_WALTOP is not set +# CONFIG_HID_GYRATION is not set +# CONFIG_HID_ICADE is not set +# CONFIG_HID_ITE is not set +# CONFIG_HID_JABRA is not set +# CONFIG_HID_TWINHAN is not set +# CONFIG_HID_KENSINGTON is not set +# CONFIG_HID_LCPOWER is not set +# CONFIG_HID_LED is not set +# CONFIG_HID_LENOVO is not set +# CONFIG_HID_LOGITECH is not set +CONFIG_HID_MAGICMOUSE=y +# CONFIG_HID_MAYFLASH is not set +# CONFIG_HID_REDRAGON is not set +CONFIG_HID_MICROSOFT=y +# CONFIG_HID_MONTEREY is not set +CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_NTI is not set +# CONFIG_HID_NTRIG is not set +# CONFIG_HID_ORTEK is not set +# CONFIG_HID_PANTHERLORD is not set +# CONFIG_HID_PENMOUNT is not set +# CONFIG_HID_PETALYNX is not set +# CONFIG_HID_PICOLCD is not set +CONFIG_HID_PLANTRONICS=y +# CONFIG_HID_PRIMAX is not set +# CONFIG_HID_RETRODE is not set +# CONFIG_HID_ROCCAT is not set +# CONFIG_HID_SAITEK is not set +# CONFIG_HID_SAMSUNG is not set +CONFIG_HID_SONY=y +# CONFIG_SONY_FF is not set +# CONFIG_HID_SPEEDLINK is not set +# CONFIG_HID_STEAM is not set +# CONFIG_HID_STEELSERIES is not set +# CONFIG_HID_SUNPLUS is not set +# CONFIG_HID_RMI is not set +# CONFIG_HID_GREENASIA is not set +# CONFIG_HID_SMARTJOYPLUS is not set +# CONFIG_HID_TIVO is not set +# CONFIG_HID_TOPSEED is not set +# CONFIG_HID_THINGM is not set +# CONFIG_HID_THRUSTMASTER is not set +# CONFIG_HID_UDRAW_PS3 is not set +# CONFIG_HID_WACOM is not set +# CONFIG_HID_WIIMOTE is not set +# CONFIG_HID_XINMO is not set +# CONFIG_HID_ZEROPLUS is not set +# CONFIG_HID_ZYDACRON is not set +# CONFIG_HID_SENSOR_HUB is not set +# CONFIG_HID_ALPS is not set +CONFIG_HID_QVR=y + +# +# USB HID support +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# I2C HID support +# +# CONFIG_I2C_HID is not set +CONFIG_USB_OHCI_LITTLE_ENDIAN=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +CONFIG_USB_PCI=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEFAULT_PERSIST=y +# CONFIG_USB_DYNAMIC_MINORS is not set +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_LEDS_TRIGGER_USBPORT is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +CONFIG_USB_XHCI_HCD=y +# CONFIG_USB_XHCI_DBGCAP is not set +CONFIG_USB_XHCI_PCI=y +CONFIG_USB_XHCI_PLATFORM=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_ROOT_HUB_TT is not set +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_PCI=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_FOTG210_HCD is not set +# CONFIG_USB_MAX3421_HCD is not set +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PCI=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_HCD_TEST_MODE is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +# CONFIG_USB_WDM is not set +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_USBAT is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_STORAGE_ALAUDA is not set +# CONFIG_USB_STORAGE_ONETOUCH is not set +# CONFIG_USB_STORAGE_KARMA is not set +# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_USB_MUSB_HDRC is not set +CONFIG_USB_DWC3=y +# CONFIG_USB_DWC3_HOST is not set +# CONFIG_USB_DWC3_GADGET is not set +CONFIG_USB_DWC3_DUAL_ROLE=y + +# +# Platform Glue Driver Support +# +CONFIG_USB_DWC3_HAPS=y +CONFIG_USB_DWC3_OF_SIMPLE=y +CONFIG_USB_DWC3_QCOM=y +CONFIG_USB_DWC3_MSM=y +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_CHIPIDEA is not set +CONFIG_USB_ISP1760=y +CONFIG_USB_ISP1760_HCD=y +CONFIG_USB_ISP1760_HOST_ROLE=y +# CONFIG_USB_ISP1760_GADGET_ROLE is not set +# CONFIG_USB_ISP1760_DUAL_ROLE is not set + +# +# USB port drivers +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set +CONFIG_USB_EHSET_TEST_FIXTURE=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +# CONFIG_USB_EZUSB_FX2 is not set +# CONFIG_USB_HUB_USB251XB is not set +# CONFIG_USB_HSIC_USB3503 is not set +# CONFIG_USB_HSIC_USB4604 is not set +CONFIG_USB_LINK_LAYER_TEST=y +# CONFIG_USB_CHAOSKEY is not set +CONFIG_USB_REDRIVER_NB7VPQ904M=y + +# +# USB Physical Layer drivers +# +CONFIG_USB_PHY=y +CONFIG_NOP_USB_XCEIV=y +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ISP1301 is not set +CONFIG_USB_MSM_SSPHY_QMP=y +# CONFIG_MSM_QUSB_PHY is not set +CONFIG_MSM_HSUSB_PHY=y +CONFIG_USB_QCOM_EMU_PHY=y +# CONFIG_USB_ULPI is not set +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +# CONFIG_USB_GADGET_DEBUG_FILES is not set +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=900 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FOTG210_UDC is not set +# CONFIG_USB_GR_UDC is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_PXA27X is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_MV_U3D is not set +# CONFIG_USB_SNP_UDC_PLAT is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_BDC_UDC is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_EG20T is not set +# CONFIG_USB_GADGET_XILINX is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_LIBCOMPOSITE=y +CONFIG_USB_U_ETHER=y +CONFIG_USB_U_AUDIO=y +CONFIG_USB_F_NCM=y +CONFIG_USB_RNDIS=y +CONFIG_USB_F_MASS_STORAGE=y +CONFIG_USB_F_FS=y +CONFIG_USB_F_UAC2=y +CONFIG_USB_F_MIDI=y +CONFIG_USB_F_HID=y +CONFIG_USB_F_DIAG=y +CONFIG_USB_F_CDEV=y +CONFIG_USB_F_CCID=y +CONFIG_USB_F_AUDIO_SRC=y +CONFIG_USB_F_ACC=y +CONFIG_USB_F_QDSS=y +CONFIG_USB_F_GSI=y +CONFIG_USB_F_MTP=y +CONFIG_USB_F_PTP=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_UEVENT=y +# CONFIG_USB_CONFIGFS_SERIAL is not set +# CONFIG_USB_CONFIGFS_ACM is not set +# CONFIG_USB_CONFIGFS_OBEX is not set +CONFIG_USB_CONFIGFS_NCM=y +# CONFIG_USB_CONFIGFS_ECM is not set +# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set +# CONFIG_USB_CONFIGFS_RNDIS is not set +# CONFIG_USB_CONFIGFS_EEM is not set +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +# CONFIG_USB_CONFIGFS_F_LB_SS is not set +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +# CONFIG_USB_CONFIGFS_F_UAC1 is not set +# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +# CONFIG_USB_CONFIGFS_F_UVC is not set +# CONFIG_USB_CONFIGFS_F_PRINTER is not set +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_CONFIGFS_F_GSI=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_TYPEC=y +# CONFIG_TYPEC_TCPM is not set +# CONFIG_TYPEC_UCSI is not set +# CONFIG_TYPEC_TPS6598X is not set + +# +# USB Type-C Multiplexer/DeMultiplexer Switch support +# +# CONFIG_TYPEC_MUX_PI3USB30532 is not set + +# +# USB Type-C Alternate Mode drivers +# +# CONFIG_TYPEC_DP_ALTMODE is not set +# CONFIG_USB_ROLE_SWITCH is not set + +# +# USB Power Delivery +# +CONFIG_USB_PD=y +CONFIG_USB_PD_POLICY=y +CONFIG_QPNP_USB_PDPHY=y +# CONFIG_USB_LED_TRIG is not set +# CONFIG_USB_ULPI_BUS is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +CONFIG_PWRSEQ_EMMC=y +CONFIG_PWRSEQ_SIMPLE=y +CONFIG_MMC_BLOCK=y +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +# CONFIG_SDIO_UART is not set +CONFIG_MMC_TEST=y +# CONFIG_MMC_IPC_LOGGING is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_DEBUG is not set +# CONFIG_MMC_ARMMMCI is not set +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_IO_ACCESSORS=y +# CONFIG_MMC_SDHCI_PCI is not set +CONFIG_MMC_SDHCI_PLTFM=y +# CONFIG_MMC_SDHCI_OF_ARASAN is not set +# CONFIG_MMC_SDHCI_OF_AT91 is not set +# CONFIG_MMC_SDHCI_MSM_ICE is not set +# CONFIG_MMC_SDHCI_OF_DWCMSHC is not set +# CONFIG_MMC_SDHCI_CADENCE is not set +# CONFIG_MMC_SDHCI_F_SDH30 is not set +CONFIG_MMC_SDHCI_MSM=y +# CONFIG_MMC_TIFM_SD is not set +# CONFIG_MMC_SPI is not set +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MMC_USDHI6ROL0 is not set +CONFIG_MMC_CQHCI=y +# CONFIG_MMC_TOSHIBA_PCI is not set +# CONFIG_MMC_MTK is not set +# CONFIG_MMC_SDHCI_XENON is not set +# CONFIG_MMC_SDHCI_OMAP is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +# CONFIG_LEDS_CLASS_FLASH is not set +# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set + +# +# LED drivers +# +# CONFIG_LEDS_BCM6328 is not set +# CONFIG_LEDS_BCM6358 is not set +# CONFIG_LEDS_CR0014114 is not set +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_LM3642 is not set +# CONFIG_LEDS_LM3692X is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_LP3952 is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_LP5562 is not set +# CONFIG_LEDS_LP8501 is not set +# CONFIG_LEDS_LP8860 is not set +# CONFIG_LEDS_PCA955X is not set +# CONFIG_LEDS_PCA963X is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_PWM is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_TLC591XX is not set +# CONFIG_LEDS_LM355x is not set +# CONFIG_LEDS_IS31FL319X is not set +# CONFIG_LEDS_IS31FL32XX is not set + +# +# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM) +# +# CONFIG_LEDS_BLINKM is not set +# CONFIG_LEDS_SYSCON is not set +# CONFIG_LEDS_MLXREG is not set +# CONFIG_LEDS_USER is not set +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_QPNP_FLASH_V2=y +# CONFIG_LEDS_QPNP_VIBRATOR_LDO is not set +# CONFIG_LEDS_AW2015 is not set + +# +# LED Triggers +# +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +# CONFIG_LEDS_TRIGGER_ONESHOT is not set +# CONFIG_LEDS_TRIGGER_MTD is not set +# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_CPU is not set +# CONFIG_LEDS_TRIGGER_ACTIVITY is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +# CONFIG_LEDS_TRIGGER_TRANSIENT is not set +# CONFIG_LEDS_TRIGGER_CAMERA is not set +# CONFIG_LEDS_TRIGGER_PANIC is not set +# CONFIG_LEDS_TRIGGER_NETDEV is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_EDAC_SUPPORT=y +CONFIG_EDAC=y +CONFIG_EDAC_LEGACY_SYSFS=y +# CONFIG_EDAC_DEBUG is not set +# CONFIG_EDAC_THUNDERX is not set +CONFIG_EDAC_KRYO_ARM64=y +# CONFIG_EDAC_KRYO_ARM64_POLL is not set +# CONFIG_EDAC_KRYO_ARM64_PANIC_ON_CE is not set +CONFIG_EDAC_KRYO_ARM64_PANIC_ON_UE=y +# CONFIG_EDAC_XGENE is not set +# CONFIG_EDAC_CORTEX_ARM64 is not set +# CONFIG_EDAC_QCOM is not set +CONFIG_RTC_LIB=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +CONFIG_RTC_SYSTOHC=y +CONFIG_RTC_SYSTOHC_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set +CONFIG_RTC_NVMEM=y + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_ABB5ZES3 is not set +# CONFIG_RTC_DRV_ABX80X is not set +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_HYM8563 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_ISL12026 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8523 is not set +# CONFIG_RTC_DRV_PCF85063 is not set +# CONFIG_RTC_DRV_PCF85363 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8010 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV8803 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1302 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1343 is not set +# CONFIG_RTC_DRV_DS1347 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6916 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RX4581 is not set +# CONFIG_RTC_DRV_RX6110 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_PCF2123 is not set +# CONFIG_RTC_DRV_MCP795 is not set +CONFIG_RTC_I2C_AND_SPI=y + +# +# SPI and I2C RTC drivers +# +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_PCF2127 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1685_FAMILY is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_DS2404 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set +# CONFIG_RTC_DRV_ZYNQMP is not set + +# +# on-CPU RTC drivers +# +# CONFIG_RTC_DRV_PL030 is not set +# CONFIG_RTC_DRV_PL031 is not set +# CONFIG_RTC_DRV_FTRTC010 is not set +CONFIG_RTC_DRV_PM8XXX=y +# CONFIG_RTC_DRV_SNVS is not set +# CONFIG_RTC_DRV_R7301 is not set + +# +# HID Sensor RTC drivers +# +# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set +CONFIG_DMADEVICES=y +# CONFIG_DMADEVICES_DEBUG is not set + +# +# DMA Devices +# +CONFIG_DMA_ENGINE=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_DMA_OF=y +# CONFIG_ALTERA_MSGDMA is not set +# CONFIG_AMBA_PL08X is not set +# CONFIG_DW_AXI_DMAC is not set +# CONFIG_FSL_EDMA is not set +# CONFIG_INTEL_IDMA64 is not set +# CONFIG_MV_XOR_V2 is not set +# CONFIG_PL330_DMA is not set +# CONFIG_XILINX_DMA is not set +# CONFIG_XILINX_ZYNQMP_DMA is not set +# CONFIG_QCOM_BAM_DMA is not set +# CONFIG_QCOM_HIDMA_MGMT is not set +# CONFIG_QCOM_HIDMA is not set +CONFIG_QCOM_GPI_DMA=y +# CONFIG_QCOM_GPI_DMA_DEBUG is not set +# CONFIG_DW_DMAC is not set +# CONFIG_DW_DMAC_PCI is not set + +# +# DMA Clients +# +# CONFIG_ASYNC_TX_DMA is not set +# CONFIG_DMATEST is not set + +# +# DMABUF options +# +CONFIG_SYNC_FILE=y +# CONFIG_SW_SYNC is not set +# CONFIG_AUXDISPLAY is not set +CONFIG_UIO=y +# CONFIG_UIO_CIF is not set +# CONFIG_UIO_PDRV_GENIRQ is not set +# CONFIG_UIO_DMEM_GENIRQ is not set +# CONFIG_UIO_AEC is not set +# CONFIG_UIO_SERCOS3 is not set +# CONFIG_UIO_PCI_GENERIC is not set +# CONFIG_UIO_NETX is not set +# CONFIG_UIO_PRUSS is not set +# CONFIG_UIO_MF624 is not set +# CONFIG_UIO_MSM_SHAREDMEM is not set +# CONFIG_VFIO is not set +# CONFIG_VIRT_DRIVERS is not set +CONFIG_VIRTIO_MENU=y +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# +CONFIG_VSERVICES_SUPPORT=y +CONFIG_VSERVICES_CHAR_DEV=y +# CONFIG_VSERVICES_DEBUG is not set +CONFIG_VSERVICES_LOCK_DEBUG=y +CONFIG_VSERVICES_SERVER=y +CONFIG_VSERVICES_CLIENT=y +# CONFIG_VSERVICES_SKELETON_DRIVER is not set +# CONFIG_VSERVICES_NAMED_DEVICE is not set + +# +# Transport drivers +# +CONFIG_VSERVICES_OKL4_AXON=y + +# +# Protocol drivers +# +CONFIG_VSERVICES_PROTOCOL_BLOCK=y +CONFIG_VSERVICES_PROTOCOL_BLOCK_SERVER=y +CONFIG_VSERVICES_PROTOCOL_BLOCK_CLIENT=y +CONFIG_VSERVICES_PROTOCOL_SERIAL=y +CONFIG_VSERVICES_PROTOCOL_SERIAL_SERVER=y +CONFIG_VSERVICES_PROTOCOL_SERIAL_CLIENT=y + +# +# Client and Server drivers +# +CONFIG_STAGING=y +# CONFIG_PRISM2_USB is not set +# CONFIG_COMEDI is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_RTL8723BS is not set +# CONFIG_R8712U is not set +# CONFIG_R8188EU is not set +# CONFIG_RTS5208 is not set + +# +# IIO staging drivers +# + +# +# Accelerometers +# +# CONFIG_ADIS16203 is not set +# CONFIG_ADIS16240 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7606 is not set +# CONFIG_AD7780 is not set +# CONFIG_AD7816 is not set +# CONFIG_AD7192 is not set +# CONFIG_AD7280 is not set + +# +# Analog digital bi-direction converters +# +# CONFIG_ADT7316 is not set + +# +# Capacitance to digital converters +# +# CONFIG_AD7150 is not set +# CONFIG_AD7152 is not set +# CONFIG_AD7746 is not set + +# +# Direct Digital Synthesis +# +# CONFIG_AD9832 is not set +# CONFIG_AD9834 is not set + +# +# Network Analyzer, Impedance Converters +# +# CONFIG_AD5933 is not set + +# +# Active energy metering IC +# +# CONFIG_ADE7854 is not set + +# +# Resolver to digital converters +# +# CONFIG_AD2S90 is not set +# CONFIG_AD2S1210 is not set +# CONFIG_FB_SM750 is not set +# CONFIG_FB_XGI is not set + +# +# Speakup console speech +# +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# +CONFIG_ASHMEM=y +# CONFIG_ANDROID_VSOC is not set +CONFIG_ION=y +# CONFIG_ION_SYSTEM_HEAP is not set +# CONFIG_ION_CARVEOUT_HEAP is not set +# CONFIG_ION_CHUNK_HEAP is not set +# CONFIG_ION_CMA_HEAP is not set +# CONFIG_ION_FORCE_DMA_SYNC is not set +# CONFIG_ION_DEFER_FREE_NO_SCHED_IDLE is not set +CONFIG_ION_POOL_AUTO_REFILL=y +CONFIG_ION_POOL_FILL_MARK=100 +# CONFIG_STAGING_BOARD is not set +# CONFIG_LTE_GDM724X is not set +# CONFIG_DGNC is not set +# CONFIG_GS_FPGABOOT is not set +# CONFIG_UNISYSSPAR is not set +CONFIG_RTMM=y +CONFIG_KTRACE=y +# CONFIG_COMMON_CLK_XLNX_CLKWZRD is not set +# CONFIG_FB_TFT is not set +# CONFIG_WILC1000_SDIO is not set +# CONFIG_WILC1000_SPI is not set +# CONFIG_MOST is not set +# CONFIG_KS7010 is not set +# CONFIG_GREYBUS is not set +# CONFIG_PI433 is not set +# CONFIG_MTK_MMC is not set + +# +# Gasket devices +# +# CONFIG_STAGING_GASKET_FRAMEWORK is not set +# CONFIG_XIL_AXIS_FIFO is not set +# CONFIG_EROFS_FS is not set +CONFIG_MISYSINFOFREADER=y +CONFIG_KPERFEVENTS=y +CONFIG_MI_RECLAIM=y +# CONFIG_GOLDFISH is not set +# CONFIG_CHROME_PLATFORMS is not set + +# +# Qualcomm technologies inc. MSM specific device drivers +# +CONFIG_MSM_EXT_DISPLAY=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +# CONFIG_SPS_SUPPORT_BAMDMA is not set +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_GSI=y +CONFIG_GSI_REGISTER_VERSION_2=y +CONFIG_IPA3=y +# CONFIG_IPA_DEBUG is not set +CONFIG_IPA_WDI_UNIFIED_API=y +CONFIG_RMNET_IPA3=y +# CONFIG_ECM_IPA is not set +CONFIG_RNDIS_IPA=y +# CONFIG_IPA3_MHI_PROXY is not set +CONFIG_IPA3_MHI_PRIME_MANAGER=y +CONFIG_IPA_UT=y +# CONFIG_MSM_11AD is not set +CONFIG_USB_BAM=y +CONFIG_QCOM_GENI_SE=y +CONFIG_IPA3_REGDUMP=y +CONFIG_IPA3_REGDUMP_IPA_4_5=y +CONFIG_IPA3_REGDUMP_NUM_EXTRA_ENDP_REGS=0 +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y +CONFIG_COMMON_CLK=y + +# +# Common Clock Framework +# +# CONFIG_COMMON_CLK_VERSATILE is not set +# CONFIG_CLK_HSDK is not set +# CONFIG_COMMON_CLK_MAX9485 is not set +# CONFIG_COMMON_CLK_SI5351 is not set +# CONFIG_COMMON_CLK_SI514 is not set +# CONFIG_COMMON_CLK_SI544 is not set +# CONFIG_COMMON_CLK_SI570 is not set +# CONFIG_COMMON_CLK_CDCE706 is not set +# CONFIG_COMMON_CLK_CDCE925 is not set +# CONFIG_COMMON_CLK_CS2000_CP is not set +# CONFIG_CLK_QORIQ is not set +CONFIG_COMMON_CLK_XGENE=y +# CONFIG_COMMON_CLK_PWM is not set +# CONFIG_COMMON_CLK_VC5 is not set +CONFIG_QCOM_GDSC=y +CONFIG_COMMON_CLK_QCOM=y +CONFIG_QCOM_A53PLL=y +CONFIG_QCOM_CLK_APCS_MSM8916=y +CONFIG_QCOM_CLK_RPMH=y +# CONFIG_APQ_GCC_8084 is not set +# CONFIG_APQ_MMCC_8084 is not set +# CONFIG_IPQ_GCC_4019 is not set +# CONFIG_IPQ_GCC_806X is not set +# CONFIG_IPQ_LCC_806X is not set +# CONFIG_IPQ_GCC_8074 is not set +# CONFIG_MSM_GCC_8660 is not set +# CONFIG_MSM_GCC_8916 is not set +# CONFIG_MSM_GCC_8960 is not set +# CONFIG_MSM_LCC_8960 is not set +# CONFIG_MDM_GCC_9615 is not set +# CONFIG_MDM_LCC_9615 is not set +# CONFIG_MSM_MMCC_8960 is not set +# CONFIG_MSM_GCC_8974 is not set +# CONFIG_MSM_MMCC_8974 is not set +# CONFIG_MSM_GCC_8994 is not set +# CONFIG_MSM_GCC_8996 is not set +# CONFIG_MSM_MMCC_8996 is not set +# CONFIG_MSM_GCC_8998 is not set +# CONFIG_SDM_GCC_845 is not set +# CONFIG_SDM_VIDEOCC_845 is not set +# CONFIG_SDM_DISPCC_845 is not set +CONFIG_SPMI_PMIC_CLKDIV=y +CONFIG_MSM_CLK_AOP_QMP=y +CONFIG_MSM_GCC_KONA=y +CONFIG_MSM_VIDEOCC_KONA=y +CONFIG_MSM_DISPCC_KONA=y +CONFIG_MSM_CAMCC_KONA=y +CONFIG_MSM_GPUCC_KONA=y +CONFIG_MSM_DEBUGCC_KONA=y +CONFIG_MSM_NPUCC_KONA=y +# CONFIG_SM_GCC_LITO is not set +# CONFIG_SM_VIDEOCC_LITO is not set +# CONFIG_SM_CAMCC_LITO is not set +# CONFIG_SM_DISPCC_LITO is not set +# CONFIG_SM_GPUCC_LITO is not set +# CONFIG_SM_NPUCC_LITO is not set +# CONFIG_SM_DEBUGCC_LITO is not set +# CONFIG_SM_GCC_BENGAL is not set +# CONFIG_SM_GPUCC_BENGAL is not set +# CONFIG_SM_DISPCC_BENGAL is not set +# CONFIG_SM_DEBUGCC_BENGAL is not set +# CONFIG_SDM_CAMCC_LAGOON is not set +# CONFIG_SDM_DEBUGCC_LAGOON is not set +# CONFIG_SDM_DISPCC_LAGOON is not set +# CONFIG_SDM_GCC_LAGOON is not set +# CONFIG_SDM_GPUCC_LAGOON is not set +# CONFIG_SDM_NPUCC_LAGOON is not set +# CONFIG_SDM_VIDEOCC_LAGOON is not set +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y + +# +# Clock Source drivers +# +CONFIG_TIMER_OF=y +CONFIG_TIMER_PROBE=y +CONFIG_ARM_ARCH_TIMER=y +CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y +CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_FSL_ERRATUM_A008585=y +CONFIG_HISILICON_ERRATUM_161010101=y +CONFIG_ARM64_ERRATUM_858921=y +# CONFIG_ARM_ARCH_TIMER_VCT_ACCESS is not set +# CONFIG_ARM_TIMER_SP804 is not set +CONFIG_MAILBOX=y +# CONFIG_ARM_MHU is not set +# CONFIG_PLATFORM_MHU is not set +# CONFIG_PL320_MBOX is not set +# CONFIG_ALTERA_MBOX is not set +# CONFIG_MAILBOX_TEST is not set +CONFIG_QCOM_APCS_IPC=y +CONFIG_MSM_QMP=y +CONFIG_IOMMU_API=y +CONFIG_IOMMU_SUPPORT=y + +# +# Generic IOMMU Pagetable Support +# +CONFIG_IOMMU_IO_PGTABLE=y +CONFIG_IOMMU_IO_PGTABLE_LPAE=y +# CONFIG_IOMMU_IO_PGTABLE_LPAE_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set +CONFIG_IOMMU_IO_PGTABLE_FAST=y +# CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST is not set +# CONFIG_IOMMU_IO_PGTABLE_FAST_PROVE_TLB is not set +CONFIG_IOMMU_DEBUGFS=y +# CONFIG_IOMMU_DEFAULT_PASSTHROUGH is not set +CONFIG_IOMMU_IOVA=y +CONFIG_OF_IOMMU=y +CONFIG_IOMMU_DMA=y +CONFIG_QTI_IOMMU_SUPPORT=y +CONFIG_ARM_SMMU=y +# CONFIG_ARM_SMMU_V3 is not set +# CONFIG_ARM_SMMU_SELFTEST is not set +# CONFIG_IOMMU_TLBSYNC_DEBUG is not set +# CONFIG_ARM_SMMU_TESTBUS_DUMP is not set +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_TESTS=y +# CONFIG_QCOM_IOMMU is not set + +# +# Remoteproc drivers +# +# CONFIG_REMOTEPROC is not set + +# +# Rpmsg drivers +# +CONFIG_RPMSG=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_NATIVE=y +# CONFIG_RPMSG_QCOM_GLINK_RPM is not set +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_GLINK_SPSS=y +# CONFIG_RPMSG_QCOM_GLINK_SPI is not set +# CONFIG_RPMSG_QCOM_SMD is not set +# CONFIG_RPMSG_VIRTIO is not set +# CONFIG_MSM_RPM_SMD is not set +# CONFIG_SOUNDWIRE is not set + +# +# SOC (System On Chip) specific Drivers +# + +# +# Amlogic SoC drivers +# + +# +# Broadcom SoC drivers +# +# CONFIG_SOC_BRCMSTB is not set + +# +# NXP/Freescale QorIQ SoC drivers +# + +# +# i.MX SoC drivers +# + +# +# Qualcomm SoC drivers +# +CONFIG_QCOM_COMMAND_DB=y +# CONFIG_QCOM_CPUSS_DUMP is not set +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_MSM_QBT_HANDLER=y +# CONFIG_QCOM_GSBI is not set +CONFIG_QCOM_IPCC=y +CONFIG_QCOM_LLCC=y +CONFIG_QCOM_KONA_LLCC=y +# CONFIG_QCOM_LITO_LLCC is not set +# CONFIG_QCOM_LAGOON_LLCC is not set +# CONFIG_QCOM_SDM845_LLCC is not set +CONFIG_QCOM_LLCC_PERFMON=m +CONFIG_QCOM_MDT_LOADER=y +CONFIG_QPNP_PBS=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_QMI_RMNET=y +CONFIG_QCOM_QMI_DFC=y +CONFIG_RMNET_CTL=y +# CONFIG_RMNET_CTL_DEBUG is not set +CONFIG_QCOM_QMI_POWER_COLLAPSE=y +# CONFIG_QCOM_RMTFS_MEM is not set +CONFIG_QCOM_RPMH=y +CONFIG_QCOM_SMEM=y +# CONFIG_QCOM_SMD_RPM is not set +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_SMEM_STATE=y +CONFIG_QCOM_SMP2P=y +# CONFIG_QCOM_SMSM is not set +# CONFIG_QCOM_WCNSS_CTRL is not set +CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y +CONFIG_SSR_SYSMON_NOTIF_TIMEOUT=20000 +CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT=20000 +CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_REMOTEQDSS=y +CONFIG_MSM_SERVICE_LOCATOR=y +CONFIG_MSM_SERVICE_NOTIFIER=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_QCOM_DCC_V2=y +CONFIG_QCOM_EUD=y +CONFIG_QCOM_MINIDUMP=y +CONFIG_MINIDUMP_MAX_ENTRIES=200 +# CONFIG_QCOM_APR is not set +# CONFIG_MSM_CORE_HANG_DETECT is not set +# CONFIG_MSM_GLADIATOR_HANG_DETECT is not set +# CONFIG_MSM_GLADIATOR_ERP is not set +CONFIG_QCOM_FSA4480_I2C=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +# CONFIG_QCOM_WDOG_IPI_ENABLE is not set +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_BUS_CONFIG_RPMH=y +CONFIG_MSM_SPCOM=y +CONFIG_QSEE_IPC_IRQ=y +CONFIG_MSM_SPSS_UTILS=y +CONFIG_QSEE_IPC_IRQ_BRIDGE=y +CONFIG_QCOM_GLINK=y +CONFIG_QCOM_GLINK_PKT=y +CONFIG_QCOM_SMP2P_SLEEPSTATE=y +CONFIG_QCOM_QDSS_BRIDGE=y +CONFIG_MSM_CDSP_LOADER=y +CONFIG_QTI_SYSTEM_PM=y +CONFIG_QCOM_SMCINVOKE=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_MSM_IDLE_STATS=y +CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 +CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 +CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_QTI_DDR_STATS_LOG=y +# CONFIG_MSM_JTAGV8 is not set +CONFIG_QTEE_SHM_BRIDGE=y +# CONFIG_MEM_SHARE_QMI_SERVICE is not set +CONFIG_MSM_PERFORMANCE=y +CONFIG_QMP_DEBUGFS_CLIENT=y +CONFIG_QCOM_CDSP_RM=y +CONFIG_QCOM_QHEE_ENABLE_MEM_PROTECTION=y +# CONFIG_QCOM_CX_IPEAK is not set +# CONFIG_QCOM_HYP_CORE_CTL is not set +# CONFIG_ICNSS2 is not set +# CONFIG_ICNSS is not set +# CONFIG_SOC_TI is not set + +# +# Xilinx SoC drivers +# +# CONFIG_XILINX_VCU is not set +CONFIG_PM_DEVFREQ=y + +# +# DEVFREQ Governors +# +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_POWERSAVE=y +CONFIG_DEVFREQ_GOV_USERSPACE=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_GOV_CDSPL3=y + +# +# DEVFREQ Drivers +# +CONFIG_DEVFREQ_GOV_QCOM_ADRENO_TZ=y +CONFIG_DEVFREQ_GOV_QCOM_GPUBW_MON=y +CONFIG_ARM_QCOM_DEVFREQ_FW=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_ARM_QCOM_DEVFREQ_QOSLAT=y +CONFIG_DEVFREQ_GOV_STATICMAP=y +# CONFIG_PM_DEVFREQ_EVENT is not set +CONFIG_EXTCON=y + +# +# Extcon Device Drivers +# +# CONFIG_EXTCON_ADC_JACK is not set +CONFIG_EXTCON_GPIO=y +# CONFIG_EXTCON_MAX3355 is not set +# CONFIG_EXTCON_QCOM_SPMI_MISC is not set +# CONFIG_EXTCON_RT8973A is not set +# CONFIG_EXTCON_SM5502 is not set +CONFIG_EXTCON_USB_GPIO=y +# CONFIG_MEMORY is not set +CONFIG_IIO=y +CONFIG_IIO_BUFFER=y +CONFIG_IIO_BUFFER_CB=y +# CONFIG_IIO_BUFFER_HW_CONSUMER is not set +CONFIG_IIO_KFIFO_BUF=y +CONFIG_IIO_TRIGGERED_BUFFER=y +# CONFIG_IIO_CONFIGFS is not set +CONFIG_IIO_TRIGGER=y +CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 +# CONFIG_IIO_SW_DEVICE is not set +# CONFIG_IIO_SW_TRIGGER is not set + +# +# Accelerometers +# +# CONFIG_ADIS16201 is not set +# CONFIG_ADIS16209 is not set +# CONFIG_ADXL345_I2C is not set +# CONFIG_ADXL345_SPI is not set +# CONFIG_BMA180 is not set +# CONFIG_BMA220 is not set +# CONFIG_BMC150_ACCEL is not set +# CONFIG_DA280 is not set +# CONFIG_DA311 is not set +# CONFIG_DMARD06 is not set +# CONFIG_DMARD09 is not set +# CONFIG_DMARD10 is not set +# CONFIG_IIO_CROS_EC_ACCEL_LEGACY is not set +# CONFIG_IIO_ST_ACCEL_3AXIS is not set +# CONFIG_KXSD9 is not set +# CONFIG_KXCJK1013 is not set +# CONFIG_MC3230 is not set +# CONFIG_MMA7455_I2C is not set +# CONFIG_MMA7455_SPI is not set +# CONFIG_MMA7660 is not set +# CONFIG_MMA8452 is not set +# CONFIG_MMA9551 is not set +# CONFIG_MMA9553 is not set +# CONFIG_MXC4005 is not set +# CONFIG_MXC6255 is not set +# CONFIG_SCA3000 is not set +# CONFIG_STK8312 is not set +# CONFIG_STK8BA50 is not set + +# +# Analog to digital converters +# +# CONFIG_AD7266 is not set +# CONFIG_AD7291 is not set +# CONFIG_AD7298 is not set +# CONFIG_AD7476 is not set +# CONFIG_AD7766 is not set +# CONFIG_AD7791 is not set +# CONFIG_AD7793 is not set +# CONFIG_AD7887 is not set +# CONFIG_AD7923 is not set +# CONFIG_AD799X is not set +# CONFIG_CC10001_ADC is not set +# CONFIG_ENVELOPE_DETECTOR is not set +# CONFIG_HI8435 is not set +# CONFIG_HX711 is not set +# CONFIG_INA2XX_ADC is not set +# CONFIG_LTC2471 is not set +# CONFIG_LTC2485 is not set +# CONFIG_LTC2497 is not set +# CONFIG_MAX1027 is not set +# CONFIG_MAX11100 is not set +# CONFIG_MAX1118 is not set +# CONFIG_MAX1363 is not set +# CONFIG_MAX9611 is not set +# CONFIG_MCP320X is not set +# CONFIG_MCP3422 is not set +# CONFIG_NAU7802 is not set +CONFIG_QCOM_VADC_COMMON=y +CONFIG_QCOM_SPMI_ADC5=y +# CONFIG_QCOM_SPMI_IADC is not set +# CONFIG_QCOM_SPMI_VADC is not set +# CONFIG_SD_ADC_MODULATOR is not set +# CONFIG_TI_ADC081C is not set +# CONFIG_TI_ADC0832 is not set +# CONFIG_TI_ADC084S021 is not set +# CONFIG_TI_ADC12138 is not set +# CONFIG_TI_ADC108S102 is not set +# CONFIG_TI_ADC128S052 is not set +# CONFIG_TI_ADC161S626 is not set +# CONFIG_TI_ADS1015 is not set +# CONFIG_TI_ADS7950 is not set +# CONFIG_TI_ADS8688 is not set +# CONFIG_TI_TLC4541 is not set +# CONFIG_VF610_ADC is not set + +# +# Analog Front Ends +# +# CONFIG_IIO_RESCALE is not set + +# +# Amplifiers +# +# CONFIG_AD8366 is not set + +# +# Chemical Sensors +# +# CONFIG_ATLAS_PH_SENSOR is not set +# CONFIG_BME680 is not set +# CONFIG_CCS811 is not set +# CONFIG_IAQCORE is not set +# CONFIG_VZ89X is not set + +# +# Hid Sensor IIO Common +# + +# +# SSP Sensor Common +# +# CONFIG_IIO_SSP_SENSORHUB is not set + +# +# Counters +# + +# +# Digital to analog converters +# +# CONFIG_AD5064 is not set +# CONFIG_AD5360 is not set +# CONFIG_AD5380 is not set +# CONFIG_AD5421 is not set +# CONFIG_AD5446 is not set +# CONFIG_AD5449 is not set +# CONFIG_AD5592R is not set +# CONFIG_AD5593R is not set +# CONFIG_AD5504 is not set +# CONFIG_AD5624R_SPI is not set +# CONFIG_LTC2632 is not set +# CONFIG_AD5686_SPI is not set +# CONFIG_AD5696_I2C is not set +# CONFIG_AD5755 is not set +# CONFIG_AD5758 is not set +# CONFIG_AD5761 is not set +# CONFIG_AD5764 is not set +# CONFIG_AD5791 is not set +# CONFIG_AD7303 is not set +# CONFIG_AD8801 is not set +# CONFIG_DPOT_DAC is not set +# CONFIG_DS4424 is not set +# CONFIG_M62332 is not set +# CONFIG_MAX517 is not set +# CONFIG_MAX5821 is not set +# CONFIG_MCP4725 is not set +# CONFIG_MCP4922 is not set +# CONFIG_TI_DAC082S085 is not set +# CONFIG_TI_DAC5571 is not set +# CONFIG_VF610_DAC is not set + +# +# IIO dummy driver +# + +# +# Frequency Synthesizers DDS/PLL +# + +# +# Clock Generator/Distribution +# +# CONFIG_AD9523 is not set + +# +# Phase-Locked Loop (PLL) frequency synthesizers +# +# CONFIG_ADF4350 is not set + +# +# Digital gyroscope sensors +# +# CONFIG_ADIS16080 is not set +# CONFIG_ADIS16130 is not set +# CONFIG_ADIS16136 is not set +# CONFIG_ADIS16260 is not set +# CONFIG_ADXRS450 is not set +# CONFIG_BMG160 is not set +# CONFIG_MPU3050_I2C is not set +# CONFIG_IIO_ST_GYRO_3AXIS is not set +# CONFIG_ITG3200 is not set + +# +# Health Sensors +# + +# +# Heart Rate Monitors +# +# CONFIG_AFE4403 is not set +# CONFIG_AFE4404 is not set +# CONFIG_MAX30100 is not set +# CONFIG_MAX30102 is not set + +# +# Humidity sensors +# +# CONFIG_AM2315 is not set +# CONFIG_DHT11 is not set +# CONFIG_HDC100X is not set +# CONFIG_HTS221 is not set +# CONFIG_HTU21 is not set +# CONFIG_SI7005 is not set +# CONFIG_SI7020 is not set + +# +# Inertial measurement units +# +# CONFIG_ADIS16400 is not set +# CONFIG_ADIS16480 is not set +# CONFIG_BMI160_I2C is not set +# CONFIG_BMI160_SPI is not set +# CONFIG_KMX61 is not set +# CONFIG_INV_MPU6050_I2C is not set +# CONFIG_INV_MPU6050_SPI is not set +# CONFIG_IIO_ST_LSM6DSX is not set + +# +# Light sensors +# +# CONFIG_ADJD_S311 is not set +# CONFIG_AL3320A is not set +# CONFIG_APDS9300 is not set +# CONFIG_APDS9960 is not set +# CONFIG_BH1750 is not set +# CONFIG_BH1780 is not set +# CONFIG_CM32181 is not set +# CONFIG_CM3232 is not set +# CONFIG_CM3323 is not set +# CONFIG_CM3605 is not set +# CONFIG_CM36651 is not set +# CONFIG_GP2AP020A00F is not set +# CONFIG_SENSORS_ISL29018 is not set +# CONFIG_SENSORS_ISL29028 is not set +# CONFIG_ISL29125 is not set +# CONFIG_JSA1212 is not set +# CONFIG_RPR0521 is not set +# CONFIG_LTR501 is not set +# CONFIG_LV0104CS is not set +# CONFIG_MAX44000 is not set +# CONFIG_OPT3001 is not set +# CONFIG_PA12203001 is not set +# CONFIG_SI1133 is not set +# CONFIG_SI1145 is not set +# CONFIG_STK3310 is not set +# CONFIG_ST_UVIS25 is not set +# CONFIG_TCS3414 is not set +# CONFIG_TCS3472 is not set +# CONFIG_SENSORS_TSL2563 is not set +# CONFIG_TSL2583 is not set +# CONFIG_TSL2772 is not set +# CONFIG_TSL4531 is not set +# CONFIG_US5182D is not set +# CONFIG_VCNL4000 is not set +# CONFIG_VEML6070 is not set +# CONFIG_VL6180 is not set +# CONFIG_ZOPT2201 is not set + +# +# Magnetometer sensors +# +# CONFIG_AK8974 is not set +# CONFIG_AK8975 is not set +# CONFIG_AK09911 is not set +# CONFIG_BMC150_MAGN_I2C is not set +# CONFIG_BMC150_MAGN_SPI is not set +# CONFIG_MAG3110 is not set +# CONFIG_MMC35240 is not set +# CONFIG_IIO_ST_MAGN_3AXIS is not set +# CONFIG_SENSORS_HMC5843_I2C is not set +# CONFIG_SENSORS_HMC5843_SPI is not set + +# +# Multiplexers +# +# CONFIG_IIO_MUX is not set + +# +# Inclinometer sensors +# + +# +# Triggers - standalone +# +# CONFIG_IIO_INTERRUPT_TRIGGER is not set +# CONFIG_IIO_SYSFS_TRIGGER is not set + +# +# Digital potentiometers +# +# CONFIG_AD5272 is not set +# CONFIG_DS1803 is not set +# CONFIG_MAX5481 is not set +# CONFIG_MAX5487 is not set +# CONFIG_MCP4018 is not set +# CONFIG_MCP4131 is not set +# CONFIG_MCP4531 is not set +# CONFIG_TPL0102 is not set + +# +# Digital potentiostats +# +# CONFIG_LMP91000 is not set + +# +# Pressure sensors +# +# CONFIG_ABP060MG is not set +# CONFIG_BMP280 is not set +# CONFIG_HP03 is not set +# CONFIG_MPL115_I2C is not set +# CONFIG_MPL115_SPI is not set +# CONFIG_MPL3115 is not set +# CONFIG_MS5611 is not set +# CONFIG_MS5637 is not set +# CONFIG_IIO_ST_PRESS is not set +# CONFIG_T5403 is not set +# CONFIG_HP206C is not set +# CONFIG_ZPA2326 is not set + +# +# Lightning sensors +# +# CONFIG_AS3935 is not set + +# +# Proximity and distance sensors +# +# CONFIG_ISL29501 is not set +# CONFIG_LIDAR_LITE_V2 is not set +# CONFIG_RFD77402 is not set +# CONFIG_SRF04 is not set +# CONFIG_SX9500 is not set +# CONFIG_SRF08 is not set +CONFIG_US_PROXIMITY=y + +# +# Resolver to digital converters +# +# CONFIG_AD2S1200 is not set + +# +# Temperature sensors +# +# CONFIG_MAXIM_THERMOCOUPLE is not set +# CONFIG_MLX90614 is not set +# CONFIG_MLX90632 is not set +# CONFIG_TMP006 is not set +# CONFIG_TMP007 is not set +# CONFIG_TSYS01 is not set +# CONFIG_TSYS02D is not set +# CONFIG_NTB is not set +# CONFIG_VME_BUS is not set +CONFIG_PWM=y +CONFIG_PWM_SYSFS=y +# CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_PCA9685 is not set +CONFIG_PWM_QTI_LPG=y + +# +# IRQ chip support +# +CONFIG_IRQCHIP=y +CONFIG_ARM_GIC=y +CONFIG_ARM_GIC_MAX_NR=1 +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3=y +CONFIG_ARM_GIC_V3_ITS=y +CONFIG_ARM_GIC_V3_ITS_PCI=y +# CONFIG_ARM_GIC_V3_ACL is not set +CONFIG_QCOM_SHOW_RESUME_IRQ=y +CONFIG_PARTITION_PERCPU=y +CONFIG_QCOM_PDC=y +# CONFIG_QCOM_MPM is not set +# CONFIG_IPACK_BUS is not set +CONFIG_RESET_CONTROLLER=y +# CONFIG_RESET_QCOM_AOSS is not set +# CONFIG_RESET_TI_SYSCON is not set +# CONFIG_FMC is not set + +# +# PHY Subsystem +# +CONFIG_GENERIC_PHY=y +# CONFIG_PHY_XGENE is not set +# CONFIG_BCM_KONA_USB2_PHY is not set +# CONFIG_PHY_PXA_28NM_HSIC is not set +# CONFIG_PHY_PXA_28NM_USB2 is not set +# CONFIG_PHY_CPCAP_USB is not set +# CONFIG_PHY_MAPPHONE_MDM6600 is not set +# CONFIG_PHY_QCOM_APQ8064_SATA is not set +# CONFIG_PHY_QCOM_IPQ806X_SATA is not set +# CONFIG_PHY_QCOM_QMP is not set +# CONFIG_PHY_QCOM_QUSB2 is not set +CONFIG_PHY_QCOM_UFS=y +# CONFIG_POWERCAP is not set +# CONFIG_MCB is not set + +# +# Performance monitor support +# +# CONFIG_ARM_CCI_PMU is not set +# CONFIG_ARM_CCN is not set +CONFIG_ARM_PMU=y +# CONFIG_ARM_DSU_PMU is not set +# CONFIG_QCOM_L2_COUNTERS is not set +CONFIG_QCOM_LLCC_PMU=y +# CONFIG_ARM_SPE_PMU is not set +CONFIG_RAS=y + +# +# Android +# +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder,vndbinder" +# CONFIG_ANDROID_BINDER_IPC_SELFTEST is not set +CONFIG_BINDER_OPT=y +# CONFIG_LIBNVDIMM is not set +# CONFIG_DAX is not set +CONFIG_NVMEM=y +CONFIG_NVMEM_SYSFS=y +CONFIG_QCOM_QFPROM=y +CONFIG_NVMEM_SPMI_SDAM=y + +# +# HW tracing support +# +CONFIG_STM=y +# CONFIG_STM_DUMMY is not set +# CONFIG_STM_SOURCE_CONSOLE is not set +# CONFIG_STM_SOURCE_HEARTBEAT is not set +# CONFIG_INTEL_TH is not set +# CONFIG_FPGA is not set +# CONFIG_FSI is not set +# CONFIG_TEE is not set +CONFIG_PM_OPP=y +# CONFIG_SIOX is not set +CONFIG_SLIMBUS=y +# CONFIG_SLIMBUS_MSM_CTRL is not set +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_ESOC=y +CONFIG_ESOC_DEV=y +CONFIG_ESOC_CLIENT=y +# CONFIG_ESOC_DEBUG is not set +CONFIG_ESOC_MDM_4x=y +CONFIG_ESOC_MDM_DRV=y +# CONFIG_ESOC_MDM_DBG_ENG is not set +CONFIG_SENSORS_SSC=y +CONFIG_QCOM_KGSL=y +CONFIG_QCOM_ADRENO_DEFAULT_GOVERNOR="msm-adreno-tz" +CONFIG_QCOM_KGSL_IOMMU=y +CONFIG_MIGT_KGSL=y +# CONFIG_LEGACY_ENERGY_MODEL_DT is not set +CONFIG_MIGT=y +CONFIG_MILLET=y +# CONFIG_MIGT_ENERGY_MODEL is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_FS_IOMAP=y +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +CONFIG_EXT4_FS=y +CONFIG_EXT4_USE_FOR_EXT2=y +# CONFIG_EXT4_FS_POSIX_ACL is not set +CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_ENCRYPTION is not set +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_F2FS_FS=y +CONFIG_F2FS_STAT_FS=y +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +CONFIG_F2FS_FS_SECURITY=y +# CONFIG_F2FS_CHECK_FS is not set +# CONFIG_F2FS_FS_ENCRYPTION is not set +# CONFIG_F2FS_FAULT_INJECTION is not set +# CONFIG_FS_DAX is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_EXPORTFS=y +# CONFIG_EXPORTFS_BLOCK_OPS is not set +CONFIG_FILE_LOCKING=y +CONFIG_MANDATORY_FILE_LOCKING=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +CONFIG_QUOTA_TREE=y +# CONFIG_QFMT_V1 is not set +CONFIG_QFMT_V2=y +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS4_FS is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set +CONFIG_OVERLAY_FS=y +# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set +CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW=y +# CONFIG_OVERLAY_FS_INDEX is not set +# CONFIG_OVERLAY_FS_XINO_AUTO is not set +# CONFIG_OVERLAY_FS_METACOPY is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +# CONFIG_FAT_DEFAULT_UTF8 is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +# CONFIG_PROC_CHILDREN is not set +# CONFIG_PROC_UID is not set +CONFIG_KERNFS=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TMPFS_XATTR=y +# CONFIG_HUGETLBFS is not set +CONFIG_MEMFD_CREATE=y +CONFIG_ARCH_HAS_GIGANTIC_PAGE=y +CONFIG_CONFIGFS_FS=y +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ORANGEFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +CONFIG_ECRYPT_FS=y +CONFIG_ECRYPT_FS_MESSAGING=y +CONFIG_SDCARD_FS=y +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_PSTORE=y +CONFIG_PSTORE_DEFLATE_COMPRESS=y +# CONFIG_PSTORE_LZO_COMPRESS is not set +# CONFIG_PSTORE_LZ4_COMPRESS is not set +# CONFIG_PSTORE_LZ4HC_COMPRESS is not set +# CONFIG_PSTORE_842_COMPRESS is not set +# CONFIG_PSTORE_ZSTD_COMPRESS is not set +CONFIG_PSTORE_COMPRESS=y +CONFIG_PSTORE_DEFLATE_COMPRESS_DEFAULT=y +CONFIG_PSTORE_COMPRESS_DEFAULT="deflate" +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_PMSG=y +CONFIG_PSTORE_RAM=y +# CONFIG_PSTORE_LAST_KMSG is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set +# CONFIG_DLM is not set + +# +# Security options +# +CONFIG_KEYS=y +CONFIG_KEYS_COMPAT=y +# CONFIG_PERSISTENT_KEYRINGS is not set +# CONFIG_BIG_KEYS is not set +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEY_DH_OPERATIONS is not set + +# +# Qualcomm Technologies, Inc Per File Encryption security device drivers +# +# CONFIG_PFT is not set +CONFIG_PFK=y +# CONFIG_PFK_WRAPPED_KEY_SUPPORTED is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +CONFIG_LSM_MMAP_MIN_ADDR=32768 +CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_FALLBACK=y +# CONFIG_HARDENED_USERCOPY_PAGESPAN is not set +CONFIG_FORTIFY_SOURCE=y +# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_SECURITY_SELINUX=y +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=0 +CONFIG_SECURITY_SMACK=y +# CONFIG_SECURITY_SMACK_BRINGUP is not set +# CONFIG_SECURITY_SMACK_NETFILTER is not set +# CONFIG_SECURITY_SMACK_APPEND_SIGNALS is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_LOADPIN is not set +# CONFIG_SECURITY_YAMA is not set +CONFIG_INTEGRITY=y +# CONFIG_INTEGRITY_SIGNATURE is not set +CONFIG_INTEGRITY_AUDIT=y +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_SMACK is not set +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" + +# +# Kernel hardening options +# +# CONFIG_GCC_PLUGIN_STRUCTLEAK is not set + +# +# Memory initialization +# +CONFIG_INIT_STACK_NONE=y +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_RNG_DEFAULT=y +CONFIG_CRYPTO_AKCIPHER2=y +CONFIG_CRYPTO_AKCIPHER=y +CONFIG_CRYPTO_KPP2=y +CONFIG_CRYPTO_KPP=y +CONFIG_CRYPTO_ACOMP2=y +CONFIG_CRYPTO_RSA=y +# CONFIG_CRYPTO_DH is not set +CONFIG_CRYPTO_ECDH=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_NULL2=y +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +# CONFIG_CRYPTO_MCRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_SIMD=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +# CONFIG_CRYPTO_CHACHA20POLY1305 is not set +# CONFIG_CRYPTO_AEGIS128 is not set +# CONFIG_CRYPTO_AEGIS128L is not set +# CONFIG_CRYPTO_AEGIS256 is not set +# CONFIG_CRYPTO_MORUS640 is not set +# CONFIG_CRYPTO_MORUS1280 is not set +CONFIG_CRYPTO_SEQIV=y +CONFIG_CRYPTO_ECHAINIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CFB is not set +CONFIG_CRYPTO_CTR=y +CONFIG_CRYPTO_CTS=y +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +CONFIG_CRYPTO_XTS=y +# CONFIG_CRYPTO_KEYWRAP is not set +# CONFIG_CRYPTO_ADIANTUM is not set + +# +# Hash modes +# +CONFIG_CRYPTO_CMAC=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=y +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_CRC32=y +# CONFIG_CRYPTO_CRCT10DIF is not set +CONFIG_CRYPTO_GHASH=y +# CONFIG_CRYPTO_POLY1305 is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_SHA3 is not set +# CONFIG_CRYPTO_SM3 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +# CONFIG_CRYPTO_AES_TI is not set +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_CHACHA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_SM4 is not set +# CONFIG_CRYPTO_TEA is not set +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_LZO=y +# CONFIG_CRYPTO_842 is not set +# CONFIG_CRYPTO_LZ4 is not set +# CONFIG_CRYPTO_LZ4HC is not set +# CONFIG_CRYPTO_ZSTD is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DRBG_MENU=y +CONFIG_CRYPTO_DRBG_HMAC=y +# CONFIG_CRYPTO_DRBG_HASH is not set +# CONFIG_CRYPTO_DRBG_CTR is not set +CONFIG_CRYPTO_DRBG=y +CONFIG_CRYPTO_JITTERENTROPY=y +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +# CONFIG_CRYPTO_USER_API_RNG is not set +# CONFIG_CRYPTO_USER_API_AEAD is not set +CONFIG_CRYPTO_HASH_INFO=y +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_CCP is not set +# CONFIG_CRYPTO_DEV_NITROX_CNN55XX is not set +# CONFIG_CRYPTO_DEV_CAVIUM_ZIP is not set +# CONFIG_CRYPTO_DEV_QCE is not set +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +# CONFIG_CRYPTO_DEV_OTA_CRYPTO is not set +# CONFIG_CRYPTO_DEV_QCOM_RNG is not set +# CONFIG_CRYPTO_DEV_CCREE is not set +# CONFIG_CRYPTO_DEV_HISI_SEC is not set +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_ASYMMETRIC_KEY_TYPE=y +CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y +CONFIG_X509_CERTIFICATE_PARSER=y +CONFIG_PKCS7_MESSAGE_PARSER=y +# CONFIG_PKCS7_TEST_KEY is not set +# CONFIG_SIGNED_PE_FILE_VERIFICATION is not set + +# +# Certificates for signature checking +# +CONFIG_MODULE_SIG_KEY="certs/signing_key.pem" +CONFIG_SYSTEM_TRUSTED_KEYRING=y +CONFIG_SYSTEM_TRUSTED_KEYS="" +# CONFIG_SYSTEM_EXTRA_CERTIFICATE is not set +# CONFIG_SECONDARY_TRUSTED_KEYRING is not set +# CONFIG_SYSTEM_BLACKLIST_KEYRING is not set +CONFIG_BINARY_PRINTF=y + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_HAVE_ARCH_BITREVERSE=y +CONFIG_RATIONAL=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_NET_UTILS=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y +CONFIG_ARCH_HAS_FAST_MULTIPLIER=y +# CONFIG_INDIRECT_PIO is not set +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC64 is not set +# CONFIG_CRC4 is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +CONFIG_CRC8=y +CONFIG_AUDIT_GENERIC=y +CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_AUDIT_COMPAT_GENERIC=y +# CONFIG_RANDOM32_SELFTEST is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=y +CONFIG_TEXTSEARCH_BM=y +CONFIG_TEXTSEARCH_FSM=y +CONFIG_ASSOCIATIVE_ARRAY=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT_MAP=y +CONFIG_HAS_DMA=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_DMA_DIRECT_OPS=y +CONFIG_SWIOTLB=y +CONFIG_SGL_ALLOC=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_GLOB=y +# CONFIG_GLOB_SELFTEST is not set +CONFIG_NLATTR=y +CONFIG_CLZ_TAB=y +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set +# CONFIG_IRQ_POLL is not set +CONFIG_MPILIB=y +CONFIG_LIBFDT=y +CONFIG_OID_REGISTRY=y +CONFIG_SG_POOL=y +CONFIG_ARCH_HAS_SG_CHAIN=y +CONFIG_SBITMAP=y +# CONFIG_STRING_SELFTEST is not set + +# +# Kernel hacking +# + +# +# printk and dmesg options +# +CONFIG_PRINTK_TIME=y +CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 +CONFIG_CONSOLE_LOGLEVEL_QUIET=4 +CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 +# CONFIG_BOOT_PRINTK_DELAY is not set +CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS is not set +# CONFIG_DEBUG_MODULE_LOAD_INFO is not set + +# +# Compile-time checks and compiler options +# +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_INFO_SPLIT is not set +# CONFIG_DEBUG_INFO_DWARF4 is not set +# CONFIG_GDB_SCRIPTS is not set +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FIRE_WATCHDOG=y +CONFIG_DUMP_ALL_STACKS=y +CONFIG_FRAME_WARN=4096 +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_PAGE_OWNER is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_SECTION_MISMATCH_WARN_ONLY=y +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 +CONFIG_MAGIC_SYSRQ_SERIAL=y +CONFIG_DEBUG_KERNEL=y + +# +# Memory Debugging +# +# CONFIG_PAGE_EXTENSION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +# CONFIG_DEBUG_PANIC_ON_OOM is not set +# CONFIG_PAGE_POISONING is not set +# CONFIG_DEBUG_PAGE_REF is not set +# CONFIG_DEBUG_RODATA_TEST is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_VM is not set +CONFIG_ARCH_HAS_DEBUG_VIRTUAL=y +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +CONFIG_HAVE_ARCH_KASAN=y +# CONFIG_KASAN is not set +CONFIG_ARCH_HAS_KCOV=y +CONFIG_CC_HAS_SANCOV_TRACE_PC=y +# CONFIG_KCOV is not set +# CONFIG_DEBUG_SHIRQ is not set + +# +# Debug Lockups and Hangs +# +# CONFIG_SOFTLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set +# CONFIG_WQ_WATCHDOG is not set +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_ON_OOPS_VALUE=1 +CONFIG_PANIC_TIMEOUT=-1 +CONFIG_SCHED_DEBUG=y +CONFIG_SCHED_INFO=y +# CONFIG_PANIC_ON_SCHED_BUG is not set +# CONFIG_PANIC_ON_RT_THROTTLING is not set +CONFIG_SCHEDSTATS=y +# CONFIG_SCHED_STACK_END_CHECK is not set +# CONFIG_DEBUG_TIMEKEEPING is not set +# CONFIG_DEBUG_PREEMPT is not set + +# +# Lock Debugging (spinlocks, mutexes, etc...) +# +CONFIG_LOCK_DEBUGGING_SUPPORT=y +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_LOCK_TORTURE_TEST is not set +# CONFIG_WW_MUTEX_SELFTEST is not set +CONFIG_STACKTRACE=y +# CONFIG_WARN_ALL_UNSEEDED_RANDOM is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_HAVE_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_PI_LIST is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set + +# +# RCU Debugging +# +# CONFIG_RCU_PERF_TEST is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=21 +CONFIG_RCU_PANIC_ON_STALL=0 +# CONFIG_RCU_TRACE is not set +# CONFIG_RCU_EQS_DEBUG is not set +# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_NOP_TRACER=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACE_CLOCK=y +CONFIG_RING_BUFFER=y +CONFIG_EVENT_TRACING=y +CONFIG_CONTEXT_SWITCH_TRACER=y +CONFIG_IPC_LOGGING=y +# CONFIG_QCOM_RTB is not set +CONFIG_TRACING=y +CONFIG_GENERIC_TRACER=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_PREEMPTIRQ_EVENTS is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_PREEMPT_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_HWLAT_TRACER is not set +# CONFIG_FTRACE_SYSCALLS is not set +# CONFIG_TRACER_SNAPSHOT is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_UPROBE_EVENTS=y +CONFIG_BPF_EVENTS=y +CONFIG_PROBE_EVENTS=y +# CONFIG_FTRACE_STARTUP_TEST is not set +# CONFIG_HIST_TRIGGERS is not set +# CONFIG_TRACEPOINT_BENCHMARK is not set +# CONFIG_RING_BUFFER_BENCHMARK is not set +# CONFIG_RING_BUFFER_STARTUP_TEST is not set +# CONFIG_PREEMPTIRQ_DELAY_TEST is not set +# CONFIG_TRACE_EVAL_MAP_FILE is not set +CONFIG_TRACING_EVENTS_GPIO=y +# CONFIG_DMA_API_DEBUG is not set +CONFIG_RUNTIME_TESTING_MENU=y +# CONFIG_LKDTM is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_TEST_SORT is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_RBTREE_TEST is not set +# CONFIG_INTERVAL_TREE_TEST is not set +# CONFIG_PERCPU_TEST is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_TEST_HEXDUMP is not set +# CONFIG_TEST_STRING_HELPERS is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_TEST_PRINTF is not set +# CONFIG_TEST_BITMAP is not set +# CONFIG_TEST_BITFIELD is not set +# CONFIG_TEST_UUID is not set +# CONFIG_TEST_OVERFLOW is not set +# CONFIG_TEST_RHASHTABLE is not set +# CONFIG_TEST_HASH is not set +# CONFIG_TEST_IDA is not set +# CONFIG_TEST_LKM is not set +# CONFIG_TEST_USER_COPY is not set +# CONFIG_TEST_BPF is not set +# CONFIG_FIND_BIT_BENCHMARK is not set +# CONFIG_TEST_FIRMWARE is not set +# CONFIG_TEST_SYSCTL is not set +# CONFIG_TEST_UDELAY is not set +# CONFIG_TEST_STATIC_KEYS is not set +# CONFIG_TEST_KMOD is not set +# CONFIG_MEMTEST is not set +# CONFIG_BUG_ON_DATA_CORRUPTION is not set +# CONFIG_PANIC_ON_DATA_CORRUPTION is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y +# CONFIG_UBSAN is not set +CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y +CONFIG_ARM64_PTDUMP_CORE=y +# CONFIG_ARM64_PTDUMP_DEBUGFS is not set +# CONFIG_PID_IN_CONTEXTIDR is not set +# CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET is not set +# CONFIG_DEBUG_WX is not set +CONFIG_DEBUG_ALIGN_RODATA=y +# CONFIG_ARM64_RELOC_TEST is not set +# CONFIG_ARM64_STRICT_BREAK_BEFORE_MAKE is not set +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINKS_AND_SINKS=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +# CONFIG_CORESIGHT_CATU is not set +# CONFIG_CORESIGHT_SINK_TPIU is not set +# CONFIG_CORESIGHT_SINK_ETBV10 is not set +# CONFIG_CORESIGHT_SOURCE_ETM4X is not set +CONFIG_CORESIGHT_DYNAMIC_REPLICATOR=y +CONFIG_CORESIGHT_STM=y +# CONFIG_CORESIGHT_CPU_DEBUG is not set +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_CTI_SAVE_DISABLE=y +CONFIG_CORESIGHT_OST=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +# CONFIG_CORESIGHT_TPDM_DEFAULT_ENABLE is not set +CONFIG_CORESIGHT_CSR=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_DUMMY=y +CONFIG_CORESIGHT_REMOTE_ETM=y +CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0 +CONFIG_CORESIGHT_TGU=y +# CONFIG_CORESIGHT_LINK_LATE_DISABLE is not set diff --git a/arch/arm64/configs/vendor/kona-iot-perf_defconfig b/arch/arm64/configs/vendor/kona-iot-perf_defconfig index efcf65575423..c61d35cc7713 100644 --- a/arch/arm64/configs/vendor/kona-iot-perf_defconfig +++ b/arch/arm64/configs/vendor/kona-iot-perf_defconfig @@ -396,6 +396,7 @@ CONFIG_QTI_QMI_COOLING_DEVICE=y CONFIG_QTI_THERMAL_LIMITS_DCVS=y CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y CONFIG_QTI_LIMITS_ISENSE_CDSP=y +CONFIG_QTI_THERMAL_QFPROM=y CONFIG_MFD_I2C_PMIC=y CONFIG_MFD_SPMI_PMIC=y CONFIG_REGULATOR=y diff --git a/arch/arm64/configs/vendor/kona-iot_defconfig b/arch/arm64/configs/vendor/kona-iot_defconfig index c55859f70ae2..ffd02abffd11 100644 --- a/arch/arm64/configs/vendor/kona-iot_defconfig +++ b/arch/arm64/configs/vendor/kona-iot_defconfig @@ -412,6 +412,7 @@ CONFIG_QTI_QMI_COOLING_DEVICE=y CONFIG_QTI_THERMAL_LIMITS_DCVS=y CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y CONFIG_QTI_LIMITS_ISENSE_CDSP=y +CONFIG_QTI_THERMAL_QFPROM=y CONFIG_MFD_I2C_PMIC=y CONFIG_MFD_SPMI_PMIC=y CONFIG_REGULATOR=y diff --git a/arch/arm64/configs/vendor/msm8937-perf_defconfig b/arch/arm64/configs/vendor/msm8937-perf_defconfig new file mode 100644 index 000000000000..6f3bf944a570 --- /dev/null +++ b/arch/arm64/configs/vendor/msm8937-perf_defconfig @@ -0,0 +1,651 @@ +CONFIG_LOCALVERSION="-perf" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_BLK_CGROUP=y +CONFIG_DEBUG_BLK_CGROUP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_SCHED_CORE_CTL=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_FHANDLE is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_QM215=y +CONFIG_ARCH_MSM8937=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_HZ_100=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y +# CONFIG_ARM64_VHE is not set +CONFIG_RANDOMIZE_BASE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_COMPAT=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_ENERGY_MODEL=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_PANIC_ON_REFCOUNT_ERROR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_IOSCHED_BFQ=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_CMA=y +CONFIG_ZSMALLOC=y +CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_INTERFACE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPGRE_DEMUX=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_OWNER=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y +CONFIG_L2TP=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_BPF=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_BT=y +# CONFIG_BT_BREDR is not set +# CONFIG_BT_LE is not set +CONFIG_MSM_BT_POWER=y +CONFIG_BTFM_SLIM_WCN3990=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_CRDA_SUPPORT is not set +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_DMA_CMA=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y +CONFIG_FPR_FPC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFSHCD_CMD_LOGGING=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_SCSI_UFS_CRYPTO_QTI=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y +CONFIG_DM_BOW=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +# CONFIG_NET_VENDOR_AMAZON is not set +CONFIG_MSM_RMNET_BAM=y +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPTP=y +CONFIG_PPPOL2TP=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_RTL8152=y +CONFIG_USB_USBNET=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM_HS=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_MSM_SMD_PKT=y +CONFIG_DIAG_CHAR=y +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_PINCTRL_MSM8937=y +CONFIG_PINCTRL_MSM8917=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QPNP_SMB5=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_SMB1355_SLAVE_CHARGER=y +CONFIG_QPNP_QG=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_MFD_I2C_PMIC=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_QPNP_LCDB=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_MSM_VIDC_3X_GOVERNORS=y +CONFIG_MSM_VIDC_3X_V4L2=y +CONFIG_MSM_CAMERA=y +CONFIG_MSMB_CAMERA=y +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF_V2=y +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_FB=y +CONFIG_FB_MSM=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_SONY=y +CONFIG_USB_HIDDEV=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CI13XXX_MSM=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_RMNET_BAM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_TYPEC=y +CONFIG_MMC=y +# CONFIG_PWRSEQ_EMMC is not set +# CONFIG_PWRSEQ_SIMPLE is not set +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_IPC_LOGGING=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_CQHCI_CRYPTO=y +CONFIG_MMC_CQHCI_CRYPTO_QTI=y +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_QPNP_FLASH_V2=y +CONFIG_LEDS_QPNP_VIBRATOR_LDO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_EDAC=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_ION_POOL_AUTO_REFILL=y +CONFIG_MSM_EXT_DISPLAY=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y +CONFIG_RNDIS_IPA=y +CONFIG_USB_BAM=y +CONFIG_MDSS_PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SDM_GCC_429W=y +CONFIG_CLOCK_CPU_SDM=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_MSM_RPM_SMD=y +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_QPNP_PBS=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_QCOM_DCC_V2=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_GLINK=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_QTEE_SHM_BRIDGE=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_QTI_CRYPTO_COMMON=y +CONFIG_QTI_CRYPTO_TZ=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_IIO=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_ARM_GIC_V3_ACL=y +CONFIG_QCOM_MPM=y +CONFIG_RAS=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y +CONFIG_QCOM_QFPROM=y +CONFIG_NVMEM_SPMI_SDAM=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SENSORS_SSC=y +CONFIG_QCOM_KGSL=y +CONFIG_LEGACY_ENERGY_MODEL_DT=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_CHECK_FS=y +CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_SDCARD_FS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_PAGESPAN=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y +CONFIG_STATIC_USERMODEHELPER_PATH="" +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y +CONFIG_DEBUG_MODULE_LOAD_INFO=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PANIC_ON_OOM=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_NOTIFIERS=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_IPC_LOGGING=y +CONFIG_PREEMPTIRQ_EVENTS=y +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y diff --git a/arch/arm64/configs/vendor/msm8937_defconfig b/arch/arm64/configs/vendor/msm8937_defconfig new file mode 100644 index 000000000000..bce8b5d83041 --- /dev/null +++ b/arch/arm64/configs/vendor/msm8937_defconfig @@ -0,0 +1,709 @@ +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_AUDIT=y +# CONFIG_AUDITSYSCALL is not set +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_SCHED_WALT=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +CONFIG_RCU_EXPERT=y +CONFIG_RCU_FAST_NO_HZ=y +CONFIG_RCU_NOCB_CPU=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 +CONFIG_BLK_CGROUP=y +CONFIG_DEBUG_BLK_CGROUP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_DEBUG=y +CONFIG_SCHED_CORE_CTL=y +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_FHANDLE is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_ARCH_QCOM=y +CONFIG_ARCH_QM215=y +CONFIG_ARCH_MSM8937=y +# CONFIG_ARM64_ERRATUM_1024718 is not set +CONFIG_SCHED_MC=y +CONFIG_NR_CPUS=8 +CONFIG_HZ_100=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y +# CONFIG_ARM64_VHE is not set +CONFIG_RANDOMIZE_BASE=y +CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y +CONFIG_COMPAT=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_DEBUG=y +CONFIG_ENERGY_MODEL=y +CONFIG_CPU_IDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TIMES=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_BOOST=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_MSM=y +CONFIG_MSM_TZ_LOG=y +CONFIG_ARM64_CRYPTO=y +CONFIG_CRYPTO_SHA1_ARM64_CE=y +CONFIG_CRYPTO_SHA2_ARM64_CE=y +CONFIG_CRYPTO_GHASH_ARM64_CE=y +CONFIG_CRYPTO_AES_ARM64_CE_CCM=y +CONFIG_CRYPTO_AES_ARM64_CE_BLK=y +CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y +CONFIG_PANIC_ON_REFCOUNT_ERROR=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_FORCE=y +CONFIG_MODULE_SIG_SHA512=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_INLINE_ENCRYPTION=y +CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y +CONFIG_PARTITION_ADVANCED=y +# CONFIG_IOSCHED_DEADLINE is not set +CONFIG_CFQ_GROUP_IOSCHED=y +CONFIG_IOSCHED_BFQ=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_CLEANCACHE=y +CONFIG_CMA=y +CONFIG_CMA_DEBUGFS=y +CONFIG_ZSMALLOC=y +CONFIG_HAVE_USERSPACE_LOW_MEMORY_KILLER=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_INTERFACE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NET_IPGRE_DEMUX=y +CONFIG_SYN_COOKIES=y +CONFIG_NET_IPVTI=y +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_UDP_DIAG=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +CONFIG_NETFILTER=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +CONFIG_NETFILTER_XT_TARGET_TEE=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_MATCH_BPF=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +# CONFIG_NETFILTER_XT_MATCH_L2TP is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +CONFIG_NETFILTER_XT_MATCH_OWNER=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set +CONFIG_NETFILTER_XT_MATCH_SOCKET=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_RPFILTER=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_SECURITY=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_RPFILTER=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_BROUTE=y +CONFIG_IP_SCTP=y +CONFIG_L2TP=y +CONFIG_L2TP_DEBUGFS=y +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=y +CONFIG_L2TP_ETH=y +CONFIG_BRIDGE=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SCH_INGRESS=y +CONFIG_NET_CLS_FW=y +CONFIG_NET_CLS_U32=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_FLOW=y +CONFIG_NET_CLS_BPF=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +CONFIG_DNS_RESOLVER=y +CONFIG_QRTR=y +CONFIG_QRTR_SMD=y +CONFIG_BT=y +# CONFIG_BT_BREDR is not set +# CONFIG_BT_LE is not set +CONFIG_MSM_BT_POWER=y +CONFIG_BTFM_SLIM_WCN3990=y +CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y +# CONFIG_CFG80211_CRDA_SUPPORT is not set +CONFIG_RFKILL=y +CONFIG_NFC_NQ=y +CONFIG_FW_LOADER_USER_HELPER=y +CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y +# CONFIG_FW_CACHE is not set +CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y +CONFIG_DMA_CMA=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=16 +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_HDCP_QSEECOM=y +CONFIG_QSEECOM=y +CONFIG_UID_SYS_STATS=y +CONFIG_FPR_FPC=y +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_QCOM=y +CONFIG_SCSI_UFSHCD_CMD_LOGGING=y +CONFIG_SCSI_UFS_CRYPTO=y +CONFIG_SCSI_UFS_CRYPTO_QTI=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_ANDROID_VERITY=y +CONFIG_DM_BOW=y +CONFIG_NETDEVICES=y +CONFIG_DUMMY=y +CONFIG_TUN=y +# CONFIG_NET_VENDOR_AMAZON is not set +CONFIG_MSM_RMNET_BAM=y +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPTP=y +CONFIG_PPPOL2TP=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_USB_RTL8152=y +CONFIG_USB_USBNET=y +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_WCNSS_MEM_PRE_ALLOC=y +CONFIG_CLD_LL_CORE=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_HBTP_INPUT=y +CONFIG_INPUT_QPNP_POWER_ON=y +CONFIG_INPUT_UINPUT=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +CONFIG_SERIAL_MSM=y +CONFIG_SERIAL_MSM_CONSOLE=y +CONFIG_SERIAL_MSM_HS=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_MSM_LEGACY=y +CONFIG_MSM_SMD_PKT=y +CONFIG_DIAG_CHAR=y +CONFIG_MSM_ADSPRPC=y +CONFIG_MSM_RDBG=m +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MSM_V2=y +CONFIG_SPI=y +CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y +CONFIG_SPMI=y +CONFIG_PINCTRL_MSM8937=y +CONFIG_PINCTRL_MSM8917=y +CONFIG_PINCTRL_QCOM_SPMI_PMIC=y +CONFIG_GPIO_SYSFS=y +CONFIG_POWER_RESET_QCOM=y +CONFIG_QPNP_SMB5=y +CONFIG_SMB1351_USB_CHARGER=y +CONFIG_SMB1355_SLAVE_CHARGER=y +CONFIG_QPNP_QG=y +CONFIG_THERMAL=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_THERMAL_GOV_LOW_LIMITS=y +CONFIG_CPU_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_THERMAL_TSENS=y +CONFIG_QTI_VIRTUAL_SENSOR=y +CONFIG_QTI_BCL_PMIC5=y +CONFIG_QTI_BCL_SOC_DRIVER=y +CONFIG_QTI_QMI_COOLING_DEVICE=y +CONFIG_REGULATOR_COOLING_DEVICE=y +CONFIG_MFD_I2C_PMIC=y +CONFIG_MFD_SPMI_PMIC=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_QPNP_LABIBB=y +CONFIG_REGULATOR_QPNP_LCDB=y +CONFIG_REGULATOR_MEM_ACC=y +CONFIG_REGULATOR_CPR=y +CONFIG_REGULATOR_RPM_SMD=y +CONFIG_REGULATOR_SPM=y +CONFIG_REGULATOR_STUB=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y +CONFIG_VIDEO_V4L2_SUBDEV_API=y +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_MSM_VIDC_3X_GOVERNORS=y +CONFIG_MSM_VIDC_3X_V4L2=y +CONFIG_MSM_CAMERA=y +CONFIG_MSM_CAMERA_DEBUG=y +CONFIG_MSMB_CAMERA=y +CONFIG_MSMB_CAMERA_DEBUG=y +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_CPP=y +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +CONFIG_MSM_CSI22_HEADER=y +CONFIG_MSM_CSI30_HEADER=y +CONFIG_MSM_CSI31_HEADER=y +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_EEPROM=y +CONFIG_MSM_ISPIF_V2=y +CONFIG_IMX134=y +CONFIG_IMX132=y +CONFIG_OV9724=y +CONFIG_OV5648=y +CONFIG_GC0339=y +CONFIG_OV8825=y +CONFIG_OV8865=y +CONFIG_s5k4e1=y +CONFIG_OV12830=y +CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y +CONFIG_MSMB_JPEG=y +CONFIG_MSM_FD=y +CONFIG_FB=y +CONFIG_FB_VIRTUAL=y +CONFIG_FB_MSM=y +CONFIG_FB_MSM_MDSS=y +CONFIG_FB_MSM_MDSS_WRITEBACK=y +CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y +CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +# CONFIG_BACKLIGHT_CLASS_DEVICE is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_UHID=y +CONFIG_HID_APPLE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_SONY=y +CONFIG_USB_HIDDEV=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_MON=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_ACM=y +CONFIG_USB_STORAGE=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_USBAT=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y +CONFIG_USB_STORAGE_ALAUDA=y +CONFIG_USB_STORAGE_ONETOUCH=y +CONFIG_USB_STORAGE_KARMA=y +CONFIG_USB_STORAGE_CYPRESS_ATACB=y +CONFIG_USB_SERIAL=y +CONFIG_USB_EHSET_TEST_FIXTURE=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DEBUG_FILES=y +CONFIG_USB_GADGET_DEBUG_FS=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_CI13XXX_MSM=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_RMNET_BAM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_DIAG=y +CONFIG_USB_CONFIGFS_F_CDEV=y +CONFIG_USB_CONFIGFS_F_CCID=y +CONFIG_USB_CONFIGFS_F_QDSS=y +CONFIG_USB_CONFIGFS_F_MTP=y +CONFIG_USB_CONFIGFS_F_PTP=y +CONFIG_TYPEC=y +CONFIG_MMC=y +# CONFIG_PWRSEQ_EMMC is not set +# CONFIG_PWRSEQ_SIMPLE is not set +CONFIG_MMC_BLOCK_MINORS=32 +CONFIG_MMC_BLOCK_DEFERRED_RESUME=y +CONFIG_MMC_IPC_LOGGING=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_MSM=y +CONFIG_MMC_CQHCI_CRYPTO=y +CONFIG_MMC_CQHCI_CRYPTO_QTI=y +CONFIG_LEDS_QTI_TRI_LED=y +CONFIG_LEDS_QPNP_FLASH_V2=y +CONFIG_LEDS_QPNP_VIBRATOR_LDO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_EDAC=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_QCOM_SPS_DMA=y +CONFIG_UIO=y +CONFIG_UIO_MSM_SHAREDMEM=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ION=y +CONFIG_ION_POOL_AUTO_REFILL=y +CONFIG_MSM_EXT_DISPLAY=y +CONFIG_QPNP_REVID=y +CONFIG_SPS=y +CONFIG_SPS_SUPPORT_NDP_BAM=y +CONFIG_IPA=y +CONFIG_RMNET_IPA=y +CONFIG_RNDIS_IPA=y +CONFIG_USB_BAM=y +CONFIG_MDSS_PLL=y +CONFIG_QCOM_CLK_SMD_RPM=y +CONFIG_SDM_GCC_429W=y +CONFIG_CLOCK_CPU_SDM=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_QCOM=y +CONFIG_MAILBOX=y +CONFIG_ARM_SMMU=y +CONFIG_QCOM_LAZY_MAPPING=y +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_TESTS=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_QCOM_GLINK_RPM=y +CONFIG_RPMSG_QCOM_GLINK_SMEM=y +CONFIG_RPMSG_QCOM_SMD=y +CONFIG_MSM_RPM_SMD=y +CONFIG_QCOM_CPUSS_DUMP=y +CONFIG_QCOM_RUN_QUEUE_STATS=y +CONFIG_QPNP_PBS=y +CONFIG_QCOM_QMI_HELPERS=y +CONFIG_QCOM_SMEM=y +CONFIG_QCOM_SMD_RPM=y +CONFIG_MSM_SPM=y +CONFIG_MSM_L2_SPM=y +CONFIG_QCOM_EARLY_RANDOM=y +CONFIG_QCOM_MEMORY_DUMP_V2=y +CONFIG_QCOM_SMP2P=y +CONFIG_QCOM_SMSM=y +CONFIG_MSM_PIL_MSS_QDSP6V5=y +CONFIG_QCOM_SECURE_BUFFER=y +CONFIG_MSM_TZ_SMMU=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_PIL=y +CONFIG_MSM_SYSMON_QMI_COMM=y +CONFIG_MSM_PIL_SSR_GENERIC=y +CONFIG_MSM_BOOT_STATS=y +CONFIG_QCOM_DCC_V2=y +CONFIG_MSM_CORE_HANG_DETECT=y +CONFIG_QCOM_WATCHDOG_V2=y +CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y +CONFIG_QCOM_BUS_SCALING=y +CONFIG_QCOM_GLINK=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_PM=y +CONFIG_QTI_RPM_STATS_LOG=y +CONFIG_QTEE_SHM_BRIDGE=y +CONFIG_MEM_SHARE_QMI_SERVICE=y +CONFIG_MSM_PERFORMANCE=y +CONFIG_QTI_CRYPTO_COMMON=y +CONFIG_QTI_CRYPTO_TZ=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_DEVFREQ_GOV_PASSIVE=y +CONFIG_QCOM_BIMC_BWMON=y +CONFIG_ARM_MEMLAT_MON=y +CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y +CONFIG_DEVFREQ_GOV_MEMLAT=y +CONFIG_DEVFREQ_SIMPLE_DEV=y +CONFIG_QCOM_DEVFREQ_DEVBW=y +CONFIG_IIO=y +CONFIG_PWM=y +CONFIG_PWM_QTI_LPG=y +CONFIG_ARM_GIC_V3_ACL=y +CONFIG_QCOM_MPM=y +CONFIG_RAS=y +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y +CONFIG_QCOM_QFPROM=y +CONFIG_NVMEM_SPMI_SDAM=y +CONFIG_SLIMBUS_MSM_NGD=y +CONFIG_SENSORS_SSC=y +CONFIG_QCOM_KGSL=y +CONFIG_LEGACY_ENERGY_MODEL_DT=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_CHECK_FS=y +CONFIG_F2FS_FS_ENCRYPTION=y +CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y +CONFIG_FS_VERITY=y +CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_SDCARD_FS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_HARDENED_USERCOPY_PAGESPAN=y +CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y +CONFIG_STATIC_USERMODEHELPER_PATH="" +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SMACK=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_XCBC=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_CRYPTO_DEV_QCE=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y +CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCEDEV=y +CONFIG_CRYPTO_DEV_QCOM_ICE=y +CONFIG_PRINTK_TIME=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_CONSOLE_UNHASHED_POINTERS=y +CONFIG_DEBUG_MODULE_LOAD_INFO=y +CONFIG_DEBUG_INFO=y +CONFIG_PAGE_OWNER=y +CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y +CONFIG_DEBUG_SECTION_MISMATCH=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_PAGEALLOC=y +CONFIG_SLUB_DEBUG_PANIC_ON=y +CONFIG_DEBUG_PANIC_ON_OOM=y +CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y +CONFIG_PAGE_POISONING=y +CONFIG_DEBUG_OBJECTS=y +CONFIG_DEBUG_OBJECTS_FREE=y +CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_OBJECTS_WORK=y +CONFIG_DEBUG_OBJECTS_RCU_HEAD=y +CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y +CONFIG_DEBUG_KMEMLEAK=y +CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000 +CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_WQ_WATCHDOG=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANIC_ON_SCHED_BUG=y +CONFIG_PANIC_ON_RT_THROTTLING=y +CONFIG_SCHEDSTATS=y +CONFIG_SCHED_STACK_END_CHECK=y +# CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_LOCK_TORTURE_TEST=m +CONFIG_DEBUG_SG=y +CONFIG_DEBUG_NOTIFIERS=y +CONFIG_DEBUG_CREDENTIALS=y +CONFIG_FAULT_INJECTION=y +CONFIG_FAIL_PAGE_ALLOC=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y +CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y +CONFIG_IPC_LOGGING=y +CONFIG_QCOM_RTB=y +CONFIG_QCOM_RTB_SEPARATE_CPUS=y +CONFIG_PREEMPTIRQ_EVENTS=y +CONFIG_IRQSOFF_TRACER=y +CONFIG_PREEMPT_TRACER=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_LKDTM=y +CONFIG_ATOMIC64_SELFTEST=m +CONFIG_MEMTEST=y +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_PANIC_ON_DATA_CORRUPTION=y +CONFIG_CORESIGHT=y +CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y +CONFIG_CORESIGHT_STM=y +CONFIG_CORESIGHT_CTI=y +CONFIG_CORESIGHT_TPDA=y +CONFIG_CORESIGHT_TPDM=y +CONFIG_CORESIGHT_HWEVENT=y +CONFIG_CORESIGHT_REMOTE_ETM=y diff --git a/arch/arm64/crypto/aes-modes.S b/arch/arm64/crypto/aes-modes.S index 483a7130cf0e..496c243de4ac 100644 --- a/arch/arm64/crypto/aes-modes.S +++ b/arch/arm64/crypto/aes-modes.S @@ -232,17 +232,19 @@ AES_ENTRY(aes_ctr_encrypt) bmi .Lctr1x cmn w6, #4 /* 32 bit overflow? */ bcs .Lctr1x - ldr q8, =0x30000000200000001 /* addends 1,2,3[,0] */ - dup v7.4s, w6 + add w7, w6, #1 mov v0.16b, v4.16b - add v7.4s, v7.4s, v8.4s + add w8, w6, #2 mov v1.16b, v4.16b - rev32 v8.16b, v7.16b + add w9, w6, #3 mov v2.16b, v4.16b + rev w7, w7 mov v3.16b, v4.16b - mov v1.s[3], v8.s[0] - mov v2.s[3], v8.s[1] - mov v3.s[3], v8.s[2] + rev w8, w8 + mov v1.s[3], w7 + rev w9, w9 + mov v2.s[3], w8 + mov v3.s[3], w9 ld1 {v5.16b-v7.16b}, [x20], #48 /* get 3 input blocks */ bl aes_encrypt_block4x eor v0.16b, v5.16b, v0.16b diff --git a/arch/arm64/crypto/chacha-neon-glue.c b/arch/arm64/crypto/chacha-neon-glue.c index 531567a52671..3fea0be523cd 100644 --- a/arch/arm64/crypto/chacha-neon-glue.c +++ b/arch/arm64/crypto/chacha-neon-glue.c @@ -208,6 +208,22 @@ static struct skcipher_alg algs[] = { .setkey = chacha12_setkey, .encrypt = xchacha_neon, .decrypt = xchacha_neon, + }, { + .base.cra_name = "xchacha12", + .base.cra_driver_name = "xchacha12-neon", + .base.cra_priority = 300, + .base.cra_blocksize = 1, + .base.cra_ctxsize = sizeof(struct chacha_ctx), + .base.cra_module = THIS_MODULE, + + .min_keysize = CHACHA_KEY_SIZE, + .max_keysize = CHACHA_KEY_SIZE, + .ivsize = XCHACHA_IV_SIZE, + .chunksize = CHACHA_BLOCK_SIZE, + .walksize = 4 * CHACHA_BLOCK_SIZE, + .setkey = crypto_chacha12_setkey, + .encrypt = xchacha_neon, + .decrypt = xchacha_neon, } }; diff --git a/arch/arm64/crypto/sha1-ce-glue.c b/arch/arm64/crypto/sha1-ce-glue.c index c320030cc914..ff1109252561 100644 --- a/arch/arm64/crypto/sha1-ce-glue.c +++ b/arch/arm64/crypto/sha1-ce-glue.c @@ -21,6 +21,7 @@ MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha1"); struct sha1_ce_state { struct sha1_state sst; diff --git a/arch/arm64/crypto/sha2-ce-glue.c b/arch/arm64/crypto/sha2-ce-glue.c index ddc56fa01220..e7dfd98a4bc0 100644 --- a/arch/arm64/crypto/sha2-ce-glue.c +++ b/arch/arm64/crypto/sha2-ce-glue.c @@ -21,6 +21,8 @@ MODULE_DESCRIPTION("SHA-224/SHA-256 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha224"); +MODULE_ALIAS_CRYPTO("sha256"); struct sha256_ce_state { struct sha256_state sst; diff --git a/arch/arm64/crypto/sha3-ce-glue.c b/arch/arm64/crypto/sha3-ce-glue.c index a336feac0f59..df20ab645487 100644 --- a/arch/arm64/crypto/sha3-ce-glue.c +++ b/arch/arm64/crypto/sha3-ce-glue.c @@ -22,6 +22,10 @@ MODULE_DESCRIPTION("SHA3 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha3-224"); +MODULE_ALIAS_CRYPTO("sha3-256"); +MODULE_ALIAS_CRYPTO("sha3-384"); +MODULE_ALIAS_CRYPTO("sha3-512"); asmlinkage void sha3_ce_transform(u64 *st, const u8 *data, int blocks, int md_len); diff --git a/arch/arm64/crypto/sha512-ce-glue.c b/arch/arm64/crypto/sha512-ce-glue.c index f2c5f28c622a..2871e68ae3df 100644 --- a/arch/arm64/crypto/sha512-ce-glue.c +++ b/arch/arm64/crypto/sha512-ce-glue.c @@ -22,6 +22,8 @@ MODULE_DESCRIPTION("SHA-384/SHA-512 secure hash using ARMv8 Crypto Extensions"); MODULE_AUTHOR("Ard Biesheuvel "); MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CRYPTO("sha384"); +MODULE_ALIAS_CRYPTO("sha512"); asmlinkage void sha512_ce_transform(struct sha512_state *sst, u8 const *src, int blocks); diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild index 6cd5d77b6b44..1877f29f6d97 100644 --- a/arch/arm64/include/asm/Kbuild +++ b/arch/arm64/include/asm/Kbuild @@ -27,4 +27,3 @@ generic-y += trace_clock.h generic-y += unaligned.h generic-y += user.h generic-y += vga.h -generic-y += xor.h diff --git a/arch/arm64/include/asm/atomic.h b/arch/arm64/include/asm/atomic.h index 9bca54dda75c..fec91ed5f535 100644 --- a/arch/arm64/include/asm/atomic.h +++ b/arch/arm64/include/asm/atomic.h @@ -21,13 +21,37 @@ #define __ASM_ATOMIC_H #include +#include #include #include +#include #include #ifdef __KERNEL__ +/* + * To avoid having to allocate registers that pass the counter address and + * address of the call site to the overflow handler, encode the register and + * call site offset in a dummy cbz instruction that we can decode later. + */ +#define REFCOUNT_CHECK_TAIL \ +" .subsection 1\n" \ +"33: brk " __stringify(REFCOUNT_BRK_IMM) "\n" \ +" cbz %[counter], 22b\n" /* never reached */ \ +" .previous\n" + +#define REFCOUNT_POST_CHECK_NEG \ +"22: b.mi 33f\n" \ + REFCOUNT_CHECK_TAIL + +#define REFCOUNT_POST_CHECK_NEG_OR_ZERO \ +" b.eq 33f\n" \ + REFCOUNT_POST_CHECK_NEG + +#define REFCOUNT_PRE_CHECK_ZERO(reg) "ccmp " #reg ", wzr, #8, pl\n" +#define REFCOUNT_PRE_CHECK_NONE(reg) + #define __ARM64_IN_ATOMIC_IMPL #if defined(CONFIG_ARM64_LSE_ATOMICS) && defined(CONFIG_AS_LSE) diff --git a/arch/arm64/include/asm/atomic_ll_sc.h b/arch/arm64/include/asm/atomic_ll_sc.h index f5a2d09afb38..eedf79f425dd 100644 --- a/arch/arm64/include/asm/atomic_ll_sc.h +++ b/arch/arm64/include/asm/atomic_ll_sc.h @@ -327,4 +327,54 @@ __CMPXCHG_DBL(_mb, dmb ish, l, "memory") #undef __CMPXCHG_DBL +#define REFCOUNT_OP(op, asm_op, pre, post, l) \ +__LL_SC_INLINE int \ +__LL_SC_PREFIX(__refcount_##op(int i, atomic_t *r)) \ +{ \ + unsigned int tmp; \ + int result; \ + \ + asm volatile("// refcount_" #op "\n" \ +" prfm pstl1strm, %[cval]\n" \ +"1: ldxr %w1, %[cval]\n" \ +" " #asm_op " %w[val], %w1, %w[i]\n" \ + REFCOUNT_PRE_CHECK_ ## pre (%w1) \ +" st" #l "xr %w1, %w[val], %[cval]\n" \ +" cbnz %w1, 1b\n" \ + REFCOUNT_POST_CHECK_ ## post \ + : [val] "=&r"(result), "=&r"(tmp), [cval] "+Q"(r->counter) \ + : [counter] "r"(&r->counter), [i] "Ir" (i) \ + : "cc"); \ + \ + return result; \ +} \ +__LL_SC_EXPORT(__refcount_##op); + +REFCOUNT_OP(add_lt, adds, ZERO, NEG_OR_ZERO, ); +REFCOUNT_OP(sub_lt, subs, NONE, NEG, l); +REFCOUNT_OP(sub_le, subs, NONE, NEG_OR_ZERO, l); + +__LL_SC_INLINE int +__LL_SC_PREFIX(__refcount_add_not_zero(int i, atomic_t *r)) +{ + unsigned int tmp; + int result; + + asm volatile("// refcount_add_not_zero\n" +" prfm pstl1strm, %[cval]\n" +"1: ldxr %w[val], %[cval]\n" +" cbz %w[val], 2f\n" +" adds %w[val], %w[val], %w[i]\n" +" stxr %w1, %w[val], %[cval]\n" +" cbnz %w1, 1b\n" + REFCOUNT_POST_CHECK_NEG +"2:" + : [val] "=&r" (result), "=&r" (tmp), [cval] "+Q" (r->counter) + : [counter] "r"(&r->counter), [i] "Ir" (i) + : "cc"); + + return result; +} +__LL_SC_EXPORT(__refcount_add_not_zero); + #endif /* __ASM_ATOMIC_LL_SC_H */ diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h index f9b0b09153e0..17cc898c0972 100644 --- a/arch/arm64/include/asm/atomic_lse.h +++ b/arch/arm64/include/asm/atomic_lse.h @@ -32,11 +32,12 @@ static inline void atomic_##op(int i, atomic_t *v) \ register int w0 asm ("w0") = i; \ register atomic_t *x1 asm ("x1") = v; \ \ - asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC(op), \ + asm volatile(ARM64_LSE_ATOMIC_INSN( \ + /* LSE atomics */ \ +" prfm pstl1strm, %[v]\n" \ " " #asm_op " %w[i], %[v]\n") \ : [i] "+r" (w0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS); \ + : "r" (x1)); \ } ATOMIC_OP(andnot, stclr) @@ -46,29 +47,27 @@ ATOMIC_OP(add, stadd) #undef ATOMIC_OP -#define ATOMIC_FETCH_OP(name, mb, op, asm_op, cl...) \ +#define ATOMIC_FETCH_OP(name, mb, op, asm_op) \ static inline int atomic_fetch_##op##name(int i, atomic_t *v) \ { \ register int w0 asm ("w0") = i; \ register atomic_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC(fetch_##op##name), \ /* LSE atomics */ \ +" prfm pstl1strm, %[v]\n" \ " " #asm_op #mb " %w[i], %w[i], %[v]") \ : [i] "+r" (w0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "r" (x1)); \ \ return w0; \ } #define ATOMIC_FETCH_OPS(op, asm_op) \ ATOMIC_FETCH_OP(_relaxed, , op, asm_op) \ - ATOMIC_FETCH_OP(_acquire, a, op, asm_op, "memory") \ - ATOMIC_FETCH_OP(_release, l, op, asm_op, "memory") \ - ATOMIC_FETCH_OP( , al, op, asm_op, "memory") + ATOMIC_FETCH_OP(_acquire, a, op, asm_op) \ + ATOMIC_FETCH_OP(_release, l, op, asm_op) \ + ATOMIC_FETCH_OP( , al, op, asm_op) ATOMIC_FETCH_OPS(andnot, ldclr) ATOMIC_FETCH_OPS(or, ldset) @@ -85,15 +84,13 @@ static inline int atomic_add_return##name(int i, atomic_t *v) \ register atomic_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC(add_return##name) \ - __nops(1), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " ldadd" #mb " %w[i], w30, %[v]\n" \ " add %w[i], %w[i], w30") \ : [i] "+r" (w0), [v] "+Q" (v->counter) \ : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "x30", ##cl); \ \ return w0; \ } @@ -111,41 +108,35 @@ static inline void atomic_and(int i, atomic_t *v) register atomic_t *x1 asm ("x1") = v; asm volatile(ARM64_LSE_ATOMIC_INSN( - /* LL/SC */ - __LL_SC_ATOMIC(and) - __nops(1), /* LSE atomics */ + " prfm pstl1strm, %[v]\n" " mvn %w[i], %w[i]\n" " stclr %w[i], %[v]") : [i] "+&r" (w0), [v] "+Q" (v->counter) - : "r" (x1) - : __LL_SC_CLOBBERS); + : "r" (x1)); } -#define ATOMIC_FETCH_OP_AND(name, mb, cl...) \ +#define ATOMIC_FETCH_OP_AND(name, mb) \ static inline int atomic_fetch_and##name(int i, atomic_t *v) \ { \ register int w0 asm ("w0") = i; \ register atomic_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC(fetch_and##name) \ - __nops(1), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " mvn %w[i], %w[i]\n" \ " ldclr" #mb " %w[i], %w[i], %[v]") \ : [i] "+&r" (w0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "r" (x1)); \ \ return w0; \ } ATOMIC_FETCH_OP_AND(_relaxed, ) -ATOMIC_FETCH_OP_AND(_acquire, a, "memory") -ATOMIC_FETCH_OP_AND(_release, l, "memory") -ATOMIC_FETCH_OP_AND( , al, "memory") +ATOMIC_FETCH_OP_AND(_acquire, a) +ATOMIC_FETCH_OP_AND(_release, l) +ATOMIC_FETCH_OP_AND( , al) #undef ATOMIC_FETCH_OP_AND @@ -155,15 +146,12 @@ static inline void atomic_sub(int i, atomic_t *v) register atomic_t *x1 asm ("x1") = v; asm volatile(ARM64_LSE_ATOMIC_INSN( - /* LL/SC */ - __LL_SC_ATOMIC(sub) - __nops(1), /* LSE atomics */ + " prfm pstl1strm, %[v]\n" " neg %w[i], %w[i]\n" " stadd %w[i], %[v]") : [i] "+&r" (w0), [v] "+Q" (v->counter) - : "r" (x1) - : __LL_SC_CLOBBERS); + : "r" (x1)); } #define ATOMIC_OP_SUB_RETURN(name, mb, cl...) \ @@ -173,16 +161,14 @@ static inline int atomic_sub_return##name(int i, atomic_t *v) \ register atomic_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC(sub_return##name) \ - __nops(2), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " neg %w[i], %w[i]\n" \ " ldadd" #mb " %w[i], w30, %[v]\n" \ " add %w[i], %w[i], w30") \ : [i] "+&r" (w0), [v] "+Q" (v->counter) \ : "r" (x1) \ - : __LL_SC_CLOBBERS , ##cl); \ + : "x30" , ##cl); \ \ return w0; \ } @@ -194,30 +180,27 @@ ATOMIC_OP_SUB_RETURN( , al, "memory") #undef ATOMIC_OP_SUB_RETURN -#define ATOMIC_FETCH_OP_SUB(name, mb, cl...) \ +#define ATOMIC_FETCH_OP_SUB(name, mb) \ static inline int atomic_fetch_sub##name(int i, atomic_t *v) \ { \ register int w0 asm ("w0") = i; \ register atomic_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC(fetch_sub##name) \ - __nops(1), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " neg %w[i], %w[i]\n" \ " ldadd" #mb " %w[i], %w[i], %[v]") \ : [i] "+&r" (w0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "r" (x1)); \ \ return w0; \ } ATOMIC_FETCH_OP_SUB(_relaxed, ) -ATOMIC_FETCH_OP_SUB(_acquire, a, "memory") -ATOMIC_FETCH_OP_SUB(_release, l, "memory") -ATOMIC_FETCH_OP_SUB( , al, "memory") +ATOMIC_FETCH_OP_SUB(_acquire, a) +ATOMIC_FETCH_OP_SUB(_release, l) +ATOMIC_FETCH_OP_SUB( , al) #undef ATOMIC_FETCH_OP_SUB #undef __LL_SC_ATOMIC @@ -229,11 +212,12 @@ static inline void atomic64_##op(long i, atomic64_t *v) \ register long x0 asm ("x0") = i; \ register atomic64_t *x1 asm ("x1") = v; \ \ - asm volatile(ARM64_LSE_ATOMIC_INSN(__LL_SC_ATOMIC64(op), \ + asm volatile(ARM64_LSE_ATOMIC_INSN( \ + /* LSE atomics */ \ +" prfm pstl1strm, %[v]\n" \ " " #asm_op " %[i], %[v]\n") \ : [i] "+r" (x0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS); \ + : "r" (x1)); \ } ATOMIC64_OP(andnot, stclr) @@ -243,29 +227,27 @@ ATOMIC64_OP(add, stadd) #undef ATOMIC64_OP -#define ATOMIC64_FETCH_OP(name, mb, op, asm_op, cl...) \ +#define ATOMIC64_FETCH_OP(name, mb, op, asm_op) \ static inline long atomic64_fetch_##op##name(long i, atomic64_t *v) \ { \ register long x0 asm ("x0") = i; \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC64(fetch_##op##name), \ /* LSE atomics */ \ +" prfm pstl1strm, %[v]\n" \ " " #asm_op #mb " %[i], %[i], %[v]") \ : [i] "+r" (x0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "r" (x1)); \ \ return x0; \ } #define ATOMIC64_FETCH_OPS(op, asm_op) \ ATOMIC64_FETCH_OP(_relaxed, , op, asm_op) \ - ATOMIC64_FETCH_OP(_acquire, a, op, asm_op, "memory") \ - ATOMIC64_FETCH_OP(_release, l, op, asm_op, "memory") \ - ATOMIC64_FETCH_OP( , al, op, asm_op, "memory") + ATOMIC64_FETCH_OP(_acquire, a, op, asm_op) \ + ATOMIC64_FETCH_OP(_release, l, op, asm_op) \ + ATOMIC64_FETCH_OP( , al, op, asm_op) ATOMIC64_FETCH_OPS(andnot, ldclr) ATOMIC64_FETCH_OPS(or, ldset) @@ -282,15 +264,13 @@ static inline long atomic64_add_return##name(long i, atomic64_t *v) \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC64(add_return##name) \ - __nops(1), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " ldadd" #mb " %[i], x30, %[v]\n" \ " add %[i], %[i], x30") \ : [i] "+r" (x0), [v] "+Q" (v->counter) \ : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "x30", ##cl); \ \ return x0; \ } @@ -308,41 +288,35 @@ static inline void atomic64_and(long i, atomic64_t *v) register atomic64_t *x1 asm ("x1") = v; asm volatile(ARM64_LSE_ATOMIC_INSN( - /* LL/SC */ - __LL_SC_ATOMIC64(and) - __nops(1), /* LSE atomics */ + " prfm pstl1strm, %[v]\n" " mvn %[i], %[i]\n" " stclr %[i], %[v]") : [i] "+&r" (x0), [v] "+Q" (v->counter) - : "r" (x1) - : __LL_SC_CLOBBERS); + : "r" (x1)); } -#define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \ +#define ATOMIC64_FETCH_OP_AND(name, mb) \ static inline long atomic64_fetch_and##name(long i, atomic64_t *v) \ { \ register long x0 asm ("x0") = i; \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC64(fetch_and##name) \ - __nops(1), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " mvn %[i], %[i]\n" \ " ldclr" #mb " %[i], %[i], %[v]") \ : [i] "+&r" (x0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "r" (x1)); \ \ return x0; \ } ATOMIC64_FETCH_OP_AND(_relaxed, ) -ATOMIC64_FETCH_OP_AND(_acquire, a, "memory") -ATOMIC64_FETCH_OP_AND(_release, l, "memory") -ATOMIC64_FETCH_OP_AND( , al, "memory") +ATOMIC64_FETCH_OP_AND(_acquire, a) +ATOMIC64_FETCH_OP_AND(_release, l) +ATOMIC64_FETCH_OP_AND( , al) #undef ATOMIC64_FETCH_OP_AND @@ -352,15 +326,12 @@ static inline void atomic64_sub(long i, atomic64_t *v) register atomic64_t *x1 asm ("x1") = v; asm volatile(ARM64_LSE_ATOMIC_INSN( - /* LL/SC */ - __LL_SC_ATOMIC64(sub) - __nops(1), /* LSE atomics */ + " prfm pstl1strm, %[v]\n" " neg %[i], %[i]\n" " stadd %[i], %[v]") : [i] "+&r" (x0), [v] "+Q" (v->counter) - : "r" (x1) - : __LL_SC_CLOBBERS); + : "r" (x1)); } #define ATOMIC64_OP_SUB_RETURN(name, mb, cl...) \ @@ -370,16 +341,14 @@ static inline long atomic64_sub_return##name(long i, atomic64_t *v) \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC64(sub_return##name) \ - __nops(2), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " neg %[i], %[i]\n" \ " ldadd" #mb " %[i], x30, %[v]\n" \ " add %[i], %[i], x30") \ : [i] "+&r" (x0), [v] "+Q" (v->counter) \ : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "x30", ##cl); \ \ return x0; \ } @@ -391,30 +360,27 @@ ATOMIC64_OP_SUB_RETURN( , al, "memory") #undef ATOMIC64_OP_SUB_RETURN -#define ATOMIC64_FETCH_OP_SUB(name, mb, cl...) \ +#define ATOMIC64_FETCH_OP_SUB(name, mb) \ static inline long atomic64_fetch_sub##name(long i, atomic64_t *v) \ { \ register long x0 asm ("x0") = i; \ register atomic64_t *x1 asm ("x1") = v; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_ATOMIC64(fetch_sub##name) \ - __nops(1), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " neg %[i], %[i]\n" \ " ldadd" #mb " %[i], %[i], %[v]") \ : [i] "+&r" (x0), [v] "+Q" (v->counter) \ - : "r" (x1) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "r" (x1)); \ \ return x0; \ } ATOMIC64_FETCH_OP_SUB(_relaxed, ) -ATOMIC64_FETCH_OP_SUB(_acquire, a, "memory") -ATOMIC64_FETCH_OP_SUB(_release, l, "memory") -ATOMIC64_FETCH_OP_SUB( , al, "memory") +ATOMIC64_FETCH_OP_SUB(_acquire, a) +ATOMIC64_FETCH_OP_SUB(_release, l) +ATOMIC64_FETCH_OP_SUB( , al) #undef ATOMIC64_FETCH_OP_SUB @@ -423,10 +389,8 @@ static inline long atomic64_dec_if_positive(atomic64_t *v) register long x0 asm ("x0") = (long)v; asm volatile(ARM64_LSE_ATOMIC_INSN( - /* LL/SC */ - __LL_SC_ATOMIC64(dec_if_positive) - __nops(6), /* LSE atomics */ + " prfm pstl1strm, %[v]\n" "1: ldr x30, %[v]\n" " subs %[ret], x30, #1\n" " b.lt 2f\n" @@ -437,7 +401,7 @@ static inline long atomic64_dec_if_positive(atomic64_t *v) "2:") : [ret] "+&r" (x0), [v] "+Q" (v->counter) : - : __LL_SC_CLOBBERS, "cc", "memory"); + : "x30", "cc", "memory"); return x0; } @@ -456,16 +420,14 @@ static inline unsigned long __cmpxchg_case_##name(volatile void *ptr, \ register unsigned long x2 asm ("x2") = new; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_CMPXCHG(name) \ - __nops(2), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " mov " #w "30, %" #w "[old]\n" \ " cas" #mb #sz "\t" #w "30, %" #w "[new], %[v]\n" \ " mov %" #w "[ret], " #w "30") \ : [ret] "+r" (x0), [v] "+Q" (*(unsigned long *)ptr) \ : [old] "r" (x1), [new] "r" (x2) \ - : __LL_SC_CLOBBERS, ##cl); \ + : "x30", ##cl); \ \ return x0; \ } @@ -492,7 +454,7 @@ __CMPXCHG_CASE(x, , mb_8, al, "memory") #define __LL_SC_CMPXCHG_DBL(op) __LL_SC_CALL(__cmpxchg_double##op) -#define __CMPXCHG_DBL(name, mb, cl...) \ +#define __CMPXCHG_DBL(name, mb) \ static inline long __cmpxchg_double##name(unsigned long old1, \ unsigned long old2, \ unsigned long new1, \ @@ -508,10 +470,8 @@ static inline long __cmpxchg_double##name(unsigned long old1, \ register unsigned long x4 asm ("x4") = (unsigned long)ptr; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - __LL_SC_CMPXCHG_DBL(name) \ - __nops(3), \ /* LSE atomics */ \ + " prfm pstl1strm, %[v]\n" \ " casp" #mb "\t%[old1], %[old2], %[new1], %[new2], %[v]\n"\ " eor %[old1], %[old1], %[oldval1]\n" \ " eor %[old2], %[old2], %[oldval2]\n" \ @@ -519,16 +479,87 @@ static inline long __cmpxchg_double##name(unsigned long old1, \ : [old1] "+&r" (x0), [old2] "+&r" (x1), \ [v] "+Q" (*(unsigned long *)ptr) \ : [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \ - [oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \ - : __LL_SC_CLOBBERS, ##cl); \ + [oldval1] "r" (oldval1), [oldval2] "r" (oldval2)); \ \ return x0; \ } __CMPXCHG_DBL( , ) -__CMPXCHG_DBL(_mb, al, "memory") +__CMPXCHG_DBL(_mb, al) #undef __LL_SC_CMPXCHG_DBL #undef __CMPXCHG_DBL +#define REFCOUNT_ADD_OP(op, pre, post) \ +static inline int __refcount_##op(int i, atomic_t *r) \ +{ \ + register int w0 asm ("w0") = i; \ + register atomic_t *x1 asm ("x1") = r; \ + \ + asm volatile(ARM64_LSE_ATOMIC_INSN( \ + /* LSE atomics */ \ + " prfm pstl1strm, %[cval]\n" \ + " ldadd %w[i], w30, %[cval]\n" \ + " adds %w[i], %w[i], w30\n" \ + REFCOUNT_PRE_CHECK_ ## pre (w30)) \ + REFCOUNT_POST_CHECK_ ## post \ + : [i] "+r" (w0), [cval] "+Q" (r->counter) \ + : [counter] "r"(&r->counter), "r" (x1) \ + : "x30", "cc"); \ + \ + return w0; \ +} + +REFCOUNT_ADD_OP(add_lt, ZERO, NEG_OR_ZERO); + +#define REFCOUNT_SUB_OP(op, post) \ +static inline int __refcount_##op(int i, atomic_t *r) \ +{ \ + register int w0 asm ("w0") = i; \ + register atomic_t *x1 asm ("x1") = r; \ + \ + asm volatile(ARM64_LSE_ATOMIC_INSN( \ + /* LSE atomics */ \ + " prfm pstl1strm, %[cval]\n" \ + " neg %w[i], %w[i]\n" \ + " ldaddl %w[i], w30, %[cval]\n" \ + " adds %w[i], %w[i], w30\n") \ + REFCOUNT_POST_CHECK_ ## post \ + : [i] "+r" (w0), [cval] "+Q" (r->counter) \ + : [counter] "r" (&r->counter), "r" (x1) \ + : "x30", "cc"); \ + \ + return w0; \ +} + +REFCOUNT_SUB_OP(sub_lt, NEG); +REFCOUNT_SUB_OP(sub_le, NEG_OR_ZERO); + +static inline int __refcount_add_not_zero(int i, atomic_t *r) +{ + register int result asm ("w0"); + register atomic_t *x1 asm ("x1") = r; + + asm volatile(ARM64_LSE_ATOMIC_INSN( + /* LSE atomics */ + " prfm pstl1strm, %[cval]\n" + " ldr %w0, %[cval]\n" + "1: cmp %w0, wzr\n" + " b.eq 2f\n" + " add w30, %w0, %w[i]\n" + " cas %w0, w30, %[cval]\n" + " sub w30, w30, %w[i]\n" + " cmp %w0, w30\n" + " b.ne 1b\n" + " adds %w0, w30, %w[i]\n" + "2:\n") + REFCOUNT_POST_CHECK_NEG + : "=&r" (result), [cval] "+Q" (r->counter) + : [counter] "r" (&r->counter), [i] "Ir" (i), "r" (x1) + : "x30", "cc"); + + return result; +} + #endif /* __ASM_ATOMIC_LSE_H */ + diff --git a/arch/arm64/include/asm/brk-imm.h b/arch/arm64/include/asm/brk-imm.h index 2945fe6cd863..f3a372e3636e 100644 --- a/arch/arm64/include/asm/brk-imm.h +++ b/arch/arm64/include/asm/brk-imm.h @@ -19,9 +19,11 @@ * 0x9xx: tag-based KASAN trap (allowed values 0x900 - 0x9ff) */ #define FAULT_BRK_IMM 0x100 +#define REFCOUNT_BRK_IMM 0x101 #define KGDB_DYN_DBG_BRK_IMM 0x400 #define KGDB_COMPILED_DBG_BRK_IMM 0x401 #define BUG_BRK_IMM 0x800 #define KASAN_BRK_IMM 0x900 +#define KASAN_BRK_MASK 0x0ff #endif diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h index 147f3ebe2855..0d7f06c82b5d 100644 --- a/arch/arm64/include/asm/cache.h +++ b/arch/arm64/include/asm/cache.h @@ -38,7 +38,7 @@ #define ICACHE_POLICY_VIPT 2 #define ICACHE_POLICY_PIPT 3 -#define L1_CACHE_SHIFT (6) +#define L1_CACHE_SHIFT (7) #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) /* diff --git a/arch/arm64/include/asm/checksum.h b/arch/arm64/include/asm/checksum.h index fd11e0d70e44..bb7b748e8067 100644 --- a/arch/arm64/include/asm/checksum.h +++ b/arch/arm64/include/asm/checksum.h @@ -16,7 +16,12 @@ #ifndef __ASM_CHECKSUM_H #define __ASM_CHECKSUM_H -#include +#include + +#define _HAVE_ARCH_IPV6_CSUM +__sum16 csum_ipv6_magic(const struct in6_addr *saddr, + const struct in6_addr *daddr, + __u32 len, __u8 proto, __wsum sum); static inline __sum16 csum_fold(__wsum csum) { @@ -47,6 +52,9 @@ static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) } #define ip_fast_csum ip_fast_csum +extern unsigned int do_csum(const unsigned char *buff, int len); +#define do_csum do_csum + #include #endif /* __ASM_CHECKSUM_H */ diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index d8b01c7c9cd3..a086218c00dc 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h @@ -30,23 +30,17 @@ * barrier case is generated as release+dmb for the former and * acquire+release for the latter. */ -#define __XCHG_CASE(w, sz, name, mb, nop_lse, acq, acq_lse, rel, cl) \ +#define __XCHG_CASE(w, sz, name, mb, acq, acq_lse, rel, cl) \ static inline unsigned long __xchg_case_##name(unsigned long x, \ volatile void *ptr) \ { \ unsigned long ret, tmp; \ \ asm volatile(ARM64_LSE_ATOMIC_INSN( \ - /* LL/SC */ \ - " prfm pstl1strm, %2\n" \ - "1: ld" #acq "xr" #sz "\t%" #w "0, %2\n" \ - " st" #rel "xr" #sz "\t%w1, %" #w "3, %2\n" \ - " cbnz %w1, 1b\n" \ - " " #mb, \ /* LSE atomics */ \ + " prfm pstl1strm, %2\n" \ " swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n" \ - __nops(3) \ - " " #nop_lse) \ + ) \ : "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr) \ : "r" (x) \ : cl); \ @@ -54,22 +48,22 @@ static inline unsigned long __xchg_case_##name(unsigned long x, \ return ret; \ } -__XCHG_CASE(w, b, 1, , , , , , ) -__XCHG_CASE(w, h, 2, , , , , , ) -__XCHG_CASE(w, , 4, , , , , , ) -__XCHG_CASE( , , 8, , , , , , ) -__XCHG_CASE(w, b, acq_1, , , a, a, , "memory") -__XCHG_CASE(w, h, acq_2, , , a, a, , "memory") -__XCHG_CASE(w, , acq_4, , , a, a, , "memory") -__XCHG_CASE( , , acq_8, , , a, a, , "memory") -__XCHG_CASE(w, b, rel_1, , , , , l, "memory") -__XCHG_CASE(w, h, rel_2, , , , , l, "memory") -__XCHG_CASE(w, , rel_4, , , , , l, "memory") -__XCHG_CASE( , , rel_8, , , , , l, "memory") -__XCHG_CASE(w, b, mb_1, dmb ish, nop, , a, l, "memory") -__XCHG_CASE(w, h, mb_2, dmb ish, nop, , a, l, "memory") -__XCHG_CASE(w, , mb_4, dmb ish, nop, , a, l, "memory") -__XCHG_CASE( , , mb_8, dmb ish, nop, , a, l, "memory") +__XCHG_CASE(w, b, 1, , , , , ) +__XCHG_CASE(w, h, 2, , , , , ) +__XCHG_CASE(w, , 4, , , , , ) +__XCHG_CASE( , , 8, , , , , ) +__XCHG_CASE(w, b, acq_1, , a, a, , "memory") +__XCHG_CASE(w, h, acq_2, , a, a, , "memory") +__XCHG_CASE(w, , acq_4, , a, a, , "memory") +__XCHG_CASE( , , acq_8, , a, a, , "memory") +__XCHG_CASE(w, b, rel_1, , , , l, "memory") +__XCHG_CASE(w, h, rel_2, , , , l, "memory") +__XCHG_CASE(w, , rel_4, , , , l, "memory") +__XCHG_CASE( , , rel_8, , , , l, "memory") +__XCHG_CASE(w, b, mb_1, dmb ish, , a, l, "memory") +__XCHG_CASE(w, h, mb_2, dmb ish, , a, l, "memory") +__XCHG_CASE(w, , mb_4, dmb ish, , a, l, "memory") +__XCHG_CASE( , , mb_8, dmb ish, , a, l, "memory") #undef __XCHG_CASE diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 67557249ce59..527e5554b69d 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -23,7 +23,6 @@ #define ARM64_WORKAROUND_845719 2 #define ARM64_HAS_SYSREG_GIC_CPUIF 3 #define ARM64_HAS_PAN 4 -#define ARM64_HAS_LSE_ATOMICS 5 #define ARM64_WORKAROUND_CAVIUM_23154 6 #define ARM64_WORKAROUND_834220 7 #define ARM64_HAS_NO_HW_PREFETCH 8 @@ -56,6 +55,7 @@ #define ARM64_WORKAROUND_1188873 35 #define ARM64_WORKAROUND_1542418 36 #define ARM64_WORKAROUND_1542419 37 +#define ARM64_HAS_CRC32 38 /* kabi: reserve 38 - 62 for future cpu capabilities */ #define ARM64_NCAPS 62 diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index 6bd2ab9746f8..4fcafbe4e041 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h @@ -95,18 +95,24 @@ struct step_hook { int (*fn)(struct pt_regs *regs, unsigned int esr); }; -void register_step_hook(struct step_hook *hook); -void unregister_step_hook(struct step_hook *hook); +void register_user_step_hook(struct step_hook *hook); +void unregister_user_step_hook(struct step_hook *hook); + +void register_kernel_step_hook(struct step_hook *hook); +void unregister_kernel_step_hook(struct step_hook *hook); struct break_hook { struct list_head node; - u32 esr_val; - u32 esr_mask; int (*fn)(struct pt_regs *regs, unsigned int esr); + u16 imm; + u16 mask; /* These bits are ignored when comparing with imm */ }; -void register_break_hook(struct break_hook *hook); -void unregister_break_hook(struct break_hook *hook); +void register_user_break_hook(struct break_hook *hook); +void unregister_user_break_hook(struct break_hook *hook); + +void register_kernel_break_hook(struct break_hook *hook); +void unregister_kernel_break_hook(struct break_hook *hook); u8 debug_monitors_arch(void); diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h index 7e2b3e360086..472023498d71 100644 --- a/arch/arm64/include/asm/jump_label.h +++ b/arch/arm64/include/asm/jump_label.h @@ -26,13 +26,16 @@ #define JUMP_LABEL_NOP_SIZE AARCH64_INSN_SIZE -static __always_inline bool arch_static_branch(struct static_key *key, bool branch) +static __always_inline bool arch_static_branch(struct static_key *key, + bool branch) { - asm_volatile_goto("1: nop\n\t" - ".pushsection __jump_table, \"aw\"\n\t" - ".align 3\n\t" - ".quad 1b, %l[l_yes], %c0\n\t" - ".popsection\n\t" + asm_volatile_goto( + "1: nop \n\t" + " .pushsection __jump_table, \"aw\" \n\t" + " .align 3 \n\t" + " .long 1b - ., %l[l_yes] - . \n\t" + " .quad %c0 - . \n\t" + " .popsection \n\t" : : "i"(&((char *)key)[branch]) : : l_yes); return false; @@ -40,13 +43,16 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran return true; } -static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) +static __always_inline bool arch_static_branch_jump(struct static_key *key, + bool branch) { - asm_volatile_goto("1: b %l[l_yes]\n\t" - ".pushsection __jump_table, \"aw\"\n\t" - ".align 3\n\t" - ".quad 1b, %l[l_yes], %c0\n\t" - ".popsection\n\t" + asm_volatile_goto( + "1: b %l[l_yes] \n\t" + " .pushsection __jump_table, \"aw\" \n\t" + " .align 3 \n\t" + " .long 1b - ., %l[l_yes] - . \n\t" + " .quad %c0 - . \n\t" + " .popsection \n\t" : : "i"(&((char *)key)[branch]) : : l_yes); return false; @@ -54,13 +60,5 @@ static __always_inline bool arch_static_branch_jump(struct static_key *key, bool return true; } -typedef u64 jump_label_t; - -struct jump_entry { - jump_label_t code; - jump_label_t target; - jump_label_t key; -}; - #endif /* __ASSEMBLY__ */ #endif /* __ASM_JUMP_LABEL_H */ diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index a3b6f58d188c..6d43f7901da2 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -198,6 +198,7 @@ #define CPTR_EL2_DEFAULT CPTR_EL2_RES1 /* Hyp Debug Configuration Register bits */ +#define MDCR_EL2_TTRF (1 << 19) #define MDCR_EL2_TPMS (1 << 14) #define MDCR_EL2_E2PB_MASK (UL(0x3)) #define MDCR_EL2_E2PB_SHIFT (UL(12)) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index c67cae9d5229..151e69a93e34 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -165,6 +165,7 @@ enum vcpu_sysreg { #define c2_TTBR1 (TTBR1_EL1 * 2) /* Translation Table Base Register 1 */ #define c2_TTBR1_high (c2_TTBR1 + 1) /* TTBR1 top 32 bits */ #define c2_TTBCR (TCR_EL1 * 2) /* Translation Table Base Control R. */ +#define c2_TTBCR2 (c2_TTBCR + 1) /* Translation Table Base Control R. 2 */ #define c3_DACR (DACR32_EL2 * 2)/* Domain Access Control Register */ #define c5_DFSR (ESR_EL1 * 2) /* Data Fault Status Register */ #define c5_IFSR (IFSR32_EL2 * 2)/* Instruction Fault Status Register */ diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index f150c0f44bbf..d1a79a5c5797 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -144,6 +144,9 @@ void __sysreg32_restore_state(struct kvm_vcpu *vcpu); void __debug_switch_to_guest(struct kvm_vcpu *vcpu); void __debug_switch_to_host(struct kvm_vcpu *vcpu); +void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu); +void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu); + void __fpsimd_save_state(struct user_fpsimd_state *fp_regs); void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs); diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h index 90894d8e7960..a580d0a62f9f 100644 --- a/arch/arm64/include/asm/lse.h +++ b/arch/arm64/include/asm/lse.h @@ -4,59 +4,32 @@ #if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS) -#include -#include -#include -#include -#include - #ifdef __ASSEMBLER__ .arch_extension lse -.macro alt_lse, llsc, lse - alternative_insn "\llsc", "\lse", ARM64_HAS_LSE_ATOMICS -.endm - #else /* __ASSEMBLER__ */ #ifdef CONFIG_LTO_CLANG -#define __LSE_PREAMBLE ".arch_extension lse\n" +#define __LSE_PREAMBLE ".arch armv8-a+lse\n" #else __asm__(".arch_extension lse"); #define __LSE_PREAMBLE #endif -/* Move the ll/sc atomics out-of-line */ -#define __LL_SC_INLINE notrace -#define __LL_SC_PREFIX(x) __ll_sc_##x -#define __LL_SC_EXPORT(x) EXPORT_SYMBOL(__LL_SC_PREFIX(x)) - -/* Macro for constructing calls to out-of-line ll/sc atomics */ -#define __LL_SC_CALL(op) "bl\t" __stringify(__LL_SC_PREFIX(op)) "\n" -#define __LL_SC_CLOBBERS "x16", "x17", "x30" - -/* In-line patching at runtime */ -#define ARM64_LSE_ATOMIC_INSN(llsc, lse) \ - ALTERNATIVE(llsc, __LSE_PREAMBLE lse, ARM64_HAS_LSE_ATOMICS) +#define ARM64_LSE_ATOMIC_INSN(lse) \ + __LSE_PREAMBLE lse #endif /* __ASSEMBLER__ */ #else /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ -#ifdef __ASSEMBLER__ - -.macro alt_lse, llsc, lse - \llsc -.endm - -#else /* __ASSEMBLER__ */ +#ifndef __ASSEMBLER__ #define __LL_SC_INLINE static inline #define __LL_SC_PREFIX(x) x #define __LL_SC_EXPORT(x) -#define ARM64_LSE_ATOMIC_INSN(llsc, lse) llsc - #endif /* __ASSEMBLER__ */ #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ #endif /* __ASM_LSE_H */ + diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h index 957336254fc8..0d6e01fc4206 100644 --- a/arch/arm64/include/asm/memory.h +++ b/arch/arm64/include/asm/memory.h @@ -62,8 +62,11 @@ #define PAGE_OFFSET (UL(0xffffffffffffffff) - \ (UL(1) << (VA_BITS - 1)) + 1) #define KIMAGE_VADDR (MODULES_END) +#define BPF_JIT_REGION_START (VA_START + KASAN_SHADOW_SIZE) +#define BPF_JIT_REGION_SIZE (SZ_128M) +#define BPF_JIT_REGION_END (BPF_JIT_REGION_START + BPF_JIT_REGION_SIZE) #define MODULES_END (MODULES_VADDR + MODULES_VSIZE) -#define MODULES_VADDR (VA_START + KASAN_SHADOW_SIZE) +#define MODULES_VADDR (BPF_JIT_REGION_END) #define MODULES_VSIZE (SZ_128M) #define VMEMMAP_START (PAGE_OFFSET - VMEMMAP_SIZE) #define PCI_IO_END (VMEMMAP_START - SZ_2M) diff --git a/arch/arm64/include/asm/neon-intrinsics.h b/arch/arm64/include/asm/neon-intrinsics.h new file mode 100644 index 000000000000..71abfc7612b2 --- /dev/null +++ b/arch/arm64/include/asm/neon-intrinsics.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2018 Linaro, Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_NEON_INTRINSICS_H +#define __ASM_NEON_INTRINSICS_H + +#include + +/* + * In the kernel, u64/s64 are [un]signed long long, not [un]signed long. + * So by redefining these macros to the former, we can force gcc-stdint.h + * to define uint64_t / in64_t in a compatible manner. + */ + +#ifdef __INT64_TYPE__ +#undef __INT64_TYPE__ +#define __INT64_TYPE__ long long +#endif + +#ifdef __UINT64_TYPE__ +#undef __UINT64_TYPE__ +#define __UINT64_TYPE__ unsigned long long +#endif + +/* + * genksyms chokes on the ARM NEON instrinsics system header, but we + * don't export anything it defines anyway, so just disregard when + * genksyms execute. + */ +#ifndef __GENKSYMS__ +#include +#endif + +#ifdef CONFIG_CC_IS_CLANG +#pragma clang diagnostic ignored "-Wincompatible-pointer-types" +#endif + +#endif /* __ASM_NEON_INTRINSICS_H */ diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index 45705d19f6cc..1dec74d77a96 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -108,8 +108,6 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; #define pte_valid(pte) (!!(pte_val(pte) & PTE_VALID)) #define pte_valid_not_user(pte) \ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID) -#define pte_valid_young(pte) \ - ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF)) #define pte_valid_user(pte) \ ((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER)) @@ -117,9 +115,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; * Could the pte be present in the TLB? We must check mm_tlb_flush_pending * so that we don't erroneously return false for pages that have been * remapped as PROT_NONE but are yet to be flushed from the TLB. + * Note that we can't make any assumptions based on the state of the access + * flag, since ptep_clear_flush_young() elides a DSB when invalidating the + * TLB. */ #define pte_accessible(mm, pte) \ - (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid_young(pte)) + (mm_tlb_flush_pending(mm) ? pte_present(pte) : pte_valid(pte)) /* * p??_access_permitted() is true for valid user mappings (subject to the @@ -145,13 +146,6 @@ static inline pte_t set_pte_bit(pte_t pte, pgprot_t prot) return pte; } -static inline pte_t pte_wrprotect(pte_t pte) -{ - pte = clear_pte_bit(pte, __pgprot(PTE_WRITE)); - pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); - return pte; -} - static inline pte_t pte_mkwrite(pte_t pte) { pte = set_pte_bit(pte, __pgprot(PTE_WRITE)); @@ -177,6 +171,20 @@ static inline pte_t pte_mkdirty(pte_t pte) return pte; } +static inline pte_t pte_wrprotect(pte_t pte) +{ + /* + * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY + * clear), set the PTE_DIRTY bit. + */ + if (pte_hw_dirty(pte)) + pte = pte_mkdirty(pte); + + pte = clear_pte_bit(pte, __pgprot(PTE_WRITE)); + pte = set_pte_bit(pte, __pgprot(PTE_RDONLY)); + return pte; +} + static inline pte_t pte_mkold(pte_t pte) { return clear_pte_bit(pte, __pgprot(PTE_AF)); @@ -712,12 +720,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres pte = READ_ONCE(*ptep); do { old_pte = pte; - /* - * If hardware-dirty (PTE_WRITE/DBM bit set and PTE_RDONLY - * clear), set the PTE_DIRTY bit. - */ - if (pte_hw_dirty(pte)) - pte = pte_mkdirty(pte); pte = pte_wrprotect(pte); pte_val(pte) = cmpxchg_relaxed(&pte_val(*ptep), pte_val(old_pte), pte_val(pte)); diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 462ead176240..d0bbfb2a1ddd 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -260,9 +260,7 @@ static inline void prefetchw(const void *ptr) #define ARCH_HAS_SPINLOCK_PREFETCH static inline void spin_lock_prefetch(const void *ptr) { - asm volatile(ARM64_LSE_ATOMIC_INSN( - "prfm pstl1strm, %a0", - "nop") : : "p" (ptr)); + asm volatile("prfm pstl1strm, %a0\n" : : "p" (ptr)); } #define HAVE_ARCH_PICK_MMAP_LAYOUT diff --git a/arch/arm64/include/asm/refcount.h b/arch/arm64/include/asm/refcount.h new file mode 100644 index 000000000000..3c99b29f4549 --- /dev/null +++ b/arch/arm64/include/asm/refcount.h @@ -0,0 +1,60 @@ +/* + * arm64-specific implementation of refcount_t. Based on x86 version and + * PAX_REFCOUNT from PaX/grsecurity. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_REFCOUNT_H +#define __ASM_REFCOUNT_H + +#include + +#include + +static __always_inline void refcount_add(int i, refcount_t *r) +{ + __refcount_add_lt(i, &r->refs); +} + +static __always_inline void refcount_inc(refcount_t *r) +{ + __refcount_add_lt(1, &r->refs); +} + +static __always_inline void refcount_dec(refcount_t *r) +{ + __refcount_sub_le(1, &r->refs); +} + +static __always_inline __must_check bool refcount_sub_and_test(unsigned int i, + refcount_t *r) +{ + bool ret = __refcount_sub_lt(i, &r->refs) == 0; + + if (ret) { + smp_acquire__after_ctrl_dep(); + return true; + } + return false; +} + +static __always_inline __must_check bool refcount_dec_and_test(refcount_t *r) +{ + return refcount_sub_and_test(1, r); +} + +static __always_inline __must_check bool refcount_add_not_zero(unsigned int i, + refcount_t *r) +{ + return __refcount_add_not_zero(i, &r->refs) != 0; +} + +static __always_inline __must_check bool refcount_inc_not_zero(refcount_t *r) +{ + return __refcount_add_not_zero(1, &r->refs) != 0; +} + +#endif diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index 79a9aa27957e..2d3bddcaf47c 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -101,14 +101,7 @@ extern void secondary_entry(void); extern void arch_send_call_function_single_ipi(int cpu); extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); -#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL extern void arch_send_wakeup_ipi_mask(const struct cpumask *mask); -#else -static inline void arch_send_wakeup_ipi_mask(const struct cpumask *mask) -{ - BUILD_BUG(); -} -#endif extern int __cpu_disable(void); diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h index 38116008d18b..1210e34b4c08 100644 --- a/arch/arm64/include/asm/spinlock.h +++ b/arch/arm64/include/asm/spinlock.h @@ -22,4 +22,13 @@ /* See include/linux/spinlock.h */ #define smp_mb__after_spinlock() smp_mb() +/* + * Changing this will break osq_lock() thanks to the call inside + * smp_cond_load_relaxed(). + * + * See: + * https://lore.kernel.org/lkml/20200110100612.GC2827@hirez.programming.kicks-ass.net + */ +#define vcpu_is_preempted(cpu) false + #endif /* __ASM_SPINLOCK_H */ diff --git a/arch/arm64/include/asm/word-at-a-time.h b/arch/arm64/include/asm/word-at-a-time.h index b0d708ff7f4e..a2601c1ccf43 100644 --- a/arch/arm64/include/asm/word-at-a-time.h +++ b/arch/arm64/include/asm/word-at-a-time.h @@ -64,7 +64,7 @@ static inline unsigned long find_zero(unsigned long mask) */ static inline unsigned long load_unaligned_zeropad(const void *addr) { - unsigned long ret, offset; + unsigned long ret, tmp; /* Load word from unaligned pointer addr */ asm( @@ -72,9 +72,9 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) "2:\n" " .pushsection .fixup,\"ax\"\n" " .align 2\n" - "3: and %1, %2, #0x7\n" - " bic %2, %2, #0x7\n" - " ldr %0, [%2]\n" + "3: bic %1, %2, #0x7\n" + " ldr %0, [%1]\n" + " and %1, %2, #0x7\n" " lsl %1, %1, #0x3\n" #ifndef __AARCH64EB__ " lsr %0, %0, %1\n" @@ -84,7 +84,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) " b 2b\n" " .popsection\n" _ASM_EXTABLE(1b, 3b) - : "=&r" (ret), "=&r" (offset) + : "=&r" (ret), "=&r" (tmp) : "r" (addr), "Q" (*(unsigned long *)addr)); return ret; diff --git a/arch/arm64/include/asm/xor.h b/arch/arm64/include/asm/xor.h new file mode 100644 index 000000000000..856386ad076c --- /dev/null +++ b/arch/arm64/include/asm/xor.h @@ -0,0 +1,73 @@ +/* + * arch/arm64/include/asm/xor.h + * + * Authors: Jackie Liu + * Copyright (C) 2018,Tianjin KYLIN Information Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#ifdef CONFIG_KERNEL_MODE_NEON + +extern struct xor_block_template const xor_block_inner_neon; + +static void +xor_neon_2(unsigned long bytes, unsigned long *p1, unsigned long *p2) +{ + kernel_neon_begin(); + xor_block_inner_neon.do_2(bytes, p1, p2); + kernel_neon_end(); +} + +static void +xor_neon_3(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3) +{ + kernel_neon_begin(); + xor_block_inner_neon.do_3(bytes, p1, p2, p3); + kernel_neon_end(); +} + +static void +xor_neon_4(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3, unsigned long *p4) +{ + kernel_neon_begin(); + xor_block_inner_neon.do_4(bytes, p1, p2, p3, p4); + kernel_neon_end(); +} + +static void +xor_neon_5(unsigned long bytes, unsigned long *p1, unsigned long *p2, + unsigned long *p3, unsigned long *p4, unsigned long *p5) +{ + kernel_neon_begin(); + xor_block_inner_neon.do_5(bytes, p1, p2, p3, p4, p5); + kernel_neon_end(); +} + +static struct xor_block_template xor_block_arm64 = { + .name = "arm64_neon", + .do_2 = xor_neon_2, + .do_3 = xor_neon_3, + .do_4 = xor_neon_4, + .do_5 = xor_neon_5 +}; +#undef XOR_TRY_TEMPLATES +#define XOR_TRY_TEMPLATES \ + do { \ + xor_speed(&xor_block_8regs); \ + xor_speed(&xor_block_32regs); \ + if (cpu_has_neon()) { \ + xor_speed(&xor_block_arm64);\ + } \ + } while (0) + +#endif /* ! CONFIG_KERNEL_MODE_NEON */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 1e025d6b2071..5d29f34fc3cc 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -15,7 +15,7 @@ CFLAGS_REMOVE_return_address.o = -pg arm64-obj-y := debug-monitors.o entry.o irq.o fpsimd.o \ entry-fpsimd.o process.o ptrace.o setup.o signal.o \ sys.o stacktrace.o time.o traps.o io.o vdso.o \ - hyp-stub.o psci.o cpu_ops.o insn.o \ + hyp-stub.o psci.o cpu_ops.o insn.o module.o \ return_address.o cpuinfo.o cpu_errata.o \ cpufeature.o alternative.o cacheinfo.o \ smp.o smp_spin_table.o topology.o smccc-call.o \ @@ -34,7 +34,7 @@ arm64-obj-$(CONFIG_COMPAT) += sigreturn32.o endif arm64-obj-$(CONFIG_KUSER_HELPERS) += kuser32.o arm64-obj-$(CONFIG_FUNCTION_TRACER) += ftrace.o entry-ftrace.o -arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o module.o +arm64-obj-$(CONFIG_MODULES) += arm64ksyms.o arm64-obj-$(CONFIG_ARM64_MODULE_PLTS) += module-plts.o arm64-obj-$(CONFIG_PERF_EVENTS) += perf_regs.o perf_callchain.o arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o perf_trace_counters.o \ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index cb6635fa994d..546c4d7f4ba3 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -258,7 +258,6 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = { * of support. */ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0), - ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6), ARM64_FTR_END, }; @@ -1160,18 +1159,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .cpu_enable = cpu_enable_pan, }, #endif /* CONFIG_ARM64_PAN */ -#if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS) - { - .desc = "LSE atomic instructions", - .capability = ARM64_HAS_LSE_ATOMICS, - .type = ARM64_CPUCAP_SYSTEM_FEATURE, - .matches = has_cpuid_feature, - .sys_reg = SYS_ID_AA64ISAR0_EL1, - .field_pos = ID_AA64ISAR0_ATOMICS_SHIFT, - .sign = FTR_UNSIGNED, - .min_field_value = 2, - }, -#endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ { .desc = "Software prefetching using PRFM", .capability = ARM64_HAS_NO_HW_PREFETCH, @@ -1321,6 +1308,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .cpu_enable = cpu_enable_hw_dbm, }, #endif + { + .desc = "CRC32 instructions", + .capability = ARM64_HAS_CRC32, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, + .matches = has_cpuid_feature, + .sys_reg = SYS_ID_AA64ISAR0_EL1, + .field_pos = ID_AA64ISAR0_CRC32_SHIFT, + .min_field_value = 1, + }, #ifdef CONFIG_ARM64_SSBD { .desc = "Speculative Store Bypassing Safe (SSBS)", diff --git a/arch/arm64/kernel/crash_dump.c b/arch/arm64/kernel/crash_dump.c index f46d57c31443..76905a258550 100644 --- a/arch/arm64/kernel/crash_dump.c +++ b/arch/arm64/kernel/crash_dump.c @@ -67,5 +67,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf, ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos) { memcpy(buf, phys_to_virt((phys_addr_t)*ppos), count); + *ppos += count; + return count; } diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index 501e835c6500..dcece78251ec 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -64,7 +64,7 @@ NOKPROBE_SYMBOL(mdscr_read); * Allow root to disable self-hosted debug from userspace. * This is useful if you want to connect an external JTAG debugger. */ -static bool debug_enabled = true; +static bool debug_enabled; static int create_debug_debugfs_entry(void) { @@ -167,25 +167,46 @@ NOKPROBE_SYMBOL(clear_user_regs_spsr_ss); #define set_regs_spsr_ss(r) set_user_regs_spsr_ss(&(r)->user_regs) #define clear_regs_spsr_ss(r) clear_user_regs_spsr_ss(&(r)->user_regs) -/* EL1 Single Step Handler hooks */ -static LIST_HEAD(step_hook); -static DEFINE_SPINLOCK(step_hook_lock); +static DEFINE_SPINLOCK(debug_hook_lock); +static LIST_HEAD(user_step_hook); +static LIST_HEAD(kernel_step_hook); -void register_step_hook(struct step_hook *hook) +static void register_debug_hook(struct list_head *node, struct list_head *list) { - spin_lock(&step_hook_lock); - list_add_rcu(&hook->node, &step_hook); - spin_unlock(&step_hook_lock); + spin_lock(&debug_hook_lock); + list_add_rcu(node, list); + spin_unlock(&debug_hook_lock); + } -void unregister_step_hook(struct step_hook *hook) +static void unregister_debug_hook(struct list_head *node) { - spin_lock(&step_hook_lock); - list_del_rcu(&hook->node); - spin_unlock(&step_hook_lock); + spin_lock(&debug_hook_lock); + list_del_rcu(node); + spin_unlock(&debug_hook_lock); synchronize_rcu(); } +void register_user_step_hook(struct step_hook *hook) +{ + register_debug_hook(&hook->node, &user_step_hook); +} + +void unregister_user_step_hook(struct step_hook *hook) +{ + unregister_debug_hook(&hook->node); +} + +void register_kernel_step_hook(struct step_hook *hook) +{ + register_debug_hook(&hook->node, &kernel_step_hook); +} + +void unregister_kernel_step_hook(struct step_hook *hook) +{ + unregister_debug_hook(&hook->node); +} + /* * Call registered single step handlers * There is no Syndrome info to check for determining the handler. @@ -195,11 +216,14 @@ void unregister_step_hook(struct step_hook *hook) static int call_step_hook(struct pt_regs *regs, unsigned int esr) { struct step_hook *hook; + struct list_head *list; int retval = DBG_HOOK_ERROR; + list = user_mode(regs) ? &user_step_hook : &kernel_step_hook; + rcu_read_lock(); - list_for_each_entry_rcu(hook, &step_hook, node) { + list_for_each_entry_rcu(hook, list, node) { retval = hook->fn(regs, esr); if (retval == DBG_HOOK_HANDLED) break; @@ -278,33 +302,44 @@ NOKPROBE_SYMBOL(single_step_handler); * hit within breakpoint handler, especically in kprobes. * Use reader/writer locks instead of plain spinlock. */ -static LIST_HEAD(break_hook); -static DEFINE_SPINLOCK(break_hook_lock); +static LIST_HEAD(user_break_hook); +static LIST_HEAD(kernel_break_hook); -void register_break_hook(struct break_hook *hook) +void register_user_break_hook(struct break_hook *hook) { - spin_lock(&break_hook_lock); - list_add_rcu(&hook->node, &break_hook); - spin_unlock(&break_hook_lock); + register_debug_hook(&hook->node, &user_break_hook); } -void unregister_break_hook(struct break_hook *hook) +void unregister_user_break_hook(struct break_hook *hook) { - spin_lock(&break_hook_lock); - list_del_rcu(&hook->node); - spin_unlock(&break_hook_lock); - synchronize_rcu(); + unregister_debug_hook(&hook->node); +} + +void register_kernel_break_hook(struct break_hook *hook) +{ + register_debug_hook(&hook->node, &kernel_break_hook); +} + +void unregister_kernel_break_hook(struct break_hook *hook) +{ + unregister_debug_hook(&hook->node); } static int call_break_hook(struct pt_regs *regs, unsigned int esr) { struct break_hook *hook; + struct list_head *list; int (*fn)(struct pt_regs *regs, unsigned int esr) = NULL; + list = user_mode(regs) ? &user_break_hook : &kernel_break_hook; + rcu_read_lock(); - list_for_each_entry_rcu(hook, &break_hook, node) - if ((esr & hook->esr_mask) == hook->esr_val) + list_for_each_entry_rcu(hook, list, node) { + unsigned int comment = esr & BRK64_ESR_MASK; + + if ((comment & ~hook->mask) == hook->imm) fn = hook->fn; + } rcu_read_unlock(); return fn ? fn(regs, esr) : DBG_HOOK_ERROR; diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 285be7332414..f98ca13224d8 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -332,6 +332,21 @@ alternative_if ARM64_WORKAROUND_845719 alternative_else_nop_endif #endif 3: +#ifdef CONFIG_ARM64_ERRATUM_1188873 +alternative_if_not ARM64_WORKAROUND_1188873 + b 4f +alternative_else_nop_endif + /* + * if (x22.mode32 == cntkctl_el1.el0vcten) + * cntkctl_el1.el0vcten = ~cntkctl_el1.el0vcten + */ + mrs x1, cntkctl_el1 + eon x0, x1, x22, lsr #3 + tbz x0, #1, 4f + eor x1, x1, #2 // ARCH_TIMER_USR_VCT_ACCESS_EN + msr cntkctl_el1, x1 +4: +#endif apply_ssbd 0, x0, x1 .endif @@ -362,11 +377,11 @@ alternative_else_nop_endif .if \el == 0 alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 - bne 4f + bne 5f msr far_el1, x30 tramp_alias x30, tramp_exit_native br x30 -4: +5: tramp_alias x30, tramp_exit_compat br x30 #endif diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 416c9ac88975..543785432c1e 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -960,6 +960,7 @@ __primary_switch: tlbi vmalle1 // Remove any stale TLB entries dsb nsh + isb msr sctlr_el1, x19 // re-enable the MMU isb diff --git a/arch/arm64/kernel/jump_label.c b/arch/arm64/kernel/jump_label.c index b90754aebd12..1eff270e8861 100644 --- a/arch/arm64/kernel/jump_label.c +++ b/arch/arm64/kernel/jump_label.c @@ -23,12 +23,12 @@ void arch_jump_label_transform(struct jump_entry *entry, enum jump_label_type type) { - void *addr = (void *)entry->code; + void *addr = (void *)jump_entry_code(entry); u32 insn; if (type == JUMP_LABEL_JMP) { - insn = aarch64_insn_gen_branch_imm(entry->code, - entry->target, + insn = aarch64_insn_gen_branch_imm(jump_entry_code(entry), + jump_entry_target(entry), AARCH64_INSN_BRANCH_NOLINK); } else { insn = aarch64_insn_gen_nop(); diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c index 8815b5457dd0..b3a124bfe72d 100644 --- a/arch/arm64/kernel/kgdb.c +++ b/arch/arm64/kernel/kgdb.c @@ -275,15 +275,13 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) NOKPROBE_SYMBOL(kgdb_step_brk_fn); static struct break_hook kgdb_brkpt_hook = { - .esr_mask = 0xffffffff, - .esr_val = (u32)ESR_ELx_VAL_BRK64(KGDB_DYN_DBG_BRK_IMM), - .fn = kgdb_brk_fn + .fn = kgdb_brk_fn, + .imm = KGDB_DYN_DBG_BRK_IMM, }; static struct break_hook kgdb_compiled_brkpt_hook = { - .esr_mask = 0xffffffff, - .esr_val = (u32)ESR_ELx_VAL_BRK64(KGDB_COMPILED_DBG_BRK_IMM), - .fn = kgdb_compiled_brk_fn + .fn = kgdb_compiled_brk_fn, + .imm = KGDB_COMPILED_DBG_BRK_IMM, }; static struct step_hook kgdb_step_hook = { @@ -344,9 +342,9 @@ int kgdb_arch_init(void) if (ret != 0) return ret; - register_break_hook(&kgdb_brkpt_hook); - register_break_hook(&kgdb_compiled_brkpt_hook); - register_step_hook(&kgdb_step_hook); + register_kernel_break_hook(&kgdb_brkpt_hook); + register_kernel_break_hook(&kgdb_compiled_brkpt_hook); + register_kernel_step_hook(&kgdb_step_hook); return 0; } @@ -357,9 +355,9 @@ int kgdb_arch_init(void) */ void kgdb_arch_exit(void) { - unregister_break_hook(&kgdb_brkpt_hook); - unregister_break_hook(&kgdb_compiled_brkpt_hook); - unregister_step_hook(&kgdb_step_hook); + unregister_kernel_break_hook(&kgdb_brkpt_hook); + unregister_kernel_break_hook(&kgdb_compiled_brkpt_hook); + unregister_kernel_step_hook(&kgdb_step_hook); unregister_die_notifier(&kgdb_notifier); } diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 8644f154ea7a..f04537c930b3 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -30,6 +30,7 @@ #include #include +#if defined(CONFIG_MODULES) || defined(CONFIG_BPF_JIT) void *module_alloc(unsigned long size) { u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; @@ -72,6 +73,13 @@ void *module_alloc(unsigned long size) return p; } +void module_memfree(void *module_region) +{ + vfree(module_region); +} +#endif /* CONFIG_MODULES || CONFIG_BPF_JIT */ + +#ifdef CONFIG_MODULES enum aarch64_reloc_op { RELOC_OP_NONE, RELOC_OP_ABS, @@ -463,3 +471,4 @@ int module_finalize(const Elf_Ehdr *hdr, return 0; } +#endif /* CONFIG_MODULES */ diff --git a/arch/arm64/kernel/module.lds b/arch/arm64/kernel/module.lds index 22e36a21c113..09a0eef71d12 100644 --- a/arch/arm64/kernel/module.lds +++ b/arch/arm64/kernel/module.lds @@ -1,5 +1,5 @@ SECTIONS { - .plt (NOLOAD) : { BYTE(0) } - .init.plt (NOLOAD) : { BYTE(0) } - .text.ftrace_trampoline (NOLOAD) : { BYTE(0) } + .plt 0 (NOLOAD) : { BYTE(0) } + .init.plt 0 (NOLOAD) : { BYTE(0) } + .text.ftrace_trampoline 0 (NOLOAD) : { BYTE(0) } } diff --git a/arch/arm64/kernel/probes/uprobes.c b/arch/arm64/kernel/probes/uprobes.c index 636ca0119c0e..17ba65140cbb 100644 --- a/arch/arm64/kernel/probes/uprobes.c +++ b/arch/arm64/kernel/probes/uprobes.c @@ -41,7 +41,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, /* TODO: Currently we do not support AARCH32 instruction probing */ if (mm->context.flags & MMCF_AARCH32) - return -ENOTSUPP; + return -EOPNOTSUPP; else if (!IS_ALIGNED(addr, AARCH64_INSN_SIZE)) return -EINVAL; @@ -195,8 +195,7 @@ static int uprobe_single_step_handler(struct pt_regs *regs, /* uprobe breakpoint handler hook */ static struct break_hook uprobes_break_hook = { - .esr_mask = BRK64_ESR_MASK, - .esr_val = BRK64_ESR_UPROBES, + .imm = BRK64_ESR_UPROBES, .fn = uprobe_breakpoint_handler, }; @@ -207,8 +206,8 @@ static struct step_hook uprobes_step_hook = { static int __init arch_init_uprobes(void) { - register_break_hook(&uprobes_break_hook); - register_step_hook(&uprobes_step_hook); + register_user_break_hook(&uprobes_break_hook); + register_user_step_hook(&uprobes_step_hook); return 0; } diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index e5ace4b93f48..f03982a7cacb 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -64,7 +64,7 @@ #ifdef CONFIG_STACKPROTECTOR #include -unsigned long __stack_chk_guard __read_mostly; +__visible unsigned long __stack_chk_guard __read_mostly; EXPORT_SYMBOL(__stack_chk_guard); #endif diff --git a/arch/arm64/kernel/psci.c b/arch/arm64/kernel/psci.c index 73d5ac36803d..cd0638ed1113 100644 --- a/arch/arm64/kernel/psci.c +++ b/arch/arm64/kernel/psci.c @@ -70,7 +70,6 @@ static int cpu_psci_cpu_disable(unsigned int cpu) static void cpu_psci_cpu_die(unsigned int cpu) { - int ret; /* * There are no known implementations of PSCI actually using the * power state field, pass a sensible default for now. @@ -78,9 +77,7 @@ static void cpu_psci_cpu_die(unsigned int cpu) u32 state = PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT; - ret = psci_ops.cpu_off(state); - - pr_crit("unable to power off CPU%u (%d)\n", cpu, ret); + psci_ops.cpu_off(state); } static int cpu_psci_cpu_kill(unsigned int cpu) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index e621b256f208..b154c5fd4ec3 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -821,12 +821,10 @@ void arch_send_call_function_single_ipi(int cpu) smp_cross_call_common(cpumask_of(cpu), IPI_CALL_FUNC); } -#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL void arch_send_wakeup_ipi_mask(const struct cpumask *mask) { smp_cross_call_common(mask, IPI_WAKEUP); } -#endif #ifdef CONFIG_IRQ_WORK void arch_irq_work_raise(void) @@ -946,13 +944,8 @@ void handle_IPI(int ipinr, struct pt_regs *regs) break; #endif -#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL case IPI_WAKEUP: - WARN_ONCE(!acpi_parking_protocol_valid(cpu), - "CPU%u: Wake-up IPI outside the ACPI parking protocol\n", - cpu); break; -#endif default: pr_crit("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c index 1457a0ba83db..f2d2dbbbfca2 100644 --- a/arch/arm64/kernel/syscall.c +++ b/arch/arm64/kernel/syscall.c @@ -102,8 +102,8 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr, regs->syscallno = scno; cortex_a76_erratum_1463225_svc_handler(); + user_exit_irqoff(); local_daif_restore(DAIF_PROCCTX); - user_exit(); if (has_syscall_work(flags)) { /* set default errno for user-issued syscall(-1) */ diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 3ec5561ac9b1..1ec429d92c2e 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -983,9 +983,8 @@ static int bug_handler(struct pt_regs *regs, unsigned int esr) } static struct break_hook bug_break_hook = { - .esr_val = 0xf2000000 | BUG_BRK_IMM, - .esr_mask = 0xffffffff, .fn = bug_handler, + .imm = BUG_BRK_IMM, }; #ifdef CONFIG_KASAN_SW_TAGS @@ -1034,9 +1033,9 @@ static int kasan_handler(struct pt_regs *regs, unsigned int esr) #define KASAN_ESR_MASK 0xffffff00 static struct break_hook kasan_break_hook = { - .esr_val = KASAN_ESR_VAL, - .esr_mask = KASAN_ESR_MASK, .fn = kasan_handler, + .imm = KASAN_BRK_IMM, + .mask = KASAN_BRK_MASK, }; #endif @@ -1054,11 +1053,48 @@ int __init early_brk64(unsigned long addr, unsigned int esr, return bug_handler(regs, esr) != DBG_HOOK_HANDLED; } +static int refcount_overflow_handler(struct pt_regs *regs, unsigned int esr) +{ + u32 dummy_cbz = le32_to_cpup((__le32 *)(regs->pc + 4)); + bool zero = regs->pstate & PSR_Z_BIT; + u32 rt; + + /* + * Find the register that holds the counter address from the + * dummy 'cbz' instruction that follows the 'brk' instruction + * that sent us here. + */ + rt = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, dummy_cbz); + + /* First unconditionally saturate the refcount. */ + *(int *)regs->regs[rt] = INT_MIN / 2; + + /* + * This function has been called because either a negative refcount + * value was seen by any of the refcount functions, or a zero + * refcount value was seen by refcount_{add,dec}(). + */ + + /* point pc to the branch instruction that detected the overflow */ + regs->pc += 4 + aarch64_get_branch_offset(dummy_cbz); + refcount_error_report(regs, zero ? "hit zero" : "overflow"); + + /* advance pc and proceed */ + regs->pc += 4; + return DBG_HOOK_HANDLED; +} + +static struct break_hook refcount_break_hook = { + .fn = refcount_overflow_handler, + .imm = REFCOUNT_BRK_IMM, +}; + /* This registration must happen early, before debug_traps_init(). */ void __init trap_init(void) { - register_break_hook(&bug_break_hook); + register_kernel_break_hook(&bug_break_hook); #ifdef CONFIG_KASAN_SW_TAGS - register_break_hook(&kasan_break_hook); + register_kernel_break_hook(&kasan_break_hook); #endif + register_kernel_break_hook(&refcount_break_hook); } diff --git a/arch/arm64/kernel/vdso/Makefile b/arch/arm64/kernel/vdso/Makefile index 7155a6ff320d..3a458a191c0f 100644 --- a/arch/arm64/kernel/vdso/Makefile +++ b/arch/arm64/kernel/vdso/Makefile @@ -19,7 +19,7 @@ obj-vdso := $(addprefix $(obj)/, $(obj-vdso)) ldflags-y := -shared -nostdlib -soname=linux-vdso.so.1 --hash-style=sysv \ --build-id -n -T -ccflags-y += $(DISABLE_LTO) +ccflags-y += $(call cc-option, -fno-whole-program) ccflags-y := -fno-common -fno-builtin -fno-stack-protector -ffixed-x18 ccflags-y += -DDISABLE_BRANCH_PROFILING @@ -27,13 +27,18 @@ ccflags-y += -DDISABLE_BRANCH_PROFILING VDSO_LDFLAGS := -Bsymbolic CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) -Os $(CC_FLAGS_SCS) -KBUILD_CFLAGS += $(DISABLE_LTO) +KBUILD_CFLAGS += $ KASAN_SANITIZE := n UBSAN_SANITIZE := n OBJECT_FILES_NON_STANDARD := y KCOV_INSTRUMENT := n -CFLAGS_vgettimeofday.o = -O2 -mcmodel=tiny +ifeq ($(cc-name),clang) +CFLAGS_vgettimeofday.o = -O3 -fasynchronous-unwind-tables +else +CFLAGS_vgettimeofday.o = -O2 -fasynchronous-unwind-tables +endif +CFLAGS_vgettimeofday.o = -O3 -mcmodel=tiny -fasynchronous-unwind-tables ifneq ($(c-gettimeofday-y),) CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile index 8fddb291c0e2..41bc73f31ae1 100644 --- a/arch/arm64/kernel/vdso32/Makefile +++ b/arch/arm64/kernel/vdso32/Makefile @@ -15,7 +15,7 @@ COMPAT_GCC_TOOLCHAIN := $(realpath $(COMPAT_GCC_TOOLCHAIN_DIR)/..) CC_COMPAT_CLANG_FLAGS := --target=$(notdir $(CROSS_COMPILE_COMPAT:%-=%)) CC_COMPAT_CLANG_FLAGS += --prefix=$(COMPAT_GCC_TOOLCHAIN_DIR) -CC_COMPAT_CLANG_FLAGS += -no-integrated-as -Qunused-arguments +CC_COMPAT_CLANG_FLAGS += -Qunused-arguments ifneq ($(COMPAT_GCC_TOOLCHAIN),) CC_COMPAT_CLANG_FLAGS += --gcc-toolchain=$(COMPAT_GCC_TOOLCHAIN) endif @@ -91,7 +91,11 @@ VDSO_CFLAGS += -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -Werror-implicit-function-declaration \ -Wno-format-security \ -std=gnu89 +ifeq ($(cc-name),clang) +VDSO_CFLAGS += -O3 +else VDSO_CFLAGS += -O2 +endif # Some useful compiler-dependent flags from top-level Makefile VDSO_CFLAGS += $(call cc32-option,-Wdeclaration-after-statement,) VDSO_CFLAGS += $(call cc32-option,-Wno-pointer-sign) @@ -202,7 +206,7 @@ quiet_cmd_vdsosym = VDSOSYM $@ cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ # Install commands for the unstripped file -quiet_cmd_vdso_install = INSTALL $@ +quiet_cmd_vdso_install = INSTALL32 $@ cmd_vdso_install = cp $(obj)/$@.dbg $(MODLIB)/vdso/vdso32.so vdso.so: $(obj)/vdso.so.dbg diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 86a57e2fa9af..d34dae685351 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -76,10 +76,6 @@ jiffies = jiffies_64; #define TRAMP_TEXT #endif -#define RTIC_BSS \ - . = ALIGN(PAGE_SIZE); \ - KEEP(*(.bss.rtic)); \ - . = ALIGN(PAGE_SIZE); \ /* * The size of the PE/COFF section that covers the kernel image, which * runs from stext to _edata, must be a round multiple of the PE/COFF @@ -163,11 +159,11 @@ SECTIONS . = ALIGN(4); .altinstructions : { __alt_instructions = .; - *(.altinstructions) + KEEP(*(.altinstructions)) __alt_instructions_end = .; } .altinstr_replacement : { - *(.altinstr_replacement) + KEEP(*(.altinstr_replacement)) } . = ALIGN(PAGE_SIZE); @@ -260,10 +256,6 @@ SECTIONS STABS_DEBUG HEAD_SYMBOLS - - .bss : { /* bss segment */ - RTIC_BSS - } } /* diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 4e722d73a3c3..3606f6b89094 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -100,6 +100,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) * - Debug ROM Address (MDCR_EL2_TDRA) * - OS related registers (MDCR_EL2_TDOSA) * - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB) + * - Self-hosted Trace Filter controls (MDCR_EL2_TTRF) * * Additionally, KVM only traps guest accesses to the debug registers if * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY @@ -123,6 +124,7 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK; vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | MDCR_EL2_TPMS | + MDCR_EL2_TTRF | MDCR_EL2_TPMCR | MDCR_EL2_TDRA | MDCR_EL2_TDOSA); diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c index 50009766e5e5..3c5414633bb7 100644 --- a/arch/arm64/kvm/hyp/debug-sr.c +++ b/arch/arm64/kvm/hyp/debug-sr.c @@ -149,6 +149,21 @@ static void __hyp_text __debug_restore_state(struct kvm_vcpu *vcpu, write_sysreg(ctxt->sys_regs[MDCCINT_EL1], mdccint_el1); } +void __hyp_text __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu) +{ + /* + * Non-VHE: Disable and flush SPE data generation + * VHE: The vcpu can run, but it can't hide. + */ + __debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1); + +} + +void __hyp_text __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu) +{ + __debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1); +} + void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu) { struct kvm_cpu_context *host_ctxt; @@ -156,13 +171,6 @@ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu) struct kvm_guest_debug_arch *host_dbg; struct kvm_guest_debug_arch *guest_dbg; - /* - * Non-VHE: Disable and flush SPE data generation - * VHE: The vcpu can run, but it can't hide. - */ - if (!has_vhe()) - __debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1); - if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)) return; @@ -182,8 +190,6 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu) struct kvm_guest_debug_arch *host_dbg; struct kvm_guest_debug_arch *guest_dbg; - if (!has_vhe()) - __debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1); if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)) return; diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 15312e429b7d..1d16ce0b7e0d 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -560,6 +560,7 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) guest_ctxt = &vcpu->arch.ctxt; __sysreg_save_state_nvhe(host_ctxt); + __debug_save_host_buffers_nvhe(vcpu); __activate_traps(vcpu); __activate_vm(kern_hyp_va(vcpu->kvm)); @@ -599,11 +600,12 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) __fpsimd_save_fpexc32(vcpu); + __debug_switch_to_host(vcpu); /* * This must come after restoring the host sysregs, since a non-VHE * system may enable SPE here and make use of the TTBRs. */ - __debug_switch_to_host(vcpu); + __debug_restore_host_buffers_nvhe(vcpu); return exit_code; } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index b53d0ebb87fc..fe97b2ad82b9 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -619,6 +619,10 @@ static void reset_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) { u64 pmcr, val; + /* No PMU available, PMCR_EL0 may UNDEF... */ + if (!kvm_arm_support_pmu_v3()) + return; + pmcr = read_sysreg(pmcr_el0); /* * Writable bits of PMCR_EL0 (ARMV8_PMU_PMCR_MASK) are reset to UNKNOWN @@ -1661,6 +1665,7 @@ static const struct sys_reg_desc cp15_regs[] = { { Op1( 0), CRn( 2), CRm( 0), Op2( 0), access_vm_reg, NULL, c2_TTBR0 }, { Op1( 0), CRn( 2), CRm( 0), Op2( 1), access_vm_reg, NULL, c2_TTBR1 }, { Op1( 0), CRn( 2), CRm( 0), Op2( 2), access_vm_reg, NULL, c2_TTBCR }, + { Op1( 0), CRn( 2), CRm( 0), Op2( 3), access_vm_reg, NULL, c2_TTBCR2 }, { Op1( 0), CRn( 3), CRm( 0), Op2( 0), access_vm_reg, NULL, c3_DACR }, { Op1( 0), CRn( 5), CRm( 0), Op2( 0), access_vm_reg, NULL, c5_DFSR }, { Op1( 0), CRn( 5), CRm( 0), Op2( 1), access_vm_reg, NULL, c5_IFSR }, diff --git a/arch/arm64/lib/Makefile b/arch/arm64/lib/Makefile index 33ce9a5c324b..7a6ea1b151ba 100644 --- a/arch/arm64/lib/Makefile +++ b/arch/arm64/lib/Makefile @@ -1,32 +1,16 @@ # SPDX-License-Identifier: GPL-2.0 lib-y := clear_user.o delay.o copy_from_user.o \ copy_to_user.o copy_in_user.o copy_page.o \ - clear_page.o memchr.o memcpy.o memmove.o memset.o \ - memcmp.o strcmp.o strncmp.o strlen.o strnlen.o \ - strchr.o strrchr.o tishift.o + clear_page.o csum.o memchr.o memcpy.o memmove.o \ + memset.o memcmp.o strcmp.o strncmp.o strlen.o \ + strnlen.o strchr.o strrchr.o tishift.o -# Tell the compiler to treat all general purpose registers (with the -# exception of the IP registers, which are already handled by the caller -# in case of a PLT) as callee-saved, which allows for efficient runtime -# patching of the bl instruction in the caller with an atomic instruction -# when supported by the CPU. Result and argument registers are handled -# correctly, based on the function prototype. -ifeq ($(CONFIG_LD_IS_LLD), y) -# https://bugs.llvm.org/show_bug.cgi?id=35841 -obj-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o -else -lib-$(CONFIG_ARM64_LSE_ATOMICS) += atomic_ll_sc.o +ifeq ($(CONFIG_KERNEL_MODE_NEON), y) +obj-$(CONFIG_XOR_BLOCKS) += xor-neon.o +CFLAGS_REMOVE_xor-neon.o += -mgeneral-regs-only +CFLAGS_xor-neon.o += -ffreestanding endif -CFLAGS_atomic_ll_sc.o := -ffixed-x1 -ffixed-x2 \ - -ffixed-x3 -ffixed-x4 -ffixed-x5 -ffixed-x6 \ - -ffixed-x7 -fcall-saved-x8 -fcall-saved-x9 \ - -fcall-saved-x10 -fcall-saved-x11 -fcall-saved-x12 \ - -fcall-saved-x13 -fcall-saved-x14 -fcall-saved-x15 \ - -fcall-saved-x18 -fomit-frame-pointer -CFLAGS_REMOVE_atomic_ll_sc.o := -pg -GCOV_PROFILE_atomic_ll_sc.o := n -KASAN_SANITIZE_atomic_ll_sc.o := n -KCOV_INSTRUMENT_atomic_ll_sc.o := n -UBSAN_SANITIZE_atomic_ll_sc.o := n lib-$(CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE) += uaccess_flushcache.o + +obj-$(CONFIG_CRC32) += crc32.o diff --git a/arch/arm64/lib/atomic_ll_sc.c b/arch/arm64/lib/atomic_ll_sc.c deleted file mode 100644 index b0c538b0da28..000000000000 --- a/arch/arm64/lib/atomic_ll_sc.c +++ /dev/null @@ -1,3 +0,0 @@ -#include -#define __ARM64_IN_ATOMIC_IMPL -#include diff --git a/arch/arm64/lib/copy_template.S b/arch/arm64/lib/copy_template.S index f5b9210f1c83..7d2e550d4282 100644 --- a/arch/arm64/lib/copy_template.S +++ b/arch/arm64/lib/copy_template.S @@ -51,6 +51,7 @@ C_h .req x12 D_l .req x13 D_h .req x14 + prfm pldl1strm, [src, #(1*L1_CACHE_BYTES)] mov dst, dstin cmp count, #16 /*When memory length is less than 16, the accessed are not aligned.*/ @@ -181,6 +182,7 @@ D_h .req x14 ldp1 C_l, C_h, src, #16 stp1 D_l, D_h, dst, #16 ldp1 D_l, D_h, src, #16 + prfm pldl1strm, [src, #(4*L1_CACHE_BYTES)] subs count, count, #64 b.ge 1b stp1 A_l, A_h, dst, #16 diff --git a/arch/arm64/lib/crc32.S b/arch/arm64/lib/crc32.S new file mode 100644 index 000000000000..e8f6bcdcae0d --- /dev/null +++ b/arch/arm64/lib/crc32.S @@ -0,0 +1,104 @@ +/* + * Accelerated CRC32(C) using AArch64 CRC instructions + * + * Copyright (C) 2016 - 2018 Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + + .arch armv8-a+crc + + .macro __crc32, c + cmp x2, #16 + b.lt 8f // less than 16 bytes + + and x7, x2, #0x1f + and x2, x2, #~0x1f + cbz x7, 32f // multiple of 32 bytes + + and x8, x7, #0xf + ldp x3, x4, [x1] + add x8, x8, x1 + add x1, x1, x7 + ldp x5, x6, [x8] +CPU_BE( rev x3, x3 ) +CPU_BE( rev x4, x4 ) +CPU_BE( rev x5, x5 ) +CPU_BE( rev x6, x6 ) + + tst x7, #8 + crc32\c\()x w8, w0, x3 + csel x3, x3, x4, eq + csel w0, w0, w8, eq + tst x7, #4 + lsr x4, x3, #32 + crc32\c\()w w8, w0, w3 + csel x3, x3, x4, eq + csel w0, w0, w8, eq + tst x7, #2 + lsr w4, w3, #16 + crc32\c\()h w8, w0, w3 + csel w3, w3, w4, eq + csel w0, w0, w8, eq + tst x7, #1 + crc32\c\()b w8, w0, w3 + csel w0, w0, w8, eq + tst x7, #16 + crc32\c\()x w8, w0, x5 + crc32\c\()x w8, w8, x6 + csel w0, w0, w8, eq + cbz x2, 0f + +32: ldp x3, x4, [x1], #32 + sub x2, x2, #32 + ldp x5, x6, [x1, #-16] +CPU_BE( rev x3, x3 ) +CPU_BE( rev x4, x4 ) +CPU_BE( rev x5, x5 ) +CPU_BE( rev x6, x6 ) + crc32\c\()x w0, w0, x3 + crc32\c\()x w0, w0, x4 + crc32\c\()x w0, w0, x5 + crc32\c\()x w0, w0, x6 + cbnz x2, 32b +0: ret + +8: tbz x2, #3, 4f + ldr x3, [x1], #8 +CPU_BE( rev x3, x3 ) + crc32\c\()x w0, w0, x3 +4: tbz x2, #2, 2f + ldr w3, [x1], #4 +CPU_BE( rev w3, w3 ) + crc32\c\()w w0, w0, w3 +2: tbz x2, #1, 1f + ldrh w3, [x1], #2 +CPU_BE( rev16 w3, w3 ) + crc32\c\()h w0, w0, w3 +1: tbz x2, #0, 0f + ldrb w3, [x1] + crc32\c\()b w0, w0, w3 +0: ret + .endm + + .align 5 +ENTRY(crc32_le) +alternative_if_not ARM64_HAS_CRC32 + b crc32_le_base +alternative_else_nop_endif + __crc32 +ENDPROC(crc32_le) + + .align 5 +ENTRY(__crc32c_le) +alternative_if_not ARM64_HAS_CRC32 + b __crc32c_le_base +alternative_else_nop_endif + __crc32 c +ENDPROC(__crc32c_le) diff --git a/arch/arm64/lib/csum.c b/arch/arm64/lib/csum.c new file mode 100644 index 000000000000..78b87a64ca0a --- /dev/null +++ b/arch/arm64/lib/csum.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2019-2020 Arm Ltd. + +#include +#include +#include + +#include + +/* Looks dumb, but generates nice-ish code */ +static u64 accumulate(u64 sum, u64 data) +{ + __uint128_t tmp = (__uint128_t)sum + data; + return tmp + (tmp >> 64); +} + +/* + * We over-read the buffer and this makes KASAN unhappy. Instead, disable + * instrumentation and call kasan explicitly. + */ +unsigned int __no_sanitize_address do_csum(const unsigned char *buff, int len) +{ + unsigned int offset, shift, sum; + const u64 *ptr; + u64 data, sum64 = 0; + + if (unlikely(len == 0)) + return 0; + + offset = (unsigned long)buff & 7; + /* + * This is to all intents and purposes safe, since rounding down cannot + * result in a different page or cache line being accessed, and @buff + * should absolutely not be pointing to anything read-sensitive. We do, + * however, have to be careful not to piss off KASAN, which means using + * unchecked reads to accommodate the head and tail, for which we'll + * compensate with an explicit check up-front. + */ + kasan_check_read(buff, len); + ptr = (u64 *)(buff - offset); + len = len + offset - 8; + + /* + * Head: zero out any excess leading bytes. Shifting back by the same + * amount should be at least as fast as any other way of handling the + * odd/even alignment, and means we can ignore it until the very end. + */ + shift = offset * 8; + data = *ptr++; +#ifdef __LITTLE_ENDIAN + data = (data >> shift) << shift; +#else + data = (data << shift) >> shift; +#endif + + /* + * Body: straightforward aligned loads from here on (the paired loads + * underlying the quadword type still only need dword alignment). The + * main loop strictly excludes the tail, so the second loop will always + * run at least once. + */ + while (unlikely(len > 64)) { + __uint128_t tmp1, tmp2, tmp3, tmp4; + + tmp1 = *(__uint128_t *)ptr; + tmp2 = *(__uint128_t *)(ptr + 2); + tmp3 = *(__uint128_t *)(ptr + 4); + tmp4 = *(__uint128_t *)(ptr + 6); + + len -= 64; + ptr += 8; + + /* This is the "don't dump the carry flag into a GPR" idiom */ + tmp1 += (tmp1 >> 64) | (tmp1 << 64); + tmp2 += (tmp2 >> 64) | (tmp2 << 64); + tmp3 += (tmp3 >> 64) | (tmp3 << 64); + tmp4 += (tmp4 >> 64) | (tmp4 << 64); + tmp1 = ((tmp1 >> 64) << 64) | (tmp2 >> 64); + tmp1 += (tmp1 >> 64) | (tmp1 << 64); + tmp3 = ((tmp3 >> 64) << 64) | (tmp4 >> 64); + tmp3 += (tmp3 >> 64) | (tmp3 << 64); + tmp1 = ((tmp1 >> 64) << 64) | (tmp3 >> 64); + tmp1 += (tmp1 >> 64) | (tmp1 << 64); + tmp1 = ((tmp1 >> 64) << 64) | sum64; + tmp1 += (tmp1 >> 64) | (tmp1 << 64); + sum64 = tmp1 >> 64; + } + while (len > 8) { + __uint128_t tmp; + + sum64 = accumulate(sum64, data); + tmp = *(__uint128_t *)ptr; + + len -= 16; + ptr += 2; + +#ifdef __LITTLE_ENDIAN + data = tmp >> 64; + sum64 = accumulate(sum64, tmp); +#else + data = tmp; + sum64 = accumulate(sum64, tmp >> 64); +#endif + } + if (len > 0) { + sum64 = accumulate(sum64, data); + data = *ptr; + len -= 8; + } + /* + * Tail: zero any over-read bytes similarly to the head, again + * preserving odd/even alignment. + */ + shift = len * -8; +#ifdef __LITTLE_ENDIAN + data = (data << shift) >> shift; +#else + data = (data >> shift) << shift; +#endif + sum64 = accumulate(sum64, data); + + /* Finally, folding */ + sum64 += (sum64 >> 32) | (sum64 << 32); + sum = sum64 >> 32; + sum += (sum >> 16) | (sum << 16); + if (offset & 1) + return (u16)swab32(sum); + + return sum >> 16; +} + +__sum16 csum_ipv6_magic(const struct in6_addr *saddr, + const struct in6_addr *daddr, + __u32 len, __u8 proto, __wsum csum) +{ + __uint128_t src, dst; + u64 sum = (__force u64)csum; + + src = *(const __uint128_t *)saddr->s6_addr; + dst = *(const __uint128_t *)daddr->s6_addr; + + sum += (__force u32)htonl(len); +#ifdef __LITTLE_ENDIAN + sum += (u32)proto << 24; +#else + sum += proto; +#endif + src += (src >> 64) | (src << 64); + dst += (dst >> 64) | (dst << 64); + + sum = accumulate(sum, src >> 64); + sum = accumulate(sum, dst >> 64); + + sum += ((sum >> 32) | (sum << 32)); + return csum_fold((__force __wsum)(sum >> 32)); +} +EXPORT_SYMBOL(csum_ipv6_magic); diff --git a/arch/arm64/lib/memcmp.S b/arch/arm64/lib/memcmp.S index fb295f52e9f8..f365a5055c30 100644 --- a/arch/arm64/lib/memcmp.S +++ b/arch/arm64/lib/memcmp.S @@ -1,258 +1,131 @@ /* - * Copyright (C) 2013 ARM Ltd. - * Copyright (C) 2013 Linaro. + * Copyright (c) 2017 ARM Ltd + * All rights reserved. * - * This code is based on glibc cortex strings work originally authored by Linaro - * and re-licensed under GPLv2 for the Linux kernel. The original code can - * be found @ + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. * - * http://bazaar.launchpad.net/~linaro-toolchain-dev/cortex-strings/trunk/ - * files/head:/src/aarch64/ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Assumptions: * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * ARMv8-a, AArch64, unaligned accesses. */ +/* includes here */ #include #include -/* -* compare memory areas(when two memory areas' offset are different, -* alignment handled by the hardware) -* -* Parameters: -* x0 - const memory area 1 pointer -* x1 - const memory area 2 pointer -* x2 - the maximal compare byte length -* Returns: -* x0 - a compare result, maybe less than, equal to, or greater than ZERO -*/ - /* Parameters and result. */ -src1 .req x0 -src2 .req x1 -limit .req x2 -result .req x0 +#define src1 x0 +#define src2 x1 +#define limit x2 +#define result w0 /* Internal variables. */ -data1 .req x3 -data1w .req w3 -data2 .req x4 -data2w .req w4 -has_nul .req x5 -diff .req x6 -endloop .req x7 -tmp1 .req x8 -tmp2 .req x9 -tmp3 .req x10 -pos .req x11 -limit_wd .req x12 -mask .req x13 - +#define data1 x3 +#define data1w w3 +#define data2 x4 +#define data2w w4 +#define tmp1 x5 + +/* Small inputs of less than 8 bytes are handled separately. This allows the + main code to be sped up using unaligned loads since there are now at least + 8 bytes to be compared. If the first 8 bytes are equal, align src1. + This ensures each iteration does at most one unaligned access even if both + src1 and src2 are unaligned, and mutually aligned inputs behave as if + aligned. After the main loop, process the last 8 bytes using unaligned + accesses. */ + +.p2align 6 WEAK(memcmp) - cbz limit, .Lret0 - eor tmp1, src1, src2 - tst tmp1, #7 - b.ne .Lmisaligned8 - ands tmp1, src1, #7 - b.ne .Lmutual_align - sub limit_wd, limit, #1 /* limit != 0, so no underflow. */ - lsr limit_wd, limit_wd, #3 /* Convert to Dwords. */ - /* - * The input source addresses are at alignment boundary. - * Directly compare eight bytes each time. - */ -.Lloop_aligned: - ldr data1, [src1], #8 - ldr data2, [src2], #8 -.Lstart_realigned: - subs limit_wd, limit_wd, #1 - eor diff, data1, data2 /* Non-zero if differences found. */ - csinv endloop, diff, xzr, cs /* Last Dword or differences. */ - cbz endloop, .Lloop_aligned - - /* Not reached the limit, must have found a diff. */ - tbz limit_wd, #63, .Lnot_limit - - /* Limit % 8 == 0 => the diff is in the last 8 bytes. */ - ands limit, limit, #7 - b.eq .Lnot_limit - /* - * The remained bytes less than 8. It is needed to extract valid data - * from last eight bytes of the intended memory range. - */ - lsl limit, limit, #3 /* bytes-> bits. */ - mov mask, #~0 -CPU_BE( lsr mask, mask, limit ) -CPU_LE( lsl mask, mask, limit ) - bic data1, data1, mask - bic data2, data2, mask - - orr diff, diff, mask - b .Lnot_limit - -.Lmutual_align: - /* - * Sources are mutually aligned, but are not currently at an - * alignment boundary. Round down the addresses and then mask off - * the bytes that precede the start point. - */ - bic src1, src1, #7 - bic src2, src2, #7 - ldr data1, [src1], #8 - ldr data2, [src2], #8 - /* - * We can not add limit with alignment offset(tmp1) here. Since the - * addition probably make the limit overflown. - */ - sub limit_wd, limit, #1/*limit != 0, so no underflow.*/ - and tmp3, limit_wd, #7 - lsr limit_wd, limit_wd, #3 - add tmp3, tmp3, tmp1 - add limit_wd, limit_wd, tmp3, lsr #3 - add limit, limit, tmp1/* Adjust the limit for the extra. */ - - lsl tmp1, tmp1, #3/* Bytes beyond alignment -> bits.*/ - neg tmp1, tmp1/* Bits to alignment -64. */ - mov tmp2, #~0 - /*mask off the non-intended bytes before the start address.*/ -CPU_BE( lsl tmp2, tmp2, tmp1 )/*Big-endian.Early bytes are at MSB*/ - /* Little-endian. Early bytes are at LSB. */ -CPU_LE( lsr tmp2, tmp2, tmp1 ) - - orr data1, data1, tmp2 - orr data2, data2, tmp2 - b .Lstart_realigned - - /*src1 and src2 have different alignment offset.*/ -.Lmisaligned8: - cmp limit, #8 - b.lo .Ltiny8proc /*limit < 8: compare byte by byte*/ - - and tmp1, src1, #7 - neg tmp1, tmp1 - add tmp1, tmp1, #8/*valid length in the first 8 bytes of src1*/ - and tmp2, src2, #7 - neg tmp2, tmp2 - add tmp2, tmp2, #8/*valid length in the first 8 bytes of src2*/ - subs tmp3, tmp1, tmp2 - csel pos, tmp1, tmp2, hi /*Choose the maximum.*/ - - sub limit, limit, pos - /*compare the proceeding bytes in the first 8 byte segment.*/ -.Ltinycmp: - ldrb data1w, [src1], #1 - ldrb data2w, [src2], #1 - subs pos, pos, #1 - ccmp data1w, data2w, #0, ne /* NZCV = 0b0000. */ - b.eq .Ltinycmp - cbnz pos, 1f /*diff occurred before the last byte.*/ + subs limit, limit, 8 + b.lo .Lless8 + + /* Limit >= 8, so check first 8 bytes using unaligned loads. */ + ldr data1, [src1], 8 + ldr data2, [src2], 8 + and tmp1, src1, 7 + add limit, limit, tmp1 + cmp data1, data2 + bne .Lreturn + + /* Align src1 and adjust src2 with bytes not yet done. */ + sub src1, src1, tmp1 + sub src2, src2, tmp1 + + subs limit, limit, 8 + b.ls .Llast_bytes + + /* Loop performing 8 bytes per iteration using aligned src1. + Limit is pre-decremented by 8 and must be larger than zero. + Exit if <= 8 bytes left to do or if the data is not equal. */ + .p2align 4 +.Lloop8: + ldr data1, [src1], 8 + ldr data2, [src2], 8 + subs limit, limit, 8 + ccmp data1, data2, 0, hi /* NZCV = 0b0000. */ + b.eq .Lloop8 + + cmp data1, data2 + bne .Lreturn + + /* Compare last 1-8 bytes using unaligned access. */ +.Llast_bytes: + ldr data1, [src1, limit] + ldr data2, [src2, limit] + + /* Compare data bytes and set return value to 0, -1 or 1. */ +.Lreturn: +#ifndef __AARCH64EB__ + rev data1, data1 + rev data2, data2 +#endif + cmp data1, data2 +.Lret_eq: + cset result, ne + cneg result, result, lo + ret + + .p2align 4 + /* Compare up to 8 bytes. Limit is [-8..-1]. */ +.Lless8: + adds limit, limit, 4 + b.lo .Lless4 + ldr data1w, [src1], 4 + ldr data2w, [src2], 4 cmp data1w, data2w - b.eq .Lstart_align -1: - sub result, data1, data2 - ret - -.Lstart_align: - lsr limit_wd, limit, #3 - cbz limit_wd, .Lremain8 - - ands xzr, src1, #7 - b.eq .Lrecal_offset - /*process more leading bytes to make src1 aligned...*/ - add src1, src1, tmp3 /*backwards src1 to alignment boundary*/ - add src2, src2, tmp3 - sub limit, limit, tmp3 - lsr limit_wd, limit, #3 - cbz limit_wd, .Lremain8 - /*load 8 bytes from aligned SRC1..*/ - ldr data1, [src1], #8 - ldr data2, [src2], #8 - - subs limit_wd, limit_wd, #1 - eor diff, data1, data2 /*Non-zero if differences found.*/ - csinv endloop, diff, xzr, ne - cbnz endloop, .Lunequal_proc - /*How far is the current SRC2 from the alignment boundary...*/ - and tmp3, tmp3, #7 - -.Lrecal_offset:/*src1 is aligned now..*/ - neg pos, tmp3 -.Lloopcmp_proc: - /* - * Divide the eight bytes into two parts. First,backwards the src2 - * to an alignment boundary,load eight bytes and compare from - * the SRC2 alignment boundary. If all 8 bytes are equal,then start - * the second part's comparison. Otherwise finish the comparison. - * This special handle can garantee all the accesses are in the - * thread/task space in avoid to overrange access. - */ - ldr data1, [src1,pos] - ldr data2, [src2,pos] - eor diff, data1, data2 /* Non-zero if differences found. */ - cbnz diff, .Lnot_limit - - /*The second part process*/ - ldr data1, [src1], #8 - ldr data2, [src2], #8 - eor diff, data1, data2 /* Non-zero if differences found. */ - subs limit_wd, limit_wd, #1 - csinv endloop, diff, xzr, ne/*if limit_wd is 0,will finish the cmp*/ - cbz endloop, .Lloopcmp_proc -.Lunequal_proc: - cbz diff, .Lremain8 - -/* There is difference occurred in the latest comparison. */ -.Lnot_limit: -/* -* For little endian,reverse the low significant equal bits into MSB,then -* following CLZ can find how many equal bits exist. -*/ -CPU_LE( rev diff, diff ) -CPU_LE( rev data1, data1 ) -CPU_LE( rev data2, data2 ) - - /* - * The MS-non-zero bit of DIFF marks either the first bit - * that is different, or the end of the significant data. - * Shifting left now will bring the critical information into the - * top bits. - */ - clz pos, diff - lsl data1, data1, pos - lsl data2, data2, pos - /* - * We need to zero-extend (char is unsigned) the value and then - * perform a signed subtraction. - */ - lsr data1, data1, #56 - sub result, data1, data2, lsr #56 - ret - -.Lremain8: - /* Limit % 8 == 0 =>. all data are equal.*/ - ands limit, limit, #7 - b.eq .Lret0 - -.Ltiny8proc: - ldrb data1w, [src1], #1 - ldrb data2w, [src2], #1 - subs limit, limit, #1 - - ccmp data1w, data2w, #0, ne /* NZCV = 0b0000. */ - b.eq .Ltiny8proc - sub result, data1, data2 - ret -.Lret0: - mov result, #0 + b.ne .Lreturn + sub limit, limit, 4 +.Lless4: + adds limit, limit, 4 + beq .Lret_eq +.Lbyte_loop: + ldrb data1w, [src1], 1 + ldrb data2w, [src2], 1 + subs limit, limit, 1 + ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */ + b.eq .Lbyte_loop + sub result, data1w, data2w ret ENDPIPROC(memcmp) diff --git a/arch/arm64/lib/memcpy.S b/arch/arm64/lib/memcpy.S index 67613937711f..dfedd4ab1a76 100644 --- a/arch/arm64/lib/memcpy.S +++ b/arch/arm64/lib/memcpy.S @@ -68,9 +68,8 @@ stp \ptr, \regB, [\regC], \val .endm - .weak memcpy ENTRY(__memcpy) -ENTRY(memcpy) +WEAK(memcpy) #include "copy_template.S" ret ENDPIPROC(memcpy) diff --git a/arch/arm64/lib/memmove.S b/arch/arm64/lib/memmove.S index a5a4459013b1..b7c4e1acb6b0 100644 --- a/arch/arm64/lib/memmove.S +++ b/arch/arm64/lib/memmove.S @@ -57,9 +57,9 @@ C_h .req x12 D_l .req x13 D_h .req x14 - .weak memmove ENTRY(__memmove) ENTRY(memmove) + prfm pldl1strm, [src, #L1_CACHE_BYTES] cmp dstin, src b.lo __memcpy add tmp1, src, count @@ -186,6 +186,7 @@ ENTRY(memmove) ldp C_l, C_h, [src, #-48] stp D_l, D_h, [dst, #-64]! ldp D_l, D_h, [src, #-64]! + prfm pldl1strm, [src, #(4*L1_CACHE_BYTES)] subs count, count, #64 b.ge 1b stp A_l, A_h, [dst, #-16] diff --git a/arch/arm64/lib/memset.S b/arch/arm64/lib/memset.S index f2670a9f218c..316263c47c00 100644 --- a/arch/arm64/lib/memset.S +++ b/arch/arm64/lib/memset.S @@ -54,9 +54,8 @@ dst .req x8 tmp3w .req w9 tmp3 .req x9 - .weak memset ENTRY(__memset) -ENTRY(memset) +WEAK(memset) mov dst, dstin /* Preserve return value. */ and A_lw, val, #255 orr A_lw, A_lw, A_lw, lsl #8 diff --git a/arch/arm64/lib/xor-neon.c b/arch/arm64/lib/xor-neon.c new file mode 100644 index 000000000000..131c60c27dff --- /dev/null +++ b/arch/arm64/lib/xor-neon.c @@ -0,0 +1,184 @@ +/* + * arch/arm64/lib/xor-neon.c + * + * Authors: Jackie Liu + * Copyright (C) 2018,Tianjin KYLIN Information Technology Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +void xor_arm64_neon_2(unsigned long bytes, unsigned long *p1, + unsigned long *p2) +{ + uint64_t *dp1 = (uint64_t *)p1; + uint64_t *dp2 = (uint64_t *)p2; + + register uint64x2_t v0, v1, v2, v3; + long lines = bytes / (sizeof(uint64x2_t) * 4); + + do { + /* p1 ^= p2 */ + v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0)); + v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2)); + v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4)); + v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6)); + + /* store */ + vst1q_u64(dp1 + 0, v0); + vst1q_u64(dp1 + 2, v1); + vst1q_u64(dp1 + 4, v2); + vst1q_u64(dp1 + 6, v3); + + dp1 += 8; + dp2 += 8; + } while (--lines > 0); +} + +void xor_arm64_neon_3(unsigned long bytes, unsigned long *p1, + unsigned long *p2, unsigned long *p3) +{ + uint64_t *dp1 = (uint64_t *)p1; + uint64_t *dp2 = (uint64_t *)p2; + uint64_t *dp3 = (uint64_t *)p3; + + register uint64x2_t v0, v1, v2, v3; + long lines = bytes / (sizeof(uint64x2_t) * 4); + + do { + /* p1 ^= p2 */ + v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0)); + v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2)); + v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4)); + v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6)); + + /* p1 ^= p3 */ + v0 = veorq_u64(v0, vld1q_u64(dp3 + 0)); + v1 = veorq_u64(v1, vld1q_u64(dp3 + 2)); + v2 = veorq_u64(v2, vld1q_u64(dp3 + 4)); + v3 = veorq_u64(v3, vld1q_u64(dp3 + 6)); + + /* store */ + vst1q_u64(dp1 + 0, v0); + vst1q_u64(dp1 + 2, v1); + vst1q_u64(dp1 + 4, v2); + vst1q_u64(dp1 + 6, v3); + + dp1 += 8; + dp2 += 8; + dp3 += 8; + } while (--lines > 0); +} + +void xor_arm64_neon_4(unsigned long bytes, unsigned long *p1, + unsigned long *p2, unsigned long *p3, unsigned long *p4) +{ + uint64_t *dp1 = (uint64_t *)p1; + uint64_t *dp2 = (uint64_t *)p2; + uint64_t *dp3 = (uint64_t *)p3; + uint64_t *dp4 = (uint64_t *)p4; + + register uint64x2_t v0, v1, v2, v3; + long lines = bytes / (sizeof(uint64x2_t) * 4); + + do { + /* p1 ^= p2 */ + v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0)); + v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2)); + v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4)); + v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6)); + + /* p1 ^= p3 */ + v0 = veorq_u64(v0, vld1q_u64(dp3 + 0)); + v1 = veorq_u64(v1, vld1q_u64(dp3 + 2)); + v2 = veorq_u64(v2, vld1q_u64(dp3 + 4)); + v3 = veorq_u64(v3, vld1q_u64(dp3 + 6)); + + /* p1 ^= p4 */ + v0 = veorq_u64(v0, vld1q_u64(dp4 + 0)); + v1 = veorq_u64(v1, vld1q_u64(dp4 + 2)); + v2 = veorq_u64(v2, vld1q_u64(dp4 + 4)); + v3 = veorq_u64(v3, vld1q_u64(dp4 + 6)); + + /* store */ + vst1q_u64(dp1 + 0, v0); + vst1q_u64(dp1 + 2, v1); + vst1q_u64(dp1 + 4, v2); + vst1q_u64(dp1 + 6, v3); + + dp1 += 8; + dp2 += 8; + dp3 += 8; + dp4 += 8; + } while (--lines > 0); +} + +void xor_arm64_neon_5(unsigned long bytes, unsigned long *p1, + unsigned long *p2, unsigned long *p3, + unsigned long *p4, unsigned long *p5) +{ + uint64_t *dp1 = (uint64_t *)p1; + uint64_t *dp2 = (uint64_t *)p2; + uint64_t *dp3 = (uint64_t *)p3; + uint64_t *dp4 = (uint64_t *)p4; + uint64_t *dp5 = (uint64_t *)p5; + + register uint64x2_t v0, v1, v2, v3; + long lines = bytes / (sizeof(uint64x2_t) * 4); + + do { + /* p1 ^= p2 */ + v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0)); + v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2)); + v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4)); + v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6)); + + /* p1 ^= p3 */ + v0 = veorq_u64(v0, vld1q_u64(dp3 + 0)); + v1 = veorq_u64(v1, vld1q_u64(dp3 + 2)); + v2 = veorq_u64(v2, vld1q_u64(dp3 + 4)); + v3 = veorq_u64(v3, vld1q_u64(dp3 + 6)); + + /* p1 ^= p4 */ + v0 = veorq_u64(v0, vld1q_u64(dp4 + 0)); + v1 = veorq_u64(v1, vld1q_u64(dp4 + 2)); + v2 = veorq_u64(v2, vld1q_u64(dp4 + 4)); + v3 = veorq_u64(v3, vld1q_u64(dp4 + 6)); + + /* p1 ^= p5 */ + v0 = veorq_u64(v0, vld1q_u64(dp5 + 0)); + v1 = veorq_u64(v1, vld1q_u64(dp5 + 2)); + v2 = veorq_u64(v2, vld1q_u64(dp5 + 4)); + v3 = veorq_u64(v3, vld1q_u64(dp5 + 6)); + + /* store */ + vst1q_u64(dp1 + 0, v0); + vst1q_u64(dp1 + 2, v1); + vst1q_u64(dp1 + 4, v2); + vst1q_u64(dp1 + 6, v3); + + dp1 += 8; + dp2 += 8; + dp3 += 8; + dp4 += 8; + dp5 += 8; + } while (--lines > 0); +} + +struct xor_block_template const xor_block_inner_neon = { + .name = "__inner_neon__", + .do_2 = xor_arm64_neon_2, + .do_3 = xor_arm64_neon_3, + .do_4 = xor_arm64_neon_4, + .do_5 = xor_arm64_neon_5, +}; +EXPORT_SYMBOL(xor_block_inner_neon); + +MODULE_AUTHOR("Jackie Liu "); +MODULE_DESCRIPTION("ARMv8 XOR Extensions"); +MODULE_LICENSE("GPL"); diff --git a/arch/arm64/net/bpf_jit.h b/arch/arm64/net/bpf_jit.h index 76606e87233f..3a6e8dc910c8 100644 --- a/arch/arm64/net/bpf_jit.h +++ b/arch/arm64/net/bpf_jit.h @@ -182,6 +182,9 @@ /* Rd = Ra + Rn * Rm */ #define A64_MADD(sf, Rd, Ra, Rn, Rm) aarch64_insn_gen_data3(Rd, Ra, Rn, Rm, \ A64_VARIANT(sf), AARCH64_INSN_DATA3_MADD) +/* Rd = Ra - Rn * Rm */ +#define A64_MSUB(sf, Rd, Ra, Rn, Rm) aarch64_insn_gen_data3(Rd, Ra, Rn, Rm, \ + A64_VARIANT(sf), AARCH64_INSN_DATA3_MSUB) /* Rd = Rn * Rm */ #define A64_MUL(sf, Rd, Rn, Rm) A64_MADD(sf, Rd, A64_ZR, Rn, Rm) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index dd6b600bcf1f..d0907a6e0ae3 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -419,8 +419,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) break; case BPF_MOD: emit(A64_UDIV(is64, tmp, dst, src), ctx); - emit(A64_MUL(is64, tmp, tmp, src), ctx); - emit(A64_SUB(is64, dst, dst, tmp), ctx); + emit(A64_MSUB(is64, dst, dst, tmp, src), ctx); break; } break; @@ -526,8 +525,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) case BPF_ALU64 | BPF_MOD | BPF_K: emit_a64_mov_i(is64, tmp2, imm, ctx); emit(A64_UDIV(is64, tmp, dst, tmp2), ctx); - emit(A64_MUL(is64, tmp, tmp, tmp2), ctx); - emit(A64_SUB(is64, dst, dst, tmp), ctx); + emit(A64_MSUB(is64, dst, dst, tmp, tmp2), ctx); break; case BPF_ALU | BPF_LSH | BPF_K: case BPF_ALU64 | BPF_LSH | BPF_K: @@ -742,7 +740,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) emit(A64_ADD(1, tmp, tmp, dst), ctx); reg = tmp; } - if (cpus_have_cap(ARM64_HAS_LSE_ATOMICS)) { + if (IS_ENABLED(CONFIG_AS_LSE) && + IS_ENABLED(CONFIG_ARM64_LSE_ATOMICS)) { emit(A64_STADD(isdw, reg, src), ctx); } else { emit(A64_LDXR(isdw, tmp2, reg), ctx); @@ -950,6 +949,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) return prog; } +void *bpf_jit_alloc_exec(unsigned long size) +{ + return __vmalloc_node_range(size, PAGE_SIZE, BPF_JIT_REGION_START, + BPF_JIT_REGION_END, GFP_KERNEL, + PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, + __builtin_return_address(0)); +} + +void bpf_jit_free_exec(void *addr) +{ + return vfree(addr); +} + #ifdef CONFIG_CFI_CLANG bool arch_bpf_jit_check_func(const struct bpf_prog *prog) { @@ -957,17 +969,10 @@ bool arch_bpf_jit_check_func(const struct bpf_prog *prog) /* * bpf_func must be correctly aligned and within the correct region. - * module_alloc places JIT code in the module region, unless - * ARM64_MODULE_PLTS is enabled, in which case we might end up using - * the vmalloc region too. */ if (unlikely(!IS_ALIGNED(func, sizeof(u32)))) return false; - if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && - is_vmalloc_addr(prog->bpf_func)) - return true; - - return (func >= MODULES_VADDR && func < MODULES_END); + return (func >= BPF_JIT_REGION_START && func < BPF_JIT_REGION_END); } #endif diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c index 85e60509f0a8..d4b53af657c8 100644 --- a/arch/h8300/kernel/asm-offsets.c +++ b/arch/h8300/kernel/asm-offsets.c @@ -63,6 +63,9 @@ int main(void) OFFSET(TI_FLAGS, thread_info, flags); OFFSET(TI_CPU, thread_info, cpu); OFFSET(TI_PRE, thread_info, preempt_count); +#ifdef CONFIG_PREEMPTION + DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); +#endif return 0; } diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h index 7ff574d56429..f31e07fc936d 100644 --- a/arch/ia64/include/asm/ptrace.h +++ b/arch/ia64/include/asm/ptrace.h @@ -54,8 +54,7 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) { - /* FIXME: should this be bspstore + nr_dirty regs? */ - return regs->ar_bspstore; + return regs->r12; } static inline int is_syscall_success(struct pt_regs *regs) @@ -79,11 +78,6 @@ static inline long regs_return_value(struct pt_regs *regs) unsigned long __ip = instruction_pointer(regs); \ (__ip & ~3UL) + ((__ip & 3UL) << 2); \ }) -/* - * Why not default? Because user_stack_pointer() on ia64 gives register - * stack backing store instead... - */ -#define current_user_stack_pointer() (current_pt_regs()->r12) /* given a pointer to a task_struct, return the user's pt_regs */ # define task_pt_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) diff --git a/arch/ia64/include/asm/syscall.h b/arch/ia64/include/asm/syscall.h index 1d0b875fec44..ec909eec0b4c 100644 --- a/arch/ia64/include/asm/syscall.h +++ b/arch/ia64/include/asm/syscall.h @@ -35,7 +35,7 @@ static inline void syscall_rollback(struct task_struct *task, static inline long syscall_get_error(struct task_struct *task, struct pt_regs *regs) { - return regs->r10 == -1 ? regs->r8:0; + return regs->r10 == -1 ? -regs->r8:0; } static inline long syscall_get_return_value(struct task_struct *task, diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c index 8b5b8e6bc9d9..dd5bfed52031 100644 --- a/arch/ia64/kernel/err_inject.c +++ b/arch/ia64/kernel/err_inject.c @@ -59,7 +59,7 @@ show_##name(struct device *dev, struct device_attribute *attr, \ char *buf) \ { \ u32 cpu=dev->id; \ - return sprintf(buf, "%lx\n", name[cpu]); \ + return sprintf(buf, "%llx\n", name[cpu]); \ } #define store(name) \ @@ -86,9 +86,9 @@ store_call_start(struct device *dev, struct device_attribute *attr, #ifdef ERR_INJ_DEBUG printk(KERN_DEBUG "pal_mc_err_inject for cpu%d:\n", cpu); - printk(KERN_DEBUG "err_type_info=%lx,\n", err_type_info[cpu]); - printk(KERN_DEBUG "err_struct_info=%lx,\n", err_struct_info[cpu]); - printk(KERN_DEBUG "err_data_buffer=%lx, %lx, %lx.\n", + printk(KERN_DEBUG "err_type_info=%llx,\n", err_type_info[cpu]); + printk(KERN_DEBUG "err_struct_info=%llx,\n", err_struct_info[cpu]); + printk(KERN_DEBUG "err_data_buffer=%llx, %llx, %llx.\n", err_data_buffer[cpu].data1, err_data_buffer[cpu].data2, err_data_buffer[cpu].data3); @@ -117,8 +117,8 @@ store_call_start(struct device *dev, struct device_attribute *attr, #ifdef ERR_INJ_DEBUG printk(KERN_DEBUG "Returns: status=%d,\n", (int)status[cpu]); - printk(KERN_DEBUG "capabilities=%lx,\n", capabilities[cpu]); - printk(KERN_DEBUG "resources=%lx\n", resources[cpu]); + printk(KERN_DEBUG "capabilities=%llx,\n", capabilities[cpu]); + printk(KERN_DEBUG "resources=%llx\n", resources[cpu]); #endif return size; } @@ -131,7 +131,7 @@ show_virtual_to_phys(struct device *dev, struct device_attribute *attr, char *buf) { unsigned int cpu=dev->id; - return sprintf(buf, "%lx\n", phys_addr[cpu]); + return sprintf(buf, "%llx\n", phys_addr[cpu]); } static ssize_t @@ -145,7 +145,7 @@ store_virtual_to_phys(struct device *dev, struct device_attribute *attr, ret = get_user_pages_fast(virt_addr, 1, FOLL_WRITE, NULL); if (ret<=0) { #ifdef ERR_INJ_DEBUG - printk("Virtual address %lx is not existing.\n",virt_addr); + printk("Virtual address %llx is not existing.\n", virt_addr); #endif return -EINVAL; } @@ -163,7 +163,7 @@ show_err_data_buffer(struct device *dev, { unsigned int cpu=dev->id; - return sprintf(buf, "%lx, %lx, %lx\n", + return sprintf(buf, "%llx, %llx, %llx\n", err_data_buffer[cpu].data1, err_data_buffer[cpu].data2, err_data_buffer[cpu].data3); @@ -178,13 +178,13 @@ store_err_data_buffer(struct device *dev, int ret; #ifdef ERR_INJ_DEBUG - printk("write err_data_buffer=[%lx,%lx,%lx] on cpu%d\n", + printk("write err_data_buffer=[%llx,%llx,%llx] on cpu%d\n", err_data_buffer[cpu].data1, err_data_buffer[cpu].data2, err_data_buffer[cpu].data3, cpu); #endif - ret=sscanf(buf, "%lx, %lx, %lx", + ret = sscanf(buf, "%llx, %llx, %llx", &err_data_buffer[cpu].data1, &err_data_buffer[cpu].data2, &err_data_buffer[cpu].data3); diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 6115464d5f03..d7400b2844f1 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -1860,7 +1860,7 @@ ia64_mca_cpu_init(void *cpu_data) data = mca_bootmem(); first_time = 0; } else - data = (void *)__get_free_pages(GFP_KERNEL, + data = (void *)__get_free_pages(GFP_ATOMIC, get_order(sz)); if (!data) panic("Could not allocate MCA memory for cpu %d\n", diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c index 427cd565fd61..799400287cda 100644 --- a/arch/ia64/kernel/ptrace.c +++ b/arch/ia64/kernel/ptrace.c @@ -2147,27 +2147,39 @@ static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data) { struct syscall_get_set_args *args = data; struct pt_regs *pt = args->regs; - unsigned long *krbs, cfm, ndirty; + unsigned long *krbs, cfm, ndirty, nlocals, nouts; int i, count; if (unw_unwind_to_user(info) < 0) return; + /* + * We get here via a few paths: + * - break instruction: cfm is shared with caller. + * syscall args are in out= regs, locals are non-empty. + * - epsinstruction: cfm is set by br.call + * locals don't exist. + * + * For both cases argguments are reachable in cfm.sof - cfm.sol. + * CFM: [ ... | sor: 17..14 | sol : 13..7 | sof : 6..0 ] + */ cfm = pt->cr_ifs; + nlocals = (cfm >> 7) & 0x7f; /* aka sol */ + nouts = (cfm & 0x7f) - nlocals; /* aka sof - sol */ krbs = (unsigned long *)info->task + IA64_RBS_OFFSET/8; ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); count = 0; if (in_syscall(pt)) - count = min_t(int, args->n, cfm & 0x7f); + count = min_t(int, args->n, nouts); + /* Iterate over outs. */ for (i = 0; i < count; i++) { + int j = ndirty + nlocals + i + args->i; if (args->rw) - *ia64_rse_skip_regs(krbs, ndirty + i + args->i) = - args->args[i]; + *ia64_rse_skip_regs(krbs, j) = args->args[i]; else - args->args[i] = *ia64_rse_skip_regs(krbs, - ndirty + i + args->i); + args->args[i] = *ia64_rse_skip_regs(krbs, j); } if (!args->rw) { diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 1928d5719e41..db3104c9fac5 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -96,7 +96,7 @@ static int __init build_node_maps(unsigned long start, unsigned long len, * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been * called yet. Note that node 0 will also count all non-existent cpus. */ -static int __meminit early_nr_cpus_node(int node) +static int early_nr_cpus_node(int node) { int cpu, n = 0; @@ -111,7 +111,7 @@ static int __meminit early_nr_cpus_node(int node) * compute_pernodesize - compute size of pernode data * @node: the node id. */ -static unsigned long __meminit compute_pernodesize(int node) +static unsigned long compute_pernodesize(int node) { unsigned long pernodesize = 0, cpus; @@ -371,7 +371,7 @@ static void __init reserve_pernode_space(void) } } -static void __meminit scatter_node_data(void) +static void scatter_node_data(void) { pg_data_t **dst; int node; diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c index d129475fd40d..4254ba13c5c5 100644 --- a/arch/mips/alchemy/common/clock.c +++ b/arch/mips/alchemy/common/clock.c @@ -152,6 +152,7 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name, { struct clk_init_data id; struct clk_hw *h; + struct clk *clk; h = kzalloc(sizeof(*h), GFP_KERNEL); if (!h) @@ -164,7 +165,13 @@ static struct clk __init *alchemy_clk_setup_cpu(const char *parent_name, id.ops = &alchemy_clkops_cpu; h->init = &id; - return clk_register(NULL, h); + clk = clk_register(NULL, h); + if (IS_ERR(clk)) { + pr_err("failed to register clock\n"); + kfree(h); + } + + return clk; } /* AUXPLLs ************************************************************/ diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig index 29471038d817..c6b99845fb37 100644 --- a/arch/mips/bcm47xx/Kconfig +++ b/arch/mips/bcm47xx/Kconfig @@ -27,6 +27,7 @@ config BCM47XX_BCMA select BCMA select BCMA_HOST_SOC select BCMA_DRIVER_MIPS + select BCMA_DRIVER_PCI if PCI select BCMA_DRIVER_PCI_HOSTMODE if PCI select BCMA_DRIVER_GPIO default y diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index 81df9047e110..40218be0b7ce 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -17,6 +17,7 @@ #include #include +#include /* * These two variables specify the free mem region @@ -117,7 +118,7 @@ void decompress_kernel(unsigned long boot_heap_start) dtb_size = fdt_totalsize((void *)&__appended_dtb); /* last four bytes is always image size in little endian */ - image_size = le32_to_cpup((void *)&__image_end - 4); + image_size = get_unaligned_le32((void *)&__image_end - 4); /* copy dtb to where the booted kernel will expect it */ memcpy((void *)VMLINUX_LOAD_ADDRESS_ULL + image_size, diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index cbf4cc0b0b6c..934caf204078 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -187,8 +187,14 @@ static int __init relocate_exception_table(long offset) static inline __init unsigned long rotate_xor(unsigned long hash, const void *area, size_t size) { - size_t i; - unsigned long *ptr = (unsigned long *)area; + const typeof(hash) *ptr = PTR_ALIGN(area, sizeof(hash)); + size_t diff, i; + + diff = (void *)ptr - area; + if (unlikely(size < diff + sizeof(hash))) + return hash; + + size = ALIGN_DOWN(size - diff, sizeof(hash)); for (i = 0; i < size / sizeof(hash); i++) { /* Rotate by odd number of bits and XOR. */ diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index be63fff95b2a..968c5765020c 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -93,6 +93,7 @@ SECTIONS INIT_TASK_DATA(THREAD_SIZE) NOSAVE_DATA + PAGE_ALIGNED_DATA(PAGE_SIZE) CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) DATA_DATA diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index 37caeadb2964..0476d7e97a03 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -244,7 +244,7 @@ static void ltq_hw_irq_handler(struct irq_desc *desc) generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq)); /* if this is a EBU irq, we need to ack it or get a deadlock */ - if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) + if (irq == LTQ_ICU_EBU_IRQ && !module && LTQ_EBU_PCC_ISTAT != 0) ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10, LTQ_EBU_PCC_ISTAT); } diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index 7650edd5cf7f..60fe72170856 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -1673,7 +1673,7 @@ static int probe_scache(void) return 1; } -static void __init loongson2_sc_init(void) +static void loongson2_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data; diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index 0596505770db..11985399c469 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -424,6 +424,7 @@ int has_transparent_hugepage(void) } return mask == PM_HUGE_MASK; } +EXPORT_SYMBOL(has_transparent_hugepage); #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ diff --git a/arch/nds32/mm/cacheflush.c b/arch/nds32/mm/cacheflush.c index 254703653b6f..f34dc9bc6758 100644 --- a/arch/nds32/mm/cacheflush.c +++ b/arch/nds32/mm/cacheflush.c @@ -239,7 +239,7 @@ void flush_dcache_page(struct page *page) { struct address_space *mapping; - mapping = page_mapping(page); + mapping = page_mapping_file(page); if (mapping && !mapping_mapped(mapping)) set_bit(PG_dcache_dirty, &page->flags); else { diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index 068958575871..a736dc59bbef 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -72,7 +72,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) #endif case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int)old, (unsigned int)new_); - case 1: return __cmpxchg_u8((u8 *)ptr, (u8)old, (u8)new_); + case 1: return __cmpxchg_u8((u8 *)ptr, old & 0xff, new_ & 0xff); } __cmpxchg_called_with_bad_pointer(); return old; diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index 0ca254085a66..c152c30c2d06 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -380,7 +380,11 @@ static inline int eirr_to_irq(unsigned long eirr) /* * IRQ STACK - used for irq handler */ +#ifdef CONFIG_64BIT +#define IRQ_STACK_SIZE (4096 << 4) /* 64k irq stack size */ +#else #define IRQ_STACK_SIZE (4096 << 3) /* 32k irq stack size */ +#endif union irq_stack_union { unsigned long stack[IRQ_STACK_SIZE/sizeof(unsigned long)]; diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index d18ea3c1f4fa..6dd2a14e1ebc 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -709,7 +709,7 @@ config PPC_64K_PAGES config PPC_256K_PAGES bool "256k page size" - depends on 44x && !STDBINUTILS + depends on 44x && !STDBINUTILS && !PPC_47x help Make the page size 256k. diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 8954108df457..f51e21ea5349 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -251,7 +251,6 @@ endif cpu-as-$(CONFIG_4xx) += -Wa,-m405 cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec) -cpu-as-$(CONFIG_E200) += -Wa,-me200 cpu-as-$(CONFIG_E500) += -Wa,-me500 # When using '-many -mpower4' gas will first try and find a matching power4 diff --git a/arch/powerpc/include/asm/bitops.h b/arch/powerpc/include/asm/bitops.h index ff71566dadee..76db1c5000bd 100644 --- a/arch/powerpc/include/asm/bitops.h +++ b/arch/powerpc/include/asm/bitops.h @@ -221,15 +221,34 @@ static __inline__ void __clear_bit_unlock(int nr, volatile unsigned long *addr) */ static __inline__ int fls(unsigned int x) { - return 32 - __builtin_clz(x); + int lz; + + if (__builtin_constant_p(x)) + return x ? 32 - __builtin_clz(x) : 0; + asm("cntlzw %0,%1" : "=r" (lz) : "r" (x)); + return 32 - lz; } #include +/* + * 64-bit can do this using one cntlzd (count leading zeroes doubleword) + * instruction; for 32-bit we use the generic version, which does two + * 32-bit fls calls. + */ +#ifdef CONFIG_PPC64 static __inline__ int fls64(__u64 x) { - return 64 - __builtin_clzll(x); + int lz; + + if (__builtin_constant_p(x)) + return x ? 64 - __builtin_clzll(x) : 0; + asm("cntlzd %0,%1" : "=r" (lz) : "r" (x)); + return 64 - lz; } +#else +#include +#endif #ifdef CONFIG_PPC64 unsigned int __arch_hweight8(unsigned int w); diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index 751cf931bb3f..a4f4820826b7 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h @@ -434,9 +434,9 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, if (pte_val(*ptep) & _PAGE_HASHPTE) flush_hash_entry(mm, ptep, addr); __asm__ __volatile__("\ - stw%U0%X0 %2,%0\n\ + stw%X0 %2,%0\n\ eieio\n\ - stw%U0%X0 %L2,%1" + stw%X1 %L2,%1" : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) : "r" (pte) : "memory"); diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h b/arch/powerpc/include/asm/book3s/64/kup-radix.h new file mode 100644 index 000000000000..aa54ac2e5659 --- /dev/null +++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H +#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H + +DECLARE_STATIC_KEY_FALSE(uaccess_flush_key); + +/* Prototype for function defined in exceptions-64s.S */ +void do_uaccess_flush(void); + +static __always_inline void allow_user_access(void __user *to, const void __user *from, + unsigned long size) +{ +} + +static inline void prevent_user_access(void __user *to, const void __user *from, + unsigned long size) +{ + if (static_branch_unlikely(&uaccess_flush_key)) + do_uaccess_flush(); +} + +#endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */ diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h index 31733a95bbd0..4cd6e19ee90f 100644 --- a/arch/powerpc/include/asm/code-patching.h +++ b/arch/powerpc/include/asm/code-patching.h @@ -52,7 +52,7 @@ void __patch_exception(int exc, unsigned long addr); #endif #define OP_RT_RA_MASK 0xffff0000UL -#define LIS_R2 0x3c020000UL +#define LIS_R2 0x3c400000UL #define ADDIS_R2_R12 0x3c4c0000UL #define ADDI_R2_R2 0x38420000UL diff --git a/arch/powerpc/include/asm/cpu_has_feature.h b/arch/powerpc/include/asm/cpu_has_feature.h index 7897d16e0990..727d4b321937 100644 --- a/arch/powerpc/include/asm/cpu_has_feature.h +++ b/arch/powerpc/include/asm/cpu_has_feature.h @@ -7,7 +7,7 @@ #include #include -static inline bool early_cpu_has_feature(unsigned long feature) +static __always_inline bool early_cpu_has_feature(unsigned long feature) { return !!((CPU_FTRS_ALWAYS & feature) || (CPU_FTRS_POSSIBLE & cur_cpu_spec->cpu_features & feature)); @@ -46,7 +46,7 @@ static __always_inline bool cpu_has_feature(unsigned long feature) return static_branch_likely(&cpu_feature_keys[i]); } #else -static inline bool cpu_has_feature(unsigned long feature) +static __always_inline bool cpu_has_feature(unsigned long feature) { return early_cpu_has_feature(feature); } diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 59b35b93eade..d90093a88e09 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -411,7 +411,6 @@ static inline void cpu_feature_keys_init(void) { } CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \ CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT) -#define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) /* 64-bit CPUs */ #define CPU_FTRS_PPC970 (CPU_FTR_LWSYNC | \ @@ -509,8 +508,6 @@ enum { CPU_FTRS_7447 | CPU_FTRS_7447A | CPU_FTRS_82XX | CPU_FTRS_G2_LE | CPU_FTRS_E300 | CPU_FTRS_E300C2 | CPU_FTRS_CLASSIC32 | -#else - CPU_FTRS_GENERIC_32 | #endif #ifdef CONFIG_PPC_8xx CPU_FTRS_8XX | @@ -585,8 +582,6 @@ enum { CPU_FTRS_7447 & CPU_FTRS_7447A & CPU_FTRS_82XX & CPU_FTRS_G2_LE & CPU_FTRS_E300 & CPU_FTRS_E300C2 & CPU_FTRS_CLASSIC32 & -#else - CPU_FTRS_GENERIC_32 & #endif #ifdef CONFIG_PPC_8xx CPU_FTRS_8XX & diff --git a/arch/powerpc/include/asm/dcr-native.h b/arch/powerpc/include/asm/dcr-native.h index 151dff555f50..9d9e323f5e9b 100644 --- a/arch/powerpc/include/asm/dcr-native.h +++ b/arch/powerpc/include/asm/dcr-native.h @@ -66,8 +66,8 @@ static inline void mtdcrx(unsigned int reg, unsigned int val) #define mfdcr(rn) \ ({unsigned int rval; \ if (__builtin_constant_p(rn) && rn < 1024) \ - asm volatile("mfdcr %0," __stringify(rn) \ - : "=r" (rval)); \ + asm volatile("mfdcr %0, %1" : "=r" (rval) \ + : "n" (rn)); \ else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \ rval = mfdcrx(rn); \ else \ @@ -77,8 +77,8 @@ static inline void mtdcrx(unsigned int reg, unsigned int val) #define mtdcr(rn, v) \ do { \ if (__builtin_constant_p(rn) && rn < 1024) \ - asm volatile("mtdcr " __stringify(rn) ",%0" \ - : : "r" (v)); \ + asm volatile("mtdcr %0, %1" \ + : : "n" (rn), "r" (v)); \ else if (likely(cpu_has_feature(CPU_FTR_INDEXED_DCR))) \ mtdcrx(rn, v); \ else \ diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index a86feddddad0..35fb5b11955a 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -90,11 +90,18 @@ nop; \ nop +#define ENTRY_FLUSH_SLOT \ + ENTRY_FLUSH_FIXUP_SECTION; \ + nop; \ + nop; \ + nop; + /* * r10 must be free to use, r13 must be paca */ #define INTERRUPT_TO_KERNEL \ - STF_ENTRY_BARRIER_SLOT + STF_ENTRY_BARRIER_SLOT; \ + ENTRY_FLUSH_SLOT /* * Macros for annotating the expected destination of (h)rfid diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h index 40a6c9261a6b..5bf3f0779b93 100644 --- a/arch/powerpc/include/asm/feature-fixups.h +++ b/arch/powerpc/include/asm/feature-fixups.h @@ -205,6 +205,22 @@ label##3: \ FTR_ENTRY_OFFSET 955b-956b; \ .popsection; +#define UACCESS_FLUSH_FIXUP_SECTION \ +959: \ + .pushsection __uaccess_flush_fixup,"a"; \ + .align 2; \ +960: \ + FTR_ENTRY_OFFSET 959b-960b; \ + .popsection; + +#define ENTRY_FLUSH_FIXUP_SECTION \ +957: \ + .pushsection __entry_flush_fixup,"a"; \ + .align 2; \ +958: \ + FTR_ENTRY_OFFSET 957b-958b; \ + .popsection; + #define RFI_FLUSH_FIXUP_SECTION \ 951: \ .pushsection __rfi_flush_fixup,"a"; \ @@ -237,8 +253,11 @@ label##3: \ #include extern long stf_barrier_fallback; +extern long entry_flush_fallback; extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; +extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup; +extern long __start___entry_flush_fixup, __stop___entry_flush_fixup; extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup; extern long __start__btb_flush_fixup, __stop__btb_flush_fixup; diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h index 2a7b01f97a56..1eabc20dddd3 100644 --- a/arch/powerpc/include/asm/futex.h +++ b/arch/powerpc/include/asm/futex.h @@ -35,6 +35,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, { int oldval = 0, ret; + allow_write_to_user(uaddr, sizeof(*uaddr)); pagefault_disable(); switch (op) { @@ -61,6 +62,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, *oval = oldval; + prevent_write_to_user(uaddr, sizeof(*uaddr)); return ret; } @@ -74,6 +76,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; + allow_write_to_user(uaddr, sizeof(*uaddr)); __asm__ __volatile__ ( PPC_ATOMIC_ENTRY_BARRIER "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\ @@ -94,6 +97,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, : "cc", "memory"); *uval = prev; + prevent_write_to_user(uaddr, sizeof(*uaddr)); return ret; } diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h new file mode 100644 index 000000000000..f0f8e36ad71f --- /dev/null +++ b/arch/powerpc/include/asm/kup.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_POWERPC_KUP_H_ +#define _ASM_POWERPC_KUP_H_ + +#ifndef __ASSEMBLY__ + +#include + +#ifdef CONFIG_PPC_BOOK3S_64 +#include +#else +static inline void allow_user_access(void __user *to, const void __user *from, + unsigned long size) { } +static inline void prevent_user_access(void __user *to, const void __user *from, + unsigned long size) { } +#endif /* CONFIG_PPC_BOOK3S_64 */ + +static inline void allow_read_from_user(const void __user *from, unsigned long size) +{ + allow_user_access(NULL, from, size); +} + +static inline void allow_write_to_user(void __user *to, unsigned long size) +{ + allow_user_access(to, NULL, size); +} + +static inline void prevent_read_from_user(const void __user *from, unsigned long size) +{ + prevent_user_access(NULL, from, size); +} + +static inline void prevent_write_to_user(void __user *to, unsigned long size) +{ + prevent_user_access(to, NULL, size); +} + +#endif /* !__ASSEMBLY__ */ + +#endif /* _ASM_POWERPC_KUP_H_ */ diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index a47de82fb8e2..bda87cbf106d 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -71,6 +71,9 @@ struct machdep_calls { int (*pcibios_root_bridge_prepare)(struct pci_host_bridge *bridge); + /* finds all the pci_controllers present at boot */ + void (*discover_phbs)(void); + /* To setup PHBs when using automatic OF platform driver for PCI */ int (*pci_setup_phb)(struct pci_controller *host); diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index b321c82b3624..913878d8e3be 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h @@ -151,9 +151,9 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, */ if (IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_PTE_64BIT) && !percpu) { __asm__ __volatile__("\ - stw%U0%X0 %2,%0\n\ + stw%X0 %2,%0\n\ eieio\n\ - stw%U0%X0 %L2,%1" + stw%X1 %L2,%1" : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) : "r" (pte) : "memory"); return; diff --git a/arch/powerpc/include/asm/security_features.h b/arch/powerpc/include/asm/security_features.h index ccf44c135389..3b45a64e491e 100644 --- a/arch/powerpc/include/asm/security_features.h +++ b/arch/powerpc/include/asm/security_features.h @@ -84,12 +84,19 @@ static inline bool security_ftr_enabled(unsigned long feature) // Software required to flush link stack on context switch #define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull +// The L1-D cache should be flushed when entering the kernel +#define SEC_FTR_L1D_FLUSH_ENTRY 0x0000000000004000ull + +// The L1-D cache should be flushed after user accesses from the kernel +#define SEC_FTR_L1D_FLUSH_UACCESS 0x0000000000008000ull // Features enabled by default #define SEC_FTR_DEFAULT \ (SEC_FTR_L1D_FLUSH_HV | \ SEC_FTR_L1D_FLUSH_PR | \ SEC_FTR_BNDS_CHK_SPEC_BAR | \ + SEC_FTR_L1D_FLUSH_ENTRY | \ + SEC_FTR_L1D_FLUSH_UACCESS | \ SEC_FTR_FAVOUR_SECURITY) #endif /* _ASM_POWERPC_SECURITY_FEATURES_H */ diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index 65676e2325b8..6f2f4497e13b 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h @@ -52,12 +52,16 @@ enum l1d_flush_type { }; void setup_rfi_flush(enum l1d_flush_type, bool enable); +void setup_entry_flush(bool enable); +void setup_uaccess_flush(bool enable); void do_rfi_flush_fixups(enum l1d_flush_type types); #ifdef CONFIG_PPC_BARRIER_NOSPEC void setup_barrier_nospec(void); #else static inline void setup_barrier_nospec(void) { }; #endif +void do_uaccess_flush_fixups(enum l1d_flush_type types); +void do_entry_flush_fixups(enum l1d_flush_type types); void do_barrier_nospec_fixups(bool enable); extern bool barrier_nospec_enabled; diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index 38a25ff8afb7..ab6612e35ace 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h @@ -6,6 +6,7 @@ #include #include #include +#include /* * The fs value determines whether argument validity checking should be @@ -91,9 +92,14 @@ static inline int __access_ok(unsigned long addr, unsigned long size, __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) #define __get_user(x, ptr) \ - __get_user_nocheck((x), (ptr), sizeof(*(ptr))) + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), true) #define __put_user(x, ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), true) + +#define __get_user_allowed(x, ptr) \ + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), false) +#define __put_user_allowed(x, ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), false) #define __get_user_inatomic(x, ptr) \ __get_user_nosleep((x), (ptr), sizeof(*(ptr))) @@ -138,7 +144,7 @@ extern long __put_user_bad(void); : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) #endif /* __powerpc64__ */ -#define __put_user_size(x, ptr, size, retval) \ +#define __put_user_size_allowed(x, ptr, size, retval) \ do { \ retval = 0; \ switch (size) { \ @@ -150,14 +156,28 @@ do { \ } \ } while (0) -#define __put_user_nocheck(x, ptr, size) \ +#define __put_user_size(x, ptr, size, retval) \ +do { \ + allow_write_to_user(ptr, size); \ + __put_user_size_allowed(x, ptr, size, retval); \ + prevent_write_to_user(ptr, size); \ +} while (0) + +#define __put_user_nocheck(x, ptr, size, do_allow) \ ({ \ long __pu_err; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + __typeof__(size) __pu_size = (size); \ + \ if (!is_kernel_addr((unsigned long)__pu_addr)) \ might_fault(); \ - __chk_user_ptr(ptr); \ - __put_user_size((x), __pu_addr, (size), __pu_err); \ + __chk_user_ptr(__pu_addr); \ + if (do_allow) \ + __put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \ + else \ + __put_user_size_allowed(__pu_val, __pu_addr, __pu_size, __pu_err); \ + \ __pu_err; \ }) @@ -165,9 +185,13 @@ do { \ ({ \ long __pu_err = -EFAULT; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + __typeof__(size) __pu_size = (size); \ + \ might_fault(); \ - if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ - __put_user_size((x), __pu_addr, (size), __pu_err); \ + if (access_ok(VERIFY_WRITE, __pu_addr, __pu_size)) \ + __put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \ + \ __pu_err; \ }) @@ -175,8 +199,12 @@ do { \ ({ \ long __pu_err; \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - __chk_user_ptr(ptr); \ - __put_user_size((x), __pu_addr, (size), __pu_err); \ + __typeof__(*(ptr)) __pu_val = (x); \ + __typeof__(size) __pu_size = (size); \ + \ + __chk_user_ptr(__pu_addr); \ + __put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \ + \ __pu_err; \ }) @@ -234,7 +262,7 @@ extern long __get_user_bad(void); : "b" (addr), "i" (-EFAULT), "0" (err)) #endif /* __powerpc64__ */ -#define __get_user_size(x, ptr, size, retval) \ +#define __get_user_size_allowed(x, ptr, size, retval) \ do { \ retval = 0; \ __chk_user_ptr(ptr); \ @@ -249,6 +277,13 @@ do { \ } \ } while (0) +#define __get_user_size(x, ptr, size, retval) \ +do { \ + allow_read_from_user(ptr, size); \ + __get_user_size_allowed(x, ptr, size, retval); \ + prevent_read_from_user(ptr, size); \ +} while (0) + /* * This is a type: either unsigned long, if the argument fits into * that type, or otherwise unsigned long long. @@ -256,17 +291,23 @@ do { \ #define __long_type(x) \ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) -#define __get_user_nocheck(x, ptr, size) \ +#define __get_user_nocheck(x, ptr, size, do_allow) \ ({ \ long __gu_err; \ __long_type(*(ptr)) __gu_val; \ __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - __chk_user_ptr(ptr); \ + __typeof__(size) __gu_size = (size); \ + \ + __chk_user_ptr(__gu_addr); \ if (!is_kernel_addr((unsigned long)__gu_addr)) \ might_fault(); \ barrier_nospec(); \ - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + if (do_allow) \ + __get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \ + else \ + __get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \ (x) = (__typeof__(*(ptr)))__gu_val; \ + \ __gu_err; \ }) @@ -275,12 +316,15 @@ do { \ long __gu_err = -EFAULT; \ __long_type(*(ptr)) __gu_val = 0; \ __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ + __typeof__(size) __gu_size = (size); \ + \ might_fault(); \ - if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ + if (access_ok(VERIFY_READ, __gu_addr, __gu_size)) { \ barrier_nospec(); \ - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + __get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \ } \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ + \ __gu_err; \ }) @@ -289,10 +333,13 @@ do { \ long __gu_err; \ __long_type(*(ptr)) __gu_val; \ __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ - __chk_user_ptr(ptr); \ + __typeof__(size) __gu_size = (size); \ + \ + __chk_user_ptr(__gu_addr); \ barrier_nospec(); \ - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ + __get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ + \ __gu_err; \ }) @@ -306,16 +353,22 @@ extern unsigned long __copy_tofrom_user(void __user *to, static inline unsigned long raw_copy_in_user(void __user *to, const void __user *from, unsigned long n) { + unsigned long ret; + barrier_nospec(); - return __copy_tofrom_user(to, from, n); + allow_user_access(to, from, n); + ret = __copy_tofrom_user(to, from, n); + prevent_user_access(to, from, n); + return ret; } #endif /* __powerpc64__ */ static inline unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n) { + unsigned long ret; if (__builtin_constant_p(n) && (n <= 8)) { - unsigned long ret = 1; + ret = 1; switch (n) { case 1: @@ -340,27 +393,30 @@ static inline unsigned long raw_copy_from_user(void *to, } barrier_nospec(); - return __copy_tofrom_user((__force void __user *)to, from, n); + allow_read_from_user(from, n); + ret = __copy_tofrom_user((__force void __user *)to, from, n); + prevent_read_from_user(from, n); + return ret; } -static inline unsigned long raw_copy_to_user(void __user *to, - const void *from, unsigned long n) +static inline unsigned long +raw_copy_to_user_allowed(void __user *to, const void *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { unsigned long ret = 1; switch (n) { case 1: - __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret); + __put_user_size_allowed(*(u8 *)from, (u8 __user *)to, 1, ret); break; case 2: - __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret); + __put_user_size_allowed(*(u16 *)from, (u16 __user *)to, 2, ret); break; case 4: - __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret); + __put_user_size_allowed(*(u32 *)from, (u32 __user *)to, 4, ret); break; case 8: - __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret); + __put_user_size_allowed(*(u64 *)from, (u64 __user *)to, 8, ret); break; } if (ret == 0) @@ -370,14 +426,34 @@ static inline unsigned long raw_copy_to_user(void __user *to, return __copy_tofrom_user(to, (__force const void __user *)from, n); } -extern unsigned long __clear_user(void __user *addr, unsigned long size); +static inline unsigned long +raw_copy_to_user(void __user *to, const void *from, unsigned long n) +{ + unsigned long ret; + + allow_write_to_user(to, n); + ret = raw_copy_to_user_allowed(to, from, n); + prevent_write_to_user(to, n); + return ret; +} + +unsigned long __arch_clear_user(void __user *addr, unsigned long size); static inline unsigned long clear_user(void __user *addr, unsigned long size) { + unsigned long ret = size; might_fault(); - if (likely(access_ok(VERIFY_WRITE, addr, size))) - return __clear_user(addr, size); - return size; + if (likely(access_ok(VERIFY_WRITE, addr, size))) { + allow_write_to_user(addr, size); + ret = __arch_clear_user(addr, size); + prevent_write_to_user(addr, size); + } + return ret; +} + +static inline unsigned long __clear_user(void __user *addr, unsigned long size) +{ + return clear_user(addr, size); } extern long strncpy_from_user(char *dst, const char __user *src, long count); @@ -388,4 +464,13 @@ extern long __copy_from_user_flushcache(void *dst, const void __user *src, extern void memcpy_page_flushcache(char *to, struct page *page, size_t offset, size_t len); +#define user_access_begin(type, ptr, len) access_ok(type, ptr, len) +#define user_access_end() prevent_user_access(NULL, NULL, ~0ul) + +#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0) +#define unsafe_get_user(x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e) +#define unsafe_put_user(x, p, e) unsafe_op_wrap(__put_user_allowed(x, p), e) +#define unsafe_copy_to_user(d, s, l, e) \ + unsafe_op_wrap(raw_copy_to_user_allowed(d, s, l), e) + #endif /* _ARCH_POWERPC_UACCESS_H */ diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index e1dab9b1e447..344e2758b22d 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S @@ -540,7 +540,7 @@ EXC_COMMON_BEGIN(unrecover_mce) b 1b -EXC_REAL(data_access, 0x300, 0x80) +EXC_REAL_OOL(data_access, 0x300, 0x80) EXC_VIRT(data_access, 0x4300, 0x80, 0x300) TRAMP_KVM_SKIP(PACA_EXGEN, 0x300) @@ -572,13 +572,16 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) EXC_REAL_BEGIN(data_access_slb, 0x380, 0x80) SET_SCRATCH0(r13) EXCEPTION_PROLOG_0(PACA_EXSLB) + b tramp_data_access_slb +EXC_REAL_END(data_access_slb, 0x380, 0x80) + +TRAMP_REAL_BEGIN(tramp_data_access_slb) EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380) mr r12,r3 /* save r3 */ mfspr r3,SPRN_DAR mfspr r11,SPRN_SRR1 crset 4*cr6+eq BRANCH_TO_COMMON(r10, slb_miss_common) -EXC_REAL_END(data_access_slb, 0x380, 0x80) EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x80) SET_SCRATCH0(r13) @@ -593,7 +596,7 @@ EXC_VIRT_END(data_access_slb, 0x4380, 0x80) TRAMP_KVM_SKIP(PACA_EXSLB, 0x380) -EXC_REAL(instruction_access, 0x400, 0x80) +EXC_REAL_OOL(instruction_access, 0x400, 0x80) EXC_VIRT(instruction_access, 0x4400, 0x80, 0x400) TRAMP_KVM(PACA_EXGEN, 0x400) @@ -616,13 +619,16 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x80) SET_SCRATCH0(r13) EXCEPTION_PROLOG_0(PACA_EXSLB) + b tramp_instruction_access_slb +EXC_REAL_END(instruction_access_slb, 0x480, 0x80) + +TRAMP_REAL_BEGIN(tramp_instruction_access_slb) EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) mr r12,r3 /* save r3 */ mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ mfspr r11,SPRN_SRR1 crclr 4*cr6+eq BRANCH_TO_COMMON(r10, slb_miss_common) -EXC_REAL_END(instruction_access_slb, 0x480, 0x80) EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x80) SET_SCRATCH0(r13) @@ -883,13 +889,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x80, IRQS_DISABLED) -EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED) +EXC_VIRT_OOL_MASKABLE(decrementer, 0x4900, 0x80, 0x900, IRQS_DISABLED) TRAMP_KVM(PACA_EXGEN, 0x900) EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt) -EXC_REAL_HV(hdecrementer, 0x980, 0x80) -EXC_VIRT_HV(hdecrementer, 0x4980, 0x80, 0x980) +EXC_REAL_OOL_HV(hdecrementer, 0x980, 0x80) +EXC_VIRT_OOL_HV(hdecrementer, 0x4980, 0x80, 0x980) TRAMP_KVM_HV(PACA_EXGEN, 0x980) EXC_COMMON(hdecrementer_common, 0x980, hdec_interrupt) @@ -1523,15 +1529,8 @@ TRAMP_REAL_BEGIN(stf_barrier_fallback) .endr blr -TRAMP_REAL_BEGIN(rfi_flush_fallback) - SET_SCRATCH0(r13); - GET_PACA(r13); - std r1,PACA_EXRFI+EX_R12(r13) - ld r1,PACAKSAVE(r13) - std r9,PACA_EXRFI+EX_R9(r13) - std r10,PACA_EXRFI+EX_R10(r13) - std r11,PACA_EXRFI+EX_R11(r13) - mfctr r9 +/* Clobbers r10, r11, ctr */ +.macro L1D_DISPLACEMENT_FLUSH ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) ld r11,PACA_L1D_FLUSH_SIZE(r13) srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ @@ -1542,7 +1541,7 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback) sync /* - * The load adresses are at staggered offsets within cachelines, + * The load addresses are at staggered offsets within cachelines, * which suits some pipelines better (on others it should not * hurt). */ @@ -1557,7 +1556,30 @@ TRAMP_REAL_BEGIN(rfi_flush_fallback) ld r11,(0x80 + 8)*7(r10) addi r10,r10,0x80*8 bdnz 1b +.endm + +TRAMP_REAL_BEGIN(entry_flush_fallback) + std r9,PACA_EXRFI+EX_R9(r13) + std r10,PACA_EXRFI+EX_R10(r13) + std r11,PACA_EXRFI+EX_R11(r13) + mfctr r9 + L1D_DISPLACEMENT_FLUSH + mtctr r9 + ld r9,PACA_EXRFI+EX_R9(r13) + ld r10,PACA_EXRFI+EX_R10(r13) + ld r11,PACA_EXRFI+EX_R11(r13) + blr +TRAMP_REAL_BEGIN(rfi_flush_fallback) + SET_SCRATCH0(r13); + GET_PACA(r13); + std r1,PACA_EXRFI+EX_R12(r13) + ld r1,PACAKSAVE(r13) + std r9,PACA_EXRFI+EX_R9(r13) + std r10,PACA_EXRFI+EX_R10(r13) + std r11,PACA_EXRFI+EX_R11(r13) + mfctr r9 + L1D_DISPLACEMENT_FLUSH mtctr r9 ld r9,PACA_EXRFI+EX_R9(r13) ld r10,PACA_EXRFI+EX_R10(r13) @@ -1575,32 +1597,7 @@ TRAMP_REAL_BEGIN(hrfi_flush_fallback) std r10,PACA_EXRFI+EX_R10(r13) std r11,PACA_EXRFI+EX_R11(r13) mfctr r9 - ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) - ld r11,PACA_L1D_FLUSH_SIZE(r13) - srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ - mtctr r11 - DCBT_BOOK3S_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ - - /* order ld/st prior to dcbt stop all streams with flushing */ - sync - - /* - * The load adresses are at staggered offsets within cachelines, - * which suits some pipelines better (on others it should not - * hurt). - */ -1: - ld r11,(0x80 + 8)*0(r10) - ld r11,(0x80 + 8)*1(r10) - ld r11,(0x80 + 8)*2(r10) - ld r11,(0x80 + 8)*3(r10) - ld r11,(0x80 + 8)*4(r10) - ld r11,(0x80 + 8)*5(r10) - ld r11,(0x80 + 8)*6(r10) - ld r11,(0x80 + 8)*7(r10) - addi r10,r10,0x80*8 - bdnz 1b - + L1D_DISPLACEMENT_FLUSH mtctr r9 ld r9,PACA_EXRFI+EX_R9(r13) ld r10,PACA_EXRFI+EX_R10(r13) @@ -1609,6 +1606,19 @@ TRAMP_REAL_BEGIN(hrfi_flush_fallback) GET_SCRATCH0(r13); hrfid +USE_TEXT_SECTION() + +_GLOBAL(do_uaccess_flush) + UACCESS_FLUSH_FIXUP_SECTION + nop + nop + nop + blr + L1D_DISPLACEMENT_FLUSH + blr +_ASM_NOKPROBE_SYMBOL(do_uaccess_flush) +EXPORT_SYMBOL(do_uaccess_flush) + /* * Real mode exceptions actually use this too, but alternate * instruction code patches (which end up in the common .text area) diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 389da790c129..4f7b225d78cf 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -423,6 +423,10 @@ generic_secondary_common_init: /* From now on, r24 is expected to be logical cpuid */ mr r24,r5 + /* Create a temp kernel stack for use before relocation is on. */ + ld r1,PACAEMERGSP(r13) + subi r1,r1,STACK_FRAME_OVERHEAD + /* See if we need to call a cpu state restore handler */ LOAD_REG_ADDR(r23, cur_cpu_spec) ld r23,0(r23) @@ -451,10 +455,6 @@ generic_secondary_common_init: sync /* order paca.run and cur_cpu_spec */ isync /* In case code patching happened */ - /* Create a temp kernel stack for use before relocation is on. */ - ld r1,PACAEMERGSP(r13) - subi r1,r1,STACK_FRAME_OVERHEAD - b __secondary_start #endif /* SMP */ diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 9fd2ff28b8ff..08c16aa0dd53 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -269,7 +269,7 @@ SystemCall: /* On the MPC8xx, this is a software emulation interrupt. It occurs * for all unimplemented and illegal instructions. */ - EXCEPTION(0x1000, SoftEmu, program_check_exception, EXC_XFER_STD) + EXCEPTION(0x1000, SoftEmu, emulation_assist_interrupt, EXC_XFER_STD) . = 0x1100 /* @@ -356,11 +356,9 @@ _ENTRY(ITLBMiss_cmp) /* Load the MI_TWC with the attributes for this "segment." */ mtspr SPRN_MI_TWC, r11 /* Set segment attributes */ -#ifdef CONFIG_SWAP - rlwinm r11, r10, 32-5, _PAGE_PRESENT + rlwinm r11, r10, 32-7, _PAGE_PRESENT and r11, r11, r10 rlwimi r10, r11, 0, _PAGE_PRESENT -#endif li r11, RPN_PATTERN | 0x200 /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 20 and 23 must be clear. @@ -482,11 +480,9 @@ _ENTRY(DTLBMiss_jmp) * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); * r10 = (r10 & ~PRESENT) | r11; */ -#ifdef CONFIG_SWAP - rlwinm r11, r10, 32-5, _PAGE_PRESENT + rlwinm r11, r10, 32-7, _PAGE_PRESENT and r11, r11, r10 rlwimi r10, r11, 0, _PAGE_PRESENT -#endif /* The Linux PTE won't go exactly into the MMU TLB. * Software indicator bits 24, 25, 26, and 27 must be * set. All other Linux PTE bits control the behavior diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 88e4f69a09e5..74628aca2bf1 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -1671,3 +1671,13 @@ static void fixup_hide_host_resource_fsl(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MOTOROLA, PCI_ANY_ID, fixup_hide_host_resource_fsl); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, fixup_hide_host_resource_fsl); + + +static int __init discover_phbs(void) +{ + if (ppc_md.discover_phbs) + ppc_md.discover_phbs(); + + return 0; +} +core_initcall(discover_phbs); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 7e0722b62cae..b3aa0cea6283 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -1095,7 +1095,7 @@ static struct rtas_filter rtas_filters[] __ro_after_init = { { "ibm,display-message", -1, 0, -1, -1, -1 }, { "ibm,errinjct", -1, 2, -1, -1, -1, 1024 }, { "ibm,close-errinjct", -1, -1, -1, -1, -1 }, - { "ibm,open-errinct", -1, -1, -1, -1, -1 }, + { "ibm,open-errinjct", -1, -1, -1, -1, -1 }, { "ibm,get-config-addr-info2", -1, -1, -1, -1, -1 }, { "ibm,get-dynamic-sensor-state", -1, 1, -1, -1, -1 }, { "ibm,get-indices", -1, 2, 3, -1, -1 }, diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 508244bcf19c..7787a26d4777 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -929,8 +929,6 @@ void __init setup_arch(char **cmdline_p) /* On BookE, setup per-core TLB data structures. */ setup_tlb_core_data(); - - smp_release_cpus(); #endif /* Print various info about the machine that has been gathered so far. */ @@ -964,6 +962,8 @@ void __init setup_arch(char **cmdline_p) exc_lvl_early_init(); emergency_stack_init(); + smp_release_cpus(); + initmem_init(); #ifdef CONFIG_DUMMY_CONSOLE diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index bd4996958b13..122365624d3d 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -863,7 +863,13 @@ early_initcall(disable_hardlockup_detector); static enum l1d_flush_type enabled_flush_types; static void *l1d_flush_fallback_area; static bool no_rfi_flush; +static bool no_entry_flush; +static bool no_uaccess_flush; bool rfi_flush; +bool entry_flush; +bool uaccess_flush; +DEFINE_STATIC_KEY_FALSE(uaccess_flush_key); +EXPORT_SYMBOL(uaccess_flush_key); static int __init handle_no_rfi_flush(char *p) { @@ -873,6 +879,22 @@ static int __init handle_no_rfi_flush(char *p) } early_param("no_rfi_flush", handle_no_rfi_flush); +static int __init handle_no_entry_flush(char *p) +{ + pr_info("entry-flush: disabled on command line."); + no_entry_flush = true; + return 0; +} +early_param("no_entry_flush", handle_no_entry_flush); + +static int __init handle_no_uaccess_flush(char *p) +{ + pr_info("uaccess-flush: disabled on command line."); + no_uaccess_flush = true; + return 0; +} +early_param("no_uaccess_flush", handle_no_uaccess_flush); + /* * The RFI flush is not KPTI, but because users will see doco that says to use * nopti we hijack that option here to also disable the RFI flush. @@ -904,6 +926,32 @@ void rfi_flush_enable(bool enable) rfi_flush = enable; } +void entry_flush_enable(bool enable) +{ + if (enable) { + do_entry_flush_fixups(enabled_flush_types); + on_each_cpu(do_nothing, NULL, 1); + } else { + do_entry_flush_fixups(L1D_FLUSH_NONE); + } + + entry_flush = enable; +} + +void uaccess_flush_enable(bool enable) +{ + if (enable) { + do_uaccess_flush_fixups(enabled_flush_types); + static_branch_enable(&uaccess_flush_key); + on_each_cpu(do_nothing, NULL, 1); + } else { + static_branch_disable(&uaccess_flush_key); + do_uaccess_flush_fixups(L1D_FLUSH_NONE); + } + + uaccess_flush = enable; +} + static void __ref init_fallback_flush(void) { u64 l1d_size, limit; @@ -957,10 +1005,28 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable) enabled_flush_types = types; - if (!no_rfi_flush && !cpu_mitigations_off()) + if (!cpu_mitigations_off() && !no_rfi_flush) rfi_flush_enable(enable); } +void setup_entry_flush(bool enable) +{ + if (cpu_mitigations_off()) + return; + + if (!no_entry_flush) + entry_flush_enable(enable); +} + +void setup_uaccess_flush(bool enable) +{ + if (cpu_mitigations_off()) + return; + + if (!no_uaccess_flush) + uaccess_flush_enable(enable); +} + #ifdef CONFIG_DEBUG_FS static int rfi_flush_set(void *data, u64 val) { @@ -988,9 +1054,63 @@ static int rfi_flush_get(void *data, u64 *val) DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n"); +static int entry_flush_set(void *data, u64 val) +{ + bool enable; + + if (val == 1) + enable = true; + else if (val == 0) + enable = false; + else + return -EINVAL; + + /* Only do anything if we're changing state */ + if (enable != entry_flush) + entry_flush_enable(enable); + + return 0; +} + +static int entry_flush_get(void *data, u64 *val) +{ + *val = entry_flush ? 1 : 0; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_entry_flush, entry_flush_get, entry_flush_set, "%llu\n"); + +static int uaccess_flush_set(void *data, u64 val) +{ + bool enable; + + if (val == 1) + enable = true; + else if (val == 0) + enable = false; + else + return -EINVAL; + + /* Only do anything if we're changing state */ + if (enable != uaccess_flush) + uaccess_flush_enable(enable); + + return 0; +} + +static int uaccess_flush_get(void *data, u64 *val) +{ + *val = uaccess_flush ? 1 : 0; + return 0; +} + +DEFINE_SIMPLE_ATTRIBUTE(fops_uaccess_flush, uaccess_flush_get, uaccess_flush_set, "%llu\n"); + static __init int rfi_flush_debugfs_init(void) { debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush); + debugfs_create_file("entry_flush", 0600, powerpc_debugfs_root, NULL, &fops_entry_flush); + debugfs_create_file("uaccess_flush", 0600, powerpc_debugfs_root, NULL, &fops_uaccess_flush); return 0; } device_initcall(rfi_flush_debugfs_init); diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 1b2d84cb373b..2379c4bf3979 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -433,8 +433,11 @@ void system_reset_exception(struct pt_regs *regs) die("Unrecoverable nested System Reset", regs, SIGABRT); #endif /* Must die if the interrupt is not recoverable */ - if (!(regs->msr & MSR_RI)) + if (!(regs->msr & MSR_RI)) { + /* For the reason explained in die_mce, nmi_exit before die */ + nmi_exit(); die("Unrecoverable System Reset", regs, SIGABRT); + } if (!nested) nmi_exit(); diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index d081d726ca8e..695432965f20 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -140,6 +140,20 @@ SECTIONS __stop___stf_entry_barrier_fixup = .; } + . = ALIGN(8); + __uaccess_flush_fixup : AT(ADDR(__uaccess_flush_fixup) - LOAD_OFFSET) { + __start___uaccess_flush_fixup = .; + *(__uaccess_flush_fixup) + __stop___uaccess_flush_fixup = .; + } + + . = ALIGN(8); + __entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) { + __start___entry_flush_fixup = .; + *(__entry_flush_fixup) + __stop___entry_flush_fixup = .; + } + . = ALIGN(8); __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) { __start___stf_exit_barrier_fixup = .; diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 51cd66dc1bb0..7c8354dfe80e 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c @@ -1497,7 +1497,7 @@ int kvmppc_handle_vmx_load(struct kvm_run *run, struct kvm_vcpu *vcpu, return emulated; } -int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; @@ -1515,7 +1515,7 @@ int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val) return result; } -int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; @@ -1533,7 +1533,7 @@ int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val) return result; } -int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; @@ -1551,7 +1551,7 @@ int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val) return result; } -int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val) +static int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val) { union kvmppc_one_reg reg; int vmx_offset = 0; diff --git a/arch/powerpc/lib/checksum_wrappers.c b/arch/powerpc/lib/checksum_wrappers.c index a0cb63fb76a1..8d83c39be7e4 100644 --- a/arch/powerpc/lib/checksum_wrappers.c +++ b/arch/powerpc/lib/checksum_wrappers.c @@ -29,6 +29,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst, unsigned int csum; might_sleep(); + allow_read_from_user(src, len); *err_ptr = 0; @@ -60,6 +61,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst, } out: + prevent_read_from_user(src, len); return (__force __wsum)csum; } EXPORT_SYMBOL(csum_and_copy_from_user); @@ -70,6 +72,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, unsigned int csum; might_sleep(); + allow_write_to_user(dst, len); *err_ptr = 0; @@ -97,6 +100,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, } out: + prevent_write_to_user(dst, len); return (__force __wsum)csum; } EXPORT_SYMBOL(csum_and_copy_to_user); diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index dbe478e7b8e0..065a3426f0eb 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c @@ -232,6 +232,110 @@ void do_stf_barrier_fixups(enum stf_barrier_type types) do_stf_exit_barrier_fixups(types); } +void do_uaccess_flush_fixups(enum l1d_flush_type types) +{ + unsigned int instrs[4], *dest; + long *start, *end; + int i; + + start = PTRRELOC(&__start___uaccess_flush_fixup); + end = PTRRELOC(&__stop___uaccess_flush_fixup); + + instrs[0] = 0x60000000; /* nop */ + instrs[1] = 0x60000000; /* nop */ + instrs[2] = 0x60000000; /* nop */ + instrs[3] = 0x4e800020; /* blr */ + + i = 0; + if (types == L1D_FLUSH_FALLBACK) { + instrs[3] = 0x60000000; /* nop */ + /* fallthrough to fallback flush */ + } + + if (types & L1D_FLUSH_ORI) { + instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ + instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/ + } + + if (types & L1D_FLUSH_MTTRIG) + instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */ + + for (i = 0; start < end; start++, i++) { + dest = (void *)start + *start; + + pr_devel("patching dest %lx\n", (unsigned long)dest); + + patch_instruction(dest, instrs[0]); + + patch_instruction((dest + 1), instrs[1]); + patch_instruction((dest + 2), instrs[2]); + patch_instruction((dest + 3), instrs[3]); + } + + printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i, + (types == L1D_FLUSH_NONE) ? "no" : + (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : + (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) + ? "ori+mttrig type" + : "ori type" : + (types & L1D_FLUSH_MTTRIG) ? "mttrig type" + : "unknown"); +} + +void do_entry_flush_fixups(enum l1d_flush_type types) +{ + unsigned int instrs[3], *dest; + long *start, *end; + int i; + + start = PTRRELOC(&__start___entry_flush_fixup); + end = PTRRELOC(&__stop___entry_flush_fixup); + + instrs[0] = 0x60000000; /* nop */ + instrs[1] = 0x60000000; /* nop */ + instrs[2] = 0x60000000; /* nop */ + + i = 0; + if (types == L1D_FLUSH_FALLBACK) { + instrs[i++] = 0x7d4802a6; /* mflr r10 */ + instrs[i++] = 0x60000000; /* branch patched below */ + instrs[i++] = 0x7d4803a6; /* mtlr r10 */ + } + + if (types & L1D_FLUSH_ORI) { + instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ + instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/ + } + + if (types & L1D_FLUSH_MTTRIG) + instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */ + + for (i = 0; start < end; start++, i++) { + dest = (void *)start + *start; + + pr_devel("patching dest %lx\n", (unsigned long)dest); + + patch_instruction(dest, instrs[0]); + + if (types == L1D_FLUSH_FALLBACK) + patch_branch((dest + 1), (unsigned long)&entry_flush_fallback, + BRANCH_SET_LINK); + else + patch_instruction((dest + 1), instrs[1]); + + patch_instruction((dest + 2), instrs[2]); + } + + printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i, + (types == L1D_FLUSH_NONE) ? "no" : + (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : + (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) + ? "ori+mttrig type" + : "ori type" : + (types & L1D_FLUSH_MTTRIG) ? "mttrig type" + : "unknown"); +} + void do_rfi_flush_fixups(enum l1d_flush_type types) { unsigned int instrs[3], *dest; diff --git a/arch/powerpc/lib/string_32.S b/arch/powerpc/lib/string_32.S index f69a6aab7bfb..1ddb26394e8a 100644 --- a/arch/powerpc/lib/string_32.S +++ b/arch/powerpc/lib/string_32.S @@ -17,7 +17,7 @@ CACHELINE_BYTES = L1_CACHE_BYTES LG_CACHELINE_BYTES = L1_CACHE_SHIFT CACHELINE_MASK = (L1_CACHE_BYTES-1) -_GLOBAL(__clear_user) +_GLOBAL(__arch_clear_user) /* * Use dcbz on the complete cache lines in the destination * to set them to zero. This requires that the destination @@ -87,4 +87,4 @@ _GLOBAL(__clear_user) EX_TABLE(8b, 91b) EX_TABLE(9b, 91b) -EXPORT_SYMBOL(__clear_user) +EXPORT_SYMBOL(__arch_clear_user) diff --git a/arch/powerpc/lib/string_64.S b/arch/powerpc/lib/string_64.S index 56aac4c22025..ea3798f4f25f 100644 --- a/arch/powerpc/lib/string_64.S +++ b/arch/powerpc/lib/string_64.S @@ -29,7 +29,7 @@ PPC64_CACHES: .section ".text" /** - * __clear_user: - Zero a block of memory in user space, with less checking. + * __arch_clear_user: - Zero a block of memory in user space, with less checking. * @to: Destination address, in user space. * @n: Number of bytes to zero. * @@ -70,7 +70,7 @@ err3; stb r0,0(r3) mr r3,r4 blr -_GLOBAL_TOC(__clear_user) +_GLOBAL_TOC(__arch_clear_user) cmpdi r4,32 neg r6,r3 li r0,0 @@ -193,4 +193,4 @@ err1; dcbz 0,r3 cmpdi r4,32 blt .Lshort_clear b .Lmedium_clear -EXPORT_SYMBOL(__clear_user) +EXPORT_SYMBOL(__arch_clear_user) diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index f227e7b7e6fc..904bddcb8e17 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -2044,7 +2044,17 @@ static void record_and_restart(struct perf_event *event, unsigned long val, left += period; if (left <= 0) left = period; - record = siar_valid(regs); + + /* + * If address is not requested in the sample via + * PERF_SAMPLE_IP, just record that sample irrespective + * of SIAR valid check. + */ + if (event->attr.sample_type & PERF_SAMPLE_IP) + record = siar_valid(regs); + else + record = 1; + event->hw.last_period = event->hw.sample_period; } if (left < 0x80000000LL) @@ -2056,6 +2066,17 @@ static void record_and_restart(struct perf_event *event, unsigned long val, local64_set(&event->hw.period_left, left); perf_event_update_userpage(event); + /* + * Due to hardware limitation, sometimes SIAR could sample a kernel + * address even when freeze on supervisor state (kernel) is set in + * MMCR2. Check attr.exclude_kernel and address to drop the sample in + * these cases. + */ + if (event->attr.exclude_kernel && + (event->attr.sample_type & PERF_SAMPLE_IP) && + is_kernel_addr(mfspr(SPRN_SIAR))) + record = 0; + /* * Finally record data if requested. */ diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index 84d038ed3882..ce6597a29bc9 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c @@ -33,6 +33,7 @@ struct memtrace_entry { char name[16]; }; +static DEFINE_MUTEX(memtrace_mutex); static u64 memtrace_size; static struct memtrace_entry *memtrace_array; @@ -70,6 +71,23 @@ static int change_memblock_state(struct memory_block *mem, void *arg) return 0; } +static void memtrace_clear_range(unsigned long start_pfn, + unsigned long nr_pages) +{ + unsigned long pfn; + + /* + * As pages are offline, we cannot trust the memmap anymore. As HIGHMEM + * does not apply, avoid passing around "struct page" and use + * clear_page() instead directly. + */ + for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) { + if (IS_ALIGNED(pfn, PAGES_PER_SECTION)) + cond_resched(); + clear_page(__va(PFN_PHYS(pfn))); + } +} + /* called with device_hotplug_lock held */ static bool memtrace_offline_pages(u32 nid, u64 start_pfn, u64 nr_pages) { @@ -114,6 +132,11 @@ static u64 memtrace_alloc_node(u32 nid, u64 size) lock_device_hotplug(); for (base_pfn = end_pfn; base_pfn > start_pfn; base_pfn -= nr_pages) { if (memtrace_offline_pages(nid, base_pfn, nr_pages) == true) { + /* + * Clear the range while we still have a linear + * mapping. + */ + memtrace_clear_range(base_pfn, nr_pages); /* * Remove memory in memory block size chunks so that * iomem resources are always split to the same size and @@ -272,6 +295,7 @@ static int memtrace_online(void) static int memtrace_enable_set(void *data, u64 val) { + int rc = -EAGAIN; u64 bytes; /* @@ -284,25 +308,31 @@ static int memtrace_enable_set(void *data, u64 val) return -EINVAL; } + mutex_lock(&memtrace_mutex); + /* Re-add/online previously removed/offlined memory */ if (memtrace_size) { if (memtrace_online()) - return -EAGAIN; + goto out_unlock; } - if (!val) - return 0; + if (!val) { + rc = 0; + goto out_unlock; + } /* Offline and remove memory */ if (memtrace_init_regions_runtime(val)) - return -EINVAL; + goto out_unlock; if (memtrace_init_debugfs()) - return -EINVAL; + goto out_unlock; memtrace_size = val; - - return 0; + rc = 0; +out_unlock: + mutex_unlock(&memtrace_mutex); + return rc; } static int memtrace_enable_get(void *data, u64 *val) diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index adddde023622..5068dd7f6e74 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c @@ -125,12 +125,29 @@ static void pnv_setup_rfi_flush(void) type = L1D_FLUSH_ORI; } + /* + * If we are non-Power9 bare metal, we don't need to flush on kernel + * entry or after user access: they fix a P9 specific vulnerability. + */ + if (!pvr_version_is(PVR_POWER9)) { + security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY); + security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS); + } + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \ security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); setup_rfi_flush(type, enable); setup_count_cache_flush(); + + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && + security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY); + setup_entry_flush(enable); + + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && + security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS); + setup_uaccess_flush(enable); } static void __init pnv_setup_arch(void) diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c index 502ebcc6c3cb..142655bfd6f6 100644 --- a/arch/powerpc/platforms/pseries/cmm.c +++ b/arch/powerpc/platforms/pseries/cmm.c @@ -208,7 +208,7 @@ static long cmm_alloc_pages(long nr) pa->page[pa->index++] = addr; loaned_pages++; - totalram_pages--; + totalram_pages_dec(); spin_unlock(&cmm_lock); nr--; } @@ -247,7 +247,7 @@ static long cmm_free_pages(long nr) free_page(addr); loaned_pages--; nr--; - totalram_pages++; + totalram_pages_inc(); } spin_unlock(&cmm_lock); cmm_dbg("End request with %ld pages unfulfilled\n", nr); @@ -291,7 +291,7 @@ static void cmm_get_mpp(void) int rc; struct hvcall_mpp_data mpp_data; signed long active_pages_target, page_loan_request, target; - signed long total_pages = totalram_pages + loaned_pages; + signed long total_pages = totalram_pages() + loaned_pages; signed long min_mem_pages = (min_mem_mb * 1024 * 1024) / PAGE_SIZE; rc = h_get_mpp(&mpp_data); @@ -322,7 +322,7 @@ static void cmm_get_mpp(void) cmm_dbg("delta = %ld, loaned = %lu, target = %lu, oom = %lu, totalram = %lu\n", page_loan_request, loaned_pages, loaned_pages_target, - oom_freed_pages, totalram_pages); + oom_freed_pages, totalram_pages()); } static struct notifier_block cmm_oom_nb = { @@ -586,7 +586,7 @@ static int cmm_mem_going_offline(void *arg) free_page(pa_curr->page[idx]); freed++; loaned_pages--; - totalram_pages++; + totalram_pages_inc(); pa_curr->page[idx] = pa_last->page[--pa_last->index]; if (pa_last->index == 0) { if (pa_curr == pa_last) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index c5ffcadab730..90fd03b9d3c2 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -132,7 +132,6 @@ void dlpar_free_cc_nodes(struct device_node *dn) #define NEXT_PROPERTY 3 #define PREV_PARENT 4 #define MORE_MEMORY 5 -#define CALL_AGAIN -2 #define ERR_CFG_USE -9003 struct device_node *dlpar_configure_connector(__be32 drc_index, @@ -173,6 +172,9 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, spin_unlock(&rtas_data_buf_lock); + if (rtas_busy_delay(rc)) + continue; + switch (rc) { case COMPLETE: break; @@ -221,9 +223,6 @@ struct device_node *dlpar_configure_connector(__be32 drc_index, last_dn = last_dn->parent; break; - case CALL_AGAIN: - break; - case MORE_MEMORY: case ERR_CFG_USE: default: diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index c2d318d1df02..2e0d38cafdd4 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -565,6 +565,14 @@ void pseries_setup_rfi_flush(void) setup_rfi_flush(types, enable); setup_count_cache_flush(); + + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && + security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY); + setup_entry_flush(enable); + + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && + security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS); + setup_uaccess_flush(enable); } #ifdef CONFIG_PCI_IOV diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index 52a021e1f86b..5414d3295e0a 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c @@ -26,7 +26,6 @@ #include #include #include -#include "../../kernel/cacheinfo.h" static u64 stream_id; static struct device suspend_dev; @@ -91,9 +90,7 @@ static void pseries_suspend_enable_irqs(void) * Update configuration which can be modified based on device tree * changes during resume. */ - cacheinfo_cpu_offline(smp_processor_id()); post_mobility_fixup(); - cacheinfo_cpu_online(smp_processor_id()); } /** @@ -223,7 +220,6 @@ static struct bus_type suspend_subsys = { static const struct platform_suspend_ops pseries_suspend_ops = { .valid = suspend_valid_only_mem, - .begin = pseries_suspend_begin, .prepare_late = pseries_prepare_late, .enter = pseries_suspend_enter, }; diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index 280e964e1aa8..497e86cfb12e 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c @@ -196,7 +196,7 @@ static int mpic_msgr_probe(struct platform_device *dev) /* IO map the message register block. */ of_address_to_resource(np, 0, &rsrc); - msgr_block_addr = ioremap(rsrc.start, resource_size(&rsrc)); + msgr_block_addr = devm_ioremap(&dev->dev, rsrc.start, resource_size(&rsrc)); if (!msgr_block_addr) { dev_err(&dev->dev, "Failed to iomap MPIC message registers"); return -EFAULT; diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c index d00123421e00..eefe1b94e0aa 100644 --- a/arch/powerpc/xmon/nonstdio.c +++ b/arch/powerpc/xmon/nonstdio.c @@ -182,7 +182,7 @@ void xmon_printf(const char *format, ...) if (n && rc == 0) { /* No udbg hooks, fallback to printk() - dangerous */ - printk("%s", xmon_outbuf); + pr_cont("%s", xmon_outbuf); } } diff --git a/arch/riscv/include/asm/page.h b/arch/riscv/include/asm/page.h index 06cfbb3aacbb..abc147aeff8b 100644 --- a/arch/riscv/include/asm/page.h +++ b/arch/riscv/include/asm/page.h @@ -115,7 +115,10 @@ extern unsigned long min_low_pfn; #endif /* __ASSEMBLY__ */ -#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) +#define virt_addr_valid(vaddr) ({ \ + unsigned long _addr = (unsigned long)vaddr; \ + (unsigned long)(_addr) >= PAGE_OFFSET && pfn_valid(virt_to_pfn(_addr)); \ +}) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index a03821b2656a..d9de22686e27 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -449,6 +449,7 @@ ENDPROC(__fstate_restore) .section ".rodata" + .align LGREG /* Exception vector table */ ENTRY(excp_vect_table) RISCV_PTR do_trap_insn_misaligned diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c index 1911c8f6b8a6..15f4ab40e222 100644 --- a/arch/riscv/kernel/time.c +++ b/arch/riscv/kernel/time.c @@ -12,6 +12,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -29,5 +30,7 @@ void __init time_init(void) riscv_timebase = prop; lpj_fine = riscv_timebase / HZ; + + of_clk_init(NULL); timer_probe(); } diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c index 2bc189187ed4..0302303b823f 100644 --- a/arch/s390/crypto/aes_s390.c +++ b/arch/s390/crypto/aes_s390.c @@ -44,7 +44,7 @@ struct s390_aes_ctx { int key_len; unsigned long fc; union { - struct crypto_skcipher *blk; + struct crypto_sync_skcipher *blk; struct crypto_cipher *cip; } fallback; }; @@ -54,7 +54,7 @@ struct s390_xts_ctx { u8 pcc_key[32]; int key_len; unsigned long fc; - struct crypto_skcipher *fallback; + struct crypto_sync_skcipher *fallback; }; struct gcm_sg_walk { @@ -184,14 +184,15 @@ static int setkey_fallback_blk(struct crypto_tfm *tfm, const u8 *key, struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); unsigned int ret; - crypto_skcipher_clear_flags(sctx->fallback.blk, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(sctx->fallback.blk, tfm->crt_flags & + crypto_sync_skcipher_clear_flags(sctx->fallback.blk, + CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(sctx->fallback.blk, tfm->crt_flags & CRYPTO_TFM_REQ_MASK); - ret = crypto_skcipher_setkey(sctx->fallback.blk, key, len); + ret = crypto_sync_skcipher_setkey(sctx->fallback.blk, key, len); tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; - tfm->crt_flags |= crypto_skcipher_get_flags(sctx->fallback.blk) & + tfm->crt_flags |= crypto_sync_skcipher_get_flags(sctx->fallback.blk) & CRYPTO_TFM_RES_MASK; return ret; @@ -204,9 +205,9 @@ static int fallback_blk_dec(struct blkcipher_desc *desc, unsigned int ret; struct crypto_blkcipher *tfm = desc->tfm; struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); - skcipher_request_set_tfm(req, sctx->fallback.blk); + skcipher_request_set_sync_tfm(req, sctx->fallback.blk); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -223,9 +224,9 @@ static int fallback_blk_enc(struct blkcipher_desc *desc, unsigned int ret; struct crypto_blkcipher *tfm = desc->tfm; struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, sctx->fallback.blk); - skcipher_request_set_tfm(req, sctx->fallback.blk); + skcipher_request_set_sync_tfm(req, sctx->fallback.blk); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -306,8 +307,7 @@ static int fallback_init_blk(struct crypto_tfm *tfm) const char *name = tfm->__crt_alg->cra_name; struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - sctx->fallback.blk = crypto_alloc_skcipher(name, 0, - CRYPTO_ALG_ASYNC | + sctx->fallback.blk = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(sctx->fallback.blk)) { @@ -323,7 +323,7 @@ static void fallback_exit_blk(struct crypto_tfm *tfm) { struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm); - crypto_free_skcipher(sctx->fallback.blk); + crypto_free_sync_skcipher(sctx->fallback.blk); } static struct crypto_alg ecb_aes_alg = { @@ -453,14 +453,15 @@ static int xts_fallback_setkey(struct crypto_tfm *tfm, const u8 *key, struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); unsigned int ret; - crypto_skcipher_clear_flags(xts_ctx->fallback, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(xts_ctx->fallback, tfm->crt_flags & + crypto_sync_skcipher_clear_flags(xts_ctx->fallback, + CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(xts_ctx->fallback, tfm->crt_flags & CRYPTO_TFM_REQ_MASK); - ret = crypto_skcipher_setkey(xts_ctx->fallback, key, len); + ret = crypto_sync_skcipher_setkey(xts_ctx->fallback, key, len); tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK; - tfm->crt_flags |= crypto_skcipher_get_flags(xts_ctx->fallback) & + tfm->crt_flags |= crypto_sync_skcipher_get_flags(xts_ctx->fallback) & CRYPTO_TFM_RES_MASK; return ret; @@ -472,10 +473,10 @@ static int xts_fallback_decrypt(struct blkcipher_desc *desc, { struct crypto_blkcipher *tfm = desc->tfm; struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); unsigned int ret; - skcipher_request_set_tfm(req, xts_ctx->fallback); + skcipher_request_set_sync_tfm(req, xts_ctx->fallback); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -491,10 +492,10 @@ static int xts_fallback_encrypt(struct blkcipher_desc *desc, { struct crypto_blkcipher *tfm = desc->tfm; struct s390_xts_ctx *xts_ctx = crypto_blkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(req, xts_ctx->fallback); unsigned int ret; - skcipher_request_set_tfm(req, xts_ctx->fallback); + skcipher_request_set_sync_tfm(req, xts_ctx->fallback); skcipher_request_set_callback(req, desc->flags, NULL, NULL); skcipher_request_set_crypt(req, src, dst, nbytes, desc->info); @@ -617,8 +618,7 @@ static int xts_fallback_init(struct crypto_tfm *tfm) const char *name = tfm->__crt_alg->cra_name; struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); - xts_ctx->fallback = crypto_alloc_skcipher(name, 0, - CRYPTO_ALG_ASYNC | + xts_ctx->fallback = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(xts_ctx->fallback)) { @@ -633,7 +633,7 @@ static void xts_fallback_exit(struct crypto_tfm *tfm) { struct s390_xts_ctx *xts_ctx = crypto_tfm_ctx(tfm); - crypto_free_skcipher(xts_ctx->fallback); + crypto_free_sync_skcipher(xts_ctx->fallback); } static struct crypto_alg xts_aes_alg = { diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index af013b4244d3..2da027359798 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -37,10 +37,12 @@ static int diag8_noresponse(int cmdlen) static int diag8_response(int cmdlen, char *response, int *rlen) { + unsigned long _cmdlen = cmdlen | 0x40000000L; + unsigned long _rlen = *rlen; register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; register unsigned long reg3 asm ("3") = (addr_t) response; - register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; - register unsigned long reg5 asm ("5") = *rlen; + register unsigned long reg4 asm ("4") = _cmdlen; + register unsigned long reg5 asm ("5") = _rlen; asm volatile( " diag %2,%0,0x8\n" diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 150130c897c3..7e6a9cf863c7 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -949,6 +949,7 @@ ENTRY(ext_int_handler) * Load idle PSW. The second "half" of this function is in .Lcleanup_idle. */ ENTRY(psw_idle) + stg %r14,(__SF_GPRS+8*8)(%r15) stg %r3,__SF_EMPTY(%r15) larl %r1,.Lpsw_idle_lpsw+4 stg %r1,__SF_EMPTY+8(%r15) diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c index 0e6d01225a67..c8e1e325215b 100644 --- a/arch/s390/kernel/perf_cpum_sf.c +++ b/arch/s390/kernel/perf_cpum_sf.c @@ -2097,4 +2097,4 @@ static int __init init_cpum_sampling_pmu(void) return err; } arch_initcall(init_cpum_sampling_pmu); -core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0640); +core_param(cpum_sfb_size, CPUM_SF_MAX_SDB, sfb_size, 0644); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 8e31dfd85de3..bce678c7179c 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -751,7 +751,7 @@ static int smp_add_core(struct sclp_core_entry *core, cpumask_t *avail, static int __smp_rescan_cpus(struct sclp_core_info *info, bool early) { struct sclp_core_entry *core; - cpumask_t avail; + static cpumask_t avail; bool configured; u16 core_id; int nr, i; @@ -831,7 +831,7 @@ void __init smp_detect_cpus(void) */ static void smp_start_secondary(void *cpuvoid) { - int cpu = smp_processor_id(); + int cpu = raw_smp_processor_id(); S390_lowcore.last_update_clock = get_tod_clock(); S390_lowcore.restart_stack = (unsigned long) restart_stack; @@ -844,6 +844,7 @@ static void smp_start_secondary(void *cpuvoid) set_cpu_flag(CIF_ASCE_PRIMARY); set_cpu_flag(CIF_ASCE_SECONDARY); cpu_init(); + rcu_cpu_starting(cpu); preempt_disable(); init_cpu_timer(); vtime_init(); @@ -862,24 +863,12 @@ static void smp_start_secondary(void *cpuvoid) /* Upping and downing of CPUs */ int __cpu_up(unsigned int cpu, struct task_struct *tidle) { - struct pcpu *pcpu; - int base, i, rc; + struct pcpu *pcpu = pcpu_devices + cpu; + int rc; - pcpu = pcpu_devices + cpu; if (pcpu->state != CPU_STATE_CONFIGURED) return -EIO; - base = smp_get_base_cpu(cpu); - for (i = 0; i <= smp_cpu_mtid; i++) { - if (base + i < nr_cpu_ids) - if (cpu_online(base + i)) - break; - } - /* - * If this is the first CPU of the core to get online - * do an initial CPU reset. - */ - if (i > smp_cpu_mtid && - pcpu_sigp_retry(pcpu_devices + base, SIGP_INITIAL_CPU_RESET, 0) != + if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) != SIGP_CC_ORDER_CODE_ACCEPTED) return -EIO; diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 379a925d9e82..584af6d7d952 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -59,7 +59,7 @@ static void __init setup_zero_pages(void) order = 7; /* Limit number of empty zero pages for small memory sizes */ - while (order > 2 && (totalram_pages >> 10) < (1UL << order)) + while (order > 2 && (totalram_pages() >> 10) < (1UL << order)) order--; empty_zero_page = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); diff --git a/arch/s390/purgatory/head.S b/arch/s390/purgatory/head.S index 2e3707b12edd..9b2d7a71fd1b 100644 --- a/arch/s390/purgatory/head.S +++ b/arch/s390/purgatory/head.S @@ -61,14 +61,15 @@ jh 10b .endm -.macro START_NEXT_KERNEL base +.macro START_NEXT_KERNEL base subcode lg %r4,kernel_entry-\base(%r13) lg %r5,load_psw_mask-\base(%r13) ogr %r4,%r5 stg %r4,0(%r0) xgr %r0,%r0 - diag %r0,%r0,0x308 + lghi %r1,\subcode + diag %r0,%r1,0x308 .endm .text @@ -123,7 +124,7 @@ ENTRY(purgatory_start) je .start_crash_kernel /* start normal kernel */ - START_NEXT_KERNEL .base_crash + START_NEXT_KERNEL .base_crash 0 .return_old_kernel: lmg %r6,%r15,gprregs-.base_crash(%r13) @@ -227,7 +228,7 @@ ENTRY(purgatory_start) MEMCPY %r9,%r10,%r11 /* start crash kernel */ - START_NEXT_KERNEL .base_dst + START_NEXT_KERNEL .base_dst 1 load_psw_mask: diff --git a/arch/sh/drivers/dma/Kconfig b/arch/sh/drivers/dma/Kconfig index d0de378beefe..7d54f284ce10 100644 --- a/arch/sh/drivers/dma/Kconfig +++ b/arch/sh/drivers/dma/Kconfig @@ -63,8 +63,7 @@ config PVR2_DMA config G2_DMA tristate "G2 Bus DMA support" - depends on SH_DREAMCAST - select SH_DMA_API + depends on SH_DREAMCAST && SH_DMA_API help This enables support for the DMA controller for the Dreamcast's G2 bus. Drivers that want this will generally enable this on diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index e6f2a38d2e61..1f1a7583fa90 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -554,7 +554,7 @@ config COMPAT bool depends on SPARC64 default y - select COMPAT_BINFMT_ELF + select COMPAT_BINFMT_ELF if BINFMT_ELF select HAVE_UID16 select ARCH_WANT_OLD_COMPAT_IPC select COMPAT_OLD_SIGACTION diff --git a/arch/sparc/include/asm/mman.h b/arch/sparc/include/asm/mman.h index f94532f25db1..274217e7ed70 100644 --- a/arch/sparc/include/asm/mman.h +++ b/arch/sparc/include/asm/mman.h @@ -57,35 +57,39 @@ static inline int sparc_validate_prot(unsigned long prot, unsigned long addr) { if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM | PROT_ADI)) return 0; - if (prot & PROT_ADI) { - if (!adi_capable()) - return 0; + return 1; +} - if (addr) { - struct vm_area_struct *vma; +#define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags) +/* arch_validate_flags() - Ensure combination of flags is valid for a + * VMA. + */ +static inline bool arch_validate_flags(unsigned long vm_flags) +{ + /* If ADI is being enabled on this VMA, check for ADI + * capability on the platform and ensure VMA is suitable + * for ADI + */ + if (vm_flags & VM_SPARC_ADI) { + if (!adi_capable()) + return false; - vma = find_vma(current->mm, addr); - if (vma) { - /* ADI can not be enabled on PFN - * mapped pages - */ - if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) - return 0; + /* ADI can not be enabled on PFN mapped pages */ + if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) + return false; - /* Mergeable pages can become unmergeable - * if ADI is enabled on them even if they - * have identical data on them. This can be - * because ADI enabled pages with identical - * data may still not have identical ADI - * tags on them. Disallow ADI on mergeable - * pages. - */ - if (vma->vm_flags & VM_MERGEABLE) - return 0; - } - } + /* Mergeable pages can become unmergeable + * if ADI is enabled on them even if they + * have identical data on them. This can be + * because ADI enabled pages with identical + * data may still not have identical ADI + * tags on them. Disallow ADI on mergeable + * pages. + */ + if (vm_flags & VM_MERGEABLE) + return false; } - return 1; + return true; } #endif /* CONFIG_SPARC64 */ diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c index aa624ed79db1..86879c28910b 100644 --- a/arch/sparc/kernel/traps_64.c +++ b/arch/sparc/kernel/traps_64.c @@ -274,14 +274,13 @@ bool is_no_fault_exception(struct pt_regs *regs) asi = (regs->tstate >> 24); /* saved %asi */ else asi = (insn >> 5); /* immediate asi */ - if ((asi & 0xf2) == ASI_PNF) { - if (insn & 0x1000000) { /* op3[5:4]=3 */ - handle_ldf_stq(insn, regs); - return true; - } else if (insn & 0x200000) { /* op3[2], stores */ + if ((asi & 0xf6) == ASI_PNF) { + if (insn & 0x200000) /* op3[2], stores */ return false; - } - handle_ld_nf(insn, regs); + if (insn & 0x1000000) /* op3[5:4]=3 (fp) */ + handle_ldf_stq(insn, regs); + else + handle_ld_nf(insn, regs); return true; } } diff --git a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S index b89d42b29e34..f427f34b8b79 100644 --- a/arch/sparc/lib/memset.S +++ b/arch/sparc/lib/memset.S @@ -142,6 +142,7 @@ __bzero: ZERO_LAST_BLOCKS(%o0, 0x48, %g2) ZERO_LAST_BLOCKS(%o0, 0x08, %g2) 13: + EXT(12b, 13b, 21f) be 8f andcc %o1, 4, %g0 diff --git a/arch/sparc/mm/init_32.c b/arch/sparc/mm/init_32.c index 92634d4e440c..89a9244f2cf0 100644 --- a/arch/sparc/mm/init_32.c +++ b/arch/sparc/mm/init_32.c @@ -199,6 +199,9 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) size = memblock_phys_mem_size() - memblock_reserved_size(); *pages_avail = (size >> PAGE_SHIFT) - high_pages; + /* Only allow low memory to be allocated via memblock allocation */ + memblock_set_current_limit(max_low_pfn << PAGE_SHIFT); + return max_pfn; } diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 3fd7c3efdb18..9cffbbb15c56 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -26,10 +26,10 @@ int generic_read(int fd, char *c_out, void *unused) n = read(fd, c_out, sizeof(*c_out)); if (n > 0) return n; - else if (errno == EAGAIN) - return 0; else if (n == 0) return -EIO; + else if (errno == EAGAIN) + return 0; return -errno; } diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 20e30be44795..e3b422ebce09 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -18,6 +18,7 @@ struct xterm_chan { int pid; int helper_pid; + int chan_fd; char *title; int device; int raw; @@ -33,6 +34,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts) return NULL; *data = ((struct xterm_chan) { .pid = -1, .helper_pid = -1, + .chan_fd = -1, .device = device, .title = opts->xterm_title, .raw = opts->raw } ); @@ -149,6 +151,7 @@ static int xterm_open(int input, int output, int primary, void *d, goto out_kill; } + data->chan_fd = fd; new = xterm_fd(fd, &data->helper_pid); if (new < 0) { err = new; @@ -206,6 +209,8 @@ static void xterm_close(int fd, void *d) os_kill_process(data->helper_pid, 0); data->helper_pid = -1; + if (data->chan_fd != -1) + os_close_file(data->chan_fd); os_close_file(fd); } diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 3c0e470ea646..29f8dc275a51 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -51,8 +51,8 @@ void __init mem_init(void) /* this will put all low memory onto the freelists */ free_all_bootmem(); - max_low_pfn = totalram_pages; - max_pfn = totalram_pages; + max_low_pfn = totalram_pages(); + max_pfn = totalram_pages(); mem_init_print_info(NULL); kmalloc_ok = 1; } diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c index 365823010346..90ef40462280 100644 --- a/arch/um/os-Linux/irq.c +++ b/arch/um/os-Linux/irq.c @@ -48,7 +48,7 @@ int os_epoll_triggered(int index, int events) int os_event_mask(int irq_type) { if (irq_type == IRQ_READ) - return EPOLLIN | EPOLLPRI; + return EPOLLIN | EPOLLPRI | EPOLLERR | EPOLLHUP | EPOLLRDHUP; if (irq_type == IRQ_WRITE) return EPOLLOUT; return 0; diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 7f233461a9cd..74bfaab14b25 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -34,7 +34,7 @@ M16_CFLAGS := $(call cc-option, -m16, $(CODE16GCC_CFLAGS)) REALMODE_CFLAGS := $(M16_CFLAGS) -g -Os -DDISABLE_BRANCH_PROFILING \ -Wall -Wstrict-prototypes -march=i386 -mregparm=3 \ -fno-strict-aliasing -fomit-frame-pointer -fno-pic \ - -mno-mmx -mno-sse + -mno-mmx -mno-sse $(call cc-option,-fcf-protection=none) REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -ffreestanding) REALMODE_CFLAGS += $(call __cc-option, $(CC), $(REALMODE_CFLAGS), -fno-stack-protector) @@ -61,6 +61,9 @@ endif KBUILD_CFLAGS += -mno-sse -mno-mmx -mno-sse2 -mno-3dnow KBUILD_CFLAGS += $(call cc-option,-mno-avx,) +# Intel CET isn't enabled in the kernel +KBUILD_CFLAGS += $(call cc-option,-fcf-protection=none) + ifeq ($(CONFIG_X86_32),y) BITS := 32 UTS_MACHINE := i386 diff --git a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S index d9b734d0c8cc..3c6e01520a97 100644 --- a/arch/x86/crypto/crc32c-pcl-intel-asm_64.S +++ b/arch/x86/crypto/crc32c-pcl-intel-asm_64.S @@ -170,7 +170,7 @@ continue_block: ## branch into array lea jump_table(%rip), bufp - movzxw (bufp, %rax, 2), len + movzwq (bufp, %rax, 2), len lea crc_array(%rip), bufp lea (bufp, len, 1), bufp JMP_NOSPEC bufp diff --git a/arch/x86/crypto/fpu.c b/arch/x86/crypto/fpu.c index 406680476c52..be9b3766f241 100644 --- a/arch/x86/crypto/fpu.c +++ b/arch/x86/crypto/fpu.c @@ -20,21 +20,23 @@ #include struct crypto_fpu_ctx { - struct crypto_skcipher *child; + struct crypto_sync_skcipher *child; }; static int crypto_fpu_setkey(struct crypto_skcipher *parent, const u8 *key, unsigned int keylen) { struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(parent); - struct crypto_skcipher *child = ctx->child; + struct crypto_sync_skcipher *child = ctx->child; int err; - crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(parent) & + crypto_sync_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(child, + crypto_skcipher_get_flags(parent) & CRYPTO_TFM_REQ_MASK); - err = crypto_skcipher_setkey(child, key, keylen); - crypto_skcipher_set_flags(parent, crypto_skcipher_get_flags(child) & + err = crypto_sync_skcipher_setkey(child, key, keylen); + crypto_skcipher_set_flags(parent, + crypto_sync_skcipher_get_flags(child) & CRYPTO_TFM_RES_MASK); return err; } @@ -43,11 +45,11 @@ static int crypto_fpu_encrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_skcipher *child = ctx->child; - SKCIPHER_REQUEST_ON_STACK(subreq, child); + struct crypto_sync_skcipher *child = ctx->child; + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, child); int err; - skcipher_request_set_tfm(subreq, child); + skcipher_request_set_sync_tfm(subreq, child); skcipher_request_set_callback(subreq, 0, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, req->iv); @@ -64,11 +66,11 @@ static int crypto_fpu_decrypt(struct skcipher_request *req) { struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - struct crypto_skcipher *child = ctx->child; - SKCIPHER_REQUEST_ON_STACK(subreq, child); + struct crypto_sync_skcipher *child = ctx->child; + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, child); int err; - skcipher_request_set_tfm(subreq, child); + skcipher_request_set_sync_tfm(subreq, child); skcipher_request_set_callback(subreq, 0, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, req->iv); @@ -93,7 +95,7 @@ static int crypto_fpu_init_tfm(struct crypto_skcipher *tfm) if (IS_ERR(cipher)) return PTR_ERR(cipher); - ctx->child = cipher; + ctx->child = (struct crypto_sync_skcipher *)cipher; return 0; } @@ -102,7 +104,7 @@ static void crypto_fpu_exit_tfm(struct crypto_skcipher *tfm) { struct crypto_fpu_ctx *ctx = crypto_skcipher_ctx(tfm); - crypto_free_skcipher(ctx->child); + crypto_free_sync_skcipher(ctx->child); } static void crypto_fpu_free(struct skcipher_instance *inst) diff --git a/arch/x86/events/intel/cstate.c b/arch/x86/events/intel/cstate.c index 4a650eb3d94a..3b3cd12c0692 100644 --- a/arch/x86/events/intel/cstate.c +++ b/arch/x86/events/intel/cstate.c @@ -100,14 +100,14 @@ MODULE_LICENSE("GPL"); #define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \ -static ssize_t __cstate_##_var##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ +static ssize_t __cstate_##_var##_show(struct device *dev, \ + struct device_attribute *attr, \ char *page) \ { \ BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ return sprintf(page, _format "\n"); \ } \ -static struct kobj_attribute format_attr_##_var = \ +static struct device_attribute format_attr_##_var = \ __ATTR(_name, 0444, __cstate_##_var##_show, NULL) static ssize_t cstate_get_attr_cpumask(struct device *dev, diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 79caeba8b6f0..b3279feff458 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -1557,7 +1557,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs) */ if (!pebs_status && cpuc->pebs_enabled && !(cpuc->pebs_enabled & (cpuc->pebs_enabled-1))) - pebs_status = cpuc->pebs_enabled; + pebs_status = p->status = cpuc->pebs_enabled; bit = find_first_bit((unsigned long *)&pebs_status, x86_pmu.max_pebs_events); diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index 2413169ce362..bc348663da94 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c @@ -115,18 +115,6 @@ static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { * any other bit is reserved */ #define RAPL_EVENT_MASK 0xFFULL - -#define DEFINE_RAPL_FORMAT_ATTR(_var, _name, _format) \ -static ssize_t __rapl_##_var##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ - char *page) \ -{ \ - BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ - return sprintf(page, _format "\n"); \ -} \ -static struct kobj_attribute format_attr_##_var = \ - __ATTR(_name, 0444, __rapl_##_var##_show, NULL) - #define RAPL_CNTR_WIDTH 32 #define RAPL_EVENT_ATTR_STR(_name, v, str) \ @@ -548,7 +536,7 @@ static struct attribute_group rapl_pmu_events_group = { .attrs = NULL, /* patched at runtime */ }; -DEFINE_RAPL_FORMAT_ATTR(event, event, "config:0-7"); +PMU_FORMAT_ATTR(event, "config:0-7"); static struct attribute *rapl_formats_attr[] = { &format_attr_event.attr, NULL, diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c index 7098b9b05d56..2f4ed5aa08ba 100644 --- a/arch/x86/events/intel/uncore.c +++ b/arch/x86/events/intel/uncore.c @@ -90,8 +90,8 @@ struct pci2phy_map *__find_pci2phy_map(int segment) return map; } -ssize_t uncore_event_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) +ssize_t uncore_event_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct uncore_event_desc *event = container_of(attr, struct uncore_event_desc, attr); diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h index 40e040ec31b5..0fc86ac73b51 100644 --- a/arch/x86/events/intel/uncore.h +++ b/arch/x86/events/intel/uncore.h @@ -133,7 +133,7 @@ struct intel_uncore_box { #define UNCORE_BOX_FLAG_CTL_OFFS8 1 /* event config registers are 8-byte apart */ struct uncore_event_desc { - struct kobj_attribute attr; + struct device_attribute attr; const char *config; }; @@ -153,8 +153,8 @@ struct pci2phy_map { struct pci2phy_map *__find_pci2phy_map(int segment); -ssize_t uncore_event_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf); +ssize_t uncore_event_show(struct device *dev, + struct device_attribute *attr, char *buf); #define INTEL_UNCORE_EVENT_DESC(_name, _config) \ { \ @@ -163,14 +163,14 @@ ssize_t uncore_event_show(struct kobject *kobj, } #define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format) \ -static ssize_t __uncore_##_var##_show(struct kobject *kobj, \ - struct kobj_attribute *attr, \ +static ssize_t __uncore_##_var##_show(struct device *dev, \ + struct device_attribute *attr, \ char *page) \ { \ BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \ return sprintf(page, _format "\n"); \ } \ -static struct kobj_attribute format_attr_##_var = \ +static struct device_attribute format_attr_##_var = \ __ATTR(_name, 0444, __uncore_##_var##_show, NULL) static inline bool uncore_pmc_fixed(int idx) diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index 8e4e8e423839..c06074b847fa 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c @@ -1030,7 +1030,6 @@ enum { SNBEP_PCI_QPI_PORT0_FILTER, SNBEP_PCI_QPI_PORT1_FILTER, BDX_PCI_QPI_PORT2_FILTER, - HSWEP_PCI_PCU_3, }; static int snbep_qpi_hw_config(struct intel_uncore_box *box, struct perf_event *event) @@ -2687,22 +2686,33 @@ static struct intel_uncore_type *hswep_msr_uncores[] = { NULL, }; -void hswep_uncore_cpu_init(void) +#define HSWEP_PCU_DID 0x2fc0 +#define HSWEP_PCU_CAPID4_OFFET 0x94 +#define hswep_get_chop(_cap) (((_cap) >> 6) & 0x3) + +static bool hswep_has_limit_sbox(unsigned int device) { - int pkg = boot_cpu_data.logical_proc_id; + struct pci_dev *dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL); + u32 capid4; + + if (!dev) + return false; + + pci_read_config_dword(dev, HSWEP_PCU_CAPID4_OFFET, &capid4); + if (!hswep_get_chop(capid4)) + return true; + return false; +} + +void hswep_uncore_cpu_init(void) +{ if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores) hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores; /* Detect 6-8 core systems with only two SBOXes */ - if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) { - u32 capid4; - - pci_read_config_dword(uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3], - 0x94, &capid4); - if (((capid4 >> 6) & 0x3) == 0) - hswep_uncore_sbox.num_boxes = 2; - } + if (hswep_has_limit_sbox(HSWEP_PCU_DID)) + hswep_uncore_sbox.num_boxes = 2; uncore_msr_uncores = hswep_msr_uncores; } @@ -2965,11 +2975,6 @@ static const struct pci_device_id hswep_uncore_pci_ids[] = { .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, SNBEP_PCI_QPI_PORT1_FILTER), }, - { /* PCU.3 (for Capability registers) */ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2fc0), - .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, - HSWEP_PCI_PCU_3), - }, { /* end: all zeroes */ } }; @@ -3061,27 +3066,18 @@ static struct event_constraint bdx_uncore_pcu_constraints[] = { EVENT_CONSTRAINT_END }; +#define BDX_PCU_DID 0x6fc0 + void bdx_uncore_cpu_init(void) { - int pkg = topology_phys_to_logical_pkg(boot_cpu_data.phys_proc_id); - if (bdx_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores) bdx_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores; uncore_msr_uncores = bdx_msr_uncores; - /* BDX-DE doesn't have SBOX */ - if (boot_cpu_data.x86_model == 86) { - uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL; /* Detect systems with no SBOXes */ - } else if (uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]) { - struct pci_dev *pdev; - u32 capid4; - - pdev = uncore_extra_pci_dev[pkg].dev[HSWEP_PCI_PCU_3]; - pci_read_config_dword(pdev, 0x94, &capid4); - if (((capid4 >> 6) & 0x3) == 0) - bdx_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL; - } + if ((boot_cpu_data.x86_model == 86) || hswep_has_limit_sbox(BDX_PCU_DID)) + uncore_msr_uncores[BDX_MSR_UNCORE_SBOX] = NULL; + hswep_uncore_pcu.constraints = bdx_uncore_pcu_constraints; } @@ -3302,11 +3298,6 @@ static const struct pci_device_id bdx_uncore_pci_ids[] = { .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, BDX_PCI_QPI_PORT2_FILTER), }, - { /* PCU.3 (for Capability registers) */ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x6fc0), - .driver_data = UNCORE_PCI_DEV_DATA(UNCORE_EXTRA_PCI_DEV, - HSWEP_PCI_PCU_3), - }, { /* end: all zeroes */ } }; diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c index 2f34d5275352..e666f7eaf32d 100644 --- a/arch/x86/hyperv/mmu.c +++ b/arch/x86/hyperv/mmu.c @@ -66,11 +66,17 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus, if (!hv_hypercall_pg) goto do_native; - if (cpumask_empty(cpus)) - return; - local_irq_save(flags); + /* + * Only check the mask _after_ interrupt has been disabled to avoid the + * mask changing under our feet. + */ + if (cpumask_empty(cpus)) { + local_irq_restore(flags); + return; + } + flush_pcpu = (struct hv_tlb_flush **) this_cpu_ptr(hyperv_pcpu_input_arg); diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 3c1e51ead072..b5354e216b07 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -190,16 +190,6 @@ static inline void lapic_assign_legacy_vector(unsigned int i, bool r) { } #endif /* !CONFIG_X86_LOCAL_APIC */ #ifdef CONFIG_X86_X2APIC -/* - * Make previous memory operations globally visible before - * sending the IPI through x2apic wrmsr. We need a serializing instruction or - * mfence for this. - */ -static inline void x2apic_wrmsr_fence(void) -{ - asm volatile("mfence" : : : "memory"); -} - static inline void native_apic_msr_write(u32 reg, u32 v) { if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR || @@ -252,6 +242,7 @@ static inline u64 native_x2apic_icr_read(void) extern int x2apic_mode; extern int x2apic_phys; +extern void __init x2apic_set_max_apicid(u32 apicid); extern void __init check_x2apic(void); extern void x2apic_setup(void); static inline int x2apic_enabled(void) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index 84f848c2541a..dd22cffc6b3f 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -85,4 +85,22 @@ do { \ #include +/* + * Make previous memory operations globally visible before + * a WRMSR. + * + * MFENCE makes writes visible, but only affects load/store + * instructions. WRMSR is unfortunately not a load/store + * instruction and is unaffected by MFENCE. The LFENCE ensures + * that the WRMSR is not reordered. + * + * Most WRMSRs are full serializing instructions themselves and + * do not require this barrier. This is only required for the + * IA32_TSC_DEADLINE and X2APIC MSRs. + */ +static inline void weak_wrmsr_fence(void) +{ + asm volatile("mfence; lfence" : : : "memory"); +} + #endif /* _ASM_X86_BARRIER_H */ diff --git a/arch/x86/include/asm/insn.h b/arch/x86/include/asm/insn.h index c2c01f84df75..3e0e18d376d2 100644 --- a/arch/x86/include/asm/insn.h +++ b/arch/x86/include/asm/insn.h @@ -208,6 +208,21 @@ static inline int insn_offset_immediate(struct insn *insn) return insn_offset_displacement(insn) + insn->displacement.nbytes; } +/** + * for_each_insn_prefix() -- Iterate prefixes in the instruction + * @insn: Pointer to struct insn. + * @idx: Index storage. + * @prefix: Prefix byte. + * + * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix + * and the index is stored in @idx (note that this @idx is just for a cursor, + * do not change it.) + * Since prefixes.nbytes can be bigger than 4 if some prefixes + * are repeated, it cannot be used for looping over the prefixes. + */ +#define for_each_insn_prefix(insn, idx, prefix) \ + for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++) + #define POP_SS_OPCODE 0x1f #define MOV_SREG_OPCODE 0x8e diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4876411a072a..98b74711e6b7 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1472,6 +1472,7 @@ int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v); int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu); +int kvm_cpu_has_extint(struct kvm_vcpu *v); int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu); int kvm_cpu_get_interrupt(struct kvm_vcpu *v); void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event); diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 04addd6e0a4a..2571e2017a8b 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -88,7 +88,7 @@ static inline void do_trace_rdpmc(unsigned int msr, u64 val, int failed) {} * think of extending them - you will be slapped with a stinking trout or a frozen * shark will reach you, wherever you are! You've been warned. */ -static inline unsigned long long notrace __rdmsr(unsigned int msr) +static __always_inline unsigned long long __rdmsr(unsigned int msr) { DECLARE_ARGS(val, low, high); @@ -100,7 +100,7 @@ static inline unsigned long long notrace __rdmsr(unsigned int msr) return EAX_EDX_VAL(val, low, high); } -static inline void notrace __wrmsr(unsigned int msr, u32 low, u32 high) +static __always_inline void __wrmsr(unsigned int msr, u32 low, u32 high) { asm volatile("1: wrmsr\n" "2:\n" diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 71ea49e7db74..02806d95ad6e 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -148,6 +148,7 @@ enum page_cache_mode { #endif #define _PAGE_CACHE_MASK (_PAGE_PAT | _PAGE_PCD | _PAGE_PWT) +#define _PAGE_LARGE_CACHE_MASK (_PAGE_PWT | _PAGE_PCD | _PAGE_PAT_LARGE) #define _PAGE_NOCACHE (cachemode2protval(_PAGE_CACHE_MODE_UC)) #define _PAGE_CACHE_WP (cachemode2protval(_PAGE_CACHE_MODE_WP)) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 0bfc38f87038..aa26fe007e15 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -522,15 +522,6 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset, *size = fpu_kernel_xstate_size; } -/* - * Thread-synchronous status. - * - * This is different from the flags in that nobody else - * ever touches our thread-synchronous status, so we don't - * have to worry about atomic accesses. - */ -#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ - /* * Set IOPL bits in EFLAGS from given mask */ diff --git a/arch/x86/include/asm/sync_core.h b/arch/x86/include/asm/sync_core.h index c67caafd3381..43b5e02a7b4b 100644 --- a/arch/x86/include/asm/sync_core.h +++ b/arch/x86/include/asm/sync_core.h @@ -16,12 +16,13 @@ static inline void sync_core_before_usermode(void) /* With PTI, we unconditionally serialize before running user code. */ if (static_cpu_has(X86_FEATURE_PTI)) return; + /* - * Return from interrupt and NMI is done through iret, which is core - * serializing. + * Even if we're in an interrupt, we might reschedule before returning, + * in which case we could switch to a different thread in the same mm + * and return using SYSRET or SYSEXIT. Instead of trying to keep + * track of our need to sync the core, just sync right away. */ - if (in_irq() || in_nmi()) - return; sync_core(); } diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index 82b73b75d67c..b5e4c357523e 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -227,10 +227,31 @@ static inline int arch_within_stack_frames(const void * const stack, #endif +/* + * Thread-synchronous status. + * + * This is different from the flags in that nobody else + * ever touches our thread-synchronous status, so we don't + * have to worry about atomic accesses. + */ +#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ + +#ifndef __ASSEMBLY__ #ifdef CONFIG_COMPAT #define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */ +#define TS_COMPAT_RESTART 0x0008 + +#define arch_set_restart_data arch_set_restart_data + +static inline void arch_set_restart_data(struct restart_block *restart) +{ + struct thread_info *ti = current_thread_info(); + if (ti->status & TS_COMPAT) + ti->status |= TS_COMPAT_RESTART; + else + ti->status &= ~TS_COMPAT_RESTART; +} #endif -#ifndef __ASSEMBLY__ #ifdef CONFIG_X86_32 #define in_ia32_syscall() true diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index e9456a2eef58..da6b52c70964 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -465,6 +466,9 @@ static int lapic_next_deadline(unsigned long delta, { u64 tsc; + /* This MSR is special and need a special fence: */ + weak_wrmsr_fence(); + tsc = rdtsc(); wrmsrl(MSR_IA32_TSC_DEADLINE, tsc + (((u64) delta) * TSC_DIVISOR)); return 0; @@ -1813,20 +1817,22 @@ static __init void try_to_enable_x2apic(int remap_mode) return; if (remap_mode != IRQ_REMAP_X2APIC_MODE) { - /* IR is required if there is APIC ID > 255 even when running - * under KVM + /* + * Using X2APIC without IR is not architecturally supported + * on bare metal but may be supported in guests. */ - if (max_physical_apicid > 255 || - !x86_init.hyper.x2apic_available()) { + if (!x86_init.hyper.x2apic_available()) { pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n"); x2apic_disable(); return; } /* - * without IR all CPUs can be addressed by IOAPIC/MSI - * only in physical mode + * Without IR, all CPUs can be addressed by IOAPIC/MSI only + * in physical mode, and CPUs with an APIC ID that cannnot + * be addressed must not be brought online. */ + x2apic_set_max_apicid(255); x2apic_phys = 1; } x2apic_enable(); @@ -2273,6 +2279,11 @@ static int cpuid_to_apicid[] = { [0 ... NR_CPUS - 1] = -1, }; +bool arch_match_cpu_phys_id(int cpu, u64 phys_id) +{ + return phys_id == cpuid_to_apicid[cpu]; +} + #ifdef CONFIG_SMP /** * apic_id_is_primary_thread - Check whether APIC ID belongs to a primary thread diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 15234885e60b..a89dac380243 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -1043,6 +1043,16 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin, if (idx >= 0 && test_bit(mp_irqs[idx].srcbus, mp_bus_not_pci)) { irq = mp_irqs[idx].srcbusirq; legacy = mp_is_legacy_irq(irq); + /* + * IRQ2 is unusable for historical reasons on systems which + * have a legacy PIC. See the comment vs. IRQ2 further down. + * + * If this gets removed at some point then the related code + * in lapic_assign_system_vectors() needs to be adjusted as + * well. + */ + if (legacy && irq == PIC_CASCADE_IR) + return -EINVAL; } mutex_lock(&ioapic_mutex); diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 8b7e0b46e86e..f0d0535e8f34 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -274,20 +274,24 @@ static int assign_irq_vector_any_locked(struct irq_data *irqd) const struct cpumask *affmsk = irq_data_get_affinity_mask(irqd); int node = irq_data_get_node(irqd); - if (node == NUMA_NO_NODE) - goto all; - /* Try the intersection of @affmsk and node mask */ - cpumask_and(vector_searchmask, cpumask_of_node(node), affmsk); - if (!assign_vector_locked(irqd, vector_searchmask)) - return 0; - /* Try the node mask */ - if (!assign_vector_locked(irqd, cpumask_of_node(node))) - return 0; -all: + if (node != NUMA_NO_NODE) { + /* Try the intersection of @affmsk and node mask */ + cpumask_and(vector_searchmask, cpumask_of_node(node), affmsk); + if (!assign_vector_locked(irqd, vector_searchmask)) + return 0; + } + /* Try the full affinity mask */ cpumask_and(vector_searchmask, affmsk, cpu_online_mask); if (!assign_vector_locked(irqd, vector_searchmask)) return 0; + + if (node != NUMA_NO_NODE) { + /* Try the node mask */ + if (!assign_vector_locked(irqd, cpumask_of_node(node))) + return 0; + } + /* Try the full online mask */ return assign_vector_locked(irqd, cpu_online_mask); } diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 145517934171..b2c7e3bc55d2 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -31,7 +31,8 @@ static void x2apic_send_IPI(int cpu, int vector) { u32 dest = per_cpu(x86_cpu_to_logical_apicid, cpu); - x2apic_wrmsr_fence(); + /* x2apic MSRs are special and need a special fence: */ + weak_wrmsr_fence(); __x2apic_send_IPI_dest(dest, vector, APIC_DEST_LOGICAL); } @@ -43,7 +44,8 @@ __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) unsigned long flags; u32 dest; - x2apic_wrmsr_fence(); + /* x2apic MSRs are special and need a special fence: */ + weak_wrmsr_fence(); local_irq_save(flags); tmpmsk = this_cpu_cpumask_var_ptr(ipi_mask); diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index b5cf9e7b3830..8e70c2ba21b3 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -13,6 +13,12 @@ int x2apic_phys; static struct apic apic_x2apic_phys; +static u32 x2apic_max_apicid __ro_after_init; + +void __init x2apic_set_max_apicid(u32 apicid) +{ + x2apic_max_apicid = apicid; +} static int __init set_x2apic_phys_mode(char *arg) { @@ -42,7 +48,8 @@ static void x2apic_send_IPI(int cpu, int vector) { u32 dest = per_cpu(x86_cpu_to_apicid, cpu); - x2apic_wrmsr_fence(); + /* x2apic MSRs are special and need a special fence: */ + weak_wrmsr_fence(); __x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL); } @@ -53,7 +60,8 @@ __x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) unsigned long this_cpu; unsigned long flags; - x2apic_wrmsr_fence(); + /* x2apic MSRs are special and need a special fence: */ + weak_wrmsr_fence(); local_irq_save(flags); @@ -103,6 +111,9 @@ static int x2apic_phys_probe(void) /* Common x2apic functions, also used by x2apic_cluster */ int x2apic_apic_id_valid(u32 apicid) { + if (x2apic_max_apicid && apicid > x2apic_max_apicid) + return 0; + return 1; } diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index bf554ed2fd51..c524fa1f4c0e 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -733,11 +733,13 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) if (boot_cpu_has(X86_FEATURE_IBPB)) { setup_force_cpu_cap(X86_FEATURE_USE_IBPB); + spectre_v2_user_ibpb = mode; switch (cmd) { case SPECTRE_V2_USER_CMD_FORCE: case SPECTRE_V2_USER_CMD_PRCTL_IBPB: case SPECTRE_V2_USER_CMD_SECCOMP_IBPB: static_branch_enable(&switch_mm_always_ibpb); + spectre_v2_user_ibpb = SPECTRE_V2_USER_STRICT; break; case SPECTRE_V2_USER_CMD_PRCTL: case SPECTRE_V2_USER_CMD_AUTO: @@ -751,8 +753,6 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd) pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n", static_key_enabled(&switch_mm_always_ibpb) ? "always-on" : "conditional"); - - spectre_v2_user_ibpb = mode; } /* @@ -1240,6 +1240,14 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl) return 0; } +static bool is_spec_ib_user_controlled(void) +{ + return spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL || + spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP || + spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL || + spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP; +} + static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) { switch (ctrl) { @@ -1247,17 +1255,26 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return 0; - /* - * Indirect branch speculation is always disabled in strict - * mode. It can neither be enabled if it was force-disabled - * by a previous prctl call. + /* + * With strict mode for both IBPB and STIBP, the instruction + * code paths avoid checking this task flag and instead, + * unconditionally run the instruction. However, STIBP and IBPB + * are independent and either can be set to conditionally + * enabled regardless of the mode of the other. + * + * If either is set to conditional, allow the task flag to be + * updated, unless it was force-disabled by a previous prctl + * call. Currently, this is possible on an AMD CPU which has the + * feature X86_FEATURE_AMD_STIBP_ALWAYS_ON. In this case, if the + * kernel is booted with 'spectre_v2_user=seccomp', then + * spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP and + * spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED. */ - if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED || + if (!is_spec_ib_user_controlled() || task_spec_ib_force_disable(task)) return -EPERM; + task_clear_spec_ib_disable(task); task_update_spec_tif(task); break; @@ -1270,10 +1287,10 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return -EPERM; - if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED) + + if (!is_spec_ib_user_controlled()) return 0; + task_set_spec_ib_disable(task); if (ctrl == PR_SPEC_FORCE_DISABLE) task_set_spec_ib_force_disable(task); @@ -1336,20 +1353,17 @@ static int ib_prctl_get(struct task_struct *task) if (spectre_v2_user_ibpb == SPECTRE_V2_USER_NONE && spectre_v2_user_stibp == SPECTRE_V2_USER_NONE) return PR_SPEC_ENABLE; - else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || - spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED) - return PR_SPEC_DISABLE; - else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_PRCTL || - spectre_v2_user_ibpb == SPECTRE_V2_USER_SECCOMP || - spectre_v2_user_stibp == SPECTRE_V2_USER_PRCTL || - spectre_v2_user_stibp == SPECTRE_V2_USER_SECCOMP) { + else if (is_spec_ib_user_controlled()) { if (task_spec_ib_force_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; if (task_spec_ib_disable(task)) return PR_SPEC_PRCTL | PR_SPEC_DISABLE; return PR_SPEC_PRCTL | PR_SPEC_ENABLE; - } else + } else if (spectre_v2_user_ibpb == SPECTRE_V2_USER_STRICT || + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT || + spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED) + return PR_SPEC_DISABLE; + else return PR_SPEC_NOT_AFFECTED; } diff --git a/arch/x86/kernel/cpu/intel_rdt.h b/arch/x86/kernel/cpu/intel_rdt.h index 2b483b739cf1..8412234eabd3 100644 --- a/arch/x86/kernel/cpu/intel_rdt.h +++ b/arch/x86/kernel/cpu/intel_rdt.h @@ -251,7 +251,6 @@ struct rftype { * struct mbm_state - status for each MBM counter in each domain * @chunks: Total data moved (multiply by rdt_group.mon_scale to get bytes) * @prev_msr Value of IA32_QM_CTR for this RMID last time we read it - * @chunks_bw Total local data moved. Used for bandwidth calculation * @prev_bw_msr:Value of previous IA32_QM_CTR for bandwidth counting * @prev_bw The most recent bandwidth in MBps * @delta_bw Difference between the current and previous bandwidth @@ -260,7 +259,6 @@ struct rftype { struct mbm_state { u64 chunks; u64 prev_msr; - u64 chunks_bw; u64 prev_bw_msr; u32 prev_bw; u32 delta_bw; diff --git a/arch/x86/kernel/cpu/intel_rdt_monitor.c b/arch/x86/kernel/cpu/intel_rdt_monitor.c index 3d4ec80a6bb9..5dfa5ab9a5ae 100644 --- a/arch/x86/kernel/cpu/intel_rdt_monitor.c +++ b/arch/x86/kernel/cpu/intel_rdt_monitor.c @@ -290,8 +290,6 @@ static void mbm_bw_count(u32 rmid, struct rmid_read *rr) return; chunks = mbm_overflow_count(m->prev_bw_msr, tval); - m->chunks_bw += chunks; - m->chunks = m->chunks_bw; cur_bw = (chunks * r->mon_scale) >> 20; if (m->delta_comp) @@ -461,15 +459,14 @@ static void mbm_update(struct rdt_domain *d, int rmid) } if (is_mbm_local_enabled()) { rr.evtid = QOS_L3_MBM_LOCAL_EVENT_ID; + __mon_event_count(rmid, &rr); /* * Call the MBA software controller only for the * control groups and when user has enabled * the software controller explicitly. */ - if (!is_mba_sc(NULL)) - __mon_event_count(rmid, &rr); - else + if (is_mba_sc(NULL)) mbm_bw_count(rmid, &rr); } } diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index e62e416dd116..f406e3b85bdb 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -515,85 +515,88 @@ static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of, return ret ?: nbytes; } -struct task_move_callback { - struct callback_head work; - struct rdtgroup *rdtgrp; -}; - -static void move_myself(struct callback_head *head) +/** + * rdtgroup_remove - the helper to remove resource group safely + * @rdtgrp: resource group to remove + * + * On resource group creation via a mkdir, an extra kernfs_node reference is + * taken to ensure that the rdtgroup structure remains accessible for the + * rdtgroup_kn_unlock() calls where it is removed. + * + * Drop the extra reference here, then free the rdtgroup structure. + * + * Return: void + */ +static void rdtgroup_remove(struct rdtgroup *rdtgrp) { - struct task_move_callback *callback; - struct rdtgroup *rdtgrp; - - callback = container_of(head, struct task_move_callback, work); - rdtgrp = callback->rdtgrp; + kernfs_put(rdtgrp->kn); + kfree(rdtgrp); +} +static void _update_task_closid_rmid(void *task) +{ /* - * If resource group was deleted before this task work callback - * was invoked, then assign the task to root group and free the - * resource group. + * If the task is still current on this CPU, update PQR_ASSOC MSR. + * Otherwise, the MSR is updated when the task is scheduled in. */ - if (atomic_dec_and_test(&rdtgrp->waitcount) && - (rdtgrp->flags & RDT_DELETED)) { - current->closid = 0; - current->rmid = 0; - kfree(rdtgrp); - } - - preempt_disable(); - /* update PQR_ASSOC MSR to make resource group go into effect */ - intel_rdt_sched_in(); - preempt_enable(); + if (task == current) + intel_rdt_sched_in(); +} - kfree(callback); +static void update_task_closid_rmid(struct task_struct *t) +{ + if (IS_ENABLED(CONFIG_SMP) && task_curr(t)) + smp_call_function_single(task_cpu(t), _update_task_closid_rmid, t, 1); + else + _update_task_closid_rmid(t); } static int __rdtgroup_move_task(struct task_struct *tsk, struct rdtgroup *rdtgrp) { - struct task_move_callback *callback; - int ret; - - callback = kzalloc(sizeof(*callback), GFP_KERNEL); - if (!callback) - return -ENOMEM; - callback->work.func = move_myself; - callback->rdtgrp = rdtgrp; + /* If the task is already in rdtgrp, no need to move the task. */ + if ((rdtgrp->type == RDTCTRL_GROUP && tsk->closid == rdtgrp->closid && + tsk->rmid == rdtgrp->mon.rmid) || + (rdtgrp->type == RDTMON_GROUP && tsk->rmid == rdtgrp->mon.rmid && + tsk->closid == rdtgrp->mon.parent->closid)) + return 0; /* - * Take a refcount, so rdtgrp cannot be freed before the - * callback has been invoked. + * Set the task's closid/rmid before the PQR_ASSOC MSR can be + * updated by them. + * + * For ctrl_mon groups, move both closid and rmid. + * For monitor groups, can move the tasks only from + * their parent CTRL group. */ - atomic_inc(&rdtgrp->waitcount); - ret = task_work_add(tsk, &callback->work, true); - if (ret) { - /* - * Task is exiting. Drop the refcount and free the callback. - * No need to check the refcount as the group cannot be - * deleted before the write function unlocks rdtgroup_mutex. - */ - atomic_dec(&rdtgrp->waitcount); - kfree(callback); - rdt_last_cmd_puts("task exited\n"); - } else { - /* - * For ctrl_mon groups move both closid and rmid. - * For monitor groups, can move the tasks only from - * their parent CTRL group. - */ - if (rdtgrp->type == RDTCTRL_GROUP) { - tsk->closid = rdtgrp->closid; + + if (rdtgrp->type == RDTCTRL_GROUP) { + tsk->closid = rdtgrp->closid; + tsk->rmid = rdtgrp->mon.rmid; + } else if (rdtgrp->type == RDTMON_GROUP) { + if (rdtgrp->mon.parent->closid == tsk->closid) { tsk->rmid = rdtgrp->mon.rmid; - } else if (rdtgrp->type == RDTMON_GROUP) { - if (rdtgrp->mon.parent->closid == tsk->closid) { - tsk->rmid = rdtgrp->mon.rmid; - } else { - rdt_last_cmd_puts("Can't move task to different control group\n"); - ret = -EINVAL; - } + } else { + rdt_last_cmd_puts("Can't move task to different control group\n"); + return -EINVAL; } } - return ret; + + /* + * Ensure the task's closid and rmid are written before determining if + * the task is current that will decide if it will be interrupted. + */ + barrier(); + + /* + * By now, the task's closid and rmid are set. If the task is current + * on a CPU, the PQR_ASSOC MSR needs to be updated to make the resource + * group go into effect. If the task is not current, the MSR will be + * updated when the task is scheduled in. + */ + update_task_closid_rmid(tsk); + + return 0; } /** @@ -1626,7 +1629,6 @@ static int rdtgroup_mkdir_info_resdir(struct rdt_resource *r, char *name, if (IS_ERR(kn_subdir)) return PTR_ERR(kn_subdir); - kernfs_get(kn_subdir); ret = rdtgroup_kn_set_ugid(kn_subdir); if (ret) return ret; @@ -1649,7 +1651,6 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL); if (IS_ERR(kn_info)) return PTR_ERR(kn_info); - kernfs_get(kn_info); ret = rdtgroup_add_files(kn_info, RF_TOP_INFO); if (ret) @@ -1670,12 +1671,6 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) goto out_destroy; } - /* - * This extra ref will be put in kernfs_remove() and guarantees - * that @rdtgrp->kn is always accessible. - */ - kernfs_get(kn_info); - ret = rdtgroup_kn_set_ugid(kn_info); if (ret) goto out_destroy; @@ -1704,12 +1699,6 @@ mongroup_create_dir(struct kernfs_node *parent_kn, struct rdtgroup *prgrp, if (dest_kn) *dest_kn = kn; - /* - * This extra ref will be put in kernfs_remove() and guarantees - * that @rdtgrp->kn is always accessible. - */ - kernfs_get(kn); - ret = rdtgroup_kn_set_ugid(kn); if (ret) goto out_destroy; @@ -1973,8 +1962,7 @@ void rdtgroup_kn_unlock(struct kernfs_node *kn) rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) rdtgroup_pseudo_lock_remove(rdtgrp); kernfs_unbreak_active_protection(kn); - kernfs_put(rdtgrp->kn); - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } else { kernfs_unbreak_active_protection(kn); } @@ -2025,7 +2013,6 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type, dentry = ERR_PTR(ret); goto out_info; } - kernfs_get(kn_mongrp); ret = mkdir_mondata_all(rdtgroup_default.kn, &rdtgroup_default, &kn_mondata); @@ -2033,7 +2020,6 @@ static struct dentry *rdt_mount(struct file_system_type *fs_type, dentry = ERR_PTR(ret); goto out_mongrp; } - kernfs_get(kn_mondata); rdtgroup_default.mon.mon_data_kn = kn_mondata; } @@ -2185,7 +2171,7 @@ static void free_all_child_rdtgrp(struct rdtgroup *rdtgrp) if (atomic_read(&sentry->waitcount) != 0) sentry->flags = RDT_DELETED; else - kfree(sentry); + rdtgroup_remove(sentry); } } @@ -2227,7 +2213,7 @@ static void rmdir_all_sub(void) if (atomic_read(&rdtgrp->waitcount) != 0) rdtgrp->flags = RDT_DELETED; else - kfree(rdtgrp); + rdtgroup_remove(rdtgrp); } /* Notify online CPUs to update per cpu storage and PQR_ASSOC MSR */ update_closid_rmid(cpu_online_mask, &rdtgroup_default); @@ -2326,11 +2312,6 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn, if (IS_ERR(kn)) return PTR_ERR(kn); - /* - * This extra ref will be put in kernfs_remove() and guarantees - * that kn is always accessible. - */ - kernfs_get(kn); ret = rdtgroup_kn_set_ugid(kn); if (ret) goto out_destroy; @@ -2622,8 +2603,8 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn, /* * kernfs_remove() will drop the reference count on "kn" which * will free it. But we still need it to stick around for the - * rdtgroup_kn_unlock(kn} call below. Take one extra reference - * here, which will be dropped inside rdtgroup_kn_unlock(). + * rdtgroup_kn_unlock(kn) call. Take one extra reference here, + * which will be dropped by kernfs_put() in rdtgroup_remove(). */ kernfs_get(kn); @@ -2664,6 +2645,7 @@ static int mkdir_rdt_prepare(struct kernfs_node *parent_kn, out_idfree: free_rmid(rdtgrp->mon.rmid); out_destroy: + kernfs_put(rdtgrp->kn); kernfs_remove(rdtgrp->kn); out_free_rgrp: kfree(rdtgrp); @@ -2676,7 +2658,7 @@ static void mkdir_rdt_prepare_clean(struct rdtgroup *rgrp) { kernfs_remove(rgrp->kn); free_rmid(rgrp->mon.rmid); - kfree(rgrp); + rdtgroup_remove(rgrp); } /* @@ -2838,11 +2820,6 @@ static int rdtgroup_rmdir_mon(struct kernfs_node *kn, struct rdtgroup *rdtgrp, WARN_ON(list_empty(&prdtgrp->mon.crdtgrp_list)); list_del(&rdtgrp->mon.crdtgrp_list); - /* - * one extra hold on this, will drop when we kfree(rdtgrp) - * in rdtgroup_kn_unlock() - */ - kernfs_get(kn); kernfs_remove(rdtgrp->kn); return 0; @@ -2854,11 +2831,6 @@ static int rdtgroup_ctrl_remove(struct kernfs_node *kn, rdtgrp->flags = RDT_DELETED; list_del(&rdtgrp->rdtgroup_list); - /* - * one extra hold on this, will drop when we kfree(rdtgrp) - * in rdtgroup_kn_unlock() - */ - kernfs_get(kn); kernfs_remove(rdtgrp->kn); return 0; } diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index a96091d44a45..6fc4363e4f7b 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -436,8 +436,8 @@ static ssize_t microcode_write(struct file *file, const char __user *buf, { ssize_t ret = -EINVAL; - if ((len >> PAGE_SHIFT) > totalram_pages) { - pr_err("too much data (max %ld pages)\n", totalram_pages); + if ((len >> PAGE_SHIFT) > totalram_pages()) { + pr_err("too much data (max %ld pages)\n", totalram_pages()); return ret; } diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index 16936a24795c..3aa0e5a45303 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c @@ -103,53 +103,6 @@ static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev return find_matching_signature(mc, csig, cpf); } -/* - * Given CPU signature and a microcode patch, this function finds if the - * microcode patch has matching family and model with the CPU. - * - * %true - if there's a match - * %false - otherwise - */ -static bool microcode_matches(struct microcode_header_intel *mc_header, - unsigned long sig) -{ - unsigned long total_size = get_totalsize(mc_header); - unsigned long data_size = get_datasize(mc_header); - struct extended_sigtable *ext_header; - unsigned int fam_ucode, model_ucode; - struct extended_signature *ext_sig; - unsigned int fam, model; - int ext_sigcount, i; - - fam = x86_family(sig); - model = x86_model(sig); - - fam_ucode = x86_family(mc_header->sig); - model_ucode = x86_model(mc_header->sig); - - if (fam == fam_ucode && model == model_ucode) - return true; - - /* Look for ext. headers: */ - if (total_size <= data_size + MC_HEADER_SIZE) - return false; - - ext_header = (void *) mc_header + data_size + MC_HEADER_SIZE; - ext_sig = (void *)ext_header + EXT_HEADER_SIZE; - ext_sigcount = ext_header->count; - - for (i = 0; i < ext_sigcount; i++) { - fam_ucode = x86_family(ext_sig->sig); - model_ucode = x86_model(ext_sig->sig); - - if (fam == fam_ucode && model == model_ucode) - return true; - - ext_sig++; - } - return false; -} - static struct ucode_patch *memdup_patch(void *data, unsigned int size) { struct ucode_patch *p; @@ -167,7 +120,7 @@ static struct ucode_patch *memdup_patch(void *data, unsigned int size) return p; } -static void save_microcode_patch(void *data, unsigned int size) +static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigned int size) { struct microcode_header_intel *mc_hdr, *mc_saved_hdr; struct ucode_patch *iter, *tmp, *p = NULL; @@ -213,6 +166,9 @@ static void save_microcode_patch(void *data, unsigned int size) if (!p) return; + if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf)) + return; + /* * Save for early loading. On 32-bit, that needs to be a physical * address as the APs are running from physical addresses, before @@ -347,13 +303,14 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save) size -= mc_size; - if (!microcode_matches(mc_header, uci->cpu_sig.sig)) { + if (!find_matching_signature(data, uci->cpu_sig.sig, + uci->cpu_sig.pf)) { data += mc_size; continue; } if (save) { - save_microcode_patch(data, mc_size); + save_microcode_patch(uci, data, mc_size); goto next; } @@ -486,14 +443,14 @@ static void show_saved_mc(void) * Save this microcode patch. It will be loaded early when a CPU is * hot-added or resumes. */ -static void save_mc_for_early(u8 *mc, unsigned int size) +static void save_mc_for_early(struct ucode_cpu_info *uci, u8 *mc, unsigned int size) { /* Synchronization during CPU hotplug. */ static DEFINE_MUTEX(x86_cpu_microcode_mutex); mutex_lock(&x86_cpu_microcode_mutex); - save_microcode_patch(mc, size); + save_microcode_patch(uci, mc, size); show_saved_mc(); mutex_unlock(&x86_cpu_microcode_mutex); @@ -937,7 +894,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size, * permanent memory. So it will be loaded early when a CPU is hot added * or resumes. */ - save_mc_for_early(new_mc, new_mc_size); + save_mc_for_early(uci, new_mc, new_mc_size); pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n", cpu, new_rev, uci->cpu_sig.rev); diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index e12ee86906c6..9436f3452049 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -166,9 +166,6 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, *repeat = 0; *uniform = 1; - /* Make end inclusive instead of exclusive */ - end--; - prev_match = MTRR_TYPE_INVALID; for (i = 0; i < num_var_ranges; ++i) { unsigned short start_state, end_state, inclusive; @@ -260,6 +257,9 @@ u8 mtrr_type_lookup(u64 start, u64 end, u8 *uniform) int repeat; u64 partial_end; + /* Make end inclusive instead of exclusive */ + end--; + if (!mtrr_state_set) return MTRR_TYPE_INVALID; diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index f631a3f15587..91b3483e5085 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -356,7 +356,7 @@ int crash_setup_memmap_entries(struct kimage *image, struct boot_params *params) struct crash_memmap_data cmd; struct crash_mem *cmem; - cmem = vzalloc(sizeof(struct crash_mem)); + cmem = vzalloc(struct_size(cmem, ranges, 1)); if (!cmem) return -ENOMEM; diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 07e290244ca9..dfc3ab44bc5d 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -1041,6 +1041,11 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr) * So clear it by resetting the current kprobe: */ regs->flags &= ~X86_EFLAGS_TF; + /* + * Since the single step (trap) has been cancelled, + * we need to restore BTF here. + */ + restore_btf(); /* * If the TF flag was set before the kprobe hit, diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 6bf351f1f180..afc0302769b8 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c @@ -126,6 +126,7 @@ int apply_relocate(Elf32_Shdr *sechdrs, *location += sym->st_value; break; case R_386_PC32: + case R_386_PLT32: /* Add the value, subtract its position */ *location += sym->st_value - (uint32_t)location; break; diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 39f3cad58b6c..6489cc19ed06 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -477,6 +477,15 @@ static const struct dmi_system_id reboot_dmi_table[] __initconst = { }, }, + { /* PCIe Wifi card isn't detected after reboot otherwise */ + .callback = set_pci_reboot, + .ident = "Zotac ZBOX CI327 nano", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "NA"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZBOX-CI327NANO-GS-01"), + }, + }, + /* Sony */ { /* Handle problems with rebooting on Sony VGN-Z540N */ .callback = set_bios_reboot, @@ -538,29 +547,20 @@ static void emergency_vmx_disable_all(void) local_irq_disable(); /* - * We need to disable VMX on all CPUs before rebooting, otherwise - * we risk hanging up the machine, because the CPU ignore INIT - * signals when VMX is enabled. - * - * We can't take any locks and we may be on an inconsistent - * state, so we use NMIs as IPIs to tell the other CPUs to disable - * VMX and halt. + * Disable VMX on all CPUs before rebooting, otherwise we risk hanging + * the machine, because the CPU blocks INIT when it's in VMX root. * - * For safety, we will avoid running the nmi_shootdown_cpus() - * stuff unnecessarily, but we don't have a way to check - * if other CPUs have VMX enabled. So we will call it only if the - * CPU we are running on has VMX enabled. + * We can't take any locks and we may be on an inconsistent state, so + * use NMIs as IPIs to tell the other CPUs to exit VMX root and halt. * - * We will miss cases where VMX is not enabled on all CPUs. This - * shouldn't do much harm because KVM always enable VMX on all - * CPUs anyway. But we can miss it on the small window where KVM - * is still enabling VMX. + * Do the NMI shootdown even if VMX if off on _this_ CPU, as that + * doesn't prevent a different CPU from being in VMX root operation. */ - if (cpu_has_vmx() && cpu_vmx_enabled()) { - /* Disable VMX on this CPU. */ - cpu_vmxoff(); + if (cpu_has_vmx()) { + /* Safely force _this_ CPU out of VMX root operation. */ + __cpu_emergency_vmxoff(); - /* Halt and disable VMX on the other CPUs */ + /* Halt and exit VMX root operation on the other CPUs. */ nmi_shootdown_cpus(vmxoff_nmi); } diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 44e647a65de8..16e908000550 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -776,30 +776,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs) { - /* - * This function is fundamentally broken as currently - * implemented. - * - * The idea is that we want to trigger a call to the - * restart_block() syscall and that we want in_ia32_syscall(), - * in_x32_syscall(), etc. to match whatever they were in the - * syscall being restarted. We assume that the syscall - * instruction at (regs->ip - 2) matches whatever syscall - * instruction we used to enter in the first place. - * - * The problem is that we can get here when ptrace pokes - * syscall-like values into regs even if we're not in a syscall - * at all. - * - * For now, we maintain historical behavior and guess based on - * stored state. We could do better by saving the actual - * syscall arch in restart_block or (with caveats on x32) by - * checking if regs->ip points to 'int $0x80'. The current - * behavior is incorrect if a tracer has a different bitness - * than the tracee. - */ #ifdef CONFIG_IA32_EMULATION - if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED)) + if (current_thread_info()->status & TS_COMPAT_RESTART) return __NR_ia32_restart_syscall; #endif #ifdef CONFIG_X86_X32_ABI diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index 8fa9ca3c3bd7..4f17c1c94949 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -346,8 +346,8 @@ static bool deref_stack_regs(struct unwind_state *state, unsigned long addr, if (!stack_access_ok(state, addr, sizeof(struct pt_regs))) return false; - *ip = regs->ip; - *sp = regs->sp; + *ip = READ_ONCE_NOCHECK(regs->ip); + *sp = READ_ONCE_NOCHECK(regs->sp); return true; } @@ -359,8 +359,8 @@ static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr if (!stack_access_ok(state, addr, IRET_FRAME_SIZE)) return false; - *ip = regs->ip; - *sp = regs->sp; + *ip = READ_ONCE_NOCHECK(regs->ip); + *sp = READ_ONCE_NOCHECK(regs->sp); return true; } @@ -381,12 +381,12 @@ static bool get_reg(struct unwind_state *state, unsigned int reg_off, return false; if (state->full_regs) { - *val = ((unsigned long *)state->regs)[reg]; + *val = READ_ONCE_NOCHECK(((unsigned long *)state->regs)[reg]); return true; } if (state->prev_regs) { - *val = ((unsigned long *)state->prev_regs)[reg]; + *val = READ_ONCE_NOCHECK(((unsigned long *)state->prev_regs)[reg]); return true; } diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 420aa7d3a2e6..ae9e806a11de 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -268,12 +268,13 @@ static volatile u32 good_2byte_insns[256 / 32] = { static bool is_prefix_bad(struct insn *insn) { + insn_byte_t p; int i; - for (i = 0; i < insn->prefixes.nbytes; i++) { + for_each_insn_prefix(insn, i, p) { insn_attr_t attr; - attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]); + attr = inat_get_opcode_attribute(p); switch (attr) { case INAT_MAKE_PREFIX(INAT_PFX_ES): case INAT_MAKE_PREFIX(INAT_PFX_CS): @@ -728,6 +729,7 @@ static const struct uprobe_xol_ops push_xol_ops = { static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) { u8 opc1 = OPCODE1(insn); + insn_byte_t p; int i; switch (opc1) { @@ -758,8 +760,8 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) * Intel and AMD behavior differ in 64-bit mode: Intel ignores 66 prefix. * No one uses these insns, reject any branch insns with such prefix. */ - for (i = 0; i < insn->prefixes.nbytes; i++) { - if (insn->prefixes.bytes[i] == 0x66) + for_each_insn_prefix(insn, i, p) { + if (p == 0x66) return -ENOTSUPP; } diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index d78a61408243..7dec43b2c420 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -154,6 +154,20 @@ static inline int guest_cpuid_stepping(struct kvm_vcpu *vcpu) return x86_stepping(best->eax); } +static inline bool guest_has_spec_ctrl_msr(struct kvm_vcpu *vcpu) +{ + return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) || + guest_cpuid_has(vcpu, X86_FEATURE_AMD_STIBP) || + guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) || + guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)); +} + +static inline bool guest_has_pred_cmd_msr(struct kvm_vcpu *vcpu) +{ + return (guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL) || + guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB)); +} + static inline bool supports_cpuid_fault(struct kvm_vcpu *vcpu) { return vcpu->arch.msr_platform_info & MSR_PLATFORM_INFO_CPUID_FAULT; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 670c2aedcefa..3e182c7ae771 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3994,6 +3994,12 @@ static int em_clflush(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } +static int em_clflushopt(struct x86_emulate_ctxt *ctxt) +{ + /* emulating clflushopt regardless of cpuid */ + return X86EMUL_CONTINUE; +} + static int em_movsxd(struct x86_emulate_ctxt *ctxt) { ctxt->dst.val = (s32) ctxt->src.val; @@ -4507,7 +4513,7 @@ static const struct opcode group11[] = { }; static const struct gprefix pfx_0f_ae_7 = { - I(SrcMem | ByteOp, em_clflush), N, N, N, + I(SrcMem | ByteOp, em_clflush), I(SrcMem | ByteOp, em_clflushopt), N, N, }; static const struct group_dual group15 = { { diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c index 007bc654f928..295ebadb8f2c 100644 --- a/arch/x86/kvm/irq.c +++ b/arch/x86/kvm/irq.c @@ -52,29 +52,10 @@ static int pending_userspace_extint(struct kvm_vcpu *v) * check if there is pending interrupt from * non-APIC source without intack. */ -static int kvm_cpu_has_extint(struct kvm_vcpu *v) -{ - u8 accept = kvm_apic_accept_pic_intr(v); - - if (accept) { - if (irqchip_split(v->kvm)) - return pending_userspace_extint(v); - else - return v->kvm->arch.vpic->output; - } else - return 0; -} - -/* - * check if there is injectable interrupt: - * when virtual interrupt delivery enabled, - * interrupt from apic will handled by hardware, - * we don't need to check it here. - */ -int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) +int kvm_cpu_has_extint(struct kvm_vcpu *v) { /* - * FIXME: interrupt.injected represents an interrupt that it's + * FIXME: interrupt.injected represents an interrupt whose * side-effects have already been applied (e.g. bit from IRR * already moved to ISR). Therefore, it is incorrect to rely * on interrupt.injected to know if there is a pending @@ -87,6 +68,23 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) if (!lapic_in_kernel(v)) return v->arch.interrupt.injected; + if (!kvm_apic_accept_pic_intr(v)) + return 0; + + if (irqchip_split(v->kvm)) + return pending_userspace_extint(v); + else + return v->kvm->arch.vpic->output; +} + +/* + * check if there is injectable interrupt: + * when virtual interrupt delivery enabled, + * interrupt from apic will handled by hardware, + * we don't need to check it here. + */ +int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) +{ if (kvm_cpu_has_extint(v)) return 1; @@ -102,20 +100,6 @@ int kvm_cpu_has_injectable_intr(struct kvm_vcpu *v) */ int kvm_cpu_has_interrupt(struct kvm_vcpu *v) { - /* - * FIXME: interrupt.injected represents an interrupt that it's - * side-effects have already been applied (e.g. bit from IRR - * already moved to ISR). Therefore, it is incorrect to rely - * on interrupt.injected to know if there is a pending - * interrupt in the user-mode LAPIC. - * This leads to nVMX/nSVM not be able to distinguish - * if it should exit from L2 to L1 on EXTERNAL_INTERRUPT on - * pending interrupt or should re-inject an injected - * interrupt. - */ - if (!lapic_in_kernel(v)) - return v->arch.interrupt.injected; - if (kvm_cpu_has_extint(v)) return 1; @@ -129,16 +113,21 @@ EXPORT_SYMBOL_GPL(kvm_cpu_has_interrupt); */ static int kvm_cpu_get_extint(struct kvm_vcpu *v) { - if (kvm_cpu_has_extint(v)) { - if (irqchip_split(v->kvm)) { - int vector = v->arch.pending_external_vector; - - v->arch.pending_external_vector = -1; - return vector; - } else - return kvm_pic_read_irq(v->kvm); /* PIC */ - } else + if (!kvm_cpu_has_extint(v)) { + WARN_ON(!lapic_in_kernel(v)); return -1; + } + + if (!lapic_in_kernel(v)) + return v->arch.interrupt.nr; + + if (irqchip_split(v->kvm)) { + int vector = v->arch.pending_external_vector; + + v->arch.pending_external_vector = -1; + return vector; + } else + return kvm_pic_read_irq(v->kvm); /* PIC */ } /* @@ -146,13 +135,7 @@ static int kvm_cpu_get_extint(struct kvm_vcpu *v) */ int kvm_cpu_get_interrupt(struct kvm_vcpu *v) { - int vector; - - if (!lapic_in_kernel(v)) - return v->arch.interrupt.nr; - - vector = kvm_cpu_get_extint(v); - + int vector = kvm_cpu_get_extint(v); if (vector != -1) return vector; /* PIC */ diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index bba2f76c356d..56a4b9762b0c 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2284,7 +2284,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu) struct kvm_lapic *apic = vcpu->arch.apic; u32 ppr; - if (!kvm_apic_hw_enabled(apic)) + if (!kvm_apic_present(vcpu)) return -1; __apic_update_ppr(apic, &ppr); diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h index 0b62c817f63f..05a02b8ace6b 100644 --- a/arch/x86/kvm/mmu.h +++ b/arch/x86/kvm/mmu.h @@ -53,7 +53,7 @@ static inline u64 rsvd_bits(int s, int e) if (e < s) return 0; - return ((1ULL << (e - s + 1)) - 1) << s; + return ((2ULL << (e - s)) - 1) << s; } void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value); diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c index 2ab8c20c8bfa..611f9e60f815 100644 --- a/arch/x86/kvm/pmu_intel.c +++ b/arch/x86/kvm/pmu_intel.c @@ -29,7 +29,7 @@ static struct kvm_event_hw_type_mapping intel_arch_events[] = { [4] = { 0x2e, 0x41, PERF_COUNT_HW_CACHE_MISSES }, [5] = { 0xc4, 0x00, PERF_COUNT_HW_BRANCH_INSTRUCTIONS }, [6] = { 0xc5, 0x00, PERF_COUNT_HW_BRANCH_MISSES }, - [7] = { 0x00, 0x30, PERF_COUNT_HW_REF_CPU_CYCLES }, + [7] = { 0x00, 0x03, PERF_COUNT_HW_REF_CPU_CYCLES }, }; /* mapping between fixed pmc index and intel_arch_events array */ diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index a0c3d1b4b295..8cb9277aa6ff 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -892,6 +892,11 @@ static int has_svm(void) return 0; } + if (sev_active()) { + pr_info("KVM is unsupported when running as an SEV guest\n"); + return 0; + } + return 1; } @@ -1827,6 +1832,8 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, struct page **pages; unsigned long first, last; + lockdep_assert_held(&kvm->lock); + if (ulen == 0 || uaddr + ulen < uaddr) return NULL; @@ -4209,8 +4216,7 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) break; case MSR_IA32_SPEC_CTRL: if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) + !guest_has_spec_ctrl_msr(vcpu)) return 1; msr_info->data = svm->spec_ctrl; @@ -4312,8 +4318,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) break; case MSR_IA32_SPEC_CTRL: if (!msr->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBRS) && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_SSBD)) + !guest_has_spec_ctrl_msr(vcpu)) return 1; /* The STIBP bit doesn't fault even if it's not advertised */ @@ -4340,12 +4345,11 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) break; case MSR_IA32_PRED_CMD: if (!msr->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_AMD_IBPB)) + !guest_has_pred_cmd_msr(vcpu)) return 1; if (data & ~PRED_CMD_IBPB) return 1; - if (!data) break; @@ -7082,12 +7086,20 @@ static int svm_register_enc_region(struct kvm *kvm, if (!region) return -ENOMEM; + mutex_lock(&kvm->lock); region->pages = sev_pin_memory(kvm, range->addr, range->size, ®ion->npages, 1); if (!region->pages) { ret = -ENOMEM; + mutex_unlock(&kvm->lock); goto e_free; } + region->uaddr = range->addr; + region->size = range->size; + + list_add_tail(®ion->list, &sev->regions_list); + mutex_unlock(&kvm->lock); + /* * The guest may change the memory encryption attribute from C=0 -> C=1 * or vice versa for this memory range. Lets make sure caches are @@ -7096,13 +7108,6 @@ static int svm_register_enc_region(struct kvm *kvm, */ sev_clflush_pages(region->pages, region->npages); - region->uaddr = range->addr; - region->size = range->size; - - mutex_lock(&kvm->lock); - list_add_tail(®ion->list, &sev->regions_list); - mutex_unlock(&kvm->lock); - return ret; e_free: diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d6bcbce6c15c..77b9ed5223f3 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4066,7 +4066,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) return kvm_get_msr_common(vcpu, msr_info); case MSR_IA32_SPEC_CTRL: if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) + !guest_has_spec_ctrl_msr(vcpu)) return 1; msr_info->data = to_vmx(vcpu)->spec_ctrl; @@ -4180,7 +4180,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) break; case MSR_IA32_SPEC_CTRL: if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) + !guest_has_spec_ctrl_msr(vcpu)) return 1; /* The STIBP bit doesn't fault even if it's not advertised */ @@ -4210,7 +4210,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) break; case MSR_IA32_PRED_CMD: if (!msr_info->host_initiated && - !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) + !guest_has_pred_cmd_msr(vcpu)) return 1; if (data & ~PRED_CMD_IBPB) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index dd182228be71..8e4eef73531a 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -102,6 +102,7 @@ static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS; static void update_cr8_intercept(struct kvm_vcpu *vcpu); static void process_nmi(struct kvm_vcpu *vcpu); +static void process_smi(struct kvm_vcpu *vcpu); static void enter_smm(struct kvm_vcpu *vcpu); static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags); static void store_regs(struct kvm_vcpu *vcpu); @@ -3351,21 +3352,23 @@ static int kvm_vcpu_ioctl_set_lapic(struct kvm_vcpu *vcpu, static int kvm_cpu_accept_dm_intr(struct kvm_vcpu *vcpu) { + /* + * We can accept userspace's request for interrupt injection + * as long as we have a place to store the interrupt number. + * The actual injection will happen when the CPU is able to + * deliver the interrupt. + */ + if (kvm_cpu_has_extint(vcpu)) + return false; + + /* Acknowledging ExtINT does not happen if LINT0 is masked. */ return (!lapic_in_kernel(vcpu) || kvm_apic_accept_pic_intr(vcpu)); } -/* - * if userspace requested an interrupt window, check that the - * interrupt window is open. - * - * No need to exit to userspace if we already have an interrupt queued. - */ static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu) { return kvm_arch_interrupt_allowed(vcpu) && - !kvm_cpu_has_interrupt(vcpu) && - !kvm_event_needs_reinjection(vcpu) && kvm_cpu_accept_dm_intr(vcpu); } @@ -3497,6 +3500,10 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu, struct kvm_vcpu_events *events) { process_nmi(vcpu); + + if (kvm_check_request(KVM_REQ_SMI, vcpu)) + process_smi(vcpu); + /* * FIXME: pass injected and pending separately. This is only * needed for nested virtualization, whose state cannot be diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 87dcba101e56..3172eaf4ec5e 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -70,14 +70,15 @@ static int get_seg_reg_override_idx(struct insn *insn) { int idx = INAT_SEG_REG_DEFAULT; int num_overrides = 0, i; + insn_byte_t p; insn_get_prefixes(insn); /* Look for any segment override prefixes. */ - for (i = 0; i < insn->prefixes.nbytes; i++) { + for_each_insn_prefix(insn, i, p) { insn_attr_t attr; - attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]); + attr = inat_get_opcode_attribute(p); switch (attr) { case INAT_MAKE_PREFIX(INAT_PFX_CS): idx = INAT_SEG_REG_CS; diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S index 9d05572370ed..84b0078272d1 100644 --- a/arch/x86/lib/memcpy_64.S +++ b/arch/x86/lib/memcpy_64.S @@ -14,8 +14,6 @@ * to a jmp to memcpy_erms which does the REP; MOVSB mem copy. */ -.weak memcpy - /* * memcpy - Copy a memory block. * @@ -28,7 +26,9 @@ * rax original destination */ ENTRY(__memcpy) -ENTRY(memcpy) +.weak memcpy +.p2align 4, 0x90 +memcpy: ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \ "jmp memcpy_erms", X86_FEATURE_ERMS diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S index bbec69d8223b..e1cfc880f42d 100644 --- a/arch/x86/lib/memmove_64.S +++ b/arch/x86/lib/memmove_64.S @@ -25,8 +25,8 @@ * rax: dest */ .weak memmove - -ENTRY(memmove) +.p2align 4, 0x90 +memmove: ENTRY(__memmove) /* Handle more 32 bytes in loop */ diff --git a/arch/x86/lib/memset_64.S b/arch/x86/lib/memset_64.S index 9bc861c71e75..084189acdcd0 100644 --- a/arch/x86/lib/memset_64.S +++ b/arch/x86/lib/memset_64.S @@ -6,8 +6,6 @@ #include #include -.weak memset - /* * ISO C memset - set a memory block to a byte value. This function uses fast * string to get better performance than the original function. The code is @@ -19,7 +17,9 @@ * * rax original destination */ -ENTRY(memset) +.weak memset +.p2align 4, 0x90 +memset: ENTRY(__memset) /* * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended diff --git a/arch/x86/mm/highmem_32.c b/arch/x86/mm/highmem_32.c index 6d18b70ed5a9..8ac7132919a3 100644 --- a/arch/x86/mm/highmem_32.c +++ b/arch/x86/mm/highmem_32.c @@ -1,6 +1,6 @@ #include #include -#include /* for totalram_pages */ +#include /* for totalram_pages() */ #include void *kmap(struct page *page) diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c index fe7a12599d8e..968d7005f4a7 100644 --- a/arch/x86/mm/ident_map.c +++ b/arch/x86/mm/ident_map.c @@ -62,6 +62,7 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page, unsigned long addr, unsigned long end) { unsigned long next; + int result; for (; addr < end; addr = next) { p4d_t *p4d = p4d_page + p4d_index(addr); @@ -73,13 +74,20 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page, if (p4d_present(*p4d)) { pud = pud_offset(p4d, 0); - ident_pud_init(info, pud, addr, next); + result = ident_pud_init(info, pud, addr, next); + if (result) + return result; + continue; } pud = (pud_t *)info->alloc_pgt_page(info->context); if (!pud) return -ENOMEM; - ident_pud_init(info, pud, addr, next); + + result = ident_pud_init(info, pud, addr, next); + if (result) + return result; + set_p4d(p4d, __p4d(__pa(pud) | info->kernpg_flag)); } diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c index 006f373f54ab..c0499c38962b 100644 --- a/arch/x86/mm/mem_encrypt.c +++ b/arch/x86/mm/mem_encrypt.c @@ -228,7 +228,7 @@ static void __init __set_clr_pte_enc(pte_t *kpte, int level, bool enc) if (pgprot_val(old_prot) == pgprot_val(new_prot)) return; - pa = pfn << page_level_shift(level); + pa = pfn << PAGE_SHIFT; size = page_level_size(level); /* diff --git a/arch/x86/mm/mem_encrypt_identity.c b/arch/x86/mm/mem_encrypt_identity.c index c9faf34cbb62..1f25201de0af 100644 --- a/arch/x86/mm/mem_encrypt_identity.c +++ b/arch/x86/mm/mem_encrypt_identity.c @@ -47,8 +47,8 @@ #define PMD_FLAGS_LARGE (__PAGE_KERNEL_LARGE_EXEC & ~_PAGE_GLOBAL) #define PMD_FLAGS_DEC PMD_FLAGS_LARGE -#define PMD_FLAGS_DEC_WP ((PMD_FLAGS_DEC & ~_PAGE_CACHE_MASK) | \ - (_PAGE_PAT | _PAGE_PWT)) +#define PMD_FLAGS_DEC_WP ((PMD_FLAGS_DEC & ~_PAGE_LARGE_CACHE_MASK) | \ + (_PAGE_PAT_LARGE | _PAGE_PWT)) #define PMD_FLAGS_ENC (PMD_FLAGS_LARGE | _PAGE_ENC) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index a3c9ea29d7cc..324e26d0607b 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -1131,12 +1131,14 @@ static void *memtype_seq_start(struct seq_file *seq, loff_t *pos) static void *memtype_seq_next(struct seq_file *seq, void *v, loff_t *pos) { + kfree(v); ++*pos; return memtype_get_idx(*pos); } static void memtype_seq_stop(struct seq_file *seq, void *v) { + kfree(v); } static int memtype_seq_show(struct seq_file *seq, void *v) @@ -1145,7 +1147,6 @@ static int memtype_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%s @ 0x%Lx-0x%Lx\n", cattr_name(print_entry->type), print_entry->start, print_entry->end); - kfree(print_entry); return 0; } diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c index bf52106ab9c4..c0e9c00402ac 100644 --- a/arch/x86/mm/pgtable.c +++ b/arch/x86/mm/pgtable.c @@ -838,6 +838,8 @@ int pud_free_pmd_page(pud_t *pud, unsigned long addr) } free_page((unsigned long)pmd_sv); + + pgtable_pmd_page_dtor(virt_to_page(pmd)); free_page((unsigned long)pmd); return 1; diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index b72296bd04a2..2f41a34c8f57 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -321,8 +321,14 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, /* * The membarrier system call requires a full memory barrier and * core serialization before returning to user-space, after - * storing to rq->curr. Writing to CR3 provides that full - * memory barrier and core serializing instruction. + * storing to rq->curr, when changing mm. This is because + * membarrier() sends IPIs to all CPUs that are in the target mm + * to make them issue memory barriers. However, if another CPU + * switches to/from the target mm concurrently with + * membarrier(), it can cause that CPU not to receive an IPI + * when it really should issue a memory barrier. Writing to CR3 + * provides that full memory barrier and core serializing + * instruction. */ if (real_prev == next) { VM_WARN_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) != diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 46ab92831251..924ca27a6139 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1019,7 +1019,16 @@ xadd: if (is_imm8(insn->off)) } if (image) { - if (unlikely(proglen + ilen > oldproglen)) { + /* + * When populating the image, assert that: + * + * i) We do not write beyond the allocated space, and + * ii) addrs[i] did not change from the prior run, in order + * to validate assumptions made for computing branch + * displacements. + */ + if (unlikely(proglen + ilen > oldproglen || + proglen + ilen != addrs[i])) { pr_err("bpf_jit: fatal error\n"); return -EFAULT; } diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c index 2eaf1900ba67..adee990abab1 100644 --- a/arch/x86/net/bpf_jit_comp32.c +++ b/arch/x86/net/bpf_jit_comp32.c @@ -2201,7 +2201,16 @@ emit_cond_jmp: jmp_cond = get_cond_jmp_opcode(BPF_OP(code), false); } if (image) { - if (unlikely(proglen + ilen > oldproglen)) { + /* + * When populating the image, assert that: + * + * i) We do not write beyond the allocated space, and + * ii) addrs[i] did not change from the prior run, in order + * to validate assumptions made for computing branch + * displacements. + */ + if (unlikely(proglen + ilen > oldproglen || + proglen + ilen != addrs[i])) { pr_err("bpf_jit: fatal error\n"); return -EFAULT; } diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index 52dd59af873e..77d05b56089a 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -214,28 +214,30 @@ int __init efi_alloc_page_tables(void) gfp_mask = GFP_KERNEL | __GFP_ZERO; efi_pgd = (pgd_t *)__get_free_pages(gfp_mask, PGD_ALLOCATION_ORDER); if (!efi_pgd) - return -ENOMEM; + goto fail; pgd = efi_pgd + pgd_index(EFI_VA_END); p4d = p4d_alloc(&init_mm, pgd, EFI_VA_END); - if (!p4d) { - free_page((unsigned long)efi_pgd); - return -ENOMEM; - } + if (!p4d) + goto free_pgd; pud = pud_alloc(&init_mm, p4d, EFI_VA_END); - if (!pud) { - if (pgtable_l5_enabled()) - free_page((unsigned long) pgd_page_vaddr(*pgd)); - free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER); - return -ENOMEM; - } + if (!pud) + goto free_p4d; efi_mm.pgd = efi_pgd; mm_init_cpumask(&efi_mm); init_new_context(NULL, &efi_mm); return 0; + +free_p4d: + if (pgtable_l5_enabled()) + free_page((unsigned long)pgd_page_vaddr(*pgd)); +free_pgd: + free_pages((unsigned long)efi_pgd, PGD_ALLOCATION_ORDER); +fail: + return -ENOMEM; } /* diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index 494a8840b102..437c36288b03 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -848,9 +848,11 @@ static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, case R_386_PC32: case R_386_PC16: case R_386_PC8: + case R_386_PLT32: /* - * NONE can be ignored and PC relative relocations don't - * need to be adjusted. + * NONE can be ignored and PC relative relocations don't need + * to be adjusted. Because sym must be defined, R_386_PLT32 can + * be treated the same way as R_386_PC32. */ break; @@ -891,9 +893,11 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, case R_386_PC32: case R_386_PC16: case R_386_PC8: + case R_386_PLT32: /* - * NONE can be ignored and PC relative relocations don't - * need to be adjusted. + * NONE can be ignored and PC relative relocations don't need + * to be adjusted. Because sym must be defined, R_386_PLT32 can + * be treated the same way as R_386_PC32. */ break; diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c index 66bcdeeee639..90d2e4ce7064 100644 --- a/arch/x86/xen/efi.c +++ b/arch/x86/xen/efi.c @@ -172,7 +172,7 @@ static enum efi_secureboot_mode xen_efi_get_secureboot(void) return efi_secureboot_mode_unknown; } -void __init xen_efi_init(void) +void __init xen_efi_init(struct boot_params *boot_params) { efi_system_table_t *efi_systab_xen; @@ -181,12 +181,12 @@ void __init xen_efi_init(void) if (efi_systab_xen == NULL) return; - strncpy((char *)&boot_params.efi_info.efi_loader_signature, "Xen", - sizeof(boot_params.efi_info.efi_loader_signature)); - boot_params.efi_info.efi_systab = (__u32)__pa(efi_systab_xen); - boot_params.efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32); + strncpy((char *)&boot_params->efi_info.efi_loader_signature, "Xen", + sizeof(boot_params->efi_info.efi_loader_signature)); + boot_params->efi_info.efi_systab = (__u32)__pa(efi_systab_xen); + boot_params->efi_info.efi_systab_hi = (__u32)(__pa(efi_systab_xen) >> 32); - boot_params.secure_boot = xen_efi_get_secureboot(); + boot_params->secure_boot = xen_efi_get_secureboot(); set_bit(EFI_BOOT, &efi.flags); set_bit(EFI_PARAVIRT, &efi.flags); diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 9f8995cd28f6..1c3e9185934c 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -1409,7 +1409,7 @@ asmlinkage __visible void __init xen_start_kernel(void) /* We need this for printk timestamps */ xen_setup_runstate_info(0); - xen_efi_init(); + xen_efi_init(&boot_params); /* Start the world */ #ifdef CONFIG_X86_32 diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c index dab07827d25e..f04d22bcf08d 100644 --- a/arch/x86/xen/enlighten_pvh.c +++ b/arch/x86/xen/enlighten_pvh.c @@ -14,6 +14,8 @@ #include #include +#include "xen-ops.h" + /* * PVH variables. * @@ -79,6 +81,8 @@ static void __init init_pvh_bootparams(void) pvh_bootparams.hdr.type_of_loader = (9 << 4) | 0; /* Xen loader */ x86_init.acpi.get_root_pointer = pvh_get_root_pointer; + + xen_efi_init(&pvh_bootparams); } /* diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 159a897151d6..82577eec6d0a 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -706,9 +706,12 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, for (i = 0; i < count; i++) { unsigned long mfn, pfn; + struct gnttab_unmap_grant_ref unmap[2]; + int rc; /* Do not add to override if the map failed. */ - if (map_ops[i].status) + if (map_ops[i].status != GNTST_okay || + (kmap_ops && kmap_ops[i].status != GNTST_okay)) continue; if (map_ops[i].flags & GNTMAP_contains_pte) { @@ -722,10 +725,46 @@ int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops, WARN(pfn_to_mfn(pfn) != INVALID_P2M_ENTRY, "page must be ballooned"); - if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) { - ret = -ENOMEM; - goto out; + if (likely(set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)))) + continue; + + /* + * Signal an error for this slot. This in turn requires + * immediate unmapping. + */ + map_ops[i].status = GNTST_general_error; + unmap[0].host_addr = map_ops[i].host_addr, + unmap[0].handle = map_ops[i].handle; + map_ops[i].handle = ~0; + if (map_ops[i].flags & GNTMAP_device_map) + unmap[0].dev_bus_addr = map_ops[i].dev_bus_addr; + else + unmap[0].dev_bus_addr = 0; + + if (kmap_ops) { + kmap_ops[i].status = GNTST_general_error; + unmap[1].host_addr = kmap_ops[i].host_addr, + unmap[1].handle = kmap_ops[i].handle; + kmap_ops[i].handle = ~0; + if (kmap_ops[i].flags & GNTMAP_device_map) + unmap[1].dev_bus_addr = kmap_ops[i].dev_bus_addr; + else + unmap[1].dev_bus_addr = 0; } + + /* + * Pre-populate both status fields, to be recognizable in + * the log message below. + */ + unmap[0].status = 1; + unmap[1].status = 1; + + rc = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, + unmap, 1 + !!kmap_ops); + if (rc || unmap[0].status != GNTST_okay || + unmap[1].status != GNTST_okay) + pr_err_once("gnttab unmap failed: rc=%d st0=%d st1=%d\n", + rc, unmap[0].status, unmap[1].status); } out: @@ -746,17 +785,15 @@ int clear_foreign_p2m_mapping(struct gnttab_unmap_grant_ref *unmap_ops, unsigned long mfn = __pfn_to_mfn(page_to_pfn(pages[i])); unsigned long pfn = page_to_pfn(pages[i]); - if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT)) { + if (mfn != INVALID_P2M_ENTRY && (mfn & FOREIGN_FRAME_BIT)) + set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + else ret = -EINVAL; - goto out; - } - - set_phys_to_machine(pfn, INVALID_P2M_ENTRY); } if (kunmap_ops) ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, - kunmap_ops, count); -out: + kunmap_ops, count) ?: ret; + return ret; } EXPORT_SYMBOL_GPL(clear_foreign_p2m_mapping); diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 717b4847b473..6fffb86a32ad 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -101,10 +101,20 @@ void xen_init_lock_cpu(int cpu) void xen_uninit_lock_cpu(int cpu) { + int irq; + if (!xen_pvspin) return; - unbind_from_irqhandler(per_cpu(lock_kicker_irq, cpu), NULL); + /* + * When booting the kernel with 'mitigations=auto,nosmt', the secondary + * CPUs are not activated, and lock_kicker_irq is not initialized. + */ + irq = per_cpu(lock_kicker_irq, cpu); + if (irq == -1) + return; + + unbind_from_irqhandler(irq, NULL); per_cpu(lock_kicker_irq, cpu) = -1; kfree(per_cpu(irq_name, cpu)); per_cpu(irq_name, cpu) = NULL; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 0e60bd918695..2f111f47ba98 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -122,9 +122,9 @@ static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, void __init xen_init_apic(void); #ifdef CONFIG_XEN_EFI -extern void xen_efi_init(void); +extern void xen_efi_init(struct boot_params *boot_params); #else -static inline void __init xen_efi_init(void) +static inline void __init xen_efi_init(struct boot_params *boot_params) { } #endif diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index f1158b4c629c..da4effe27007 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h @@ -291,7 +291,7 @@ strncpy_from_user(char *dst, const char *src, long count) return -EFAULT; } #else -long strncpy_from_user(char *dst, const char *src, long count); +long strncpy_from_user(char *dst, const char __user *src, long count); #endif /* diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 9220dcde7520..d1ebe67c68d4 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c @@ -71,8 +71,10 @@ static inline void kmap_invalidate_coherent(struct page *page, kvaddr = TLBTEMP_BASE_1 + (page_to_phys(page) & DCACHE_ALIAS_MASK); + preempt_disable(); __invalidate_dcache_page_alias(kvaddr, page_to_phys(page)); + preempt_enable(); } } } @@ -157,6 +159,7 @@ void flush_dcache_page(struct page *page) if (!alias && !mapping) return; + preempt_disable(); virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK); __flush_invalidate_dcache_page_alias(virt, phys); @@ -167,6 +170,7 @@ void flush_dcache_page(struct page *page) if (mapping) __invalidate_icache_page_alias(virt, phys); + preempt_enable(); } /* There shouldn't be an entry in the cache for this page anymore. */ @@ -200,8 +204,10 @@ void local_flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long phys = page_to_phys(pfn_to_page(pfn)); unsigned long virt = TLBTEMP_BASE_1 + (address & DCACHE_ALIAS_MASK); + preempt_disable(); __flush_invalidate_dcache_page_alias(virt, phys); __invalidate_icache_page_alias(virt, phys); + preempt_enable(); } EXPORT_SYMBOL(local_flush_cache_page); @@ -228,11 +234,13 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) unsigned long phys = page_to_phys(page); unsigned long tmp; + preempt_disable(); tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK); __flush_invalidate_dcache_page_alias(tmp, phys); tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); __flush_invalidate_dcache_page_alias(tmp, phys); __invalidate_icache_page_alias(tmp, phys); + preempt_enable(); clear_bit(PG_arch_1, &page->flags); } @@ -266,7 +274,9 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, if (alias) { unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); + preempt_disable(); __flush_invalidate_dcache_page_alias(t, phys); + preempt_enable(); } /* Copy data */ @@ -281,9 +291,11 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page, if (alias) { unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); + preempt_disable(); __flush_invalidate_dcache_range((unsigned long) dst, len); if ((vma->vm_flags & VM_EXEC) != 0) __invalidate_icache_page_alias(t, phys); + preempt_enable(); } else if ((vma->vm_flags & VM_EXEC) != 0) { __flush_dcache_range((unsigned long)dst,len); @@ -305,7 +317,9 @@ extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page, if (alias) { unsigned long t = TLBTEMP_BASE_1 + (vaddr & DCACHE_ALIAS_MASK); + preempt_disable(); __flush_invalidate_dcache_page_alias(t, phys); + preempt_enable(); } memcpy(dst, src, len); diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index ceb72a70b32a..a117bba0eea1 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -2478,6 +2478,7 @@ static void __bfq_set_in_service_queue(struct bfq_data *bfqd, } bfqd->in_service_queue = bfqq; + bfqd->in_serv_last_pos = 0; } /* diff --git a/block/bio.c b/block/bio.c index ee3bae8b9dcd..871312c47b3c 100644 --- a/block/bio.c +++ b/block/bio.c @@ -317,7 +317,7 @@ static struct bio *__bio_chain_endio(struct bio *bio) { struct bio *parent = bio->bi_private; - if (!parent->bi_status) + if (bio->bi_status && !parent->bi_status) parent->bi_status = bio->bi_status; bio_put(bio); return parent; @@ -937,6 +937,25 @@ int submit_bio_wait(struct bio *bio) } EXPORT_SYMBOL(submit_bio_wait); +static void submit_bio_nowait_endio(struct bio *bio) +{ + bio_put(bio); +} + +/** + * submit_bio_nowait - submit a bio for fire-and-forget + * @bio: The &struct bio which describes the I/O + * + * Simple wrapper around submit_bio() that takes care of bio_put() on completion + */ +void submit_bio_nowait(struct bio *bio) +{ + bio->bi_end_io = submit_bio_nowait_endio; + bio->bi_opf |= REQ_SYNC; + submit_bio(bio); +} +EXPORT_SYMBOL(submit_bio_nowait); + /** * bio_advance - increment/complete a bio by some number of bytes * @bio: bio to advance diff --git a/block/blk-flush.c b/block/blk-flush.c index 256fa1ccc2bd..86496c5d4c27 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -575,6 +575,47 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, } EXPORT_SYMBOL(blkdev_issue_flush); +/** + * blkdev_issue_flush_nowait - queue a flush + * @bdev: blockdev to issue flush for + * @gfp_mask: memory allocation flags (for bio_alloc) + * @error_sector: error sector + * + * Description: + * Issue a flush for the block device in question. Caller can supply + * room for storing the error offset in case of a flush error, if they + * wish to. If WAIT flag is not passed then caller may check only what + * request was pushed in some internal queue for later handling. + */ +void blkdev_issue_flush_nowait(struct block_device *bdev, gfp_t gfp_mask) +{ + struct request_queue *q; + struct bio *bio; + + if (bdev->bd_disk == NULL) + return; + + q = bdev_get_queue(bdev); + if (!q) + return; + + /* + * some block devices may not have their queue correctly set up here + * (e.g. loop device without a backing file) and so issuing a flush + * here will panic. Ensure there is a request function before issuing + * the flush. + */ + if (!q->make_request_fn) + return; + + bio = bio_alloc(gfp_mask, 0); + bio_set_dev(bio, bdev); + bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; + + submit_bio_nowait(bio); +} +EXPORT_SYMBOL(blkdev_issue_flush_nowait); + struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q, int node, int cmd_size, gfp_t flags) { diff --git a/block/blk-mq.c b/block/blk-mq.c index db2db0b70d34..195526b93895 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1118,6 +1118,23 @@ static void blk_mq_update_dispatch_busy(struct blk_mq_hw_ctx *hctx, bool busy) #define BLK_MQ_RESOURCE_DELAY 3 /* ms units */ +static void blk_mq_handle_dev_resource(struct request *rq, + struct list_head *list) +{ + struct request *next = + list_first_entry_or_null(list, struct request, queuelist); + + /* + * If an I/O scheduler has been configured and we got a driver tag for + * the next request already, free it. + */ + if (next) + blk_mq_put_driver_tag(next); + + list_add(&rq->queuelist, list); + __blk_mq_requeue_request(rq); +} + /* * Returns true if we did some work AND can potentially do more. */ @@ -1185,17 +1202,7 @@ bool blk_mq_dispatch_rq_list(struct request_queue *q, struct list_head *list, ret = q->mq_ops->queue_rq(hctx, &bd); if (ret == BLK_STS_RESOURCE || ret == BLK_STS_DEV_RESOURCE) { - /* - * If an I/O scheduler has been configured and we got a - * driver tag for the next request already, free it - * again. - */ - if (!list_empty(list)) { - nxt = list_first_entry(list, struct request, queuelist); - blk_mq_put_driver_tag(nxt); - } - list_add(&rq->queuelist, list); - __blk_mq_requeue_request(rq); + blk_mq_handle_dev_resource(rq, list); break; } @@ -2317,11 +2324,6 @@ static void blk_mq_map_swqueue(struct request_queue *q) struct blk_mq_ctx *ctx; struct blk_mq_tag_set *set = q->tag_set; - /* - * Avoid others reading imcomplete hctx->cpumask through sysfs - */ - mutex_lock(&q->sysfs_lock); - queue_for_each_hw_ctx(q, hctx, i) { cpumask_clear(hctx->cpumask); hctx->nr_ctx = 0; @@ -2355,8 +2357,6 @@ static void blk_mq_map_swqueue(struct request_queue *q) hctx->ctxs[hctx->nr_ctx++] = ctx; } - mutex_unlock(&q->sysfs_lock); - queue_for_each_hw_ctx(q, hctx, i) { /* * If no software queues are mapped to this hardware queue, diff --git a/block/blk-settings.c b/block/blk-settings.c index 01093b8f3e62..2c01b6f65110 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -513,6 +513,14 @@ void blk_queue_io_opt(struct request_queue *q, unsigned int opt) } EXPORT_SYMBOL(blk_queue_io_opt); +static unsigned int blk_round_down_sectors(unsigned int sectors, unsigned int lbs) +{ + sectors = round_down(sectors, lbs >> SECTOR_SHIFT); + if (sectors < PAGE_SIZE >> SECTOR_SHIFT) + sectors = PAGE_SIZE >> SECTOR_SHIFT; + return sectors; +} + /** * blk_queue_stack_limits - inherit underlying queue limits for stacked drivers * @t: the stacking driver (top) @@ -639,6 +647,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, ret = -1; } + t->max_sectors = blk_round_down_sectors(t->max_sectors, t->logical_block_size); + t->max_hw_sectors = blk_round_down_sectors(t->max_hw_sectors, t->logical_block_size); + t->max_dev_sectors = blk_round_down_sectors(t->max_dev_sectors, t->logical_block_size); + /* Discard alignment and granularity */ if (b->discard_granularity) { alignment = queue_limit_discard_alignment(b, start); diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 8286640d4d66..0a7636d24563 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -896,7 +896,7 @@ int blk_register_queue(struct gendisk *disk) if (WARN_ON(!q)) return -ENXIO; - WARN_ONCE(test_bit(QUEUE_FLAG_REGISTERED, &q->queue_flags), + WARN_ONCE(blk_queue_registered(q), "%s is registering an already registered queue\n", kobject_name(&dev->kobj)); queue_flag_set_unlocked(QUEUE_FLAG_REGISTERED, q); @@ -973,7 +973,7 @@ void blk_unregister_queue(struct gendisk *disk) return; /* Return early if disk->queue was never registered. */ - if (!test_bit(QUEUE_FLAG_REGISTERED, &q->queue_flags)) + if (!blk_queue_registered(q)) return; /* diff --git a/block/blk-wbt.c b/block/blk-wbt.c index f1de8ba483a9..50f2abfa1a60 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -708,7 +708,7 @@ void wbt_enable_default(struct request_queue *q) return; /* Queue not registered? Maybe shutting down... */ - if (!test_bit(QUEUE_FLAG_REGISTERED, &q->queue_flags)) + if (!blk_queue_registered(q)) return; if ((q->mq_ops && IS_ENABLED(CONFIG_BLK_WBT_MQ)) || diff --git a/block/elevator.c b/block/elevator.c index 6d94044681f7..219670d4b309 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -1093,7 +1093,7 @@ static int __elevator_change(struct request_queue *q, const char *name) struct elevator_type *e; /* Make sure queue is not in the middle of being removed */ - if (!test_bit(QUEUE_FLAG_REGISTERED, &q->queue_flags)) + if (!blk_queue_registered(q)) return -ENOENT; /* diff --git a/block/genhd.c b/block/genhd.c index 2b2a936cf848..fe1c236a2b9d 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -208,14 +208,17 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) part = rcu_dereference(ptbl->part[piter->idx]); if (!part) continue; + get_device(part_to_dev(part)); + piter->part = part; if (!part_nr_sects_read(part) && !(piter->flags & DISK_PITER_INCL_EMPTY) && !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && - piter->idx == 0)) + piter->idx == 0)) { + put_device(part_to_dev(part)); + piter->part = NULL; continue; + } - get_device(part_to_dev(part)); - piter->part = part; piter->idx += inc; break; } @@ -615,10 +618,8 @@ static void register_disk(struct device *parent, struct gendisk *disk) disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj); disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj); - if (disk->flags & GENHD_FL_HIDDEN) { - dev_set_uevent_suppress(ddev, 0); + if (disk->flags & GENHD_FL_HIDDEN) return; - } /* No minors to use for partitions */ if (!disk_part_scan_enabled(disk)) @@ -649,10 +650,12 @@ static void register_disk(struct device *parent, struct gendisk *disk) kobject_uevent(&part_to_dev(part)->kobj, KOBJ_ADD); disk_part_iter_exit(&piter); - err = sysfs_create_link(&ddev->kobj, - &disk->queue->backing_dev_info->dev->kobj, - "bdi"); - WARN_ON(err); + if (disk->queue->backing_dev_info->dev) { + err = sysfs_create_link(&ddev->kobj, + &disk->queue->backing_dev_info->dev->kobj, + "bdi"); + WARN_ON(err); + } } /** diff --git a/certs/blacklist.c b/certs/blacklist.c index 3a507b9e2568..e9f3f81c51f9 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -157,7 +157,7 @@ static int __init blacklist_init(void) KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH, KEY_ALLOC_NOT_IN_QUOTA | - KEY_FLAG_KEEP, + KEY_ALLOC_SET_KEEP, NULL, NULL); if (IS_ERR(blacklist_keyring)) panic("Can't allocate system blacklist keyring\n"); diff --git a/complete_commit_time b/complete_commit_time new file mode 100644 index 000000000000..4394d19592be --- /dev/null +++ b/complete_commit_time @@ -0,0 +1,33 @@ +44: struct msm_kms *kms = priv->kms; +130: struct msm_kms *kms = priv->kms; +346: struct msm_kms *kms = priv->kms; +474: struct msm_kms *kms = priv->kms; +505: struct msm_kms *kms = priv->kms; +542: priv->complete_commit_time = ktime_get()/1000; +549: spin_lock(&priv->pending_crtcs_event.lock); +551: priv->pending_crtcs &= ~crtc_mask; +552: priv->pending_planes &= ~plane_mask; +553: wake_up_all_locked(&priv->pending_crtcs_event); +554: spin_unlock(&priv->pending_crtcs_event.lock); +577: kthread_queue_work(&priv->clean_thread.worker, &c->commit_work); +618: for (j = 0; j < priv->num_crtcs; j++) { +619: if (priv->disp_thread[j].crtc_id == +621: if (priv->disp_thread[j].thread) { +623: &priv->disp_thread[j].worker, +631: priv->disp_thread[j].crtc_id); +643: if (j < priv->num_crtcs) +693: if (!priv || priv->shutdown_in_progress) { +750: if (!atomic_cmpxchg_acquire(&priv->pm_req_set, 1, 0)) +751: pm_qos_update_request(&priv->pm_irq_req, 100); +752: mod_delayed_work(system_unbound_wq, &priv->pm_unreq_dwork, HZ / 10); +755: spin_lock(&priv->pending_crtcs_event.lock); +756: ret = wait_event_interruptible_locked(priv->pending_crtcs_event, +757: !(priv->pending_crtcs & c->crtc_mask) && +758: !(priv->pending_planes & c->plane_mask)); +761: priv->pending_crtcs |= c->crtc_mask; +762: priv->pending_planes |= c->plane_mask; +764: spin_unlock(&priv->pending_crtcs_event.lock); +777: if (priv && priv->kms && priv->kms->funcs && +778: priv->kms->funcs->prepare_fence) +779: priv->kms->funcs->prepare_fence(priv->kms, state); +843: struct msm_kms *kms = priv->kms; diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 272879d7b0d1..d0276a4ed987 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -151,7 +151,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) const u32 allowed = CRYPTO_ALG_KERN_DRIVER_ONLY; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); - struct sockaddr_alg *sa = (void *)uaddr; + struct sockaddr_alg_new *sa = (void *)uaddr; const struct af_alg_type *type; void *private; int err; @@ -159,7 +159,11 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (sock->state == SS_CONNECTED) return -EINVAL; - if (addr_len < sizeof(*sa)) + BUILD_BUG_ON(offsetof(struct sockaddr_alg_new, salg_name) != + offsetof(struct sockaddr_alg, salg_name)); + BUILD_BUG_ON(offsetof(struct sockaddr_alg, salg_name) != sizeof(*sa)); + + if (addr_len < sizeof(*sa) + 1) return -EINVAL; /* If caller uses non-allowed flag, return error. */ @@ -167,7 +171,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) return -EINVAL; sa->salg_type[sizeof(sa->salg_type) - 1] = 0; - sa->salg_name[sizeof(sa->salg_name) + addr_len - sizeof(*sa) - 1] = 0; + sa->salg_name[addr_len - sizeof(*sa) - 1] = 0; type = alg_get_type(sa->salg_type); if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) { diff --git a/crypto/ecdh.c b/crypto/ecdh.c index bf6300175b9c..34605509b41a 100644 --- a/crypto/ecdh.c +++ b/crypto/ecdh.c @@ -43,7 +43,8 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, struct ecdh params; unsigned int ndigits; - if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0) + if (crypto_ecdh_decode_key(buf, len, ¶ms) < 0 || + params.key_size > sizeof(ctx->private_key)) return -EINVAL; ndigits = ecdh_supported_curve(params.curve_id); @@ -57,12 +58,13 @@ static int ecdh_set_secret(struct crypto_kpp *tfm, const void *buf, return ecc_gen_privkey(ctx->curve_id, ctx->ndigits, ctx->private_key); - if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits, - (const u64 *)params.key, params.key_size) < 0) - return -EINVAL; - memcpy(ctx->private_key, params.key, params.key_size); + if (ecc_is_key_valid(ctx->curve_id, ctx->ndigits, + ctx->private_key, params.key_size) < 0) { + memzero_explicit(ctx->private_key, params.key_size); + return -EINVAL; + } return 0; } diff --git a/crypto/ecdh_helper.c b/crypto/ecdh_helper.c index d3af8e8b0b5e..25711de44584 100644 --- a/crypto/ecdh_helper.c +++ b/crypto/ecdh_helper.c @@ -71,6 +71,9 @@ int crypto_ecdh_decode_key(const char *buf, unsigned int len, if (secret.type != CRYPTO_KPP_SECRET_TYPE_ECDH) return -EINVAL; + if (unlikely(len < secret.len)) + return -EINVAL; + ptr = ecdh_unpack_data(¶ms->curve_id, ptr, sizeof(params->curve_id)); ptr = ecdh_unpack_data(¶ms->key_size, ptr, sizeof(params->key_size)); if (secret.len != crypto_ecdh_key_len(params)) diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index 740ef57310ed..f26ae5e7f9dc 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -202,8 +202,8 @@ static int test_mb_aead_jiffies(struct test_mb_aead_data *data, int enc, goto out; } - pr_cont("%d operations in %d seconds (%ld bytes)\n", - bcount * num_mb, secs, (long)bcount * blen * num_mb); + pr_cont("%d operations in %d seconds (%llu bytes)\n", + bcount * num_mb, secs, (u64)bcount * blen * num_mb); out: kfree(rc); @@ -472,8 +472,8 @@ static int test_aead_jiffies(struct aead_request *req, int enc, return ret; } - printk("%d operations in %d seconds (%ld bytes)\n", - bcount, secs, (long)bcount * blen); + pr_cont("%d operations in %d seconds (%llu bytes)\n", + bcount, secs, (u64)bcount * blen); return 0; } @@ -763,8 +763,8 @@ static int test_mb_ahash_jiffies(struct test_mb_ahash_data *data, int blen, goto out; } - pr_cont("%d operations in %d seconds (%ld bytes)\n", - bcount * num_mb, secs, (long)bcount * blen * num_mb); + pr_cont("%d operations in %d seconds (%llu bytes)\n", + bcount * num_mb, secs, (u64)bcount * blen * num_mb); out: kfree(rc); @@ -1200,8 +1200,8 @@ static int test_mb_acipher_jiffies(struct test_mb_skcipher_data *data, int enc, goto out; } - pr_cont("%d operations in %d seconds (%ld bytes)\n", - bcount * num_mb, secs, (long)bcount * blen * num_mb); + pr_cont("%d operations in %d seconds (%llu bytes)\n", + bcount * num_mb, secs, (u64)bcount * blen * num_mb); out: kfree(rc); @@ -1438,8 +1438,8 @@ static int test_acipher_jiffies(struct skcipher_request *req, int enc, return ret; } - pr_cont("%d operations in %d seconds (%ld bytes)\n", - bcount, secs, (long)bcount * blen); + pr_cont("%d operations in %d seconds (%llu bytes)\n", + bcount, secs, (u64)bcount * blen); return 0; } diff --git a/drivers/Makefile b/drivers/Makefile index 9a258f18ec6f..29a72dff30b2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -60,15 +60,8 @@ obj-y += char/ # iommu/ comes before gpu as gpu are using iommu controllers obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ -# gpu/ comes after char for AGP vs DRM startup and after iommu -obj-y += gpu/ - obj-$(CONFIG_CONNECTOR) += connector/ -# i810fb and intelfb depend on char/agp/ -obj-$(CONFIG_FB_I810) += video/fbdev/i810/ -obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/ - obj-$(CONFIG_PARPORT) += parport/ obj-$(CONFIG_NVM) += lightnvm/ obj-y += base/ block/ misc/ mfd/ nfc/ @@ -83,6 +76,14 @@ obj-$(CONFIG_EXTCON) += extcon/ obj-y += scsi/ obj-y += nvme/ obj-$(CONFIG_ATA) += ata/ + +# gpu/ comes after char for AGP vs DRM startup and after iommu +obj-y += gpu/ + +# i810fb and intelfb depend on char/agp/ +obj-$(CONFIG_FB_I810) += video/fbdev/i810/ +obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/ + obj-$(CONFIG_TARGET_CORE) += target/ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_SPI) += spi/ @@ -180,6 +181,7 @@ obj-$(CONFIG_RAS) += ras/ obj-$(CONFIG_THUNDERBOLT) += thunderbolt/ obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/ obj-y += hwtracing/intel_th/ +obj-y += hwtracing/google/ obj-$(CONFIG_STM) += hwtracing/stm/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_NVMEM) += nvmem/ diff --git a/drivers/acpi/acpi_configfs.c b/drivers/acpi/acpi_configfs.c index b58850389094..c0325556a897 100644 --- a/drivers/acpi/acpi_configfs.c +++ b/drivers/acpi/acpi_configfs.c @@ -269,7 +269,12 @@ static int __init acpi_configfs_init(void) acpi_table_group = configfs_register_default_group(root, "table", &acpi_tables_type); - return PTR_ERR_OR_ZERO(acpi_table_group); + if (IS_ERR(acpi_table_group)) { + configfs_unregister_subsystem(&acpi_configfs); + return PTR_ERR(acpi_table_group); + } + + return 0; } module_init(acpi_configfs_init); diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 67d97c0090a2..5d72baf60ac8 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -320,6 +320,9 @@ static bool matching_id(const char *idstr, const char *list_id) { int i; + if (strlen(idstr) != strlen(list_id)) + return false; + if (memcmp(idstr, list_id, 3)) return false; diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c index f43f5adc21b6..abf101451c92 100644 --- a/drivers/acpi/button.c +++ b/drivers/acpi/button.c @@ -98,7 +98,18 @@ static const struct dmi_system_id lid_blacklst[] = { */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), - DMI_MATCH(DMI_PRODUCT_NAME, "E2215T MD60198"), + DMI_MATCH(DMI_PRODUCT_NAME, "E2215T"), + }, + .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, + }, + { + /* + * Medion Akoya E2228T, notification of the LID device only + * happens on close, not on open and _LID always returns closed. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E2228T"), }, .driver_data = (void *)(long)ACPI_BUTTON_LID_INIT_OPEN, }, diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 254954c0d645..b941395ed251 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -703,7 +703,7 @@ static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context) static DEFINE_MUTEX(acpi_wakeup_lock); static int __acpi_device_wakeup_enable(struct acpi_device *adev, - u32 target_state, int max_count) + u32 target_state) { struct acpi_device_wakeup *wakeup = &adev->wakeup; acpi_status status; @@ -711,9 +711,10 @@ static int __acpi_device_wakeup_enable(struct acpi_device *adev, mutex_lock(&acpi_wakeup_lock); - if (wakeup->enable_count >= max_count) + if (wakeup->enable_count >= INT_MAX) { + acpi_handle_info(adev->handle, "Wakeup enable count out of bounds!\n"); goto out; - + } if (wakeup->enable_count > 0) goto inc; @@ -750,7 +751,7 @@ static int __acpi_device_wakeup_enable(struct acpi_device *adev, */ static int acpi_device_wakeup_enable(struct acpi_device *adev, u32 target_state) { - return __acpi_device_wakeup_enable(adev, target_state, 1); + return __acpi_device_wakeup_enable(adev, target_state); } /** @@ -780,8 +781,12 @@ static void acpi_device_wakeup_disable(struct acpi_device *adev) mutex_unlock(&acpi_wakeup_lock); } -static int __acpi_pm_set_device_wakeup(struct device *dev, bool enable, - int max_count) +/** + * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device. + * @dev: Device to enable/disable to generate wakeup events. + * @enable: Whether to enable or disable the wakeup functionality. + */ +int acpi_pm_set_device_wakeup(struct device *dev, bool enable) { struct acpi_device *adev; int error; @@ -801,36 +806,14 @@ static int __acpi_pm_set_device_wakeup(struct device *dev, bool enable, return 0; } - error = __acpi_device_wakeup_enable(adev, acpi_target_system_state(), - max_count); + error = __acpi_device_wakeup_enable(adev, acpi_target_system_state()); if (!error) dev_dbg(dev, "Wakeup enabled by ACPI\n"); return error; } - -/** - * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device. - * @dev: Device to enable/disable to generate wakeup events. - * @enable: Whether to enable or disable the wakeup functionality. - */ -int acpi_pm_set_device_wakeup(struct device *dev, bool enable) -{ - return __acpi_pm_set_device_wakeup(dev, enable, 1); -} EXPORT_SYMBOL_GPL(acpi_pm_set_device_wakeup); -/** - * acpi_pm_set_bridge_wakeup - Enable/disable remote wakeup for given bridge. - * @dev: Bridge device to enable/disable to generate wakeup events. - * @enable: Whether to enable or disable the wakeup functionality. - */ -int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable) -{ - return __acpi_pm_set_device_wakeup(dev, enable, INT_MAX); -} -EXPORT_SYMBOL_GPL(acpi_pm_set_bridge_wakeup); - /** * acpi_dev_pm_low_power - Put ACPI device into a low-power state. * @dev: Device to put into a low-power state. diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 8940054d6250..b3b92c54cba8 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -259,20 +259,12 @@ int __acpi_device_uevent_modalias(struct acpi_device *adev, if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; - len = create_pnp_modalias(adev, &env->buf[env->buflen - 1], - sizeof(env->buf) - env->buflen); - if (len < 0) - return len; - - env->buflen += len; - if (!adev->data.of_compatible) - return 0; - - if (len > 0 && add_uevent_var(env, "MODALIAS=")) - return -ENOMEM; - - len = create_of_modalias(adev, &env->buf[env->buflen - 1], - sizeof(env->buf) - env->buflen); + if (adev->data.of_compatible) + len = create_of_modalias(adev, &env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); + else + len = create_pnp_modalias(adev, &env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen); if (len < 0) return len; diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c index 73f6093a5c16..9f4b405a5c20 100644 --- a/drivers/acpi/evged.c +++ b/drivers/acpi/evged.c @@ -110,7 +110,7 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, switch (gsi) { case 0 ... 255: - sprintf(ev_name, "_%c%02hhX", + sprintf(ev_name, "_%c%02X", trigger == ACPI_EDGE_SENSITIVE ? 'E' : 'L', gsi); if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle))) diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index f59d0b9e2683..913613cf5c53 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -18,6 +18,8 @@ #ifndef _ACPI_INTERNAL_H_ #define _ACPI_INTERNAL_H_ +#include + #define PREFIX "ACPI: " int early_acpi_osi_init(void); @@ -97,9 +99,11 @@ void acpi_scan_table_handler(u32 event, void *table, void *context); extern struct list_head acpi_bus_id_list; +#define ACPI_MAX_DEVICE_INSTANCES 4096 + struct acpi_device_bus_id { - char bus_id[15]; - unsigned int instance_no; + const char *bus_id; + struct ida instance_ida; struct list_head node; }; diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 288673cff85e..27db1a968241 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -720,9 +720,6 @@ static int acpi_data_prop_read_single(const struct acpi_device_data *data, const union acpi_object *obj; int ret; - if (!val) - return -EINVAL; - if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj); if (ret) @@ -732,28 +729,43 @@ static int acpi_data_prop_read_single(const struct acpi_device_data *data, case DEV_PROP_U8: if (obj->integer.value > U8_MAX) return -EOVERFLOW; - *(u8 *)val = obj->integer.value; + + if (val) + *(u8 *)val = obj->integer.value; + break; case DEV_PROP_U16: if (obj->integer.value > U16_MAX) return -EOVERFLOW; - *(u16 *)val = obj->integer.value; + + if (val) + *(u16 *)val = obj->integer.value; + break; case DEV_PROP_U32: if (obj->integer.value > U32_MAX) return -EOVERFLOW; - *(u32 *)val = obj->integer.value; + + if (val) + *(u32 *)val = obj->integer.value; + break; default: - *(u64 *)val = obj->integer.value; + if (val) + *(u64 *)val = obj->integer.value; + break; } + + if (!val) + return 1; } else if (proptype == DEV_PROP_STRING) { ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj); if (ret) return ret; - *(char **)val = obj->string.pointer; + if (val) + *(char **)val = obj->string.pointer; return 1; } else { @@ -767,7 +779,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, { int ret; - if (!adev) + if (!adev || !val) return -EINVAL; ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val); @@ -861,10 +873,20 @@ static int acpi_data_prop_read(const struct acpi_device_data *data, const union acpi_object *items; int ret; - if (val && nval == 1) { + if (nval == 1 || !val) { ret = acpi_data_prop_read_single(data, propname, proptype, val); - if (ret >= 0) + /* + * The overflow error means that the property is there and it is + * single-value, but its type does not match, so return. + */ + if (ret >= 0 || ret == -EOVERFLOW) return ret; + + /* + * Reading this property as a single-value one failed, but its + * value may still be represented as one-element array, so + * continue. + */ } ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index 316a0fc785e3..d3f9a320e880 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -549,7 +549,7 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, ret = c->preproc(ares, c->preproc_data); if (ret < 0) { c->error = ret; - return AE_CTRL_TERMINATE; + return AE_ABORT_METHOD; } else if (ret > 0) { return AE_OK; } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 1cfa3ac1d91f..d3c551bdc2da 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -482,10 +482,10 @@ static void acpi_device_del(struct acpi_device *device) list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) if (!strcmp(acpi_device_bus_id->bus_id, acpi_device_hid(device))) { - if (acpi_device_bus_id->instance_no > 0) - acpi_device_bus_id->instance_no--; - else { + ida_simple_remove(&acpi_device_bus_id->instance_ida, device->pnp.instance_no); + if (ida_is_empty(&acpi_device_bus_id->instance_ida)) { list_del(&acpi_device_bus_id->node); + kfree_const(acpi_device_bus_id->bus_id); kfree(acpi_device_bus_id); } break; @@ -585,6 +585,8 @@ static int acpi_get_device_data(acpi_handle handle, struct acpi_device **device, if (!device) return -EINVAL; + *device = NULL; + status = acpi_get_data_full(handle, acpi_scan_drop_device, (void **)device, callback); if (ACPI_FAILURE(status) || !*device) { @@ -620,12 +622,38 @@ void acpi_bus_put_acpi_device(struct acpi_device *adev) put_device(&adev->dev); } +static struct acpi_device_bus_id *acpi_device_bus_id_match(const char *dev_id) +{ + struct acpi_device_bus_id *acpi_device_bus_id; + + /* Find suitable bus_id and instance number in acpi_bus_id_list. */ + list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) { + if (!strcmp(acpi_device_bus_id->bus_id, dev_id)) + return acpi_device_bus_id; + } + return NULL; +} + +static int acpi_device_set_name(struct acpi_device *device, + struct acpi_device_bus_id *acpi_device_bus_id) +{ + struct ida *instance_ida = &acpi_device_bus_id->instance_ida; + int result; + + result = ida_simple_get(instance_ida, 0, ACPI_MAX_DEVICE_INSTANCES, GFP_KERNEL); + if (result < 0) + return result; + + device->pnp.instance_no = result; + dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, result); + return 0; +} + int acpi_device_add(struct acpi_device *device, void (*release)(struct device *)) { + struct acpi_device_bus_id *acpi_device_bus_id; int result; - struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id; - int found = 0; if (device->handle) { acpi_status status; @@ -651,34 +679,38 @@ int acpi_device_add(struct acpi_device *device, INIT_LIST_HEAD(&device->del_list); mutex_init(&device->physical_node_lock); - new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL); - if (!new_bus_id) { - pr_err(PREFIX "Memory allocation error\n"); - result = -ENOMEM; - goto err_detach; - } - mutex_lock(&acpi_device_lock); - /* - * Find suitable bus_id and instance number in acpi_bus_id_list - * If failed, create one and link it into acpi_bus_id_list - */ - list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) { - if (!strcmp(acpi_device_bus_id->bus_id, - acpi_device_hid(device))) { - acpi_device_bus_id->instance_no++; - found = 1; - kfree(new_bus_id); - break; + + acpi_device_bus_id = acpi_device_bus_id_match(acpi_device_hid(device)); + if (acpi_device_bus_id) { + result = acpi_device_set_name(device, acpi_device_bus_id); + if (result) + goto err_unlock; + } else { + acpi_device_bus_id = kzalloc(sizeof(*acpi_device_bus_id), + GFP_KERNEL); + if (!acpi_device_bus_id) { + result = -ENOMEM; + goto err_unlock; } - } - if (!found) { - acpi_device_bus_id = new_bus_id; - strcpy(acpi_device_bus_id->bus_id, acpi_device_hid(device)); - acpi_device_bus_id->instance_no = 0; + acpi_device_bus_id->bus_id = + kstrdup_const(acpi_device_hid(device), GFP_KERNEL); + if (!acpi_device_bus_id->bus_id) { + kfree(acpi_device_bus_id); + result = -ENOMEM; + goto err_unlock; + } + + ida_init(&acpi_device_bus_id->instance_ida); + + result = acpi_device_set_name(device, acpi_device_bus_id); + if (result) { + kfree(acpi_device_bus_id); + goto err_unlock; + } + list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list); } - dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no); if (device->parent) list_add_tail(&device->node, &device->parent->children); @@ -709,9 +741,10 @@ int acpi_device_add(struct acpi_device *device, if (device->parent) list_del(&device->node); list_del(&device->wakeup_list); + + err_unlock: mutex_unlock(&acpi_device_lock); - err_detach: acpi_detach_data(device->handle, acpi_scan_drop_device); return result; } diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 551b71a24b85..3bdab6eb33bf 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -188,6 +188,8 @@ struct acpi_thermal { int tz_enabled; int kelvin_offset; struct work_struct thermal_check_work; + struct mutex thermal_check_lock; + refcount_t thermal_check_count; }; /* -------------------------------------------------------------------------- @@ -513,17 +515,6 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) return 0; } -static void acpi_thermal_check(void *data) -{ - struct acpi_thermal *tz = data; - - if (!tz->tz_enabled) - return; - - thermal_zone_device_update(tz->thermal_zone, - THERMAL_EVENT_UNSPECIFIED); -} - /* sys I/F for generic thermal sysfs support */ static int thermal_get_temp(struct thermal_zone_device *thermal, int *temp) @@ -557,6 +548,8 @@ static int thermal_get_mode(struct thermal_zone_device *thermal, return 0; } +static void acpi_thermal_check_fn(struct work_struct *work); + static int thermal_set_mode(struct thermal_zone_device *thermal, enum thermal_device_mode mode) { @@ -582,7 +575,7 @@ static int thermal_set_mode(struct thermal_zone_device *thermal, ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s kernel ACPI thermal control\n", tz->tz_enabled ? "Enable" : "Disable")); - acpi_thermal_check(tz); + acpi_thermal_check_fn(&tz->thermal_check_work); } return 0; } @@ -951,6 +944,12 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) Driver Interface -------------------------------------------------------------------------- */ +static void acpi_queue_thermal_check(struct acpi_thermal *tz) +{ + if (!work_pending(&tz->thermal_check_work)) + queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work); +} + static void acpi_thermal_notify(struct acpi_device *device, u32 event) { struct acpi_thermal *tz = acpi_driver_data(device); @@ -961,17 +960,17 @@ static void acpi_thermal_notify(struct acpi_device *device, u32 event) switch (event) { case ACPI_THERMAL_NOTIFY_TEMPERATURE: - acpi_thermal_check(tz); + acpi_queue_thermal_check(tz); break; case ACPI_THERMAL_NOTIFY_THRESHOLDS: acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS); - acpi_thermal_check(tz); + acpi_queue_thermal_check(tz); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); - acpi_thermal_check(tz); + acpi_queue_thermal_check(tz); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); break; @@ -1071,7 +1070,27 @@ static void acpi_thermal_check_fn(struct work_struct *work) { struct acpi_thermal *tz = container_of(work, struct acpi_thermal, thermal_check_work); - acpi_thermal_check(tz); + + if (!tz->tz_enabled) + return; + /* + * In general, it is not sufficient to check the pending bit, because + * subsequent instances of this function may be queued after one of them + * has started running (e.g. if _TMP sleeps). Avoid bailing out if just + * one of them is running, though, because it may have done the actual + * check some time ago, so allow at least one of them to block on the + * mutex while another one is running the update. + */ + if (!refcount_dec_not_one(&tz->thermal_check_count)) + return; + + mutex_lock(&tz->thermal_check_lock); + + thermal_zone_device_update(tz->thermal_zone, THERMAL_EVENT_UNSPECIFIED); + + refcount_inc(&tz->thermal_check_count); + + mutex_unlock(&tz->thermal_check_lock); } static int acpi_thermal_add(struct acpi_device *device) @@ -1103,6 +1122,8 @@ static int acpi_thermal_add(struct acpi_device *device) if (result) goto free_memory; + refcount_set(&tz->thermal_check_count, 3); + mutex_init(&tz->thermal_check_lock); INIT_WORK(&tz->thermal_check_work, acpi_thermal_check_fn); pr_info(PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), @@ -1168,7 +1189,7 @@ static int acpi_thermal_resume(struct device *dev) tz->state.active |= tz->trips.active[i].flags.enabled; } - queue_work(acpi_thermal_pm_queue, &tz->thermal_check_work); + acpi_queue_thermal_check(tz); return AE_OK; } diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 41b706403ef7..2380ebd9b7fd 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -284,10 +284,11 @@ static int amba_remove(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *drv = to_amba_driver(dev->driver); - int ret; + int ret = 0; pm_runtime_get_sync(dev); - ret = drv->remove(pcdev); + if (drv->remove) + ret = drv->remove(pcdev); pm_runtime_put_noidle(dev); /* Undo the runtime PM settings in amba_probe() */ @@ -304,7 +305,9 @@ static int amba_remove(struct device *dev) static void amba_shutdown(struct device *dev) { struct amba_driver *drv = to_amba_driver(dev->driver); - drv->shutdown(to_amba_device(dev)); + + if (drv->shutdown) + drv->shutdown(to_amba_device(dev)); } /** @@ -317,12 +320,13 @@ static void amba_shutdown(struct device *dev) */ int amba_driver_register(struct amba_driver *drv) { - drv->drv.bus = &amba_bustype; + if (!drv->probe) + return -EINVAL; -#define SETFN(fn) if (drv->fn) drv->drv.fn = amba_##fn - SETFN(probe); - SETFN(remove); - SETFN(shutdown); + drv->drv.bus = &amba_bustype; + drv->drv.probe = amba_probe; + drv->drv.remove = amba_remove; + drv->drv.shutdown = amba_shutdown; return driver_register(&drv->drv); } diff --git a/drivers/android/Kconfig b/drivers/android/Kconfig index 003cc6f727d1..dce484c5ac92 100644 --- a/drivers/android/Kconfig +++ b/drivers/android/Kconfig @@ -60,6 +60,39 @@ config BINDER_OPT ---help--- Mark important binder calls from ui thread. +config ANDROID_SIMPLE_LMK + bool "Simple Android Low Memory Killer" + depends on !ANDROID_LOW_MEMORY_KILLER && !MEMCG && !PSI + ---help--- + This is a complete low memory killer solution for Android that is + small and simple. Processes are killed according to the priorities + that Android gives them, so that the least important processes are + always killed first. Processes are killed until memory deficits are + satisfied, as observed from direct reclaim and kswapd reclaim + struggling to free up pages, via VM pressure notifications. + +if ANDROID_SIMPLE_LMK + +config ANDROID_SIMPLE_LMK_MINFREE + int "Minimum MiB of memory to free per reclaim" + range 8 512 + default 128 + help + Simple LMK will try to free at least this much memory per reclaim. + +config ANDROID_SIMPLE_LMK_TIMEOUT_MSEC + int "Reclaim timeout in milliseconds" + range 50 1000 + default 200 + help + Simple LMK tries to wait until all of the victims it kills have their + memory freed; however, sometimes victims can take a while to die, + which can block Simple LMK from killing more processes in time when + needed. After the specified timeout elapses, Simple LMK will stop + waiting and make itself available to kill more processes. + +endif + endif # if ANDROID endmenu diff --git a/drivers/android/Makefile b/drivers/android/Makefile index c7856e3200da..7c91293b6d59 100644 --- a/drivers/android/Makefile +++ b/drivers/android/Makefile @@ -3,3 +3,4 @@ ccflags-y += -I$(src) # needed for trace events obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o +obj-$(CONFIG_ANDROID_SIMPLE_LMK) += simple_lmk.o diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 7e7dac4cd6c5..9f1cdd322703 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -126,8 +126,7 @@ enum { BINDER_DEBUG_PRIORITY_CAP = 1U << 13, BINDER_DEBUG_SPINLOCKS = 1U << 14, }; -static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR | - BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION; +static uint32_t binder_debug_mask = 0; module_param_named(debug_mask, binder_debug_mask, uint, 0644); char *binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES; @@ -149,6 +148,7 @@ static int binder_set_stop_on_user_error(const char *val, module_param_call(stop_on_user_error, binder_set_stop_on_user_error, param_get_int, &binder_stop_on_user_error, 0644); +#ifdef DEBUG #define binder_debug(mask, x...) \ do { \ if (binder_debug_mask & mask) \ @@ -162,6 +162,16 @@ module_param_call(stop_on_user_error, binder_set_stop_on_user_error, if (binder_stop_on_user_error) \ binder_stop_on_user_error = 2; \ } while (0) +#else +static inline void binder_debug(uint32_t mask, const char *fmt, ...) +{ +} +static inline void binder_user_error(const char *fmt, ...) +{ + if (binder_stop_on_user_error) + binder_stop_on_user_error = 2; +} +#endif #define to_flat_binder_object(hdr) \ container_of(hdr, struct flat_binder_object, hdr) @@ -207,6 +217,14 @@ static inline void binder_stats_created(enum binder_stat_types type) struct binder_transaction_log binder_transaction_log; struct binder_transaction_log binder_transaction_log_failed; +static struct kmem_cache *binder_node_pool; +static struct kmem_cache *binder_proc_pool; +static struct kmem_cache *binder_ref_death_pool; +static struct kmem_cache *binder_ref_pool; +static struct kmem_cache *binder_thread_pool; +static struct kmem_cache *binder_transaction_pool; +static struct kmem_cache *binder_work_pool; + static struct binder_transaction_log_entry *binder_transaction_log_add( struct binder_transaction_log *log) { @@ -1347,9 +1365,9 @@ static struct binder_node *binder_init_node_ilocked( static struct binder_node *binder_new_node(struct binder_proc *proc, struct flat_binder_object *fp) { - struct binder_node *node; - struct binder_node *new_node = kzalloc(sizeof(*node), GFP_KERNEL); + struct binder_node *node, *new_node; + new_node = kmem_cache_zalloc(binder_node_pool, GFP_KERNEL); if (!new_node) return NULL; binder_inner_proc_lock(proc); @@ -1359,14 +1377,14 @@ static struct binder_node *binder_new_node(struct binder_proc *proc, /* * The node was already added by another thread */ - kfree(new_node); + kmem_cache_free(binder_node_pool, new_node); return node; } static void binder_free_node(struct binder_node *node) { - kfree(node); + kmem_cache_free(binder_node_pool, node); binder_stats_deleted(BINDER_STAT_NODE); } @@ -1846,8 +1864,9 @@ static void binder_free_ref(struct binder_ref *ref) { if (ref->node) binder_free_node(ref->node); - kfree(ref->death); - kfree(ref); + if (ref->death) + kmem_cache_free(binder_ref_death_pool, ref->death); + kmem_cache_free(binder_ref_pool, ref); } /** @@ -1940,7 +1959,7 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, ref = binder_get_ref_for_node_olocked(proc, node, NULL); if (!ref) { binder_proc_unlock(proc); - new_ref = kzalloc(sizeof(*ref), GFP_KERNEL); + new_ref = kmem_cache_zalloc(binder_ref_pool, GFP_KERNEL); if (!new_ref) return -ENOMEM; binder_proc_lock(proc); @@ -1954,7 +1973,7 @@ static int binder_inc_ref_for_node(struct binder_proc *proc, * Another thread created the ref first so * free the one we allocated */ - kfree(new_ref); + kmem_cache_free(binder_ref_pool, new_ref); return ret; } @@ -2089,7 +2108,7 @@ static void binder_free_transaction(struct binder_transaction *t) * If the transaction has no target_proc, then * t->buffer->transaction has already been cleared. */ - kfree(t); + kmem_cache_free(binder_transaction_pool, t); binder_stats_deleted(BINDER_STAT_TRANSACTION); } @@ -3175,7 +3194,7 @@ static void binder_transaction(struct binder_proc *proc, e->to_proc = target_proc->pid; /* TODO: reuse incoming transaction for reply */ - t = kzalloc(sizeof(*t), GFP_KERNEL); + t = kmem_cache_zalloc(binder_transaction_pool, GFP_KERNEL); if (t == NULL) { return_error = BR_FAILED_REPLY; return_error_param = -ENOMEM; @@ -3185,7 +3204,7 @@ static void binder_transaction(struct binder_proc *proc, binder_stats_created(BINDER_STAT_TRANSACTION); spin_lock_init(&t->lock); - tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL); + tcomplete = kmem_cache_zalloc(binder_work_pool, GFP_KERNEL); if (tcomplete == NULL) { return_error = BR_FAILED_REPLY; return_error_param = -ENOMEM; @@ -3610,10 +3629,10 @@ static void binder_transaction(struct binder_proc *proc, if (secctx) security_release_secctx(secctx, secctx_sz); err_get_secctx_failed: - kfree(tcomplete); + kmem_cache_free(binder_work_pool, tcomplete); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); err_alloc_tcomplete_failed: - kfree(t); + kmem_cache_free(binder_transaction_pool, t); binder_stats_deleted(BINDER_STAT_TRANSACTION); err_alloc_t_failed: err_bad_todo_list: @@ -3966,7 +3985,7 @@ static int binder_thread_write(struct binder_proc *proc, * Allocate memory for death notification * before taking lock */ - death = kzalloc(sizeof(*death), GFP_KERNEL); + death = kmem_cache_zalloc(binder_ref_death_pool, GFP_KERNEL); if (death == NULL) { WARN_ON(thread->return_error.cmd != BR_OK); @@ -3991,7 +4010,8 @@ static int binder_thread_write(struct binder_proc *proc, "BC_CLEAR_DEATH_NOTIFICATION", target); binder_proc_unlock(proc); - kfree(death); + if (death) + kmem_cache_free(binder_ref_death_pool, death); break; } @@ -4012,7 +4032,7 @@ static int binder_thread_write(struct binder_proc *proc, proc->pid, thread->pid); binder_node_unlock(ref->node); binder_proc_unlock(proc); - kfree(death); + kmem_cache_free(binder_ref_death_pool, death); break; } binder_stats_created(BINDER_STAT_DEATH); @@ -4312,7 +4332,7 @@ static int binder_thread_read(struct binder_proc *proc, case BINDER_WORK_TRANSACTION_COMPLETE: { binder_inner_proc_unlock(proc); cmd = BR_TRANSACTION_COMPLETE; - kfree(w); + kmem_cache_free(binder_work_pool, w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT; @@ -4433,7 +4453,7 @@ static int binder_thread_read(struct binder_proc *proc, (u64)cookie); if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) { binder_inner_proc_unlock(proc); - kfree(death); + kmem_cache_free(binder_ref_death_pool, death); binder_stats_deleted(BINDER_STAT_DEATH); } else { binder_enqueue_work_ilocked( @@ -4611,7 +4631,7 @@ static void binder_release_work(struct binder_proc *proc, case BINDER_WORK_TRANSACTION_COMPLETE: { binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered TRANSACTION_COMPLETE\n"); - kfree(w); + kmem_cache_free(binder_work_pool, w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; case BINDER_WORK_DEAD_BINDER_AND_CLEAR: @@ -4622,7 +4642,7 @@ static void binder_release_work(struct binder_proc *proc, binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, "undelivered death notification, %016llx\n", (u64)death->cookie); - kfree(death); + kmem_cache_free(binder_ref_death_pool, death); binder_stats_deleted(BINDER_STAT_DEATH); } break; case BINDER_WORK_NODE: @@ -4685,14 +4705,14 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc) thread = binder_get_thread_ilocked(proc, NULL); binder_inner_proc_unlock(proc); if (!thread) { - new_thread = kzalloc(sizeof(*thread), GFP_KERNEL); + new_thread = kmem_cache_zalloc(binder_thread_pool, GFP_KERNEL); if (new_thread == NULL) return NULL; binder_inner_proc_lock(proc); thread = binder_get_thread_ilocked(proc, new_thread); binder_inner_proc_unlock(proc); if (thread != new_thread) - kfree(new_thread); + kmem_cache_free(binder_thread_pool, new_thread); } return thread; } @@ -4711,7 +4731,7 @@ static void binder_free_proc(struct binder_proc *proc) binder_alloc_deferred_release(&proc->alloc); put_task_struct(proc->tsk); binder_stats_deleted(BINDER_STAT_PROC); - kfree(proc); + kmem_cache_free(binder_proc_pool, proc); } static void binder_free_thread(struct binder_thread *thread) @@ -4720,7 +4740,7 @@ static void binder_free_thread(struct binder_thread *thread) binder_stats_deleted(BINDER_STAT_THREAD); binder_proc_dec_tmpref(thread->proc); put_task_struct(thread->task); - kfree(thread); + kmem_cache_free(binder_thread_pool, thread); } static int binder_thread_release(struct binder_proc *proc, @@ -5136,8 +5156,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (thread) thread->looper_need_return = false; wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2); - if (ret && ret != -ERESTARTSYS) - pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret); + if (ret && ret != -EINTR) err_unlocked: trace_binder_ioctl_done(ret); return ret; @@ -5231,7 +5250,7 @@ static int binder_open(struct inode *nodp, struct file *filp) binder_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d:%d\n", __func__, current->group_leader->pid, current->pid); - proc = kzalloc(sizeof(*proc), GFP_KERNEL); + proc = kmem_cache_zalloc(binder_proc_pool, GFP_KERNEL); if (proc == NULL) return -ENOMEM; spin_lock_init(&proc->inner_lock); @@ -6140,6 +6159,73 @@ static int __init init_binder_device(const char *name) return ret; } +static int __init binder_create_pools(void) +{ + int ret; + + ret = binder_buffer_pool_create(); + if (ret) + return ret; + + binder_node_pool = KMEM_CACHE(binder_node, SLAB_HWCACHE_ALIGN); + if (!binder_node_pool) + goto err_node_pool; + + binder_proc_pool = KMEM_CACHE(binder_proc, SLAB_HWCACHE_ALIGN); + if (!binder_proc_pool) + goto err_proc_pool; + + binder_ref_death_pool = KMEM_CACHE(binder_ref_death, SLAB_HWCACHE_ALIGN); + if (!binder_ref_death_pool) + goto err_ref_death_pool; + + binder_ref_pool = KMEM_CACHE(binder_ref, SLAB_HWCACHE_ALIGN); + if (!binder_ref_pool) + goto err_ref_pool; + + binder_thread_pool = KMEM_CACHE(binder_thread, SLAB_HWCACHE_ALIGN); + if (!binder_thread_pool) + goto err_thread_pool; + + binder_transaction_pool = KMEM_CACHE(binder_transaction, SLAB_HWCACHE_ALIGN); + if (!binder_transaction_pool) + goto err_transaction_pool; + + binder_work_pool = KMEM_CACHE(binder_work, SLAB_HWCACHE_ALIGN); + if (!binder_work_pool) + goto err_work_pool; + + return 0; + +err_work_pool: + kmem_cache_destroy(binder_transaction_pool); +err_transaction_pool: + kmem_cache_destroy(binder_thread_pool); +err_thread_pool: + kmem_cache_destroy(binder_ref_pool); +err_ref_pool: + kmem_cache_destroy(binder_ref_death_pool); +err_ref_death_pool: + kmem_cache_destroy(binder_proc_pool); +err_proc_pool: + kmem_cache_destroy(binder_node_pool); +err_node_pool: + binder_buffer_pool_destroy(); + return -ENOMEM; +} + +static void __init binder_destroy_pools(void) +{ + binder_buffer_pool_destroy(); + kmem_cache_destroy(binder_node_pool); + kmem_cache_destroy(binder_proc_pool); + kmem_cache_destroy(binder_ref_death_pool); + kmem_cache_destroy(binder_ref_pool); + kmem_cache_destroy(binder_thread_pool); + kmem_cache_destroy(binder_transaction_pool); + kmem_cache_destroy(binder_work_pool); +} + static int __init binder_init(void) { int ret; @@ -6148,10 +6234,14 @@ static int __init binder_init(void) struct hlist_node *tmp; char *device_names = NULL; - ret = binder_alloc_shrinker_init(); + ret = binder_create_pools(); if (ret) return ret; + ret = binder_alloc_shrinker_init(); + if (ret) + goto err_alloc_shrinker_failed; + atomic_set(&binder_transaction_log.cur, ~0U); atomic_set(&binder_transaction_log_failed.cur, ~0U); @@ -6226,6 +6316,9 @@ static int __init binder_init(void) err_alloc_device_names_failed: debugfs_remove_recursive(binder_debugfs_dir_entry_root); +err_alloc_shrinker_failed: + binder_destroy_pools(); + return ret; } diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index f0ff5fc9d7ea..faa8d60a4726 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -44,7 +44,7 @@ enum { BINDER_DEBUG_BUFFER_ALLOC = 1U << 2, BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 3, }; -static uint32_t binder_alloc_debug_mask = BINDER_DEBUG_USER_ERROR; +static uint32_t binder_alloc_debug_mask = 0; module_param_named(debug_mask, binder_alloc_debug_mask, uint, 0644); @@ -55,6 +55,22 @@ module_param_named(debug_mask, binder_alloc_debug_mask, pr_info_ratelimited(x); \ } while (0) +static struct kmem_cache *binder_buffer_pool; + +int binder_buffer_pool_create(void) +{ + binder_buffer_pool = KMEM_CACHE(binder_buffer, SLAB_HWCACHE_ALIGN); + if (!binder_buffer_pool) + return -ENOMEM; + + return 0; +} + +void binder_buffer_pool_destroy(void) +{ + kmem_cache_destroy(binder_buffer_pool); +} + static struct binder_buffer *binder_buffer_next(struct binder_buffer *buffer) { return list_entry(buffer->entry.next, struct binder_buffer, entry); @@ -510,7 +526,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( if (buffer_size != size) { struct binder_buffer *new_buffer; - new_buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + new_buffer = kmem_cache_zalloc(binder_buffer_pool, GFP_KERNEL); if (!new_buffer) { pr_err("%s: %d failed to alloc new buffer struct\n", __func__, alloc->pid); @@ -645,7 +661,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, buffer_start_page(buffer) + PAGE_SIZE); } list_del(&buffer->entry); - kfree(buffer); + kmem_cache_free(binder_buffer_pool, buffer); } static void binder_free_buf_locked(struct binder_alloc *alloc, @@ -759,7 +775,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, } alloc->buffer_size = vma->vm_end - vma->vm_start; - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + buffer = kmem_cache_zalloc(binder_buffer_pool, GFP_KERNEL); if (!buffer) { ret = -ENOMEM; failure_string = "alloc buffer struct"; @@ -819,7 +835,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) list_del(&buffer->entry); WARN_ON_ONCE(!list_empty(&alloc->buffers)); - kfree(buffer); + kmem_cache_free(binder_buffer_pool, buffer); } page_count = 0; diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 3daa3e211267..d534c8529a61 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -146,6 +146,8 @@ extern void binder_alloc_print_allocated(struct seq_file *m, struct binder_alloc *alloc); void binder_alloc_print_pages(struct seq_file *m, struct binder_alloc *alloc); +extern int binder_buffer_pool_create(void); +extern void binder_buffer_pool_destroy(void); /** * binder_alloc_get_free_async_space() - get free space available for async diff --git a/drivers/android/simple_lmk.c b/drivers/android/simple_lmk.c new file mode 100644 index 000000000000..c6f26dc1540c --- /dev/null +++ b/drivers/android/simple_lmk.c @@ -0,0 +1,339 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019-2021 Sultan Alsawaf . + */ + +#define pr_fmt(fmt) "simple_lmk: " fmt + +#include +#include +#include +#include +#include +#include +#include + +/* The minimum number of pages to free per reclaim */ +#define MIN_FREE_PAGES (CONFIG_ANDROID_SIMPLE_LMK_MINFREE * SZ_1M / PAGE_SIZE) + +/* Kill up to this many victims per reclaim */ +#define MAX_VICTIMS 1024 + +/* Timeout in jiffies for each reclaim */ +#define RECLAIM_EXPIRES msecs_to_jiffies(CONFIG_ANDROID_SIMPLE_LMK_TIMEOUT_MSEC) + +struct victim_info { + struct task_struct *tsk; + struct mm_struct *mm; + unsigned long size; +}; + +static struct victim_info victims[MAX_VICTIMS] __cacheline_aligned_in_smp; +static struct task_struct *task_bucket[SHRT_MAX + 1] __cacheline_aligned; +static DECLARE_WAIT_QUEUE_HEAD(oom_waitq); +static DECLARE_COMPLETION(reclaim_done); +static __cacheline_aligned_in_smp DEFINE_RWLOCK(mm_free_lock); +static int nr_victims; +static atomic_t needs_reclaim = ATOMIC_INIT(0); +static atomic_t nr_killed = ATOMIC_INIT(0); + +static int victim_cmp(const void *lhs_ptr, const void *rhs_ptr) +{ + const struct victim_info *lhs = (typeof(lhs))lhs_ptr; + const struct victim_info *rhs = (typeof(rhs))rhs_ptr; + + return rhs->size - lhs->size; +} + +static void victim_swap(void *lhs_ptr, void *rhs_ptr, int size) +{ + struct victim_info *lhs = (typeof(lhs))lhs_ptr; + struct victim_info *rhs = (typeof(rhs))rhs_ptr; + + swap(*lhs, *rhs); +} + +static unsigned long get_total_mm_pages(struct mm_struct *mm) +{ + unsigned long pages = 0; + int i; + + for (i = 0; i < NR_MM_COUNTERS; i++) + pages += get_mm_counter(mm, i); + + return pages; +} + +static unsigned long find_victims(int *vindex) +{ + short i, min_adj = SHRT_MAX, max_adj = 0; + unsigned long pages_found = 0; + struct task_struct *tsk; + + rcu_read_lock(); + for_each_process(tsk) { + struct signal_struct *sig; + short adj; + + /* + * Search for suitable tasks with a positive adj (importance). + * Since only tasks with a positive adj can be targeted, that + * naturally excludes tasks which shouldn't be killed, like init + * and kthreads. Although oom_score_adj can still be changed + * while this code runs, it doesn't really matter; we just need + * a snapshot of the task's adj. + */ + sig = tsk->signal; + adj = READ_ONCE(sig->oom_score_adj); + if (adj < 0 || + sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP) || + (thread_group_empty(tsk) && tsk->flags & PF_EXITING)) + continue; + + /* Store the task in a linked-list bucket based on its adj */ + tsk->simple_lmk_next = task_bucket[adj]; + task_bucket[adj] = tsk; + + /* Track the min and max adjs to speed up the loop below */ + if (adj > max_adj) + max_adj = adj; + if (adj < min_adj) + min_adj = adj; + } + + /* Start searching for victims from the highest adj (least important) */ + for (i = max_adj; i >= min_adj; i--) { + int old_vindex; + + tsk = task_bucket[i]; + if (!tsk) + continue; + + /* Clear out this bucket for the next time reclaim is done */ + task_bucket[i] = NULL; + + /* Iterate through every task with this adj */ + old_vindex = *vindex; + do { + struct task_struct *vtsk; + + vtsk = find_lock_task_mm(tsk); + if (!vtsk) + continue; + + /* Store this potential victim away for later */ + victims[*vindex].tsk = vtsk; + victims[*vindex].mm = vtsk->mm; + victims[*vindex].size = get_total_mm_pages(vtsk->mm); + + /* Count the number of pages that have been found */ + pages_found += victims[*vindex].size; + + /* Make sure there's space left in the victim array */ + if (++*vindex == MAX_VICTIMS) + break; + } while ((tsk = tsk->simple_lmk_next)); + + /* Go to the next bucket if nothing was found */ + if (*vindex == old_vindex) + continue; + + /* + * Sort the victims in descending order of size to prioritize + * killing the larger ones first. + */ + sort(&victims[old_vindex], *vindex - old_vindex, + sizeof(*victims), victim_cmp, victim_swap); + + /* Stop when we are out of space or have enough pages found */ + if (*vindex == MAX_VICTIMS || pages_found >= MIN_FREE_PAGES) { + /* Zero out any remaining buckets we didn't touch */ + if (i > min_adj) + memset(&task_bucket[min_adj], 0, + (i - min_adj) * sizeof(*task_bucket)); + break; + } + } + rcu_read_unlock(); + + return pages_found; +} + +static int process_victims(int vlen) +{ + unsigned long pages_found = 0; + int i, nr_to_kill = 0; + + /* + * Calculate the number of tasks that need to be killed and quickly + * release the references to those that'll live. + */ + for (i = 0; i < vlen; i++) { + struct victim_info *victim = &victims[i]; + struct task_struct *vtsk = victim->tsk; + + /* The victim's mm lock is taken in find_victims; release it */ + if (pages_found >= MIN_FREE_PAGES) { + task_unlock(vtsk); + } else { + pages_found += victim->size; + nr_to_kill++; + } + } + + return nr_to_kill; +} + +static void scan_and_kill(void) +{ + int i, nr_to_kill, nr_found = 0; + unsigned long pages_found; + + /* Populate the victims array with tasks sorted by adj and then size */ + pages_found = find_victims(&nr_found); + if (unlikely(!pages_found)) { + pr_err("No processes available to kill!\n"); + return; + } + + /* Minimize the number of victims if we found more pages than needed */ + if (pages_found > MIN_FREE_PAGES) { + /* First round of processing to weed out unneeded victims */ + nr_to_kill = process_victims(nr_found); + + /* + * Try to kill as few of the chosen victims as possible by + * sorting the chosen victims by size, which means larger + * victims that have a lower adj can be killed in place of + * smaller victims with a high adj. + */ + sort(victims, nr_to_kill, sizeof(*victims), victim_cmp, + victim_swap); + + /* Second round of processing to finally select the victims */ + nr_to_kill = process_victims(nr_to_kill); + } else { + /* Too few pages found, so all the victims need to be killed */ + nr_to_kill = nr_found; + } + + /* Store the final number of victims for simple_lmk_mm_freed() */ + write_lock(&mm_free_lock); + nr_victims = nr_to_kill; + write_unlock(&mm_free_lock); + + /* Kill the victims */ + for (i = 0; i < nr_to_kill; i++) { + static const struct sched_param sched_zero_prio; + struct victim_info *victim = &victims[i]; + struct task_struct *t, *vtsk = victim->tsk; + + pr_info("Killing %s with adj %d to free %lu KiB\n", vtsk->comm, + vtsk->signal->oom_score_adj, + victim->size << (PAGE_SHIFT - 10)); + + /* Accelerate the victim's death by forcing the kill signal */ + do_send_sig_info(SIGKILL, SEND_SIG_FORCED, vtsk, PIDTYPE_TGID); + + /* Mark the thread group dead so that other kernel code knows */ + rcu_read_lock(); + for_each_thread(vtsk, t) + set_tsk_thread_flag(t, TIF_MEMDIE); + rcu_read_unlock(); + + /* Elevate the victim to SCHED_RR with zero RT priority */ + sched_setscheduler_nocheck(vtsk, SCHED_RR, &sched_zero_prio); + + /* Allow the victim to run on any CPU. This won't schedule. */ + set_cpus_allowed_ptr(vtsk, cpu_all_mask); + + /* Finally release the victim's task lock acquired earlier */ + task_unlock(vtsk); + } + + /* Wait until all the victims die or until the timeout is reached */ + if (!wait_for_completion_timeout(&reclaim_done, RECLAIM_EXPIRES)) + pr_info("Timeout hit waiting for victims to die, proceeding\n"); + + /* Clean up for future reclaim invocations */ + write_lock(&mm_free_lock); + reinit_completion(&reclaim_done); + nr_victims = 0; + nr_killed = (atomic_t)ATOMIC_INIT(0); + write_unlock(&mm_free_lock); +} + +static int simple_lmk_reclaim_thread(void *data) +{ + static const struct sched_param sched_max_rt_prio = { + .sched_priority = MAX_RT_PRIO - 1 + }; + + sched_setscheduler_nocheck(current, SCHED_FIFO, &sched_max_rt_prio); + + while (1) { + wait_event(oom_waitq, atomic_read(&needs_reclaim)); + scan_and_kill(); + atomic_set_release(&needs_reclaim, 0); + } + + return 0; +} + +void simple_lmk_mm_freed(struct mm_struct *mm) +{ + int i; + + /* Nothing to do when reclaim is starting or ending */ + if (!read_trylock(&mm_free_lock)) + return; + + for (i = 0; i < nr_victims; i++) { + if (victims[i].mm == mm) { + victims[i].mm = NULL; + if (atomic_inc_return_relaxed(&nr_killed) == nr_victims) + complete(&reclaim_done); + break; + } + } + read_unlock(&mm_free_lock); +} + +static int simple_lmk_vmpressure_cb(struct notifier_block *nb, + unsigned long pressure, void *data) +{ + if (pressure == 100 && !atomic_cmpxchg_acquire(&needs_reclaim, 0, 1)) + wake_up(&oom_waitq); + + return NOTIFY_OK; +} + +static struct notifier_block vmpressure_notif = { + .notifier_call = simple_lmk_vmpressure_cb, + .priority = INT_MAX +}; + +/* Initialize Simple LMK when lmkd in Android writes to the minfree parameter */ +static int simple_lmk_init_set(const char *val, const struct kernel_param *kp) +{ + static atomic_t init_done = ATOMIC_INIT(0); + struct task_struct *thread; + + if (!atomic_cmpxchg(&init_done, 0, 1)) { + thread = kthread_run_perf_critical(cpu_perf_mask, simple_lmk_reclaim_thread, + NULL, "simple_lmkd"); + BUG_ON(IS_ERR(thread)); + BUG_ON(vmpressure_notifier_register(&vmpressure_notif)); + } + + return 0; +} + +static const struct kernel_param_ops simple_lmk_init_ops = { + .set = simple_lmk_init_set +}; + +/* Needed to prevent Android from thinking there's no LMK and thus rebooting */ +#undef MODULE_PARAM_PREFIX +#define MODULE_PARAM_PREFIX "lowmemorykiller." +module_param_cb(minfree, &simple_lmk_init_ops, NULL, 0200); diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 0192cab1b862..e58b336d1324 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -370,6 +370,10 @@ static int brcm_ahci_resume(struct device *dev) if (ret) return ret; + ret = ahci_platform_enable_regulators(hpriv); + if (ret) + goto out_disable_clks; + brcm_sata_init(priv); brcm_sata_phys_enable(priv); brcm_sata_alpm_init(hpriv); @@ -399,6 +403,8 @@ static int brcm_ahci_resume(struct device *dev) ahci_platform_disable_phys(hpriv); out_disable_phys: brcm_sata_phys_disable(priv); + ahci_platform_disable_regulators(hpriv); +out_disable_clks: ahci_platform_disable_clks(hpriv); return ret; } @@ -471,6 +477,10 @@ static int brcm_ahci_probe(struct platform_device *pdev) if (ret) goto out_reset; + ret = ahci_platform_enable_regulators(hpriv); + if (ret) + goto out_disable_clks; + /* Must be first so as to configure endianness including that * of the standard AHCI register space. */ @@ -480,7 +490,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) priv->port_mask = brcm_ahci_get_portmask(hpriv, priv); if (!priv->port_mask) { ret = -ENODEV; - goto out_disable_clks; + goto out_disable_regulators; } /* Must be done before ahci_platform_enable_phys() */ @@ -505,6 +515,8 @@ static int brcm_ahci_probe(struct platform_device *pdev) ahci_platform_disable_phys(hpriv); out_disable_phys: brcm_sata_phys_disable(priv); +out_disable_regulators: + ahci_platform_disable_regulators(hpriv); out_disable_clks: ahci_platform_disable_clks(hpriv); out_reset: diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 38fec976e62d..1409d48affb7 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -2279,7 +2279,8 @@ static int eni_init_one(struct pci_dev *pci_dev, return rc; err_eni_release: - eni_do_release(dev); + dev->phy = NULL; + iounmap(ENI_DEV(dev)->ioaddr); err_unregister: atm_dev_deregister(dev); err_free_consistent: diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index 0a67487c0b1d..a2ecb4190f78 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -261,7 +261,7 @@ static int idt77105_start(struct atm_dev *dev) { unsigned long flags; - if (!(dev->dev_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL))) + if (!(dev->phy_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL))) return -ENOMEM; PRIV(dev)->dev = dev; spin_lock_irqsave(&idt77105_priv_lock, flags); @@ -336,7 +336,7 @@ static int idt77105_stop(struct atm_dev *dev) else idt77105_all = walk->next; dev->phy = NULL; - dev->dev_data = NULL; + dev->phy_data = NULL; kfree(walk); break; } diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 6e737142ceaa..3e00ab8a8890 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3607,7 +3607,7 @@ static int idt77252_init_one(struct pci_dev *pcidev, if ((err = dma_set_mask_and_coherent(&pcidev->dev, DMA_BIT_MASK(32)))) { printk("idt77252: can't enable DMA for PCI device at %s\n", pci_name(pcidev)); - return err; + goto err_out_disable_pdev; } card = kzalloc(sizeof(struct idt77252_dev), GFP_KERNEL); diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 5f8e009b2da1..34e6e4b90f74 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -2238,6 +2238,7 @@ static int lanai_dev_open(struct atm_dev *atmdev) conf1_write(lanai); #endif iounmap(lanai->base); + lanai->base = NULL; error_pci: pci_disable_device(lanai->pci); error: @@ -2250,6 +2251,8 @@ static int lanai_dev_open(struct atm_dev *atmdev) static void lanai_dev_close(struct atm_dev *atmdev) { struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data; + if (lanai->base==NULL) + return; printk(KERN_INFO DEV_LABEL "(itf %d): shutting down interface\n", lanai->number); lanai_timed_poll_stop(lanai); @@ -2559,7 +2562,7 @@ static int lanai_init_one(struct pci_dev *pci, struct atm_dev *atmdev; int result; - lanai = kmalloc(sizeof(*lanai), GFP_KERNEL); + lanai = kzalloc(sizeof(*lanai), GFP_KERNEL); if (lanai == NULL) { printk(KERN_ERR DEV_LABEL ": couldn't allocate dev_data structure!\n"); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index cbec9adc01c7..0d3754a4ac20 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -1705,6 +1705,8 @@ static int ns_send(struct atm_vcc *vcc, struct sk_buff *skb) if (push_scqe(card, vc, scq, &scqe, skb) != 0) { atomic_inc(&vcc->stats->tx_err); + dma_unmap_single(&card->pcidev->dev, NS_PRV_DMA(skb), skb->len, + DMA_TO_DEVICE); dev_kfree_skb_any(skb); return -EIO; } diff --git a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c index 4fa13a807873..cf517fd148ea 100644 --- a/drivers/atm/uPD98402.c +++ b/drivers/atm/uPD98402.c @@ -210,7 +210,7 @@ static void uPD98402_int(struct atm_dev *dev) static int uPD98402_start(struct atm_dev *dev) { DPRINTK("phy_start\n"); - if (!(dev->dev_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL))) + if (!(dev->phy_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL))) return -ENOMEM; spin_lock_init(&PRIV(dev)->lock); memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats)); diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c index 21393ec3b9a4..194370ae37dd 100644 --- a/drivers/auxdisplay/ht16k33.c +++ b/drivers/auxdisplay/ht16k33.c @@ -117,8 +117,7 @@ static void ht16k33_fb_queue(struct ht16k33_priv *priv) { struct ht16k33_fbdev *fbdev = &priv->fbdev; - schedule_delayed_work(&fbdev->work, - msecs_to_jiffies(HZ / fbdev->refresh_rate)); + schedule_delayed_work(&fbdev->work, HZ / fbdev->refresh_rate); } /* diff --git a/drivers/base/core.c b/drivers/base/core.c index 8746d7d7329b..63e1e8f41426 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -100,6 +100,16 @@ void device_links_read_unlock(int not_used) } #endif /* !CONFIG_SRCU */ +static bool device_is_ancestor(struct device *dev, struct device *target) +{ + while (target->parent) { + target = target->parent; + if (dev == target) + return true; + } + return false; +} + /** * device_is_dependent - Check if one device depends on another one * @dev: Device to check dependencies for. @@ -113,7 +123,12 @@ static int device_is_dependent(struct device *dev, void *target) struct device_link *link; int ret; - if (dev == target) + /* + * The "ancestors" check is needed to catch the case when the target + * device has not been completely initialized yet and it is still + * missing from the list of children of its parent device. + */ + if (dev == target || device_is_ancestor(dev, target)) return 1; ret = device_for_each_child(dev, target, device_is_dependent); @@ -3818,7 +3833,7 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) if (fwnode_is_primary(fn)) { dev->fwnode = fn->secondary; if (!(parent && fn == parent->fwnode)) - fn->secondary = ERR_PTR(-ENODEV); + fn->secondary = NULL; } else { dev->fwnode = NULL; } diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 20b96029f2c9..89db3bed8890 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -265,14 +265,16 @@ int driver_deferred_probe_check_state(struct device *dev) static void deferred_probe_timeout_work_func(struct work_struct *work) { - struct device_private *private, *p; + struct device_private *p; deferred_probe_timeout = 0; driver_deferred_probe_trigger(); flush_work(&deferred_probe_work); - list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe) - dev_info(private->device, "deferred probe pending"); + mutex_lock(&deferred_probe_mutex); + list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe) + dev_info(p->device, "deferred probe pending\n"); + mutex_unlock(&deferred_probe_mutex); } static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func); diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index aa4908c2560f..d97c92dda93b 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -798,7 +797,6 @@ void dpm_noirq_end(void) { resume_device_irqs(); device_wakeup_disarm_wake_irqs(); - cpuidle_resume(); } /** @@ -1416,7 +1414,6 @@ static int device_suspend_noirq(struct device *dev) void dpm_noirq_begin(void) { - cpuidle_pause(); device_wakeup_arm_wake_irqs(); suspend_device_irqs(); } diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 2c99f93020bc..eaae4adf9ce4 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1572,8 +1572,8 @@ void pm_runtime_get_suppliers(struct device *dev) list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) if (link->flags & DL_FLAG_PM_RUNTIME) { link->supplier_preactivated = true; - refcount_inc(&link->rpm_active); pm_runtime_get_sync(link->supplier); + refcount_inc(&link->rpm_active); } device_links_read_unlock(idx); @@ -1586,6 +1586,8 @@ void pm_runtime_get_suppliers(struct device *dev) void pm_runtime_put_suppliers(struct device *dev) { struct device_link *link; + unsigned long flags; + bool put; int idx; idx = device_links_read_lock(); @@ -1593,7 +1595,11 @@ void pm_runtime_put_suppliers(struct device *dev) list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) if (link->supplier_preactivated) { link->supplier_preactivated = false; - if (refcount_dec_not_one(&link->rpm_active)) + spin_lock_irqsave(&dev->power.lock, flags); + put = pm_runtime_status_suspended(dev) && + refcount_dec_not_one(&link->rpm_active); + spin_unlock_irqrestore(&dev->power.lock, flags); + if (put) pm_runtime_put(link->supplier); } diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 6c859c6a2a79..51f648939612 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -642,8 +642,12 @@ void regmap_debugfs_init(struct regmap *map, const char *name) devname = dev_name(map->dev); if (name) { - map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", + if (!map->debugfs_name) { + map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s", devname, name); + if (!map->debugfs_name) + return; + } name = map->debugfs_name; } else { name = devname; @@ -651,9 +655,10 @@ void regmap_debugfs_init(struct regmap *map, const char *name) if (!strcmp(name, "dummy")) { kfree(map->debugfs_name); - map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d", dummy_index); + if (!map->debugfs_name) + return; name = map->debugfs_name; dummy_index++; } diff --git a/drivers/base/regmap/regmap-sdw.c b/drivers/base/regmap/regmap-sdw.c index 50a66382d87d..e75168b941d0 100644 --- a/drivers/base/regmap/regmap-sdw.c +++ b/drivers/base/regmap/regmap-sdw.c @@ -12,7 +12,7 @@ static int regmap_sdw_write(void *context, unsigned int reg, unsigned int val) struct device *dev = context; struct sdw_slave *slave = dev_to_sdw_dev(dev); - return sdw_write(slave, reg, val); + return sdw_write_no_pm(slave, reg, val); } static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val) @@ -21,7 +21,7 @@ static int regmap_sdw_read(void *context, unsigned int reg, unsigned int *val) struct sdw_slave *slave = dev_to_sdw_dev(dev); int read; - read = sdw_read(slave, reg); + read = sdw_read_no_pm(slave, reg); if (read < 0) return read; diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index a2c3c895d111..01a9bb865302 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -474,6 +474,7 @@ config BLK_DEV_RBD config BLK_DEV_RSXX tristate "IBM Flash Adapter 900GB Full Height PCIe Device Driver" depends on PCI + select CRC32 help Device driver for IBM's high speed PCIe SSD storage device: Flash Adapter 900GB Full Height. diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index c0ebda1283cc..015c68017a1c 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -201,7 +201,6 @@ int aoeblk_init(void); void aoeblk_exit(void); void aoeblk_gdalloc(void *); void aoedisk_rm_debugfs(struct aoedev *d); -void aoedisk_rm_sysfs(struct aoedev *d); int aoechr_init(void); void aoechr_exit(void); diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 429ebb84b592..ff770e7d9e52 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -177,10 +177,15 @@ static struct attribute *aoe_attrs[] = { NULL, }; -static const struct attribute_group attr_group = { +static const struct attribute_group aoe_attr_group = { .attrs = aoe_attrs, }; +static const struct attribute_group *aoe_attr_groups[] = { + &aoe_attr_group, + NULL, +}; + static const struct file_operations aoe_debugfs_fops = { .open = aoe_debugfs_open, .read = seq_read, @@ -219,17 +224,6 @@ aoedisk_rm_debugfs(struct aoedev *d) d->debugfs = NULL; } -static int -aoedisk_add_sysfs(struct aoedev *d) -{ - return sysfs_create_group(&disk_to_dev(d->gd)->kobj, &attr_group); -} -void -aoedisk_rm_sysfs(struct aoedev *d) -{ - sysfs_remove_group(&disk_to_dev(d->gd)->kobj, &attr_group); -} - static int aoeblk_open(struct block_device *bdev, fmode_t mode) { @@ -417,8 +411,7 @@ aoeblk_gdalloc(void *vp) spin_unlock_irqrestore(&d->lock, flags); - add_disk(gd); - aoedisk_add_sysfs(d); + device_add_disk(NULL, gd, aoe_attr_groups); aoedisk_add_debugfs(d); spin_lock_irqsave(&d->lock, flags); diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 41060e9cedf2..f29a140cdbc1 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -275,7 +275,6 @@ freedev(struct aoedev *d) del_timer_sync(&d->timer); if (d->gd) { aoedisk_rm_debugfs(d); - aoedisk_rm_sysfs(d); del_gendisk(d->gd); put_disk(d->gd); blk_cleanup_queue(d->blkq); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index bf222c4b2f82..56d4c7df9185 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4074,21 +4074,22 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) if (UFDCS->rawcmd == 1) UFDCS->rawcmd = 2; - if (!(mode & FMODE_NDELAY)) { - if (mode & (FMODE_READ|FMODE_WRITE)) { - UDRS->last_checked = 0; - clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); - check_disk_change(bdev); - if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) - goto out; - if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) - goto out; - } - res = -EROFS; - if ((mode & FMODE_WRITE) && - !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + if (mode & (FMODE_READ|FMODE_WRITE)) { + UDRS->last_checked = 0; + clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags); + check_disk_change(bdev); + if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags)) + goto out; + if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags)) goto out; } + + res = -EROFS; + + if ((mode & FMODE_WRITE) && + !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags)) + goto out; + mutex_unlock(&open_lock); mutex_unlock(&floppy_mutex); return 0; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 52e1e71e8124..81b955670b12 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -276,7 +276,7 @@ static void nbd_size_clear(struct nbd_device *nbd) } } -static void nbd_size_update(struct nbd_device *nbd) +static void nbd_size_update(struct nbd_device *nbd, bool start) { struct nbd_config *config = nbd->config; struct block_device *bdev = bdget_disk(nbd->disk, 0); @@ -292,7 +292,8 @@ static void nbd_size_update(struct nbd_device *nbd) if (bdev) { if (bdev->bd_disk) { bd_set_size(bdev, config->bytesize); - set_blocksize(bdev, config->blksize); + if (start) + set_blocksize(bdev, config->blksize); } else bdev->bd_invalidated = 1; bdput(bdev); @@ -307,7 +308,7 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize, config->blksize = blocksize; config->bytesize = blocksize * nr_blocks; if (nbd->task_recv != NULL) - nbd_size_update(nbd); + nbd_size_update(nbd, false); } static void nbd_complete_rq(struct request *req) @@ -965,6 +966,12 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, if (!sock) return err; + /* + * We need to make sure we don't get any errant requests while we're + * reallocating the ->socks array. + */ + blk_mq_freeze_queue(nbd->disk->queue); + if (!netlink && !nbd->task_setup && !test_bit(NBD_BOUND, &config->runtime_flags)) nbd->task_setup = current; @@ -1003,10 +1010,12 @@ static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, nsock->cookie = 0; socks[config->num_connections++] = nsock; atomic_inc(&config->live_connections); + blk_mq_unfreeze_queue(nbd->disk->queue); return 0; put_socket: + blk_mq_unfreeze_queue(nbd->disk->queue); sockfd_put(sock); return err; } @@ -1244,7 +1253,7 @@ static int nbd_start_device(struct nbd_device *nbd) args->index = i; queue_work(nbd->recv_workq, &args->work); } - nbd_size_update(nbd); + nbd_size_update(nbd, true); return error; } @@ -1447,6 +1456,7 @@ static void nbd_release(struct gendisk *disk, fmode_t mode) if (test_bit(NBD_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) && bdev->bd_openers == 0) nbd_disconnect_and_put(nbd); + bdput(bdev); nbd_config_put(nbd); nbd_put(nbd); diff --git a/drivers/block/null_blk_zoned.c b/drivers/block/null_blk_zoned.c index d1725ac636c0..079ed33fd806 100644 --- a/drivers/block/null_blk_zoned.c +++ b/drivers/block/null_blk_zoned.c @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include "null_blk.h" -/* zone_size in MBs to sectors. */ -#define ZONE_SIZE_SHIFT 11 +#define MB_TO_SECTS(mb) (((sector_t)mb * SZ_1M) >> SECTOR_SHIFT) static inline unsigned int null_zone_no(struct nullb_device *dev, sector_t sect) { @@ -12,7 +12,7 @@ static inline unsigned int null_zone_no(struct nullb_device *dev, sector_t sect) int null_zone_init(struct nullb_device *dev) { - sector_t dev_size = (sector_t)dev->size * 1024 * 1024; + sector_t dev_capacity_sects; sector_t sector = 0; unsigned int i; @@ -25,9 +25,12 @@ int null_zone_init(struct nullb_device *dev) return -EINVAL; } - dev->zone_size_sects = dev->zone_size << ZONE_SIZE_SHIFT; - dev->nr_zones = dev_size >> - (SECTOR_SHIFT + ilog2(dev->zone_size_sects)); + dev_capacity_sects = MB_TO_SECTS(dev->size); + dev->zone_size_sects = MB_TO_SECTS(dev->zone_size); + dev->nr_zones = dev_capacity_sects >> ilog2(dev->zone_size_sects); + if (dev_capacity_sects & (dev->zone_size_sects - 1)) + dev->nr_zones++; + dev->zones = kvmalloc_array(dev->nr_zones, sizeof(struct blk_zone), GFP_KERNEL | __GFP_ZERO); if (!dev->zones) @@ -37,7 +40,10 @@ int null_zone_init(struct nullb_device *dev) struct blk_zone *zone = &dev->zones[i]; zone->start = zone->wp = sector; - zone->len = dev->zone_size_sects; + if (zone->start + dev->zone_size_sects > dev_capacity_sects) + zone->len = dev_capacity_sects - zone->start; + else + zone->len = dev->zone_size_sects; zone->type = BLK_ZONE_TYPE_SEQWRITE_REQ; zone->cond = BLK_ZONE_COND_EMPTY; diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index 14056dc45064..08acfe11752b 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c @@ -179,15 +179,17 @@ static ssize_t rsxx_cram_read(struct file *fp, char __user *ubuf, { struct rsxx_cardinfo *card = file_inode(fp)->i_private; char *buf; - ssize_t st; + int st; buf = kzalloc(cnt, GFP_KERNEL); if (!buf) return -ENOMEM; st = rsxx_creg_read(card, CREG_ADD_CRAM + (u32)*ppos, cnt, buf, 1); - if (!st) - st = copy_to_user(ubuf, buf, cnt); + if (!st) { + if (copy_to_user(ubuf, buf, cnt)) + st = -EFAULT; + } kfree(buf); if (st) return st; @@ -881,6 +883,7 @@ static int rsxx_pci_probe(struct pci_dev *dev, card->event_wq = create_singlethread_workqueue(DRIVER_NAME"_event"); if (!card->event_wq) { dev_err(CARD_TO_DEV(card), "Failed card event setup.\n"); + st = -ENOMEM; goto failed_event_handler; } diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index b18f0162cb9c..d98cfd3b64ff 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -850,8 +850,11 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring, pages[i]->page = persistent_gnt->page; pages[i]->persistent_gnt = persistent_gnt; } else { - if (get_free_page(ring, &pages[i]->page)) - goto out_of_memory; + if (get_free_page(ring, &pages[i]->page)) { + put_free_pages(ring, pages_to_gnt, segs_to_map); + ret = -ENOMEM; + goto out; + } addr = vaddr(pages[i]->page); pages_to_gnt[segs_to_map] = pages[i]->page; pages[i]->persistent_gnt = NULL; @@ -867,10 +870,8 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring, break; } - if (segs_to_map) { + if (segs_to_map) ret = gnttab_map_refs(map, NULL, pages_to_gnt, segs_to_map); - BUG_ON(ret); - } /* * Now swizzle the MFN in our domain with the MFN from the other domain @@ -885,7 +886,7 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring, pr_debug("invalid buffer -- could not remap it\n"); put_free_pages(ring, &pages[seg_idx]->page, 1); pages[seg_idx]->handle = BLKBACK_INVALID_HANDLE; - ret |= 1; + ret |= !ret; goto next; } pages[seg_idx]->handle = map[new_map_idx].handle; @@ -937,17 +938,18 @@ static int xen_blkbk_map(struct xen_blkif_ring *ring, } segs_to_map = 0; last_map = map_until; - if (map_until != num) + if (!ret && map_until != num) goto again; - return ret; - -out_of_memory: - pr_alert("%s: out of memory\n", __func__); - put_free_pages(ring, pages_to_gnt, segs_to_map); - for (i = last_map; i < num; i++) +out: + for (i = last_map; i < num; i++) { + /* Don't zap current batch's valid persistent grants. */ + if(i >= map_until) + pages[i]->persistent_gnt = NULL; pages[i]->handle = BLKBACK_INVALID_HANDLE; - return -ENOMEM; + } + + return ret; } static int xen_blkbk_map_seg(struct pending_req *pending_req) diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 93896c992245..42af2f37ba4e 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -264,6 +264,7 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif) if (ring->xenblkd) { kthread_stop(ring->xenblkd); + ring->xenblkd = NULL; wake_up(&ring->shutdown_wq); } @@ -651,7 +652,8 @@ static int xen_blkbk_probe(struct xenbus_device *dev, /* setup back pointer */ be->blkif->be = be; - err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed, + err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL, + backend_changed, "%s/%s", dev->nodename, "physical-device"); if (err) goto fail; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index adc0e3ed01c2..d4ceee3825f8 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -936,7 +936,8 @@ static void blkif_set_queue_limits(struct blkfront_info *info) if (info->feature_discard) { blk_queue_flag_set(QUEUE_FLAG_DISCARD, rq); blk_queue_max_discard_sectors(rq, get_capacity(gd)); - rq->limits.discard_granularity = info->discard_granularity; + rq->limits.discard_granularity = info->discard_granularity ?: + info->physical_sector_size; rq->limits.discard_alignment = info->discard_alignment; if (info->feature_secdiscard) blk_queue_flag_set(QUEUE_FLAG_SECERASE, rq); @@ -2169,19 +2170,12 @@ static void blkfront_closing(struct blkfront_info *info) static void blkfront_setup_discard(struct blkfront_info *info) { - int err; - unsigned int discard_granularity; - unsigned int discard_alignment; - info->feature_discard = 1; - err = xenbus_gather(XBT_NIL, info->xbdev->otherend, - "discard-granularity", "%u", &discard_granularity, - "discard-alignment", "%u", &discard_alignment, - NULL); - if (!err) { - info->discard_granularity = discard_granularity; - info->discard_alignment = discard_alignment; - } + info->discard_granularity = xenbus_read_unsigned(info->xbdev->otherend, + "discard-granularity", + 0); + info->discard_alignment = xenbus_read_unsigned(info->xbdev->otherend, + "discard-alignment", 0); info->feature_secdiscard = !!xenbus_read_unsigned(info->xbdev->otherend, "discard-secure", 0); diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig index c8aab3115733..f06cd83cb067 100644 --- a/drivers/block/zram/Kconfig +++ b/drivers/block/zram/Kconfig @@ -2,7 +2,7 @@ config ZRAM tristate "Compressed RAM block device support" depends on BLOCK && SYSFS && ZSMALLOC && CRYPTO - select CRYPTO_LZO + select CRYPTO_LZ4 default n help Creates virtual block devices called /dev/zramX (X = 0, 1, ...). @@ -53,3 +53,8 @@ config ZRAM_MEMORY_TRACKING /sys/kernel/debug/zram/zramX/block_state. See Documentation/blockdev/zram.txt for more information. + +config ZRAM_SIZE_OVERRIDE + int "zram size to set from kernel" + range 1 8 + default 2 diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index 4ed0a78fdc09..e064fafb8ba4 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -19,9 +19,9 @@ #include "zcomp.h" static const char * const backends[] = { - "lzo", -#if IS_ENABLED(CONFIG_CRYPTO_LZ4) "lz4", +#if IS_ENABLED(CONFIG_CRYPTO_LZO) + "lzo", #endif #if IS_ENABLED(CONFIG_CRYPTO_LZ4HC) "lz4hc", diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index f39da19f0f3f..ec83ae8835f6 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -41,7 +41,7 @@ static DEFINE_IDR(zram_index_idr); static DEFINE_MUTEX(zram_index_mutex); static int zram_major; -static const char *default_compressor = "lzo"; +static const char *default_compressor = "lz4"; /* Module params (documentation at end) */ static unsigned int num_devices = 1; @@ -1839,9 +1839,14 @@ static ssize_t disksize_store(struct device *dev, struct zram *zram = dev_to_zram(dev); int err; +#ifndef CONFIG_ZRAM_SIZE_OVERRIDE disksize = memparse(buf, NULL); if (!disksize) return -EINVAL; +#else + disksize = (u64)SZ_1G * CONFIG_ZRAM_SIZE_OVERRIDE; + pr_info("Overriding zram size to %li", disksize); +#endif down_write(&zram->init_lock); if (init_done(zram)) { @@ -1998,11 +2003,6 @@ static const struct attribute_group zram_disk_attr_group = { .attrs = zram_disk_attrs, }; -static const struct attribute_group *zram_disk_attr_groups[] = { - &zram_disk_attr_group, - NULL, -}; - /* * Allocate and initialize new zram device. the function returns * '>= 0' device_id upon success, and negative value otherwise. @@ -2022,6 +2022,11 @@ static int zram_add(void) goto out_free_dev; device_id = ret; + if (device_id >= 1) { + ret = -ENOMEM; + goto out_free_idr; + } + init_rwsem(&zram->init_lock); #ifdef CONFIG_ZRAM_WRITEBACK spin_lock_init(&zram->wb_limit_lock); @@ -2085,15 +2090,24 @@ static int zram_add(void) zram->disk->queue->backing_dev_info->capabilities |= (BDI_CAP_STABLE_WRITES | BDI_CAP_SYNCHRONOUS_IO); - disk_to_dev(zram->disk)->groups = zram_disk_attr_groups; add_disk(zram->disk); + ret = sysfs_create_group(&disk_to_dev(zram->disk)->kobj, + &zram_disk_attr_group); + if (ret < 0) { + pr_err("Error creating sysfs group for device %d\n", + device_id); + goto out_free_disk; + } strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); zram_debugfs_register(zram); pr_info("Added device: %s\n", zram->disk->disk_name); return device_id; +out_free_disk: + del_gendisk(zram->disk); + put_disk(zram->disk); out_free_queue: blk_cleanup_queue(queue); out_free_idr: @@ -2122,6 +2136,16 @@ static int zram_remove(struct zram *zram) mutex_unlock(&bdev->bd_mutex); zram_debugfs_unregister(zram); + /* + * Remove sysfs first, so no one will perform a disksize + * store while we destroy the devices. This also helps during + * hot_remove -- zram_reset_device() is the last holder of + * ->init_lock, no later/concurrent disksize_store() or any + * other sysfs handlers are possible. + */ + sysfs_remove_group(&disk_to_dev(zram->disk)->kobj, + &zram_disk_attr_group); + /* Make sure all the pending I/O are finished */ fsync_bdev(bdev); zram_reset_device(zram); diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c index f404f2a4f11b..f2f3c9b3b6e1 100644 --- a/drivers/bluetooth/bluetooth-power.c +++ b/drivers/bluetooth/bluetooth-power.c @@ -448,10 +448,6 @@ static void bt_free_gpios(void) { if (bt_power_pdata->bt_gpio_sys_rst > 0) gpio_free(bt_power_pdata->bt_gpio_sys_rst); - if (bt_power_pdata->wl_gpio_sys_rst > 0) - gpio_free(bt_power_pdata->wl_gpio_sys_rst); - if (bt_power_pdata->bt_gpio_sw_ctrl > 0) - gpio_free(bt_power_pdata->bt_gpio_sw_ctrl); if (bt_power_pdata->bt_gpio_debug > 0) gpio_free(bt_power_pdata->bt_gpio_debug); } diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c index 52930ee285ed..6ecdfa3cd6a9 100644 --- a/drivers/bluetooth/btfm_slim.c +++ b/drivers/bluetooth/btfm_slim.c @@ -427,23 +427,23 @@ int btfm_slim_hw_init(struct btfmslim *btfmslim) slim_ifd = &btfmslim->slim_ifd; mutex_lock(&btfmslim->io_lock); - BTFMSLIM_INFO( + BTFMSLIM_DBG( "PGD Enum Addr: %.02x:%.02x:%.02x:%.02x:%.02x: %.02x", slim->e_addr[0], slim->e_addr[1], slim->e_addr[2], slim->e_addr[3], slim->e_addr[4], slim->e_addr[5]); - BTFMSLIM_INFO( + BTFMSLIM_DBG( "IFD Enum Addr: %.02x:%.02x:%.02x:%.02x:%.02x: %.02x", slim_ifd->e_addr[0], slim_ifd->e_addr[1], slim_ifd->e_addr[2], slim_ifd->e_addr[3], slim_ifd->e_addr[4], slim_ifd->e_addr[5]); chipset_ver = get_chipset_version(); - BTFMSLIM_INFO("chipset soc version:%x", chipset_ver); + BTFMSLIM_DBG("chipset soc version:%x", chipset_ver); if (chipset_ver == QCA_HSP_SOC_ID_0100 || chipset_ver == QCA_HSP_SOC_ID_0110 || chipset_ver == QCA_HSP_SOC_ID_0200) { - BTFMSLIM_INFO("chipset is hastings prime, overwriting EA"); + BTFMSLIM_DBG("chipset is hastings prime, overwriting EA"); slim->e_addr[0] = 0x00; slim->e_addr[1] = 0x01; slim->e_addr[2] = 0x21; @@ -458,7 +458,7 @@ int btfm_slim_hw_init(struct btfmslim *btfmslim) slim_ifd->e_addr[4] = 0x17; slim_ifd->e_addr[5] = 0x02; } else if (chipset_ver == QCA_HASTINGS_SOC_ID_0200) { - BTFMSLIM_INFO("chipset is hastings 2.0, overwriting EA"); + BTFMSLIM_DBG("chipset is hastings 2.0, overwriting EA"); slim->e_addr[0] = 0x00; slim->e_addr[1] = 0x01; slim->e_addr[2] = 0x20; @@ -473,11 +473,11 @@ int btfm_slim_hw_init(struct btfmslim *btfmslim) slim_ifd->e_addr[4] = 0x17; slim_ifd->e_addr[5] = 0x02; } - BTFMSLIM_INFO( + BTFMSLIM_DBG( "PGD Enum Addr: %.02x:%.02x:%.02x:%.02x:%.02x: %.02x", slim->e_addr[0], slim->e_addr[1], slim->e_addr[2], slim->e_addr[3], slim->e_addr[4], slim->e_addr[5]); - BTFMSLIM_INFO( + BTFMSLIM_DBG( "IFD Enum Addr: %.02x:%.02x:%.02x:%.02x:%.02x: %.02x", slim_ifd->e_addr[0], slim_ifd->e_addr[1], slim_ifd->e_addr[2], slim_ifd->e_addr[3], diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c index 7df3eed1ef5e..874172aa8e41 100644 --- a/drivers/bluetooth/btqcomsmd.c +++ b/drivers/bluetooth/btqcomsmd.c @@ -166,8 +166,10 @@ static int btqcomsmd_probe(struct platform_device *pdev) btq->cmd_channel = qcom_wcnss_open_channel(wcnss, "APPS_RIVA_BT_CMD", btqcomsmd_cmd_callback, btq); - if (IS_ERR(btq->cmd_channel)) - return PTR_ERR(btq->cmd_channel); + if (IS_ERR(btq->cmd_channel)) { + ret = PTR_ERR(btq->cmd_channel); + goto destroy_acl_channel; + } /* The local-bd-address property is usually injected by the * bootloader which has access to the allocated BD address. @@ -179,8 +181,10 @@ static int btqcomsmd_probe(struct platform_device *pdev) } hdev = hci_alloc_dev(); - if (!hdev) - return -ENOMEM; + if (!hdev) { + ret = -ENOMEM; + goto destroy_cmd_channel; + } hci_set_drvdata(hdev, btq); btq->hdev = hdev; @@ -194,14 +198,21 @@ static int btqcomsmd_probe(struct platform_device *pdev) hdev->set_bdaddr = qca_set_bdaddr_rome; ret = hci_register_dev(hdev); - if (ret < 0) { - hci_free_dev(hdev); - return ret; - } + if (ret < 0) + goto hci_free_dev; platform_set_drvdata(pdev, btq); return 0; + +hci_free_dev: + hci_free_dev(hdev); +destroy_cmd_channel: + rpmsg_destroy_ept(btq->cmd_channel); +destroy_acl_channel: + rpmsg_destroy_ept(btq->acl_channel); + + return ret; } static int btqcomsmd_remove(struct platform_device *pdev) diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index 5a68cd4dd71c..79b96251de80 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -257,6 +257,9 @@ static int h5_close(struct hci_uart *hu) skb_queue_purge(&h5->rel); skb_queue_purge(&h5->unrel); + kfree_skb(h5->rx_skb); + h5->rx_skb = NULL; + if (h5->vnd && h5->vnd->close) h5->vnd->close(h5); @@ -882,6 +885,11 @@ static int h5_btrtl_setup(struct h5 *h5) /* Give the device some time before the hci-core sends it a reset */ usleep_range(10000, 20000); + /* Enable controller to do both LE scan and BR/EDR inquiry + * simultaneously. + */ + set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &h5->hu->hdev->quirks); + out_free: btrtl_free(btrtl_dev); diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c index e906ecfe23dd..9cb0733a0399 100644 --- a/drivers/bus/fsl-mc/fsl-mc-allocator.c +++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c @@ -292,8 +292,10 @@ int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev, goto error; mc_adev = resource->data; - if (!mc_adev) + if (!mc_adev) { + error = -EINVAL; goto error; + } *new_mc_adev = mc_adev; return 0; diff --git a/drivers/bus/mhi/devices/mhi_netdev.c b/drivers/bus/mhi/devices/mhi_netdev.c index 724b38d72d2f..9f42b752eae4 100644 --- a/drivers/bus/mhi/devices/mhi_netdev.c +++ b/drivers/bus/mhi/devices/mhi_netdev.c @@ -544,12 +544,12 @@ static int mhi_netdev_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t mhi_netdev_xmit(struct sk_buff *skb, struct net_device *dev) { struct mhi_netdev_priv *mhi_netdev_priv = netdev_priv(dev); struct mhi_netdev *mhi_netdev = mhi_netdev_priv->mhi_netdev; struct mhi_device *mhi_dev = mhi_netdev->mhi_dev; - int res = 0; + netdev_tx_t res = NETDEV_TX_OK; MSG_VERB("Entered\n"); diff --git a/drivers/bus/mips_cdmm.c b/drivers/bus/mips_cdmm.c index 1b14256376d2..7c1da45be166 100644 --- a/drivers/bus/mips_cdmm.c +++ b/drivers/bus/mips_cdmm.c @@ -544,10 +544,8 @@ static void mips_cdmm_bus_discover(struct mips_cdmm_bus *bus) dev_set_name(&dev->dev, "cdmm%u-%u", cpu, id); ++id; ret = device_register(&dev->dev); - if (ret) { + if (ret) put_device(&dev->dev); - kfree(dev); - } } } diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c index b040447575ad..dcfb32ee5cb6 100644 --- a/drivers/bus/omap_l3_noc.c +++ b/drivers/bus/omap_l3_noc.c @@ -285,7 +285,7 @@ static int omap_l3_probe(struct platform_device *pdev) */ l3->debug_irq = platform_get_irq(pdev, 0); ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler, - 0x0, "l3-dbg-irq", l3); + IRQF_NO_THREAD, "l3-dbg-irq", l3); if (ret) { dev_err(l3->dev, "request_irq failed for %d\n", l3->debug_irq); @@ -294,7 +294,7 @@ static int omap_l3_probe(struct platform_device *pdev) l3->app_irq = platform_get_irq(pdev, 1); ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler, - 0x0, "l3-app-irq", l3); + IRQF_NO_THREAD, "l3-app-irq", l3); if (ret) dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq); diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 54c8c8644df2..b6a278183d82 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1814,7 +1814,9 @@ static int sysc_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - reset_control_assert(ddata->rsts); + + if (!reset_control_status(ddata->rsts)) + reset_control_assert(ddata->rsts); unprepare: sysc_unprepare(ddata); diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index cc265cd8f882..305dd883764c 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -4088,11 +4088,14 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl) { int err = 0, buf_size = 0; char strpid[PID_SIZE]; + char cur_comm[TASK_COMM_LEN]; + memcpy(cur_comm, current->comm, TASK_COMM_LEN); + cur_comm[TASK_COMM_LEN-1] = '\0'; fl->tgid = current->tgid; snprintf(strpid, PID_SIZE, "%d", current->pid); if (debugfs_root) { - buf_size = strlen(current->comm) + strlen("_") + buf_size = strlen(cur_comm) + strlen("_") + strlen(strpid) + 1; spin_lock(&fl->hlock); @@ -4107,13 +4110,13 @@ static int fastrpc_set_process_info(struct fastrpc_file *fl) err = -ENOMEM; return err; } - snprintf(fl->debug_buf, UL_SIZE, "%.10s%s%d", - current->comm, "_", current->pid); + snprintf(fl->debug_buf, buf_size, "%.10s%s%d", + cur_comm, "_", current->pid); fl->debugfs_file = debugfs_create_file(fl->debug_buf, 0644, debugfs_root, fl, &debugfs_fops); if (IS_ERR_OR_NULL(fl->debugfs_file)) { pr_warn("Error: %s: %s: failed to create debugfs file %s\n", - current->comm, __func__, fl->debug_buf); + cur_comm, __func__, fl->debug_buf); fl->debugfs_file = NULL; kfree(fl->debug_buf); fl->debug_buf_alloced_attempted = 0; @@ -4180,7 +4183,6 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, { int err = 0; unsigned int latency; - cpumask_t mask; struct fastrpc_apps *me = &gfa; u32 len = me->silvercores.corecount, i = 0; @@ -4198,11 +4200,11 @@ static int fastrpc_internal_control(struct fastrpc_file *fl, VERIFY(err, latency != 0); if (err) goto bail; - cpumask_clear(&mask); + atomic_set(&fl->pm_qos_req.cpus_affine, 0); for (i = 0; i < len; i++) - cpumask_set_cpu(me->silvercores.coreno[i], &mask); + atomic_or(BIT(me->silvercores.coreno[i]), + &fl->pm_qos_req.cpus_affine); fl->pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; - cpumask_copy(&fl->pm_qos_req.cpus_affine, &mask); if (!fl->qos_request) { pm_qos_add_request(&fl->pm_qos_req, diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 6231714ef3c8..cee9e42ce547 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -125,7 +125,7 @@ config AGP_HP_ZX1 config AGP_PARISC tristate "HP Quicksilver AGP support" - depends on AGP && PARISC && 64BIT + depends on AGP && PARISC && 64BIT && IOMMU_SBA help This option gives you AGP GART support for the HP Quicksilver AGP bus adapter on HP PA-RISC machines (Ok, just on the C8000 diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 38ffb281df97..004a3ce8ba72 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -115,9 +115,9 @@ static int agp_find_max(void) long memory, index, result; #if PAGE_SHIFT < 20 - memory = totalram_pages >> (20 - PAGE_SHIFT); + memory = totalram_pages() >> (20 - PAGE_SHIFT); #else - memory = totalram_pages << (PAGE_SHIFT - 20); + memory = totalram_pages() << (PAGE_SHIFT - 20); #endif index = 1; diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c index 3cec3053070c..ab8b13e4db84 100644 --- a/drivers/char/diag/diagmem.c +++ b/drivers/char/diag/diagmem.c @@ -172,7 +172,7 @@ void *diagmem_alloc(struct diagchar_dev *driver, int size, int pool_type) break; } if (size == 0 || size > mempool->itemsize || - size > (int)mempool->pool->pool_data) { + size > (uintptr_t)mempool->pool->pool_data) { pr_err_ratelimited("diag: cannot alloc from mempool %s, invalid size: %d\n", mempool->name, size); break; diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index f615684028af..ba01f24db6db 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -72,7 +72,7 @@ static int timeriomem_rng_read(struct hwrng *hwrng, void *data, */ if (retval > 0) usleep_range(period_us, - period_us + min(1, period_us / 100)); + period_us + max(1, period_us / 100)); *(u32 *)data = readl(priv->io_base); retval += sizeof(u32); diff --git a/drivers/char/random.c b/drivers/char/random.c index bef8c75f0429..99f49bec7e1e 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1109,8 +1109,6 @@ void add_device_randomness(const void *buf, unsigned int size) } EXPORT_SYMBOL(add_device_randomness); -static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE; - /* * This function adds entropy to the entropy "pool" by using timing * delays. It uses the timer_rand_state structure to make an estimate @@ -1173,16 +1171,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) void add_input_randomness(unsigned int type, unsigned int code, unsigned int value) { - static unsigned char last_value; - - /* ignore autorepeat and the like */ - if (value == last_value) - return; - - last_value = value; - add_timer_randomness(&input_timer_state, - (type << 4) ^ code ^ (code >> 4) ^ value); - trace_add_input_randomness(ENTROPY_BITS(&input_pool)); + return; } EXPORT_SYMBOL_GPL(add_input_randomness); @@ -1249,7 +1238,6 @@ void add_interrupt_randomness(int irq, int irq_flags) fast_mix(fast_pool); add_interrupt_bench(cycles); - this_cpu_add(net_rand_state.s1, fast_pool->pool[cycles & 3]); if (unlikely(crng_init == 0)) { if ((fast_pool->count >= 64) && @@ -1944,7 +1932,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) return -EPERM; if (crng_init < 2) return -ENODATA; - crng_reseed(&primary_crng, NULL); + crng_reseed(&primary_crng, &input_pool); crng_global_init_time = jiffies - 1; return 0; default: diff --git a/drivers/char/tpm/eventlog/efi.c b/drivers/char/tpm/eventlog/efi.c index 3e673ab22cb4..abd3beeb5158 100644 --- a/drivers/char/tpm/eventlog/efi.c +++ b/drivers/char/tpm/eventlog/efi.c @@ -43,6 +43,11 @@ int tpm_read_log_efi(struct tpm_chip *chip) log_size = log_tbl->size; memunmap(log_tbl); + if (!log_size) { + pr_warn("UEFI TPM log area empty\n"); + return -EIO; + } + log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size, MEMREMAP_WB); if (!log_tbl) { diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index f08949a5f678..5a3a4f095391 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "tpm.h" #include "tpm_tis_core.h" @@ -53,8 +54,8 @@ static inline struct tpm_tis_tcg_phy *to_tpm_tis_tcg_phy(struct tpm_tis_data *da return container_of(data, struct tpm_tis_tcg_phy, priv); } -static bool interrupts = true; -module_param(interrupts, bool, 0444); +static int interrupts = -1; +module_param(interrupts, int, 0444); MODULE_PARM_DESC(interrupts, "Enable interrupts"); static bool itpm; @@ -67,6 +68,28 @@ module_param(force, bool, 0444); MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); #endif +static int tpm_tis_disable_irq(const struct dmi_system_id *d) +{ + if (interrupts == -1) { + pr_notice("tpm_tis: %s detected: disabling interrupts.\n", d->ident); + interrupts = 0; + } + + return 0; +} + +static const struct dmi_system_id tpm_tis_dmi_table[] = { + { + .callback = tpm_tis_disable_irq, + .ident = "ThinkPad T490s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T490s"), + }, + }, + {} +}; + #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) static int has_hid(struct acpi_device *dev, const char *hid) { @@ -196,6 +219,8 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info) int irq = -1; int rc; + dmi_check_system(tpm_tis_dmi_table); + rc = check_acpi_tpm2(dev); if (rc) return rc; diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 280d60cba1f8..c9a5f34097df 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -129,7 +129,8 @@ static bool check_locality(struct tpm_chip *chip, int l) if (rc < 0) return false; - if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == + if ((access & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID + | TPM_ACCESS_REQUEST_USE)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { priv->locality = l; return true; @@ -138,58 +139,13 @@ static bool check_locality(struct tpm_chip *chip, int l) return false; } -static bool locality_inactive(struct tpm_chip *chip, int l) -{ - struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - int rc; - u8 access; - - rc = tpm_tis_read8(priv, TPM_ACCESS(l), &access); - if (rc < 0) - return false; - - if ((access & (TPM_ACCESS_VALID | TPM_ACCESS_ACTIVE_LOCALITY)) - == TPM_ACCESS_VALID) - return true; - - return false; -} - static int release_locality(struct tpm_chip *chip, int l) { struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); - unsigned long stop, timeout; - long rc; tpm_tis_write8(priv, TPM_ACCESS(l), TPM_ACCESS_ACTIVE_LOCALITY); - stop = jiffies + chip->timeout_a; - - if (chip->flags & TPM_CHIP_FLAG_IRQ) { -again: - timeout = stop - jiffies; - if ((long)timeout <= 0) - return -1; - - rc = wait_event_interruptible_timeout(priv->int_queue, - (locality_inactive(chip, l)), - timeout); - - if (rc > 0) - return 0; - - if (rc == -ERESTARTSYS && freezing(current)) { - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - } else { - do { - if (locality_inactive(chip, l)) - return 0; - tpm_msleep(TPM_TIMEOUT); - } while (time_before(jiffies, stop)); - } - return -1; + return 0; } static int request_locality(struct tpm_chip *chip, int l) diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 4080d4e78e8e..f3aaefafba89 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -211,6 +211,7 @@ static int s2mps11_clk_probe(struct platform_device *pdev) return ret; err_reg: + of_node_put(s2mps11_clks[0].clk_np); while (--i >= 0) clkdev_drop(s2mps11_clks[i].lookup); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 4ec9e0940353..3a2852b0480a 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4945,20 +4945,19 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) /* search the list of notifiers for this clk */ list_for_each_entry(cn, &clk_notifier_list, node) if (cn->clk == clk) - break; + goto found; /* if clk wasn't in the notifier list, allocate new clk_notifier */ - if (cn->clk != clk) { - cn = kzalloc(sizeof(*cn), GFP_KERNEL); - if (!cn) - goto out; + cn = kzalloc(sizeof(*cn), GFP_KERNEL); + if (!cn) + goto out; - cn->clk = clk; - srcu_init_notifier_head(&cn->notifier_head); + cn->clk = clk; + srcu_init_notifier_head(&cn->notifier_head); - list_add(&cn->node, &clk_notifier_list); - } + list_add(&cn->node, &clk_notifier_list); +found: ret = srcu_notifier_chain_register(&cn->notifier_head, nb); clk->core->notifier_count++; @@ -4983,32 +4982,28 @@ EXPORT_SYMBOL_GPL(clk_notifier_register); */ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) { - struct clk_notifier *cn = NULL; - int ret = -EINVAL; + struct clk_notifier *cn; + int ret = -ENOENT; if (!clk || !nb) return -EINVAL; clk_prepare_lock(); - list_for_each_entry(cn, &clk_notifier_list, node) - if (cn->clk == clk) - break; - - if (cn->clk == clk) { - ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); + list_for_each_entry(cn, &clk_notifier_list, node) { + if (cn->clk == clk) { + ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); - clk->core->notifier_count--; + clk->core->notifier_count--; - /* XXX the notifier code should handle this better */ - if (!cn->notifier_head.head) { - srcu_cleanup_notifier_head(&cn->notifier_head); - list_del(&cn->node); - kfree(cn); + /* XXX the notifier code should handle this better */ + if (!cn->notifier_head.head) { + srcu_cleanup_notifier_head(&cn->notifier_head); + list_del(&cn->node); + kfree(cn); + } + break; } - - } else { - ret = -ENOENT; } clk_prepare_unlock(); diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 3e04617ac47f..6fdad22a583d 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -197,7 +197,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (parent_rate == 0 || rate == 0) return -EINVAL; - old_rate = rate; + old_rate = clk_hw_get_rate(hw); pllt = meson_clk_get_pll_settings(rate, pll); if (!pllt) diff --git a/drivers/clk/mvebu/armada-37xx-xtal.c b/drivers/clk/mvebu/armada-37xx-xtal.c index 612d65ede10a..5370514959e1 100644 --- a/drivers/clk/mvebu/armada-37xx-xtal.c +++ b/drivers/clk/mvebu/armada-37xx-xtal.c @@ -15,8 +15,8 @@ #include #include -#define NB_GPIO1_LATCH 0xC -#define XTAL_MODE BIT(31) +#define NB_GPIO1_LATCH 0x8 +#define XTAL_MODE BIT(9) static int armada_3700_xtal_clock_probe(struct platform_device *pdev) { diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c index 1f4298eb7034..3a76de4e7729 100644 --- a/drivers/clk/qcom/clk-pll.c +++ b/drivers/clk/qcom/clk-pll.c @@ -138,7 +138,8 @@ clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) f = find_freq(pll->freq_tbl, req->rate); if (!f) - req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate); + req->rate = DIV_ROUND_UP_ULL(req->rate, req->best_parent_rate) + * req->best_parent_rate; else req->rate = f->freq; @@ -175,12 +176,38 @@ clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate) return 0; } +static void clk_pll_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_pll *pll = to_clk_pll(hw); + int size, i, val; + + static struct clk_register_data data[] = { + {"PLL_MODE", 0x0}, + {"PLL_L_VAL", 0x4}, + {"PLL_M_VAL", 0x8}, + {"PLL_N_VAL", 0xC}, + {"PLL_USER_CTL", 0x10}, + {"PLL_CONFIG_CTL", 0x14}, + {"PLL_STATUS_CTL", 0x1C}, + }; + + size = ARRAY_SIZE(data); + + for (i = 0; i < size; i++) { + regmap_read(pll->clkr.regmap, pll->mode_reg + data[i].offset, + &val); + clock_debug_output(f, false, + "%20s: 0x%.8x\n", data[i].name, val); + } +} + const struct clk_ops clk_pll_ops = { .enable = clk_pll_enable, .disable = clk_pll_disable, .recalc_rate = clk_pll_recalc_rate, .determine_rate = clk_pll_determine_rate, .set_rate = clk_pll_set_rate, + .list_registers = clk_pll_list_registers, }; EXPORT_SYMBOL_GPL(clk_pll_ops); diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index 78dbdb012f40..2fe527cf6b26 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, Linaro Limited - * Copyright (c) 2014, 2016-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2016-2021, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -1190,6 +1190,7 @@ static const struct of_device_id rpm_smd_clk_match_table[] = { { .compatible = "qcom,rpmcc-scuba", .data = &rpm_clk_scuba}, { .compatible = "qcom,rpmcc-sdm660", .data = &rpm_clk_sdm660 }, { .compatible = "qcom,rpmcc-qm215", .data = &rpm_clk_qm215 }, + { .compatible = "qcom,rpmcc-sdm439", .data = &rpm_clk_qm215 }, { } }; MODULE_DEVICE_TABLE(of, rpm_smd_clk_match_table); @@ -1200,7 +1201,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) struct clk *clk; struct rpm_cc *rcc; struct clk_onecell_data *data; - int ret, is_bengal, is_scuba, is_sdm660, is_qm215; + int ret, is_bengal, is_scuba, is_sdm660, is_qm215, is_sdm439; size_t num_clks, i; struct clk_hw **hw_clks; const struct rpm_smd_clk_desc *desc; @@ -1222,13 +1223,16 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) is_qm215 = of_device_is_compatible(pdev->dev.of_node, "qcom,rpmcc-qm215"); + is_sdm439 = of_device_is_compatible(pdev->dev.of_node, + "qcom,rpmcc-sdm439"); + if (is_sdm660) { ret = clk_vote_bimc(&sdm660_bimc_clk.hw, INT_MAX); if (ret < 0) return ret; } - if (is_qm215) { + if (is_qm215 || is_sdm439) { ret = clk_vote_bimc(&sdm429w_bimc_clk.hw, INT_MAX); if (ret < 0) return ret; @@ -1251,6 +1255,11 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) data->clks = clks; data->clk_num = num_clks; + if (is_sdm439) { + rpm_clk_qm215.clks[RPM_SMD_BIMC_GPU_CLK] = NULL; + rpm_clk_qm215.clks[RPM_SMD_BIMC_GPU_A_CLK] = NULL; + } + for (i = 0; i <= desc->num_rpm_clks; i++) { if (!hw_clks[i]) { clks[i] = ERR_PTR(-ENOENT); @@ -1317,7 +1326,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) /* Hold an active set vote for the cnoc_periph resource */ clk_set_rate(cnoc_periph_keepalive_a_clk.hw.clk, 19200000); clk_prepare_enable(cnoc_periph_keepalive_a_clk.hw.clk); - } else if (is_qm215) { + } else if (is_qm215 || is_sdm439) { clk_prepare_enable(sdm429w_bi_tcxo_ao.hw.clk); /* diff --git a/drivers/clk/qcom/debugcc-sdm429w.c b/drivers/clk/qcom/debugcc-sdm429w.c index d14919a3a168..341ac75a7826 100644 --- a/drivers/clk/qcom/debugcc-sdm429w.c +++ b/drivers/clk/qcom/debugcc-sdm429w.c @@ -25,6 +25,39 @@ static struct measure_clk_data debug_mux_priv = { .xo_div4_cbcr = 0x30034, }; +static const char *const apss_cc_debug_mux_parent_names[] = { + "pwrcl_clk", +}; + +static int apss_cc_debug_mux_sels[] = { + 0x0, /* pwrcl_clk */ +}; + +static int apss_cc_debug_mux_pre_divs[] = { + 0x1, /* pwrcl_clk */ +}; + +static struct clk_debug_mux apss_cc_debug_mux = { + .priv = &debug_mux_priv, + .debug_offset = 0x0, + .post_div_offset = 0x0, + .cbcr_offset = U32_MAX, + .src_sel_mask = 0x3FF00, + .src_sel_shift = 8, + .post_div_mask = 0xF0000000, + .post_div_shift = 28, + .post_div_val = 1, + .mux_sels = apss_cc_debug_mux_sels, + .pre_div_vals = apss_cc_debug_mux_pre_divs, + .hw.init = &(struct clk_init_data){ + .name = "apss_cc_debug_mux", + .ops = &clk_debug_mux_ops, + .parent_names = apss_cc_debug_mux_parent_names, + .num_parents = ARRAY_SIZE(apss_cc_debug_mux_parent_names), + .flags = CLK_IS_MEASURE, + }, +}; + static const char *const gcc_debug_mux_parent_names[] = { "gcc_ahb_clk", "gcc_apss_ahb_clk", @@ -156,6 +189,7 @@ static const char *const gcc_debug_mux_parent_names[] = { "gcc_gtcu_ahb_clk", "gcc_bimc_clk", "gcc_smmu_cfg_clk", + "apss_cc_debug_mux", }; static int gcc_debug_mux_sels[] = { @@ -289,6 +323,7 @@ static int gcc_debug_mux_sels[] = { 0x58, /* gcc_gtcu_ahb_clk */ 0x15A, /* gcc_bimc_clk */ 0x5B, /* gcc_smmu_cfg_clk */ + 0x16A, /* apss_cc_debug_mux */ }; static struct clk_debug_mux gcc_debug_mux = { @@ -312,8 +347,21 @@ static struct clk_debug_mux gcc_debug_mux = { }, }; +static struct clk_dummy pwrcl_clk = { + .rrate = 1000, + .hw.init = &(struct clk_init_data){ + .name = "pwrcl_clk", + .ops = &clk_dummy_ops, + }, +}; + +struct clk_hw *debugcc_qm215_hws[] = { + &pwrcl_clk.hw, +}; + static struct mux_regmap_names mux_list[] = { { .mux = &gcc_debug_mux, .regmap_name = "qcom,gcc" }, + { .mux = &apss_cc_debug_mux, .regmap_name = "qcom,cpu" }, }; static const struct of_device_id clk_debug_match_table[] = { @@ -356,6 +404,15 @@ static int clk_debug_sdm429w_probe(struct platform_device *pdev) } } + for (i = 0; i < ARRAY_SIZE(debugcc_qm215_hws); i++) { + clk = devm_clk_register(&pdev->dev, debugcc_qm215_hws[i]); + if (IS_ERR(clk)) { + dev_err(&pdev->dev, "Unable to register %s, err:(%d)\n", + debugcc_qm215_hws[i]->init->name, PTR_ERR(clk)); + return PTR_ERR(clk); + } + } + ret = clk_debug_measure_register(&gcc_debug_mux.hw); if (ret) { dev_err(&pdev->dev, "Could not register Measure clocks\n"); diff --git a/drivers/clk/qcom/gcc-msm8998.c b/drivers/clk/qcom/gcc-msm8998.c index 772a08101ddf..0ccd6b79cb5e 100644 --- a/drivers/clk/qcom/gcc-msm8998.c +++ b/drivers/clk/qcom/gcc-msm8998.c @@ -124,7 +124,7 @@ static struct pll_vco fabia_vco[] = { static struct clk_alpha_pll gpll0 = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -134,58 +134,58 @@ static struct clk_alpha_pll gpll0 = { .name = "gpll0", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, }; static struct clk_alpha_pll_postdiv gpll0_out_even = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_even", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll0_out_main = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_main", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll0_out_odd = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_odd", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll0_out_test = { .offset = 0x0, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll0_out_test", .parent_names = (const char *[]){ "gpll0" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll gpll1 = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -195,58 +195,58 @@ static struct clk_alpha_pll gpll1 = { .name = "gpll1", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, }; static struct clk_alpha_pll_postdiv gpll1_out_even = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_even", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll1_out_main = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_main", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll1_out_odd = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_odd", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll1_out_test = { .offset = 0x1000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll1_out_test", .parent_names = (const char *[]){ "gpll1" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll gpll2 = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -256,58 +256,58 @@ static struct clk_alpha_pll gpll2 = { .name = "gpll2", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, }; static struct clk_alpha_pll_postdiv gpll2_out_even = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_even", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll2_out_main = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_main", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll2_out_odd = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_odd", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll2_out_test = { .offset = 0x2000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll2_out_test", .parent_names = (const char *[]){ "gpll2" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll gpll3 = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -317,58 +317,58 @@ static struct clk_alpha_pll gpll3 = { .name = "gpll3", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, }; static struct clk_alpha_pll_postdiv gpll3_out_even = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_even", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll3_out_main = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_main", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll3_out_odd = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_odd", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll3_out_test = { .offset = 0x3000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll3_out_test", .parent_names = (const char *[]){ "gpll3" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll gpll4 = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .vco_table = fabia_vco, .num_vco = ARRAY_SIZE(fabia_vco), .clkr = { @@ -378,52 +378,52 @@ static struct clk_alpha_pll gpll4 = { .name = "gpll4", .parent_names = (const char *[]){ "xo" }, .num_parents = 1, - .ops = &clk_alpha_pll_ops, + .ops = &clk_alpha_pll_fixed_fabia_ops, } }, }; static struct clk_alpha_pll_postdiv gpll4_out_even = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_even", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll4_out_main = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_main", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll4_out_odd = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_odd", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; static struct clk_alpha_pll_postdiv gpll4_out_test = { .offset = 0x77000, - .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], .clkr.hw.init = &(struct clk_init_data){ .name = "gpll4_out_test", .parent_names = (const char *[]){ "gpll4" }, .num_parents = 1, - .ops = &clk_alpha_pll_postdiv_ops, + .ops = &clk_alpha_pll_postdiv_fabia_ops, }, }; diff --git a/drivers/clk/qcom/gcc-sdm429w.c b/drivers/clk/qcom/gcc-sdm429w.c index 96b99c080a59..d5d8cb39f9e8 100644 --- a/drivers/clk/qcom/gcc-sdm429w.c +++ b/drivers/clk/qcom/gcc-sdm429w.c @@ -42,6 +42,7 @@ enum { P_GPLL6_OUT_AUX, P_GPLL6_OUT_MAIN, P_SLEEP_CLK, + P_GPLL3_OUT_MAIN_DIV, }; static const struct parent_map gcc_parent_map_0[] = { @@ -240,7 +241,7 @@ static const char * const gcc_parent_names_12[] = { static const struct parent_map gcc_parent_map_14[] = { { P_BI_TCXO, 0 }, { P_GPLL0_OUT_MAIN, 1 }, - { P_GPLL3_OUT_MAIN, 2 }, + { P_GPLL3_OUT_MAIN_DIV, 2 }, { P_GPLL6_OUT_AUX, 3 }, { P_GPLL4_OUT_AUX, 4 }, { P_CORE_BI_PLL_TEST_SE, 7 }, @@ -249,7 +250,7 @@ static const struct parent_map gcc_parent_map_14[] = { static const struct parent_map gcc_parent_map_14_gfx3d[] = { { P_BI_TCXO, 0 }, { P_GPLL0_OUT_MAIN, 5 }, - { P_GPLL3_OUT_MAIN, 2 }, + { P_GPLL3_OUT_MAIN_DIV, 2 }, { P_GPLL6_OUT_AUX, 6 }, { P_GPLL4_OUT_AUX, 4 }, { P_CORE_BI_PLL_TEST_SE, 7 }, @@ -258,7 +259,7 @@ static const struct parent_map gcc_parent_map_14_gfx3d[] = { static const char * const gcc_parent_names_14[] = { "bi_tcxo", "gpll0_out_main", - "gpll3_out_main", + "gpll3_out_main_div", "gpll6_out_aux", "gpll4_out_aux", "core_bi_pll_test_se", @@ -466,6 +467,18 @@ static struct clk_alpha_pll gpll3_out_main = { }, }; +static struct clk_fixed_factor gpll3_out_main_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "gpll3_out_main_div", + .parent_names = (const char *[]){ "gpll3_out_main" }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_fixed_factor_ops, + }, +}; + static struct clk_alpha_pll gpll4_out_main = { .offset = 0x24000, .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT], @@ -1706,13 +1719,13 @@ static const struct freq_tbl ftbl_gfx3d_clk_src[] = { F_SLEW(240000000, P_GPLL6_OUT_AUX, 4.5, 0, 0, FIXED_FREQ_SRC), F_SLEW(266666667, P_GPLL0_OUT_MAIN, 3, 0, 0, FIXED_FREQ_SRC), F_SLEW(320000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0, FIXED_FREQ_SRC), - F_SLEW(355200000, P_GPLL3_OUT_MAIN, 1, 0, 0, 710400000), - F_SLEW(375000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 750000000), + F_SLEW(355200000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 710400000), + F_SLEW(375000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 750000000), F_SLEW(400000000, P_GPLL0_OUT_MAIN, 2, 0, 0, FIXED_FREQ_SRC), - F_SLEW(450000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 900000000), - F_SLEW(510000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1020000000), - F_SLEW(560000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1120000000), - F_SLEW(650000000, P_GPLL3_OUT_MAIN, 1, 0, 0, 1300000000), + F_SLEW(450000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 900000000), + F_SLEW(510000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1020000000), + F_SLEW(560000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1120000000), + F_SLEW(650000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1300000000), { } }; @@ -1729,6 +1742,12 @@ static struct freq_tbl ftbl_oxili_gfx3d_clk_src_qm215[] = { F_SLEW( 270000000, P_GPLL6_OUT_AUX, 4, 0, 0, FIXED_FREQ_SRC), F_SLEW( 320000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0, FIXED_FREQ_SRC), F_SLEW( 400000000, P_GPLL0_OUT_MAIN, 2, 0, 0, FIXED_FREQ_SRC), + F_SLEW( 465000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 930000000), + F_SLEW( 484800000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 969600000), + F_SLEW( 500000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1000000000), + F_SLEW( 523200000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1046400000), + F_SLEW( 550000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1100000000), + F_SLEW( 598000000, P_GPLL3_OUT_MAIN_DIV, 1, 0, 0, 1196000000), { } }; @@ -1743,6 +1762,7 @@ static struct clk_rcg2 gfx3d_clk_src = { .name = "gfx3d_clk_src", .parent_names = gcc_parent_names_14, .num_parents = 6, + .flags = CLK_SET_RATE_PARENT, .ops = &clk_rcg2_ops, }, }; @@ -4267,9 +4287,19 @@ static void fixup_for_qm215(struct platform_device *pdev, gcc_sdm429w_desc.clks[GCC_MDSS_ESC1_CLK] = NULL; } +static void fixup_for_sdm439_429(void) +{ + /* + * Below clocks are not available on SDM429/439, thus mark them NULL. + */ + gcc_sdm429w_desc.clks[GCC_GFX_TCU_CLK] = NULL; + gcc_sdm429w_desc.clks[GCC_GFX_TBU_CLK] = NULL; + gcc_sdm429w_desc.clks[GCC_GTCU_AHB_CLK] = NULL; +} static const struct of_device_id gcc_sdm429w_match_table[] = { { .compatible = "qcom,gcc-sdm429w" }, { .compatible = "qcom,gcc-qm215" }, + { .compatible = "qcom,gcc-sdm439" }, { } }; MODULE_DEVICE_TABLE(of, gcc_sdm429w_match_table); @@ -4279,11 +4309,14 @@ static int gcc_sdm429w_probe(struct platform_device *pdev) struct regmap *regmap; struct clk *clk; int ret, speed_bin; - bool qm215; + bool qm215, is_sdm439; qm215 = of_device_is_compatible(pdev->dev.of_node, "qcom,gcc-qm215"); + is_sdm439 = of_device_is_compatible(pdev->dev.of_node, + "qcom,gcc-sdm439"); + clk = clk_get(&pdev->dev, "bi_tcxo"); if (IS_ERR(clk)) { if (PTR_ERR(clk) != -EPROBE_DEFER) @@ -4313,6 +4346,9 @@ static int gcc_sdm429w_probe(struct platform_device *pdev) 0xff0, 0xff0); } + if (is_sdm439) + fixup_for_sdm439_429(); + clk_alpha_pll_configure(&gpll3_out_main, regmap, &gpll3_config); clk = devm_clk_register(&pdev->dev, &wcnss_m_clk.hw); @@ -4321,6 +4357,12 @@ static int gcc_sdm429w_probe(struct platform_device *pdev) return PTR_ERR(clk); } + ret = devm_clk_hw_register(&pdev->dev, &gpll3_out_main_div.hw); + if (ret) { + dev_err(&pdev->dev, "Failed to register hardware clock\n"); + return ret; + } + ret = qcom_cc_really_probe(pdev, &gcc_sdm429w_desc, regmap); if (ret) { dev_err(&pdev->dev, "Failed to register GCC clocks\n"); @@ -4380,9 +4422,22 @@ static const struct qcom_cc_desc mdss_sdm429w_desc = { .num_hwclks = ARRAY_SIZE(mdss_sdm429w_hws), }; +static void fixup_for_qm215_gcc_mdss(void) +{ + /* + * Below clocks are not available on QM215, thus mark them NULL. + */ + + mdss_sdm429w_desc.clks[BYTE1_CLK_SRC] = NULL; + mdss_sdm429w_desc.clks[PCLK1_CLK_SRC] = NULL; + mdss_sdm429w_desc.clks[GCC_MDSS_BYTE1_CLK] = NULL; + mdss_sdm429w_desc.clks[GCC_MDSS_PCLK1_CLK] = NULL; +} + static const struct of_device_id mdss_sdm429w_match_table[] = { { .compatible = "qcom,gcc-mdss-sdm429w" }, - { .compatible = "qcom,gcc-mdss-8917" }, + { .compatible = "qcom,gcc-mdss-qm215" }, + { .compatible = "qcom,gcc-mdss-sdm439" }, {} }; MODULE_DEVICE_TABLE(of, mdss_sdm429w_match_table); @@ -4394,6 +4449,10 @@ static int mdss_sdm429w_probe(struct platform_device *pdev) struct resource *res; void __iomem *base; int ret; + bool is_qm215; + + is_qm215 = of_device_is_compatible(pdev->dev.of_node, + "qcom,gcc-mdss-qm215"); clk = clk_get(&pdev->dev, "pclk0_src"); if (IS_ERR(clk)) { @@ -4426,6 +4485,9 @@ static int mdss_sdm429w_probe(struct platform_device *pdev) if (IS_ERR(regmap)) return PTR_ERR(regmap); + if (is_qm215) + fixup_for_qm215_gcc_mdss(); + ret = qcom_cc_really_probe(pdev, &mdss_sdm429w_desc, regmap); if (ret) { dev_err(&pdev->dev, "Failed to register MDSS clocks\n"); diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm-util.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm-util.c index e26698eb0d0e..876e32681fd4 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm-util.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm-util.c @@ -15,17 +15,31 @@ #define DSI_PLL_POLL_MAX_READS 15 #define DSI_PLL_POLL_TIMEOUT_US 1000 +static void __mdss_dsi_get_pll_vco_cntrl(u64 target_freq, u32 post_div_mux, + u32 *vco_cntrl, u32 *cpbias_cntrl); + int pixel_div_set_div(void *context, unsigned int reg, unsigned int div) { struct mdss_pll_resources *pll = context; + void __iomem *pll_base = pll->pll_base; + int rc; + char data = 0; struct dsi_pll_db *pdb; pdb = (struct dsi_pll_db *)pll->priv; + rc = mdss_pll_resource_enable(pll, true); + if (rc) { + pr_err("Failed to enable mdss dsi pll resources\n"); + return rc; + } /* Programming during vco_prepare. Keep this value */ - pdb->param.pixel_divhf = (div - 1); + data = ((div - 1) & 0x7f); + MDSS_PLL_REG_W(pll_base, DSIPHY_SSC9, data); + pdb->param.pixel_divhf = data; + mdss_pll_resource_enable(pll, false); pr_debug("ndx=%d div=%d divhf=%d\n", pll->index, div, pdb->param.pixel_divhf); @@ -37,6 +51,7 @@ int pixel_div_get_div(void *context, unsigned int reg, { int rc; struct mdss_pll_resources *pll = context; + u32 val = 0; if (is_gdsc_disabled(pll)) return 0; @@ -47,8 +62,9 @@ int pixel_div_get_div(void *context, unsigned int reg, return rc; } - *div = (MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SSC9) & 0x7F); - pr_debug("pixel_div = %d\n", (*div+1)); + val = (MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SSC9) & 0x7F); + *div = val + 1; + pr_debug("pixel_div = %d\n", (*div)); mdss_pll_resource_enable(pll, false); @@ -59,13 +75,30 @@ int set_post_div_mux_sel(void *context, unsigned int reg, unsigned int sel) { struct mdss_pll_resources *pll = context; + void __iomem *pll_base = pll->pll_base; struct dsi_pll_db *pdb; + u64 target_freq = 0; + u32 vco_cntrl = 0, cpbias_cntrl = 0; + char data = 0; pdb = (struct dsi_pll_db *)pll->priv; /* Programming during vco_prepare. Keep this value */ pdb->param.post_div_mux = sel; + target_freq = div_u64(pll->vco_current_rate, + BIT(pdb->param.post_div_mux)); + __mdss_dsi_get_pll_vco_cntrl(target_freq, pdb->param.post_div_mux, + &vco_cntrl, &cpbias_cntrl); + + data = ((vco_cntrl & 0x3f) | BIT(6)); + MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_CTRL, data); + pr_debug("%s: vco_cntrl 0x%x\n", __func__, vco_cntrl); + + data = ((cpbias_cntrl & 0x1) << 6) | BIT(4); + MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL, data); + pr_debug("%s: cpbias_cntrl 0x%x\n", __func__, cpbias_cntrl); + pr_debug("ndx=%d post_div_mux_sel=%d p_div=%d\n", pll->index, sel, (u32) BIT(sel)); @@ -90,6 +123,7 @@ int get_post_div_mux_sel(void *context, unsigned int reg, vco_cntrl = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_PLL_VCO_CTRL); vco_cntrl &= 0x30; + pr_debug("%s: vco_cntrl 0x%x\n", __func__, vco_cntrl); cpbias_cntrl = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL); @@ -112,6 +146,7 @@ int get_post_div_mux_sel(void *context, unsigned int reg, } mdss_pll_resource_enable(pll, false); + pr_debug("%s: sel = %d\n", __func__, *sel); return 0; } @@ -120,16 +155,24 @@ int set_gp_mux_sel(void *context, unsigned int reg, unsigned int sel) { struct mdss_pll_resources *pll = context; - struct dsi_pll_db *pdb; + void __iomem *pll_base = pll->pll_base; + char data = 0; + int rc; - pdb = (struct dsi_pll_db *)pll->priv; + rc = mdss_pll_resource_enable(pll, true); + if (rc) { + pr_err("Failed to enable mdss dsi pll resources\n"); + return rc; + } /* Programming during vco_prepare. Keep this value */ - pdb->param.gp_div_mux = sel; + data = ((sel & 0x7) << 5) | 0x5; + MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data); pr_debug("ndx=%d gp_div_mux_sel=%d gp_cntrl=%d\n", pll->index, sel, (u32) BIT(sel)); + mdss_pll_resource_enable(pll, false); return 0; } @@ -175,7 +218,9 @@ static bool pll_is_pll_locked_12nm(struct mdss_pll_resources *pll, pr_err("DSI PLL ndx=%d status=%x failed to Lock\n", pll->index, status); pll_locked = false; + pr_debug("%s: not locked\n", __func__); } else { + pr_debug("%s: locked\n", __func__); pll_locked = true; } @@ -542,13 +587,13 @@ static void mdss_dsi_pll_12nm_calc_reg(struct mdss_pll_resources *pll, { struct dsi_pll_param *param = &pdb->param; u64 target_freq = 0; + u32 post_div_mux = 0; + get_post_div_mux_sel(pll, 0, &post_div_mux); target_freq = div_u64(pll->vco_current_rate, - BIT(pdb->param.post_div_mux)); + BIT(post_div_mux)); param->hsfreqrange = __mdss_dsi_get_hsfreqrange(target_freq); - __mdss_dsi_get_pll_vco_cntrl(target_freq, param->post_div_mux, - ¶m->vco_cntrl, ¶m->cpbias_cntrl); param->osc_freq_target = __mdss_dsi_get_osc_freq_target(target_freq); param->m_div = (u32) __mdss_dsi_pll_get_m_div(pll->vco_current_rate); param->fsm_ovr_ctrl = __mdss_dsi_get_fsm_ovr_ctrl(target_freq); @@ -707,9 +752,6 @@ static void pll_db_commit_12nm(struct mdss_pll_resources *pll, data = ((param->hsfreqrange & 0x7f) | BIT(7)); MDSS_PLL_REG_W(pll_base, DSIPHY_HS_FREQ_RAN_SEL, data); - data = ((param->vco_cntrl & 0x3f) | BIT(6)); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_CTRL, data); - data = (param->osc_freq_target & 0x7f); MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_0, data); @@ -733,15 +775,6 @@ static void pll_db_commit_12nm(struct mdss_pll_resources *pll, data = ((param->gmp_cntrl & 0x3) << 4); MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_GMP_CTRL_DIG_TST, data); - data = ((param->cpbias_cntrl & 0x1) << 6) | BIT(4); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL, data); - - data = ((param->gp_div_mux & 0x7) << 5) | 0x5; - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data); - - data = (param->pixel_divhf & 0x7f); - MDSS_PLL_REG_W(pll_base, DSIPHY_SSC9, data); - MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_ANA_PROG_CTRL, 0x03); MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_ANA_TST_LOCK_ST_OVR_CTRL, 0x50); MDSS_PLL_REG_W(pll_base, @@ -779,6 +812,14 @@ int pll_vco_set_rate_12nm(struct clk_hw *hw, unsigned long rate, pll->vco_current_rate = rate; pll->vco_ref_clk_rate = vco->ref_clk_rate; + + mdss_dsi_pll_12nm_calc_reg(pll, pdb); + if (pll->ssc_en) + mdss_dsi_pll_12nm_calc_ssc(pll, pdb); + + /* commit DSI vco */ + pll_db_commit_12nm(pll, pdb); + error: return rc; } @@ -791,9 +832,13 @@ static unsigned long pll_vco_get_rate_12nm(struct clk_hw *hw) u64 ref_clk = vco->ref_clk_rate; int rc; struct mdss_pll_resources *pll = vco->priv; + u32 post_div_mux; + u32 cpbias_cntrl = 0; - if (is_gdsc_disabled(pll)) + if (is_gdsc_disabled(pll)) { + pr_err("%s:gdsc disabled\n", __func__); return 0; + } rc = mdss_pll_resource_enable(pll, true); if (rc) { @@ -811,6 +856,16 @@ static unsigned long pll_vco_get_rate_12nm(struct clk_hw *hw) m_div_11_6 &= 0x3f; pr_debug("m_div_11_6 = 0x%x\n", m_div_11_6); + post_div_mux = MDSS_PLL_REG_R(pll->pll_base, + DSIPHY_PLL_VCO_CTRL); + + pr_debug("post_div_mux = 0x%x\n", post_div_mux); + + cpbias_cntrl = MDSS_PLL_REG_R(pll->pll_base, + DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL); + cpbias_cntrl = ((cpbias_cntrl >> 6) & 0x1); + pr_debug("cpbias_cntrl = 0x%x\n", cpbias_cntrl); + m_div = ((m_div_11_6 << 6) | (m_div_5_0)); vco_rate = div_u64((ref_clk * m_div), 4); @@ -845,12 +900,22 @@ unsigned long vco_12nm_recalc_rate(struct clk_hw *hw, struct mdss_pll_resources *pll = vco->priv; unsigned long rate = 0; int rc; + struct dsi_pll_db *pdb; + + pdb = (struct dsi_pll_db *)pll->priv; if (!pll && is_gdsc_disabled(pll)) { pr_err("gdsc disabled\n"); return 0; } + if (pll->vco_current_rate != 0) { + rate = pll_vco_get_rate_12nm(hw); + pr_debug("%s:returning vco rate = %lld\n", __func__, + pll->vco_current_rate); + return rate; + } + rc = mdss_pll_resource_enable(pll, true); if (rc) { pr_err("Failed to enable mdss dsi pll=%d\n", pll->index); @@ -861,6 +926,7 @@ unsigned long vco_12nm_recalc_rate(struct clk_hw *hw, pll->handoff_resources = true; pll->pll_on = true; rate = pll_vco_get_rate_12nm(hw); + pr_debug("%s: pll locked. rate %lu\n", __func__, rate); } else { mdss_pll_resource_enable(pll, false); } @@ -921,15 +987,7 @@ int pll_vco_prepare_12nm(struct clk_hw *hw) goto end; } - mdss_dsi_pll_12nm_calc_reg(pll, pdb); - if (pll->ssc_en) - mdss_dsi_pll_12nm_calc_ssc(pll, pdb); - - /* commit DSI vco */ - pll_db_commit_12nm(pll, pdb); - rc = dsi_pll_enable(hw); - error: if (rc) { mdss_pll_resource_enable(pll, false); diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm.c index 6b63ed28d569..a2ff5f6371f3 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-12nm.c @@ -27,6 +27,7 @@ static const struct clk_ops clk_ops_vco_12nm = { .round_rate = pll_vco_round_rate_12nm, .prepare = pll_vco_prepare_12nm, .unprepare = pll_vco_unprepare_12nm, + .enable = pll_vco_enable_12nm, }; static struct regmap_bus pclk_div_regmap_bus = { @@ -206,8 +207,8 @@ static struct clk_fixed_factor dsi0pll_post_div32 = { static struct clk_regmap_mux dsi0pll_post_div_mux = { .reg = DSIPHY_PLL_VCO_CTRL, - .shift = 4, - .width = 2, + .shift = 0, + .width = 3, .clkr = { .hw.init = &(struct clk_init_data){ .name = "dsi0pll_post_div_mux", @@ -298,8 +299,8 @@ static struct clk_fixed_factor dsi1pll_post_div32 = { static struct clk_regmap_mux dsi1pll_post_div_mux = { .reg = DSIPHY_PLL_VCO_CTRL, - .shift = 4, - .width = 2, + .shift = 0, + .width = 3, .clkr = { .hw.init = &(struct clk_init_data){ .name = "dsi1pll_post_div_mux", @@ -390,7 +391,7 @@ static struct clk_fixed_factor dsi0pll_gp_div32 = { static struct clk_regmap_mux dsi0pll_gp_div_mux = { .reg = DSIPHY_PLL_CTRL, - .shift = 5, + .shift = 0, .width = 3, .clkr = { .hw.init = &(struct clk_init_data){ @@ -482,7 +483,7 @@ static struct clk_fixed_factor dsi1pll_gp_div32 = { static struct clk_regmap_mux dsi1pll_gp_div_mux = { .reg = DSIPHY_PLL_CTRL, - .shift = 5, + .shift = 0, .width = 3, .clkr = { .hw.init = &(struct clk_init_data){ @@ -506,11 +507,12 @@ static struct clk_regmap_div dsi0pll_pclk_src = { .width = 6, .clkr = { .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_pclk_src", + .name = "dsi0_phy_pll_out_dsiclk", .parent_names = (const char *[]){ "dsi0pll_gp_div_mux"}, .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_div_ops, }, }, @@ -522,11 +524,12 @@ static struct clk_regmap_div dsi1pll_pclk_src = { .width = 6, .clkr = { .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_pclk_src", + .name = "dsi1_phy_pll_out_dsiclk", .parent_names = (const char *[]){ "dsi1pll_gp_div_mux"}, .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), .ops = &clk_regmap_div_ops, }, }, @@ -536,10 +539,11 @@ static struct clk_fixed_factor dsi0pll_byte_clk_src = { .div = 4, .mult = 1, .hw.init = &(struct clk_init_data){ - .name = "dsi0pll_byte_clk_src", + .name = "dsi0_phy_pll_out_byteclk", .parent_names = (const char *[]){"dsi0pll_post_div_mux"}, .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), .ops = &clk_fixed_factor_ops, }, }; @@ -548,15 +552,15 @@ static struct clk_fixed_factor dsi1pll_byte_clk_src = { .div = 4, .mult = 1, .hw.init = &(struct clk_init_data){ - .name = "dsi1pll_byte_clk_src", + .name = "dsi1_phy_pll_out_byteclk", .parent_names = (const char *[]){"dsi1pll_post_div_mux"}, .num_parents = 1, - .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT), + .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT), .ops = &clk_fixed_factor_ops, }, }; - static struct clk_hw *mdss_dsi_pllcc_12nm[] = { [VCO_CLK_0] = &dsi0pll_vco_clk.hw, [POST_DIV1_0_CLK] = &dsi0pll_post_div1.hw, @@ -598,14 +602,14 @@ int dsi_pll_clock_register_12nm(struct platform_device *pdev, struct mdss_pll_resources *pll_res) { int rc = 0, ndx, i; - struct clk *clk; + struct clk *clk = NULL; struct clk_onecell_data *clk_data; int num_clks = ARRAY_SIZE(mdss_dsi_pllcc_12nm); struct regmap *rmap; struct dsi_pll_db *pdb; if (!pdev || !pdev->dev.of_node || - !pll_res || !pll_res->pll_base || !pll_res->phy_base) { + !pll_res || !pll_res->pll_base) { pr_err("Invalid params\n"); return -EINVAL; } @@ -637,7 +641,7 @@ int dsi_pll_clock_register_12nm(struct platform_device *pdev, clk_data->clk_num = num_clks; /* Establish client data */ - if (ndx == 0) { + if (pll_res->index == 0) { rmap = devm_regmap_init(&pdev->dev, &post_div_mux_regmap_bus, pll_res, &dsi_pll_12nm_config); dsi0pll_post_div_mux.clkr.regmap = rmap; @@ -700,8 +704,8 @@ int dsi_pll_clock_register_12nm(struct platform_device *pdev, of_clk_src_onecell_get, clk_data); } if (!rc) { - pr_info("Registered DSI PLL ndx=%d,clocks successfully\n", ndx); - + pr_info("Registered DSI PLL ndx=%d, clocks successfully\n", + pll_res->index); return rc; } clk_register_fail: diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c index 0da6b4a85c68..04db3bd66016 100644 --- a/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c +++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-28lpm.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "mdss-pll.h" #include "mdss-dsi-pll.h" @@ -388,13 +388,13 @@ static struct clk_regmap_div dsi1pll_pclk_src = { }; static struct clk_hw *mdss_dsi_pllcc_28lpm[] = { - [VCO_CLK_0] = &dsi0pll_vco_clk.hw, + [VCOCLK_0] = &dsi0pll_vco_clk.hw, [ANALOG_POSTDIV_0_CLK] = &dsi0pll_analog_postdiv.clkr.hw, [INDIRECT_PATH_SRC_0_CLK] = &dsi0pll_indirect_path_src.hw, [BYTECLK_SRC_MUX_0_CLK] = &dsi0pll_byteclk_src_mux.clkr.hw, [BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw, [PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw, - [VCO_CLK_1] = &dsi1pll_vco_clk.hw, + [VCOCLK_1] = &dsi1pll_vco_clk.hw, [ANALOG_POSTDIV_1_CLK] = &dsi1pll_analog_postdiv.clkr.hw, [INDIRECT_PATH_SRC_1_CLK] = &dsi1pll_indirect_path_src.hw, [BYTECLK_SRC_MUX_1_CLK] = &dsi1pll_byteclk_src_mux.clkr.hw, @@ -486,7 +486,7 @@ int dsi_pll_clock_register_28lpm(struct platform_device *pdev, dsi0pll_pclk_src.clkr.regmap = rmap; dsi0pll_vco_clk.priv = pll_res; - for (i = VCO_CLK_0; i <= PCLK_SRC_0_CLK; i++) { + for (i = VCOCLK_0; i <= PCLK_SRC_0_CLK; i++) { clk = devm_clk_register(&pdev->dev, mdss_dsi_pllcc_28lpm[i]); if (IS_ERR(clk)) { @@ -531,7 +531,7 @@ int dsi_pll_clock_register_28lpm(struct platform_device *pdev, dsi1pll_pclk_src.clkr.regmap = rmap; dsi1pll_vco_clk.priv = pll_res; - for (i = VCO_CLK_1; i <= PCLK_SRC_1_CLK; i++) { + for (i = VCOCLK_1; i <= PCLK_SRC_1_CLK; i++) { clk = devm_clk_register(&pdev->dev, mdss_dsi_pllcc_28lpm[i]); if (IS_ERR(clk)) { diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c index ab9589f686ba..d01d9afaf265 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.c +++ b/drivers/clk/qcom/mdss/mdss-pll.c @@ -128,7 +128,9 @@ static int mdss_pll_resource_parse(struct platform_device *pdev, pll_res->pll_interface_type = MDSS_DP_PLL_14NM; pll_res->target_id = MDSS_PLL_TARGET_SDM660; pll_res->revision = 2; - } else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_28lpm")) + } else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_12nm")) + pll_res->pll_interface_type = MDSS_DSI_PLL_12NM; + else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_28lpm")) pll_res->pll_interface_type = MDSS_DSI_PLL_28LPM; else goto err; diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h index 2a54194d50a6..5290c7cf90c8 100644 --- a/drivers/clk/qcom/mdss/mdss-pll.h +++ b/drivers/clk/qcom/mdss/mdss-pll.h @@ -220,12 +220,13 @@ static inline bool is_gdsc_disabled(struct mdss_pll_resources *pll_res) return true; } if ((pll_res->target_id == MDSS_PLL_TARGET_SDM660) || - (pll_res->pll_interface_type == MDSS_DSI_PLL_28LPM)) + (pll_res->pll_interface_type == MDSS_DSI_PLL_28LPM) || + (pll_res->pll_interface_type == MDSS_DSI_PLL_12NM)) ret = ((readl_relaxed(pll_res->gdsc_base + 0x4) & BIT(31)) && (!(readl_relaxed(pll_res->gdsc_base) & BIT(0)))) ? false : true; else ret = readl_relaxed(pll_res->gdsc_base) & BIT(31) ? - false : true; + false : true; return ret; } diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c index 8f8b325efb65..63eb65171348 100644 --- a/drivers/clk/renesas/r9a06g032-clocks.c +++ b/drivers/clk/renesas/r9a06g032-clocks.c @@ -51,7 +51,7 @@ struct r9a06g032_clkdesc { u16 sel, g1, r1, g2, r2; } dual; }; -} __packed; +}; #define I_GATE(_clk, _rst, _rdy, _midle, _scon, _mirack, _mistat) \ { .gate = _clk, .reset = _rst, \ diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c index 007f2f1c9bd7..a0a515a31837 100644 --- a/drivers/clk/socfpga/clk-gate.c +++ b/drivers/clk/socfpga/clk-gate.c @@ -107,7 +107,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; val &= GENMASK(socfpgaclk->width - 1, 0); /* Check for GPIO_DB_CLK by its offset */ - if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) + if ((uintptr_t) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) div = val + 1; else div = (1 << val); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c index 9ac6c299e074..19304d6b2c05 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c @@ -381,6 +381,7 @@ static struct clk_div_table ths_div_table[] = { { .val = 1, .div = 2 }, { .val = 2, .div = 4 }, { .val = 3, .div = 6 }, + { /* Sentinel */ }, }; static const char * const ths_parents[] = { "osc24M" }; static struct ccu_div ths_clk = { diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index d425b47cef17..1197ace59124 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -223,7 +223,7 @@ static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k", static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", psi_ahb1_ahb2_parents, 0x510, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); @@ -232,19 +232,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", "psi-ahb1-ahb2", "pll-periph0" }; static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); @@ -662,7 +662,7 @@ static struct ccu_mux hdmi_cec_clk = { .common = { .reg = 0xb10, - .features = CCU_FEATURE_VARIABLE_PREDIV, + .features = CCU_FEATURE_FIXED_PREDIV, .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec", hdmi_cec_parents, &ccu_mux_ops, diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c index 61e3ba12773e..d9789378caf5 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c @@ -328,6 +328,7 @@ static struct clk_div_table ths_div_table[] = { { .val = 1, .div = 2 }, { .val = 2, .div = 4 }, { .val = 3, .div = 6 }, + { /* Sentinel */ }, }; static SUNXI_CCU_DIV_TABLE_WITH_GATE(ths_clk, "ths", "osc24M", 0x074, 0, 2, ths_div_table, BIT(31), 0); diff --git a/drivers/clk/tegra/clk-id.h b/drivers/clk/tegra/clk-id.h index de466b4446da..0efcb200dde5 100644 --- a/drivers/clk/tegra/clk-id.h +++ b/drivers/clk/tegra/clk-id.h @@ -233,6 +233,7 @@ enum clk_id { tegra_clk_sdmmc4, tegra_clk_sdmmc4_8, tegra_clk_se, + tegra_clk_se_10, tegra_clk_soc_therm, tegra_clk_soc_therm_8, tegra_clk_sor0, diff --git a/drivers/clk/tegra/clk-tegra-periph.c b/drivers/clk/tegra/clk-tegra-periph.c index b137c5d34eec..9d05fb48686d 100644 --- a/drivers/clk/tegra/clk-tegra-periph.c +++ b/drivers/clk/tegra/clk-tegra-periph.c @@ -650,7 +650,7 @@ static struct tegra_periph_init_data periph_clks[] = { INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8), INT8("host1x", mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_9), INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se), - INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se), + INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se_10), INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8), INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8), INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03), diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index e0aaecd98fbf..678019f86bc7 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1274,6 +1274,8 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA30_CLK_I2S3_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S4_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_VIMCLK_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, + { TEGRA30_CLK_HDA, TEGRA30_CLK_PLL_P, 102000000, 0 }, + { TEGRA30_CLK_HDA2CODEC_2X, TEGRA30_CLK_PLL_P, 48000000, 0 }, /* must be the last entry */ { TEGRA30_CLK_CLK_MAX, TEGRA30_CLK_CLK_MAX, 0, 0 }, }; diff --git a/drivers/clk/ti/fapll.c b/drivers/clk/ti/fapll.c index 071af44b1ba8..e33ce851837e 100644 --- a/drivers/clk/ti/fapll.c +++ b/drivers/clk/ti/fapll.c @@ -497,6 +497,7 @@ static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, { struct clk_init_data *init; struct fapll_synth *synth; + struct clk *clk = ERR_PTR(-ENOMEM); init = kzalloc(sizeof(*init), GFP_KERNEL); if (!init) @@ -519,13 +520,19 @@ static struct clk * __init ti_fapll_synth_setup(struct fapll_data *fd, synth->hw.init = init; synth->clk_pll = pll_clk; - return clk_register(NULL, &synth->hw); + clk = clk_register(NULL, &synth->hw); + if (IS_ERR(clk)) { + pr_err("failed to register clock\n"); + goto free; + } + + return clk; free: kfree(synth); kfree(init); - return ERR_PTR(-ENOMEM); + return clk; } static void __init ti_fapll_setup(struct device_node *node) diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index 0039118e398d..23794e453195 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -383,12 +383,6 @@ static u32 notrace sun50i_a64_read_cntv_tval_el0(void) return read_sysreg(cntv_cval_el0) - sun50i_a64_read_cntvct_el0(); } #endif -#ifdef CONFIG_ARM64_ERRATUM_1188873 -static u64 notrace arm64_1188873_read_cntvct_el0(void) -{ - return read_sysreg(cntvct_el0); -} -#endif #ifdef CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND DEFINE_PER_CPU(const struct arch_timer_erratum_workaround *, timer_unstable_counter_workaround); @@ -492,14 +486,6 @@ static const struct arch_timer_erratum_workaround ool_workarounds[] = { .set_next_event_virt = erratum_set_next_event_tval_virt, }, #endif -#ifdef CONFIG_ARM64_ERRATUM_1188873 - { - .match_type = ate_match_local_cap_id, - .id = (void *)ARM64_WORKAROUND_1188873, - .desc = "ARM erratum 1188873", - .read_cntvct_el0 = arm64_1188873_read_cntvct_el0, - }, -#endif }; typedef bool (*ate_match_fn_t)(const struct arch_timer_erratum_workaround *, @@ -865,15 +851,24 @@ static void arch_timer_evtstrm_enable(int divider) static void arch_timer_configure_evtstream(void) { - int evt_stream_div, pos; + int evt_stream_div, lsb; + + /* + * As the event stream can at most be generated at half the frequency + * of the counter, use half the frequency when computing the divider. + */ + evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ / 2; + + /* + * Find the closest power of two to the divisor. If the adjacent bit + * of lsb (last set bit, starts from 0) is set, then we use (lsb + 1). + */ + lsb = fls(evt_stream_div) - 1; + if (lsb > 0 && (evt_stream_div & BIT(lsb - 1))) + lsb++; - /* Find the closest power of two to the divisor */ - evt_stream_div = arch_timer_rate / ARCH_TIMER_EVT_STREAM_FREQ; - pos = fls(evt_stream_div); - if (pos > 1 && !(evt_stream_div & (1 << (pos - 2)))) - pos--; /* enable event stream */ - arch_timer_evtstrm_enable(min(pos, 15)); + arch_timer_evtstrm_enable(max(0, min(lsb, 15))); } static void arch_counter_set_user_access(void) diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 29d51755e18b..a7eb858a84a0 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -419,10 +419,8 @@ static int __init ttc_setup_clockevent(struct clk *clk, ttcce->ttc.clk = clk; err = clk_prepare_enable(ttcce->ttc.clk); - if (err) { - kfree(ttcce); - return err; - } + if (err) + goto out_kfree; ttcce->ttc.clk_rate_change_nb.notifier_call = ttc_rate_change_clockevent_cb; @@ -432,7 +430,7 @@ static int __init ttc_setup_clockevent(struct clk *clk, &ttcce->ttc.clk_rate_change_nb); if (err) { pr_warn("Unable to register clock notifier.\n"); - return err; + goto out_kfree; } ttcce->ttc.freq = clk_get_rate(ttcce->ttc.clk); @@ -461,15 +459,17 @@ static int __init ttc_setup_clockevent(struct clk *clk, err = request_irq(irq, ttc_clock_event_interrupt, IRQF_TIMER, ttcce->ce.name, ttcce); - if (err) { - kfree(ttcce); - return err; - } + if (err) + goto out_kfree; clockevents_config_and_register(&ttcce->ce, ttcce->ttc.freq / PRESCALE, 1, 0xfffe); return 0; + +out_kfree: + kfree(ttcce); + return err; } /** diff --git a/drivers/clocksource/mxs_timer.c b/drivers/clocksource/mxs_timer.c index f6ddae30933f..dae8c0c2e606 100644 --- a/drivers/clocksource/mxs_timer.c +++ b/drivers/clocksource/mxs_timer.c @@ -138,10 +138,7 @@ static void mxs_irq_clear(char *state) /* Clear pending interrupt */ timrot_irq_acknowledge(); - -#ifdef DEBUG - pr_info("%s: changing mode to %s\n", __func__, state) -#endif /* DEBUG */ + pr_debug("%s: changing mode to %s\n", __func__, state); } static int mxs_shutdown(struct clock_event_device *evt) diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d49ac20734db..6eacd9e20030 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -110,6 +110,16 @@ config CPU_FREQ_DEFAULT_GOV_SCHEDUTIL Use the 'schedutil' CPUFreq governor by default. If unsure, have a look at the help section of that governor. The fallback governor will be 'performance'. + +config CPU_FREQ_DEFAULT_GOV_SCHEDHORIZON + bool "schedhorizon" + depends on SMP + select CPU_FREQ_GOV_SCHEDHORIZON + select CPU_FREQ_GOV_PERFORMANCE + help + Use the 'schedhorizon' CPUFreq governor by default. If unsure, + have a look at the help section of that governor. The fallback + governor will be 'performance'. endchoice @@ -220,6 +230,28 @@ config CPU_FREQ_GOV_SCHEDUTIL If in doubt, say N. +config CPU_FREQ_GOV_SCHEDHORIZON + bool "'schedhorizon' cpufreq policy governor" + depends on CPU_FREQ && SMP + select CPU_FREQ_GOV_ATTR_SET + select IRQ_WORK + help + This is a modified version of schedutil, introducing two new tunables: + "efficient_freq" and "up_delay". + + Only raise cpufreq to the non-efficient one (higher than effcient frequencies) + if the governor keeps requiring non-efficient frequencies for more than up_delay time. + + Override the new frequencies with the efficient one if the consecutive request time + doesn't reach up_delay. + + The two tunables support multiple args, e.g. you can set "1248000 1401600" for + "efficient_freq" and set "50 60" for "up_delay", which means it would wait 50ms + before raising the frequency to 1248mhz and wait for 60ms before raising the frequency + to 1401mhz. + + If in doubt, say N. + comment "CPU frequency scaling drivers" config CPUFREQ_DT diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c index 77b0e5d0fb13..a3c82f530d60 100644 --- a/drivers/cpufreq/brcmstb-avs-cpufreq.c +++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c @@ -566,6 +566,16 @@ static int brcm_avs_prepare_init(struct platform_device *pdev) return ret; } +static void brcm_avs_prepare_uninit(struct platform_device *pdev) +{ + struct private_data *priv; + + priv = platform_get_drvdata(pdev); + + iounmap(priv->avs_intr_base); + iounmap(priv->base); +} + static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy) { struct cpufreq_frequency_table *freq_table; @@ -701,21 +711,21 @@ static int brcm_avs_cpufreq_probe(struct platform_device *pdev) brcm_avs_driver.driver_data = pdev; - return cpufreq_register_driver(&brcm_avs_driver); + ret = cpufreq_register_driver(&brcm_avs_driver); + if (ret) + brcm_avs_prepare_uninit(pdev); + + return ret; } static int brcm_avs_cpufreq_remove(struct platform_device *pdev) { - struct private_data *priv; int ret; ret = cpufreq_unregister_driver(&brcm_avs_driver); - if (ret) - return ret; + WARN_ON(ret); - priv = platform_get_drvdata(pdev); - iounmap(priv->base); - iounmap(priv->avs_intr_base); + brcm_avs_prepare_uninit(pdev); return 0; } diff --git a/drivers/cpufreq/cpu-boost.c b/drivers/cpufreq/cpu-boost.c index 0278835e7764..f17793c6a335 100644 --- a/drivers/cpufreq/cpu-boost.c +++ b/drivers/cpufreq/cpu-boost.c @@ -76,7 +76,7 @@ static bool sched_boost_active; static struct delayed_work input_boost_rem; static u64 last_input_time; -#define MIN_INPUT_INTERVAL (150 * USEC_PER_MSEC) +#define MIN_INPUT_INTERVAL (100 * USEC_PER_MSEC) static ssize_t store_input_boost_freq(struct kobject *kobj, struct kobj_attribute *attr, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1691d786587e..96f65454f9d0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -232,7 +232,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) struct cpufreq_policy *policy = NULL; unsigned long flags; - if (WARN_ON(cpu >= nr_cpu_ids)) + if (cpu >= nr_cpu_ids) return NULL; /* get the cpufreq driver */ diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 21b919bfaecc..3759ee766de6 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -14,15 +14,13 @@ #include #include -static DEFINE_SPINLOCK(cpufreq_stats_lock); - struct cpufreq_stats { unsigned int total_trans; - unsigned long long last_time; + atomic64_t last_time; unsigned int max_state; unsigned int state_num; unsigned int last_index; - u64 *time_in_state; + atomic64_t *time_in_state; unsigned int *freq_table; unsigned int *trans_table; }; @@ -30,21 +28,19 @@ struct cpufreq_stats { static void cpufreq_stats_update(struct cpufreq_stats *stats) { unsigned long long cur_time = get_jiffies_64(); - unsigned long flags; + unsigned long long time = cur_time; - spin_lock_irqsave(&cpufreq_stats_lock, flags); - stats->time_in_state[stats->last_index] += cur_time - stats->last_time; - stats->last_time = cur_time; - spin_unlock_irqrestore(&cpufreq_stats_lock, flags); + time = atomic64_xchg(&stats->last_time, time); + atomic64_add(cur_time - time, &stats->time_in_state[stats->last_index]); } static void cpufreq_stats_clear_table(struct cpufreq_stats *stats) { unsigned int count = stats->max_state; - memset(stats->time_in_state, 0, count * sizeof(u64)); + memset(stats->time_in_state, 0, count * sizeof(atomic64_t)); memset(stats->trans_table, 0, count * count * sizeof(int)); - stats->last_time = get_jiffies_64(); + atomic64_set(&stats->last_time, get_jiffies_64()); stats->total_trans = 0; } @@ -63,7 +59,8 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) for (i = 0; i < stats->state_num; i++) { len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], (unsigned long long) - jiffies_64_to_clock_t(stats->time_in_state[i])); + jiffies_64_to_clock_t(atomic64_read( + &stats->time_in_state[i]))); } return len; } @@ -181,7 +178,7 @@ void cpufreq_stats_create_table(struct cpufreq_policy *policy) if (!stats) return; - alloc_size = count * sizeof(int) + count * sizeof(u64); + alloc_size = count * sizeof(int) + count * sizeof(atomic64_t); alloc_size += count * count * sizeof(int); @@ -202,7 +199,7 @@ void cpufreq_stats_create_table(struct cpufreq_policy *policy) stats->freq_table[i++] = pos->frequency; stats->state_num = i; - stats->last_time = get_jiffies_64(); + atomic64_set(&stats->last_time, get_jiffies_64()); stats->last_index = freq_table_get_index(stats, policy->cur); policy->stats = stats; diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 1608f7105c9f..ad743f2f31e7 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c @@ -104,6 +104,13 @@ static int hb_cpufreq_driver_init(void) } module_init(hb_cpufreq_driver_init); +static const struct of_device_id __maybe_unused hb_cpufreq_of_match[] = { + { .compatible = "calxeda,highbank" }, + { .compatible = "calxeda,ecx-2000" }, + { }, +}; +MODULE_DEVICE_TABLE(of, hb_cpufreq_of_match); + MODULE_AUTHOR("Mark Langsdorf "); MODULE_DESCRIPTION("Calxeda Highbank cpufreq driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 864a7e8ebdfc..c2d222f97db7 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1420,11 +1420,9 @@ static void intel_pstate_max_within_limits(struct cpudata *cpu) static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) { cpu->pstate.min_pstate = pstate_funcs.get_min(); - cpu->pstate.max_pstate = pstate_funcs.get_max(); cpu->pstate.max_pstate_physical = pstate_funcs.get_max_physical(); cpu->pstate.turbo_pstate = pstate_funcs.get_turbo(); cpu->pstate.scaling = pstate_funcs.get_scaling(); - cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling; if (hwp_active && !hwp_mode_bdw) { unsigned int phy_max, current_max; @@ -1432,9 +1430,12 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu) intel_pstate_get_hwp_max(cpu->cpu, &phy_max, ¤t_max); cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling; cpu->pstate.turbo_pstate = phy_max; + cpu->pstate.max_pstate = HWP_GUARANTEED_PERF(READ_ONCE(cpu->hwp_cap_cached)); } else { cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling; + cpu->pstate.max_pstate = pstate_funcs.get_max(); } + cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling; if (pstate_funcs.get_aperf_mperf_shift) cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift(); diff --git a/drivers/cpufreq/loongson1-cpufreq.c b/drivers/cpufreq/loongson1-cpufreq.c index be89416e2358..9d902f67f871 100644 --- a/drivers/cpufreq/loongson1-cpufreq.c +++ b/drivers/cpufreq/loongson1-cpufreq.c @@ -217,6 +217,7 @@ static struct platform_driver ls1x_cpufreq_platdrv = { module_platform_driver(ls1x_cpufreq_platdrv); +MODULE_ALIAS("platform:ls1x-cpufreq"); MODULE_AUTHOR("Kelvin Cheung "); MODULE_DESCRIPTION("Loongson1 CPUFreq driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index eb8920d39818..5a81e20f0282 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c @@ -554,6 +554,7 @@ static const struct of_device_id mtk_cpufreq_machines[] __initconst = { { } }; +MODULE_DEVICE_TABLE(of, mtk_cpufreq_machines); static int __init mtk_cpufreq_driver_init(void) { diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index fb77b39a4ce3..818f92798fb9 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -881,9 +881,9 @@ static int get_transition_latency(struct powernow_k8_data *data) /* Take a frequency, and issue the fid/vid transition command */ static int transition_frequency_fidvid(struct powernow_k8_data *data, - unsigned int index) + unsigned int index, + struct cpufreq_policy *policy) { - struct cpufreq_policy *policy; u32 fid = 0; u32 vid = 0; int res; @@ -915,9 +915,6 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data, freqs.old = find_khz_freq_from_fid(data->currfid); freqs.new = find_khz_freq_from_fid(fid); - policy = cpufreq_cpu_get(smp_processor_id()); - cpufreq_cpu_put(policy); - cpufreq_freq_transition_begin(policy, &freqs); res = transition_fid_vid(data, fid, vid); cpufreq_freq_transition_end(policy, &freqs, res); @@ -972,7 +969,7 @@ static long powernowk8_target_fn(void *arg) powernow_k8_acpi_pst_values(data, newstate); - ret = transition_frequency_fidvid(data, newstate); + ret = transition_frequency_fidvid(data, newstate, pol); if (ret) { pr_err("transition frequency failed\n"); diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 20ee8c5fa8cc..183b62296208 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -443,20 +443,57 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = { .ready = qcom_cpufreq_ready, }; +static bool of_find_freq(u32 *of_table, int of_len, long frequency) +{ + int i; + + if (!of_table) + return true; + + for (i = 0; i < of_len; i++) { + if (frequency == of_table[i]) + return true; + } + + return false; +} + static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev, - struct cpufreq_qcom *c) + struct cpufreq_qcom *c, + int domain_index) { struct device *dev = &pdev->dev, *cpu_dev; void __iomem *base_freq, *base_volt; u32 data, src, lval, i, core_count, prev_cc, prev_freq, cur_freq, volt; u32 vc; unsigned long cpu; + int ret, of_len; + u32 *of_table = NULL; + char tbl_name[] = "qcom,cpufreq-table-##"; c->table = devm_kcalloc(dev, lut_max_entries + 1, sizeof(*c->table), GFP_KERNEL); if (!c->table) return -ENOMEM; + snprintf(tbl_name, sizeof(tbl_name), "qcom,cpufreq-table-%d", + domain_index); + if (of_find_property(dev->of_node, tbl_name, &of_len) && of_len > 0) { + of_len /= sizeof(*of_table); + + of_table = devm_kcalloc(dev, of_len, sizeof(*of_table), + GFP_KERNEL); + if (!of_table) { + ret = -ENOMEM; + goto err_cpufreq_table; + } + + ret = of_property_read_u32_array(dev->of_node, tbl_name, + of_table, of_len); + if (ret) + goto err_of_table; + } + spin_lock_init(&c->skip_data.lock); base_freq = c->reg_bases[REG_FREQ_LUT_TABLE]; base_volt = c->reg_bases[REG_VOLT_LUT_TABLE]; @@ -483,38 +520,43 @@ static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev, dev_dbg(dev, "index=%d freq=%d, core_count %d\n", i, c->table[i].frequency, core_count); - if (core_count != c->max_cores) { - if (core_count == (c->max_cores - 1)) { - c->skip_data.skip = true; - c->skip_data.high_temp_index = i; - c->skip_data.freq = cur_freq; - c->skip_data.cc = core_count; - c->skip_data.final_index = i + 1; - c->skip_data.low_temp_index = i + 1; - c->skip_data.prev_freq = - c->table[i-1].frequency; - c->skip_data.prev_index = i - 1; - c->skip_data.prev_cc = prev_cc; - } else { - cur_freq = CPUFREQ_ENTRY_INVALID; - c->table[i].flags = CPUFREQ_BOOST_FREQ; + if (!of_find_freq(of_table, of_len, c->table[i].frequency)) { + c->table[i].frequency = CPUFREQ_ENTRY_INVALID; + cur_freq = CPUFREQ_ENTRY_INVALID; + } else { + if (core_count != c->max_cores) { + if (core_count == (c->max_cores - 1)) { + c->skip_data.skip = true; + c->skip_data.high_temp_index = i; + c->skip_data.freq = cur_freq; + c->skip_data.cc = core_count; + c->skip_data.final_index = i + 1; + c->skip_data.low_temp_index = i + 1; + c->skip_data.prev_freq = + c->table[i-1].frequency; + c->skip_data.prev_index = i - 1; + c->skip_data.prev_cc = prev_cc; + } else { + cur_freq = CPUFREQ_ENTRY_INVALID; + c->table[i].flags = CPUFREQ_BOOST_FREQ; + } } - } - /* - * Two of the same frequencies with the same core counts means - * end of table. - */ - if (i > 0 && c->table[i - 1].frequency == - c->table[i].frequency) { - if (prev_cc == core_count) { - struct cpufreq_frequency_table *prev = - &c->table[i - 1]; - - if (prev_freq == CPUFREQ_ENTRY_INVALID) - prev->flags = CPUFREQ_BOOST_FREQ; + /* + * Two of the same frequencies with the same core counts means + * end of table. + */ + if (i > 0 && c->table[i - 1].frequency == + c->table[i].frequency) { + if (prev_cc == core_count) { + struct cpufreq_frequency_table *prev = + &c->table[i - 1]; + + if (prev_freq == CPUFREQ_ENTRY_INVALID) + prev->flags = CPUFREQ_BOOST_FREQ; + } + break; } - break; } prev_cc = core_count; @@ -532,6 +574,9 @@ static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev, c->lut_max_entries = i; c->table[i].frequency = CPUFREQ_TABLE_END; + if (of_table) + devm_kfree(dev, of_table); + if (c->skip_data.skip) { pr_info("%s Skip: Index[%u], Frequency[%u], Core Count %u, Final Index %u Actual Index %u Prev_Freq[%u] Prev_Index[%u] Prev_CC[%u]\n", __func__, c->skip_data.high_temp_index, @@ -544,6 +589,12 @@ static int qcom_cpufreq_hw_read_lut(struct platform_device *pdev, } return 0; + +err_of_table: + devm_kfree(dev, of_table); +err_cpufreq_table: + devm_kfree(dev, c->table); + return ret; } static int qcom_get_related_cpus(int index, struct cpumask *m) @@ -627,7 +678,7 @@ static int qcom_cpu_resources_init(struct platform_device *pdev, c->xo_rate = xo_rate; c->cpu_hw_rate = cpu_hw_rate; - ret = qcom_cpufreq_hw_read_lut(pdev, c); + ret = qcom_cpufreq_hw_read_lut(pdev, c, index); if (ret) { dev_err(dev, "Domain-%d failed to read LUT\n", index); return ret; diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index 5c826910d1f7..d27f3e1c8292 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -252,6 +252,7 @@ static struct platform_driver scpi_cpufreq_platdrv = { }; module_platform_driver(scpi_cpufreq_platdrv); +MODULE_ALIAS("platform:scpi-cpufreq"); MODULE_AUTHOR("Sudeep Holla "); MODULE_DESCRIPTION("ARM SCPI CPUFreq interface driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/cpufreq/sti-cpufreq.c b/drivers/cpufreq/sti-cpufreq.c index 6b5d241c30b7..2d09960afa59 100644 --- a/drivers/cpufreq/sti-cpufreq.c +++ b/drivers/cpufreq/sti-cpufreq.c @@ -295,6 +295,13 @@ static int sti_cpufreq_init(void) } module_init(sti_cpufreq_init); +static const struct of_device_id __maybe_unused sti_cpufreq_of_match[] = { + { .compatible = "st,stih407" }, + { .compatible = "st,stih410" }, + { }, +}; +MODULE_DEVICE_TABLE(of, sti_cpufreq_of_match); + MODULE_DESCRIPTION("STMicroelectronics CPUFreq/OPP driver"); MODULE_AUTHOR("Ajitpal Singh "); MODULE_AUTHOR("Lee Jones "); diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 7e48eb5bf0a7..206ae1fe4e07 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -4,7 +4,6 @@ config CPU_IDLE bool "CPU idle PM support" default y if ACPI || PPC_PSERIES select CPU_IDLE_GOV_LADDER if (!NO_HZ && !NO_HZ_IDLE) - select CPU_IDLE_GOV_MENU if (NO_HZ || NO_HZ_IDLE) help CPU idle is a generic framework for supporting software-controlled idle processor power management. It includes modular cross-platform diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 219704cd87eb..65278a50d8ed 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -38,6 +38,24 @@ static int enabled_devices; static int off __read_mostly; static int initialized __read_mostly; +#ifdef CONFIG_SMP +static atomic_t idled = ATOMIC_INIT(0); + +#if NR_CPUS > 32 +#error idled CPU mask not big enough for NR_CPUS +#endif + +void cpuidle_set_idle_cpu(unsigned int cpu) +{ + atomic_or(BIT(cpu), &idled); +} + +void cpuidle_clear_idle_cpu(unsigned int cpu) +{ + atomic_andnot(BIT(cpu), &idled); +} +#endif + int cpuidle_disabled(void) { return off; @@ -250,17 +268,17 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv, if (!cpuidle_state_is_coupled(drv, index)) local_irq_enable(); - diff = ktime_us_delta(time_end, time_start); - if (diff > INT_MAX) - diff = INT_MAX; - - dev->last_residency = (int) diff; - if (entered_state >= 0) { - /* Update cpuidle counters */ - /* This can be moved to within driver enter routine + /* + * Update cpuidle counters + * This can be moved to within driver enter routine, * but that results in multiple copies of same code. */ + diff = ktime_us_delta(time_end, time_start); + if (diff > INT_MAX) + diff = INT_MAX; + + dev->last_residency = (int)diff; dev->states_usage[entered_state].time += dev->last_residency; dev->states_usage[entered_state].usage++; } else { @@ -656,27 +674,6 @@ int cpuidle_register(struct cpuidle_driver *drv, EXPORT_SYMBOL_GPL(cpuidle_register); #ifdef CONFIG_SMP - -static void wake_up_idle_cpus(void *v) -{ - int cpu; - struct cpumask cpus; - - preempt_disable(); - if (v) { - cpumask_andnot(&cpus, v, cpu_isolated_mask); - cpumask_and(&cpus, &cpus, cpu_online_mask); - } else - cpumask_andnot(&cpus, cpu_online_mask, cpu_isolated_mask); - - for_each_cpu(cpu, &cpus) { - if (cpu == smp_processor_id()) - continue; - wake_up_if_idle(cpu); - } - preempt_enable(); -} - /* * This function gets called when a part of the kernel has a new latency * requirement. This means we need to get only those processors out of their @@ -686,7 +683,13 @@ static void wake_up_idle_cpus(void *v) static int cpuidle_latency_notify(struct notifier_block *b, unsigned long l, void *v) { - wake_up_idle_cpus(v); + unsigned long cpus = atomic_read(&idled) & *cpumask_bits(to_cpumask(v)); + + /* Use READ_ONCE to get the isolated mask outside cpu_add_remove_lock */ + cpus &= ~READ_ONCE(*cpumask_bits(cpu_isolated_mask)); + if (cpus) + arch_send_wakeup_ipi_mask(to_cpumask(&cpus)); + return NOTIFY_OK; } diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 121a483baa88..df0152e270bb 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -753,7 +753,7 @@ static int cpu_power_select(struct cpuidle_device *dev, min_residency = pwr_params->min_residency; max_residency = pwr_params->max_residency; - if (latency_us < lvl_latency_us) + if (latency_us <= lvl_latency_us) break; calculate_next_wakeup(&next_wakeup_us, next_event_us, @@ -1090,7 +1090,7 @@ static int cluster_select(struct lpm_cluster *cluster, bool from_idle, &level->num_cpu_votes)) continue; - if (from_idle && latency_us < pwr_params->exit_latency) + if (from_idle && latency_us <= pwr_params->exit_latency) break; if (sleep_us < (pwr_params->exit_latency + @@ -1504,7 +1504,9 @@ static int lpm_cpuidle_enter(struct cpuidle_device *dev, if (need_resched()) goto exit; + cpuidle_set_idle_cpu(dev->cpu); success = psci_enter_sleep(cpu, idx, true); + cpuidle_clear_idle_cpu(dev->cpu); exit: end_time = ktime_to_ns(ktime_get()); diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c index 68d5ea818b6c..cd00afb5786e 100644 --- a/drivers/crypto/amcc/crypto4xx_core.c +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -926,7 +926,7 @@ int crypto4xx_build_pd(struct crypto_async_request *req, } pd->pd_ctl.w = PD_CTL_HOST_READY | - ((crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH) | + ((crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH) || (crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AEAD) ? PD_CTL_HASH_FINAL : 0); pd->pd_ctl_len.w = 0x00400000 | (assoclen + datalen); diff --git a/drivers/crypto/bcm/cipher.c b/drivers/crypto/bcm/cipher.c index c2736274ad63..c63992fbbc98 100644 --- a/drivers/crypto/bcm/cipher.c +++ b/drivers/crypto/bcm/cipher.c @@ -52,7 +52,7 @@ /* ================= Device Structure ================== */ -struct device_private iproc_priv; +struct bcm_device_private iproc_priv; /* ==================== Parameters ===================== */ diff --git a/drivers/crypto/bcm/cipher.h b/drivers/crypto/bcm/cipher.h index 763c425c41ca..36452d26c7c5 100644 --- a/drivers/crypto/bcm/cipher.h +++ b/drivers/crypto/bcm/cipher.h @@ -431,7 +431,7 @@ struct spu_hw { u32 num_chan; }; -struct device_private { +struct bcm_device_private { struct platform_device *pdev; struct spu_hw spu; @@ -478,6 +478,6 @@ struct device_private { struct mbox_chan **mbox; }; -extern struct device_private iproc_priv; +extern struct bcm_device_private iproc_priv; #endif diff --git a/drivers/crypto/bcm/util.c b/drivers/crypto/bcm/util.c index a912c6ad3e85..f96d1dade010 100644 --- a/drivers/crypto/bcm/util.c +++ b/drivers/crypto/bcm/util.c @@ -400,7 +400,7 @@ char *spu_alg_name(enum spu_cipher_alg alg, enum spu_cipher_mode mode) static ssize_t spu_debugfs_read(struct file *filp, char __user *ubuf, size_t count, loff_t *offp) { - struct device_private *ipriv; + struct bcm_device_private *ipriv; char *buf; ssize_t ret, out_offset, out_count; int i; diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index 35116cdb5e38..08ed3ff8b255 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -581,7 +581,7 @@ static void chtls_reset_synq(struct listen_ctx *listen_ctx) while (!skb_queue_empty(&listen_ctx->synq)) { struct chtls_sock *csk = - container_of((struct synq *)__skb_dequeue + container_of((struct synq *)skb_peek (&listen_ctx->synq), struct chtls_sock, synq); struct sock *child = csk->sk; @@ -1024,6 +1024,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk, const struct cpl_pass_accept_req *req, struct chtls_dev *cdev) { + struct adapter *adap = pci_get_drvdata(cdev->pdev); const struct tcphdr *tcph; struct inet_sock *newinet; const struct iphdr *iph; @@ -1033,9 +1034,10 @@ static struct sock *chtls_recv_sock(struct sock *lsk, struct neighbour *n; struct tcp_sock *tp; struct sock *newsk; + bool found = false; u16 port_id; int rxq_idx; - int step; + int step, i; iph = (const struct iphdr *)network_hdr; newsk = tcp_create_openreq_child(lsk, oreq, cdev->askb); @@ -1048,15 +1050,20 @@ static struct sock *chtls_recv_sock(struct sock *lsk, tcph = (struct tcphdr *)(iph + 1); n = dst_neigh_lookup(dst, &iph->saddr); - if (!n) - goto free_sk; + if (!n || !n->dev) + goto free_dst; ndev = n->dev; - if (!ndev) - goto free_dst; if (is_vlan_dev(ndev)) ndev = vlan_dev_real_dev(ndev); + for_each_port(adap, i) + if (cdev->ports[i] == ndev) + found = true; + + if (!found) + goto free_dst; + port_id = cxgb4_port_idx(ndev); csk = chtls_sock_create(cdev); @@ -1079,6 +1086,7 @@ static struct sock *chtls_recv_sock(struct sock *lsk, oreq->ts_recent = PASS_OPEN_TID_G(ntohl(req->tos_stid)); sk_setup_caps(newsk, dst); + newsk->sk_prot_creator = lsk->sk_prot_creator; csk->sk = newsk; csk->passive_reap_next = oreq; csk->tx_chan = cxgb4_port_chan(ndev); @@ -1107,6 +1115,8 @@ static struct sock *chtls_recv_sock(struct sock *lsk, free_csk: chtls_sock_release(&csk->kref); free_dst: + if (n) + neigh_release(n); dst_release(dst); free_sk: inet_csk_prepare_forced_close(newsk); @@ -1421,6 +1431,11 @@ static int chtls_pass_establish(struct chtls_dev *cdev, struct sk_buff *skb) sk_wake_async(sk, 0, POLL_OUT); data = lookup_stid(cdev->tids, stid); + if (!data) { + /* listening server close */ + kfree_skb(skb); + goto unlock; + } lsk = ((struct listen_ctx *)data)->lsk; bh_lock_sock(lsk); @@ -1806,39 +1821,6 @@ static void send_defer_abort_rpl(struct chtls_dev *cdev, struct sk_buff *skb) kfree_skb(skb); } -static void send_abort_rpl(struct sock *sk, struct sk_buff *skb, - struct chtls_dev *cdev, int status, int queue) -{ - struct cpl_abort_req_rss *req = cplhdr(skb); - struct sk_buff *reply_skb; - struct chtls_sock *csk; - - csk = rcu_dereference_sk_user_data(sk); - - reply_skb = alloc_skb(sizeof(struct cpl_abort_rpl), - GFP_KERNEL); - - if (!reply_skb) { - req->status = (queue << 1); - send_defer_abort_rpl(cdev, skb); - return; - } - - set_abort_rpl_wr(reply_skb, GET_TID(req), status); - kfree_skb(skb); - - set_wr_txq(reply_skb, CPL_PRIORITY_DATA, queue); - if (csk_conn_inline(csk)) { - struct l2t_entry *e = csk->l2t_entry; - - if (e && sk->sk_state != TCP_SYN_RECV) { - cxgb4_l2t_send(csk->egress_dev, reply_skb, e); - return; - } - } - cxgb4_ofld_send(cdev->lldi->ports[0], reply_skb); -} - /* * Add an skb to the deferred skb queue for processing from process context. */ @@ -1901,9 +1883,9 @@ static void bl_abort_syn_rcv(struct sock *lsk, struct sk_buff *skb) queue = csk->txq_idx; skb->sk = NULL; + chtls_send_abort_rpl(child, skb, BLOG_SKB_CB(skb)->cdev, + CPL_ABORT_NO_RST, queue); do_abort_syn_rcv(child, lsk); - send_abort_rpl(child, skb, BLOG_SKB_CB(skb)->cdev, - CPL_ABORT_NO_RST, queue); } static int abort_syn_rcv(struct sock *sk, struct sk_buff *skb) @@ -1933,8 +1915,8 @@ static int abort_syn_rcv(struct sock *sk, struct sk_buff *skb) if (!sock_owned_by_user(psk)) { int queue = csk->txq_idx; + chtls_send_abort_rpl(sk, skb, cdev, CPL_ABORT_NO_RST, queue); do_abort_syn_rcv(sk, psk); - send_abort_rpl(sk, skb, cdev, CPL_ABORT_NO_RST, queue); } else { skb->sk = sk; BLOG_SKB_CB(skb)->backlog_rcv = bl_abort_syn_rcv; @@ -1952,9 +1934,6 @@ static void chtls_abort_req_rss(struct sock *sk, struct sk_buff *skb) int queue = csk->txq_idx; if (is_neg_adv(req->status)) { - if (sk->sk_state == TCP_SYN_RECV) - chtls_set_tcb_tflag(sk, 0, 0); - kfree_skb(skb); return; } @@ -1980,12 +1959,11 @@ static void chtls_abort_req_rss(struct sock *sk, struct sk_buff *skb) if (sk->sk_state == TCP_SYN_RECV && !abort_syn_rcv(sk, skb)) return; - - chtls_release_resources(sk); - chtls_conn_done(sk); } chtls_send_abort_rpl(sk, skb, csk->cdev, rst_status, queue); + chtls_release_resources(sk); + chtls_conn_done(sk); } static void chtls_abort_rpl_rss(struct sock *sk, struct sk_buff *skb) diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.h b/drivers/crypto/chelsio/chtls/chtls_cm.h index 4282d8a4eae4..ef7261072434 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.h +++ b/drivers/crypto/chelsio/chtls/chtls_cm.h @@ -53,9 +53,6 @@ #define MIN_RCV_WND (24 * 1024U) #define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000)) -/* ulp_mem_io + ulptx_idata + payload + padding */ -#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8) - /* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */ #define TX_HEADER_LEN \ (sizeof(struct fw_ofld_tx_data_wr) + sizeof(struct sge_opaque_hdr)) diff --git a/drivers/crypto/chelsio/chtls/chtls_hw.c b/drivers/crypto/chelsio/chtls/chtls_hw.c index 2294fb06bef3..7ea9dcfd7c49 100644 --- a/drivers/crypto/chelsio/chtls/chtls_hw.c +++ b/drivers/crypto/chelsio/chtls/chtls_hw.c @@ -376,6 +376,7 @@ int chtls_setkey(struct chtls_sock *csk, u32 keylen, u32 optname) csk->wr_unacked += DIV_ROUND_UP(len, 16); enqueue_wr(csk, skb); cxgb4_ofld_send(csk->egress_dev, skb); + skb = NULL; chtls_set_scmd(csk); /* Clear quiesce for Rx key */ diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c index 86c699c14f84..bc6c5cb7de23 100644 --- a/drivers/crypto/inside-secure/safexcel.c +++ b/drivers/crypto/inside-secure/safexcel.c @@ -1066,7 +1066,7 @@ static int safexcel_probe(struct platform_device *pdev) priv->ring[i].rdr_req = devm_kcalloc(dev, EIP197_DEFAULT_RING_SIZE, - sizeof(priv->ring[i].rdr_req), + sizeof(*priv->ring[i].rdr_req), GFP_KERNEL); if (!priv->ring[i].rdr_req) { ret = -ENOMEM; diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c index 6696aa1a0551..f5f0ccbbef48 100644 --- a/drivers/crypto/msm/qce50.c +++ b/drivers/crypto/msm/qce50.c @@ -263,10 +263,8 @@ static int qce_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, { int i; - for (i = 0; i < nents; ++i) { + for_each_sg(sg, sg, nents, i) dma_map_sg(dev, sg, 1, direction); - sg = sg_next(sg); - } return nents; } @@ -276,10 +274,8 @@ static int qce_dma_unmap_sg(struct device *dev, struct scatterlist *sg, { int i; - for (i = 0; i < nents; ++i) { + for_each_sg(sg, sg, nents, i) dma_unmap_sg(dev, sg, 1, direction); - sg = sg_next(sg); - } return nents; } diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 79423f906f08..9a4e7395017e 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1928,7 +1928,7 @@ static inline long qcedev_ioctl(struct file *file, if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req, sizeof(struct qcedev_sha_op_req))) err = -EFAULT; - goto exit_free_qcedev_areq; + goto exit_free_qcedev_areq; } break; @@ -1972,7 +1972,7 @@ static inline long qcedev_ioctl(struct file *file, if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req, sizeof(struct qcedev_sha_op_req))) { err = -EFAULT; - goto exit_free_qcedev_areq; + goto exit_free_qcedev_areq; } handle->sha_ctxt.init_done = false; break; @@ -2020,7 +2020,7 @@ static inline long qcedev_ioctl(struct file *file, if (copy_to_user((void __user *)arg, &qcedev_areq->sha_op_req, sizeof(struct qcedev_sha_op_req))) err = -EFAULT; - goto exit_free_qcedev_areq; + goto exit_free_qcedev_areq; } break; diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c index 9578c3a1b311..d211452168b7 100644 --- a/drivers/crypto/msm/qcrypto.c +++ b/drivers/crypto/msm/qcrypto.c @@ -779,14 +779,13 @@ static size_t qcrypto_sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen) { int i; - size_t offset, len; + size_t offset = 0, len; - for (i = 0, offset = 0; i < nents; ++i) { + for_each_sg(sgl, sgl, nents, i) { len = sg_copy_from_buffer(sgl, 1, buf, buflen); buf += len; buflen -= len; offset += len; - sgl = sg_next(sgl); } return offset; @@ -796,14 +795,13 @@ static size_t qcrypto_sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents, void *buf, size_t buflen) { int i; - size_t offset, len; + size_t offset = 0, len; - for (i = 0, offset = 0; i < nents; ++i) { + for_each_sg(sgl, sgl, nents, i) { len = sg_copy_to_buffer(sgl, 1, buf, buflen); buf += len; buflen -= len; offset += len; - sgl = sg_next(sgl); } return offset; diff --git a/drivers/crypto/mxs-dcp.c b/drivers/crypto/mxs-dcp.c index b0c592073a4a..9f5246211a00 100644 --- a/drivers/crypto/mxs-dcp.c +++ b/drivers/crypto/mxs-dcp.c @@ -101,7 +101,7 @@ struct dcp_async_ctx { unsigned int hot:1; /* Crypto-specific context */ - struct crypto_skcipher *fallback; + struct crypto_sync_skcipher *fallback; unsigned int key_len; uint8_t key[AES_KEYSIZE_128]; }; @@ -426,10 +426,10 @@ static int mxs_dcp_block_fallback(struct ablkcipher_request *req, int enc) { struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct dcp_async_ctx *ctx = crypto_ablkcipher_ctx(tfm); - SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); int ret; - skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_sync_tfm(subreq, ctx->fallback); skcipher_request_set_callback(subreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes, req->info); @@ -510,16 +510,16 @@ static int mxs_dcp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, * but is supported by in-kernel software implementation, we use * software fallback. */ - crypto_skcipher_clear_flags(actx->fallback, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(actx->fallback, + crypto_sync_skcipher_clear_flags(actx->fallback, CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(actx->fallback, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); - ret = crypto_skcipher_setkey(actx->fallback, key, len); + ret = crypto_sync_skcipher_setkey(actx->fallback, key, len); if (!ret) return 0; tfm->base.crt_flags &= ~CRYPTO_TFM_RES_MASK; - tfm->base.crt_flags |= crypto_skcipher_get_flags(actx->fallback) & + tfm->base.crt_flags |= crypto_sync_skcipher_get_flags(actx->fallback) & CRYPTO_TFM_RES_MASK; return ret; @@ -528,11 +528,10 @@ static int mxs_dcp_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, static int mxs_dcp_aes_fallback_init(struct crypto_tfm *tfm) { const char *name = crypto_tfm_alg_name(tfm); - const uint32_t flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK; struct dcp_async_ctx *actx = crypto_tfm_ctx(tfm); - struct crypto_skcipher *blk; + struct crypto_sync_skcipher *blk; - blk = crypto_alloc_skcipher(name, 0, flags); + blk = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(blk)) return PTR_ERR(blk); @@ -545,7 +544,7 @@ static void mxs_dcp_aes_fallback_exit(struct crypto_tfm *tfm) { struct dcp_async_ctx *actx = crypto_tfm_ctx(tfm); - crypto_free_skcipher(actx->fallback); + crypto_free_sync_skcipher(actx->fallback); } /* diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 9019f6b67986..a5d6e1a0192b 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -1163,7 +1163,7 @@ static int omap_aes_probe(struct platform_device *pdev) if (err < 0) { dev_err(dev, "%s: failed to get_sync(%d)\n", __func__, err); - goto err_res; + goto err_pm_disable; } omap_aes_dma_stop(dd); @@ -1276,6 +1276,7 @@ static int omap_aes_probe(struct platform_device *pdev) omap_aes_dma_cleanup(dd); err_irq: tasklet_kill(&dd->done_task); +err_pm_disable: pm_runtime_disable(dev); err_res: dd = NULL; diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c index ff149e176f64..dac130bb807a 100644 --- a/drivers/crypto/qat/qat_common/qat_hal.c +++ b/drivers/crypto/qat/qat_common/qat_hal.c @@ -1189,7 +1189,7 @@ static int qat_hal_put_rel_rd_xfer(struct icp_qat_fw_loader_handle *handle, unsigned short mask; unsigned short dr_offset = 0x10; - status = ctx_enables = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES); + ctx_enables = qat_hal_rd_ae_csr(handle, ae, CTX_ENABLES); if (CE_INUSE_CONTEXTS & ctx_enables) { if (ctx & 0x1) { pr_err("QAT: bad 4-ctx mode,ctx=0x%x\n", ctx); diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c index e7540a5b8197..bbf166a97ad3 100644 --- a/drivers/crypto/sahara.c +++ b/drivers/crypto/sahara.c @@ -149,7 +149,7 @@ struct sahara_ctx { /* AES-specific context */ int keylen; u8 key[AES_KEYSIZE_128]; - struct crypto_skcipher *fallback; + struct crypto_sync_skcipher *fallback; }; struct sahara_aes_reqctx { @@ -621,14 +621,14 @@ static int sahara_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, /* * The requested key size is not supported by HW, do a fallback. */ - crypto_skcipher_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK); - crypto_skcipher_set_flags(ctx->fallback, tfm->base.crt_flags & + crypto_sync_skcipher_clear_flags(ctx->fallback, CRYPTO_TFM_REQ_MASK); + crypto_sync_skcipher_set_flags(ctx->fallback, tfm->base.crt_flags & CRYPTO_TFM_REQ_MASK); - ret = crypto_skcipher_setkey(ctx->fallback, key, keylen); + ret = crypto_sync_skcipher_setkey(ctx->fallback, key, keylen); tfm->base.crt_flags &= ~CRYPTO_TFM_RES_MASK; - tfm->base.crt_flags |= crypto_skcipher_get_flags(ctx->fallback) & + tfm->base.crt_flags |= crypto_sync_skcipher_get_flags(ctx->fallback) & CRYPTO_TFM_RES_MASK; return ret; } @@ -666,9 +666,9 @@ static int sahara_aes_ecb_encrypt(struct ablkcipher_request *req) int err; if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { - SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_sync_tfm(subreq, ctx->fallback); skcipher_request_set_callback(subreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, @@ -688,9 +688,9 @@ static int sahara_aes_ecb_decrypt(struct ablkcipher_request *req) int err; if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { - SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_sync_tfm(subreq, ctx->fallback); skcipher_request_set_callback(subreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, @@ -710,9 +710,9 @@ static int sahara_aes_cbc_encrypt(struct ablkcipher_request *req) int err; if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { - SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_sync_tfm(subreq, ctx->fallback); skcipher_request_set_callback(subreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, @@ -732,9 +732,9 @@ static int sahara_aes_cbc_decrypt(struct ablkcipher_request *req) int err; if (unlikely(ctx->keylen != AES_KEYSIZE_128)) { - SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); + SYNC_SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback); - skcipher_request_set_tfm(subreq, ctx->fallback); + skcipher_request_set_sync_tfm(subreq, ctx->fallback); skcipher_request_set_callback(subreq, req->base.flags, NULL, NULL); skcipher_request_set_crypt(subreq, req->src, req->dst, @@ -752,8 +752,7 @@ static int sahara_aes_cra_init(struct crypto_tfm *tfm) const char *name = crypto_tfm_alg_name(tfm); struct sahara_ctx *ctx = crypto_tfm_ctx(tfm); - ctx->fallback = crypto_alloc_skcipher(name, 0, - CRYPTO_ALG_ASYNC | + ctx->fallback = crypto_alloc_sync_skcipher(name, 0, CRYPTO_ALG_NEED_FALLBACK); if (IS_ERR(ctx->fallback)) { pr_err("Error allocating fallback algo %s\n", name); @@ -769,7 +768,7 @@ static void sahara_aes_cra_exit(struct crypto_tfm *tfm) { struct sahara_ctx *ctx = crypto_tfm_ctx(tfm); - crypto_free_skcipher(ctx->fallback); + crypto_free_sync_skcipher(ctx->fallback); } static u32 sahara_sha_init_hdr(struct sahara_dev *dev, diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c index 22e491857925..aa3d2f439965 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c @@ -34,6 +34,8 @@ static int sun4i_ss_opti_poll(struct skcipher_request *areq) unsigned int ileft = areq->cryptlen; unsigned int oleft = areq->cryptlen; unsigned int todo; + unsigned long pi = 0, po = 0; /* progress for in and out */ + bool miter_err; struct sg_mapping_iter mi, mo; unsigned int oi, oo; /* offset for in and out */ unsigned long flags; @@ -53,50 +55,62 @@ static int sun4i_ss_opti_poll(struct skcipher_request *areq) spin_lock_irqsave(&ss->slock, flags); - for (i = 0; i < op->keylen; i += 4) - writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); + for (i = 0; i < op->keylen / 4; i++) + writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1); if (areq->iv) { for (i = 0; i < 4 && i < ivsize / 4; i++) { v = *(u32 *)(areq->iv + i * 4); - writel(v, ss->base + SS_IV0 + i * 4); + writesl(ss->base + SS_IV0 + i * 4, &v, 1); } } writel(mode, ss->base + SS_CTL); - sg_miter_start(&mi, areq->src, sg_nents(areq->src), - SG_MITER_FROM_SG | SG_MITER_ATOMIC); - sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), - SG_MITER_TO_SG | SG_MITER_ATOMIC); - sg_miter_next(&mi); - sg_miter_next(&mo); - if (!mi.addr || !mo.addr) { - dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); - err = -EINVAL; - goto release_ss; - } ileft = areq->cryptlen / 4; oleft = areq->cryptlen / 4; oi = 0; oo = 0; do { - todo = min(rx_cnt, ileft); - todo = min_t(size_t, todo, (mi.length - oi) / 4); - if (todo) { - ileft -= todo; - writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo); - oi += todo * 4; - } - if (oi == mi.length) { - sg_miter_next(&mi); - oi = 0; + if (ileft) { + sg_miter_start(&mi, areq->src, sg_nents(areq->src), + SG_MITER_FROM_SG | SG_MITER_ATOMIC); + if (pi) + sg_miter_skip(&mi, pi); + miter_err = sg_miter_next(&mi); + if (!miter_err || !mi.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } + todo = min(rx_cnt, ileft); + todo = min_t(size_t, todo, (mi.length - oi) / 4); + if (todo) { + ileft -= todo; + writesl(ss->base + SS_RXFIFO, mi.addr + oi, todo); + oi += todo * 4; + } + if (oi == mi.length) { + pi += mi.length; + oi = 0; + } + sg_miter_stop(&mi); } spaces = readl(ss->base + SS_FCSR); rx_cnt = SS_RXFIFO_SPACES(spaces); tx_cnt = SS_TXFIFO_SPACES(spaces); + sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), + SG_MITER_TO_SG | SG_MITER_ATOMIC); + if (po) + sg_miter_skip(&mo, po); + miter_err = sg_miter_next(&mo); + if (!miter_err || !mo.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } todo = min(tx_cnt, oleft); todo = min_t(size_t, todo, (mo.length - oo) / 4); if (todo) { @@ -105,9 +119,10 @@ static int sun4i_ss_opti_poll(struct skcipher_request *areq) oo += todo * 4; } if (oo == mo.length) { - sg_miter_next(&mo); oo = 0; + po += mo.length; } + sg_miter_stop(&mo); } while (oleft); if (areq->iv) { @@ -118,8 +133,6 @@ static int sun4i_ss_opti_poll(struct skcipher_request *areq) } release_ss: - sg_miter_stop(&mi); - sg_miter_stop(&mo); writel(0, ss->base + SS_CTL); spin_unlock_irqrestore(&ss->slock, flags); return err; @@ -148,6 +161,8 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) unsigned int oleft = areq->cryptlen; unsigned int todo; struct sg_mapping_iter mi, mo; + unsigned long pi = 0, po = 0; /* progress for in and out */ + bool miter_err; unsigned int oi, oo; /* offset for in and out */ char buf[4 * SS_RX_MAX];/* buffer for linearize SG src */ char bufo[4 * SS_TX_MAX]; /* buffer for linearize SG dst */ @@ -174,12 +189,12 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) * we can use the SS optimized function */ while (in_sg && no_chunk == 1) { - if (in_sg->length % 4) + if ((in_sg->length | in_sg->offset) & 3u) no_chunk = 0; in_sg = sg_next(in_sg); } while (out_sg && no_chunk == 1) { - if (out_sg->length % 4) + if ((out_sg->length | out_sg->offset) & 3u) no_chunk = 0; out_sg = sg_next(out_sg); } @@ -189,28 +204,17 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) spin_lock_irqsave(&ss->slock, flags); - for (i = 0; i < op->keylen; i += 4) - writel(*(op->key + i / 4), ss->base + SS_KEY0 + i); + for (i = 0; i < op->keylen / 4; i++) + writesl(ss->base + SS_KEY0 + i * 4, &op->key[i], 1); if (areq->iv) { for (i = 0; i < 4 && i < ivsize / 4; i++) { v = *(u32 *)(areq->iv + i * 4); - writel(v, ss->base + SS_IV0 + i * 4); + writesl(ss->base + SS_IV0 + i * 4, &v, 1); } } writel(mode, ss->base + SS_CTL); - sg_miter_start(&mi, areq->src, sg_nents(areq->src), - SG_MITER_FROM_SG | SG_MITER_ATOMIC); - sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), - SG_MITER_TO_SG | SG_MITER_ATOMIC); - sg_miter_next(&mi); - sg_miter_next(&mo); - if (!mi.addr || !mo.addr) { - dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); - err = -EINVAL; - goto release_ss; - } ileft = areq->cryptlen; oleft = areq->cryptlen; oi = 0; @@ -218,6 +222,16 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) while (oleft) { if (ileft) { + sg_miter_start(&mi, areq->src, sg_nents(areq->src), + SG_MITER_FROM_SG | SG_MITER_ATOMIC); + if (pi) + sg_miter_skip(&mi, pi); + miter_err = sg_miter_next(&mi); + if (!miter_err || !mi.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } /* * todo is the number of consecutive 4byte word that we * can read from current SG @@ -250,31 +264,38 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) } } if (oi == mi.length) { - sg_miter_next(&mi); + pi += mi.length; oi = 0; } + sg_miter_stop(&mi); } spaces = readl(ss->base + SS_FCSR); rx_cnt = SS_RXFIFO_SPACES(spaces); tx_cnt = SS_TXFIFO_SPACES(spaces); - dev_dbg(ss->dev, - "%x %u/%zu %u/%u cnt=%u %u/%zu %u/%u cnt=%u %u\n", - mode, - oi, mi.length, ileft, areq->cryptlen, rx_cnt, - oo, mo.length, oleft, areq->cryptlen, tx_cnt, ob); if (!tx_cnt) continue; + sg_miter_start(&mo, areq->dst, sg_nents(areq->dst), + SG_MITER_TO_SG | SG_MITER_ATOMIC); + if (po) + sg_miter_skip(&mo, po); + miter_err = sg_miter_next(&mo); + if (!miter_err || !mo.addr) { + dev_err_ratelimited(ss->dev, "ERROR: sg_miter return null\n"); + err = -EINVAL; + goto release_ss; + } /* todo in 4bytes word */ todo = min(tx_cnt, oleft / 4); todo = min_t(size_t, todo, (mo.length - oo) / 4); + if (todo) { readsl(ss->base + SS_TXFIFO, mo.addr + oo, todo); oleft -= todo * 4; oo += todo * 4; if (oo == mo.length) { - sg_miter_next(&mo); + po += mo.length; oo = 0; } } else { @@ -299,12 +320,14 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) obo += todo; oo += todo; if (oo == mo.length) { + po += mo.length; sg_miter_next(&mo); oo = 0; } } while (obo < obl); /* bufo must be fully used here */ } + sg_miter_stop(&mo); } if (areq->iv) { for (i = 0; i < 4 && i < ivsize / 4; i++) { @@ -314,8 +337,6 @@ static int sun4i_ss_cipher_poll(struct skcipher_request *areq) } release_ss: - sg_miter_stop(&mi); - sg_miter_stop(&mo); writel(0, ss->base + SS_CTL); spin_unlock_irqrestore(&ss->slock, flags); diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index ea16308fae0a..7a55baa861e5 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -474,7 +474,7 @@ DEF_TALITOS2_DONE(ch1_3, TALITOS2_ISR_CH_1_3_DONE) /* * locate current (offending) descriptor */ -static u32 current_desc_hdr(struct device *dev, int ch) +static __be32 current_desc_hdr(struct device *dev, int ch) { struct talitos_private *priv = dev_get_drvdata(dev); int tail, iter; @@ -492,7 +492,7 @@ static u32 current_desc_hdr(struct device *dev, int ch) iter = tail; while (priv->chan[ch].fifo[iter].dma_desc != cur_desc && - priv->chan[ch].fifo[iter].desc->next_desc != cur_desc) { + priv->chan[ch].fifo[iter].desc->next_desc != cpu_to_be32(cur_desc)) { iter = (iter + 1) & (priv->fifo_len - 1); if (iter == tail) { dev_err(dev, "couldn't locate current descriptor\n"); @@ -500,7 +500,7 @@ static u32 current_desc_hdr(struct device *dev, int ch) } } - if (priv->chan[ch].fifo[iter].desc->next_desc == cur_desc) { + if (priv->chan[ch].fifo[iter].desc->next_desc == cpu_to_be32(cur_desc)) { struct talitos_edesc *edesc; edesc = container_of(priv->chan[ch].fifo[iter].desc, @@ -515,13 +515,13 @@ static u32 current_desc_hdr(struct device *dev, int ch) /* * user diagnostics; report root cause of error based on execution unit status */ -static void report_eu_error(struct device *dev, int ch, u32 desc_hdr) +static void report_eu_error(struct device *dev, int ch, __be32 desc_hdr) { struct talitos_private *priv = dev_get_drvdata(dev); int i; if (!desc_hdr) - desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF); + desc_hdr = cpu_to_be32(in_be32(priv->chan[ch].reg + TALITOS_DESCBUF)); switch (desc_hdr & DESC_HDR_SEL0_MASK) { case DESC_HDR_SEL0_AFEU: @@ -1066,11 +1066,12 @@ static void ipsec_esp_decrypt_hwauth_done(struct device *dev, */ static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, unsigned int offset, int datalen, int elen, - struct talitos_ptr *link_tbl_ptr) + struct talitos_ptr *link_tbl_ptr, int align) { int n_sg = elen ? sg_count + 1 : sg_count; int count = 0; int cryptlen = datalen + elen; + int padding = ALIGN(cryptlen, align) - cryptlen; while (cryptlen && sg && n_sg--) { unsigned int len = sg_dma_len(sg); @@ -1094,7 +1095,7 @@ static int sg_to_link_tbl_offset(struct scatterlist *sg, int sg_count, offset += datalen; } to_talitos_ptr(link_tbl_ptr + count, - sg_dma_address(sg) + offset, len, 0); + sg_dma_address(sg) + offset, sg_next(sg) ? len : len + padding, 0); to_talitos_ptr_ext_set(link_tbl_ptr + count, 0, 0); count++; cryptlen -= len; @@ -1117,10 +1118,11 @@ static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, unsigned int len, struct talitos_edesc *edesc, struct talitos_ptr *ptr, int sg_count, unsigned int offset, int tbl_off, int elen, - bool force) + bool force, int align) { struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); + int aligned_len = ALIGN(len, align); if (!src) { to_talitos_ptr(ptr, 0, 0, is_sec1); @@ -1128,22 +1130,22 @@ static int talitos_sg_map_ext(struct device *dev, struct scatterlist *src, } to_talitos_ptr_ext_set(ptr, elen, is_sec1); if (sg_count == 1 && !force) { - to_talitos_ptr(ptr, sg_dma_address(src) + offset, len, is_sec1); + to_talitos_ptr(ptr, sg_dma_address(src) + offset, aligned_len, is_sec1); return sg_count; } if (is_sec1) { - to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, len, is_sec1); + to_talitos_ptr(ptr, edesc->dma_link_tbl + offset, aligned_len, is_sec1); return sg_count; } sg_count = sg_to_link_tbl_offset(src, sg_count, offset, len, elen, - &edesc->link_tbl[tbl_off]); + &edesc->link_tbl[tbl_off], align); if (sg_count == 1 && !force) { /* Only one segment now, so no link tbl needed*/ copy_talitos_ptr(ptr, &edesc->link_tbl[tbl_off], is_sec1); return sg_count; } to_talitos_ptr(ptr, edesc->dma_link_tbl + - tbl_off * sizeof(struct talitos_ptr), len, is_sec1); + tbl_off * sizeof(struct talitos_ptr), aligned_len, is_sec1); to_talitos_ptr_ext_or(ptr, DESC_PTR_LNKTBL_JUMP, is_sec1); return sg_count; @@ -1155,7 +1157,7 @@ static int talitos_sg_map(struct device *dev, struct scatterlist *src, unsigned int offset, int tbl_off) { return talitos_sg_map_ext(dev, src, len, edesc, ptr, sg_count, offset, - tbl_off, 0, false); + tbl_off, 0, false, 1); } /* @@ -1224,7 +1226,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], sg_count, areq->assoclen, tbl_off, elen, - false); + false, 1); if (ret > 1) { tbl_off += ret; @@ -1244,7 +1246,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq, elen = 0; ret = talitos_sg_map_ext(dev, areq->dst, cryptlen, edesc, &desc->ptr[5], sg_count, areq->assoclen, tbl_off, elen, - is_ipsec_esp && !encrypt); + is_ipsec_esp && !encrypt, 1); tbl_off += ret; /* ICV data */ @@ -1554,6 +1556,8 @@ static int common_nonsnoop(struct talitos_edesc *edesc, bool sync_needed = false; struct talitos_private *priv = dev_get_drvdata(dev); bool is_sec1 = has_ftr_sec1(priv); + bool is_ctr = (desc->hdr & DESC_HDR_SEL0_MASK) == DESC_HDR_SEL0_AESU && + (desc->hdr & DESC_HDR_MODE0_AESU_MASK) == DESC_HDR_MODE0_AESU_CTR; /* first DWORD empty */ @@ -1574,8 +1578,8 @@ static int common_nonsnoop(struct talitos_edesc *edesc, /* * cipher in */ - sg_count = talitos_sg_map(dev, areq->src, cryptlen, edesc, - &desc->ptr[3], sg_count, 0, 0); + sg_count = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[3], + sg_count, 0, 0, 0, false, is_ctr ? 16 : 1); if (sg_count > 1) sync_needed = true; diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h index cb0137e131cc..16f96c57de34 100644 --- a/drivers/crypto/talitos.h +++ b/drivers/crypto/talitos.h @@ -377,6 +377,7 @@ static inline bool has_ftr_sec1(struct talitos_private *priv) /* primary execution unit mode (MODE0) and derivatives */ #define DESC_HDR_MODE0_ENCRYPT cpu_to_be32(0x00100000) +#define DESC_HDR_MODE0_AESU_MASK cpu_to_be32(0x00600000) #define DESC_HDR_MODE0_AESU_CBC cpu_to_be32(0x00200000) #define DESC_HDR_MODE0_AESU_CTR cpu_to_be32(0x00600000) #define DESC_HDR_MODE0_DEU_CBC cpu_to_be32(0x00400000) diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig index 80ab58fb6adf..a0a01fc93c59 100644 --- a/drivers/devfreq/Kconfig +++ b/drivers/devfreq/Kconfig @@ -247,6 +247,45 @@ config DEVFREQ_GOV_STATICMAP This governor votes for the DDR BW based on the device's clock rate change. +config DEVFREQ_BOOST + bool "Devfreq Boost" + help + Boosts enumerated devfreq devices upon input, and allows for boosting + specific devfreq devices on other custom events. The boost frequencies + for this driver should be set so that frame drops are near-zero at the + boosted frequencies and power consumption is minimized at said + frequencies. The goal of this driver is to provide an interface to + achieve optimal device performance by requesting boosts on key events, + such as when a frame is ready to rendered to the display. + +if DEVFREQ_BOOST + +config DEVFREQ_INPUT_BOOST_DURATION_MS + int "Input boost duration" + default "100" + help + Input boost duration in milliseconds for all boostable devices. + +config DEVFREQ_WAKE_BOOST_DURATION_MS + int "Wake boost duration" + default "1000" + help + Wake boost duration in milliseconds for all boostable devices. + +config DEVFREQ_MSM_LLCCBW_DDR_BOOST_FREQ + int "Boost freq for llccbw-ddr device" + default "0" + help + Boost frequency for the MSM DDR bus. + +config DEVFREQ_MSM_CPU_LLCCBW_BOOST_FREQ + int "Boost freq for cpu-llcc device" + default "0" + help + Boost frequency for the MSM DDR bus. + +endif + source "drivers/devfreq/event/Kconfig" endif # PM_DEVFREQ diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile index c511cf0397ab..ed2f6e6e756b 100644 --- a/drivers/devfreq/Makefile +++ b/drivers/devfreq/Makefile @@ -28,3 +28,6 @@ obj-$(CONFIG_DEVFREQ_GOV_STATICMAP) += governor_staticmap.o # DEVFREQ Event Drivers obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/ + +# DEVFREQ Boost +obj-$(CONFIG_DEVFREQ_BOOST) += devfreq_boost.o diff --git a/drivers/devfreq/arm-memlat-mon.c b/drivers/devfreq/arm-memlat-mon.c index db2ee56e7f3e..ee70fe36dccc 100644 --- a/drivers/devfreq/arm-memlat-mon.c +++ b/drivers/devfreq/arm-memlat-mon.c @@ -26,6 +26,7 @@ #include #include #include +#include enum common_ev_idx { INST_IDX, @@ -222,6 +223,13 @@ static unsigned long get_cnt(struct memlat_hwmon *hw) struct memlat_cpu_grp *cpu_grp = mon->cpu_grp; unsigned int cpu; + /* + * Some of SCM call is very heavy(+20ms) so perf IPI could + * be stuck on the CPU which contributes long latency. + */ + if (under_scm_call()) + return 0; + for_each_cpu(cpu, &mon->cpus) { struct cpu_data *cpu_data = to_cpu_data(cpu_grp, cpu); struct event_data *common_evs = cpu_data->common_evs; diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 1b76beecf0e2..904aa6ee5b6a 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -313,10 +313,15 @@ int update_devfreq(struct devfreq *devfreq) if (!devfreq->governor) return -EINVAL; - /* Reevaluate the proper frequency */ - err = devfreq->governor->get_target_freq(devfreq, &freq); - if (err) - return err; + if (devfreq->max_boost) { + /* Use the max freq for max boosts */ + freq = ULONG_MAX; + } else { + /* Reevaluate the proper frequency */ + err = devfreq->governor->get_target_freq(devfreq, &freq); + if (err) + return err; + } /* * Adjust the frequency with user freq, QoS and available freq. @@ -1216,6 +1221,10 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr, unsigned long value; int ret; + /* Minfreq is managed by devfreq_boost */ + if (df->is_boost_device) + return count; + ret = sscanf(buf, "%lu", &value); if (ret != 1) return -EINVAL; @@ -1400,7 +1409,8 @@ static int __init devfreq_init(void) return PTR_ERR(devfreq_class); } - devfreq_wq = create_freezable_workqueue("devfreq_wq"); + devfreq_wq = alloc_workqueue("devfreq_wq", WQ_HIGHPRI | WQ_FREEZABLE + | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); if (!devfreq_wq) { class_destroy(devfreq_class); pr_err("%s: couldn't create workqueue\n", __FILE__); diff --git a/drivers/devfreq/devfreq_boost.c b/drivers/devfreq/devfreq_boost.c new file mode 100644 index 000000000000..58d16b81d2f1 --- /dev/null +++ b/drivers/devfreq/devfreq_boost.c @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2019 Sultan Alsawaf . + */ + +#define pr_fmt(fmt) "devfreq_boost: " fmt + +#include +#include +#include +#include +#include +#include + +enum { + SCREEN_OFF, + INPUT_BOOST, + MAX_BOOST +}; + +struct boost_dev { + struct devfreq *df; + struct delayed_work input_unboost; + struct delayed_work max_unboost; + wait_queue_head_t boost_waitq; + atomic_long_t max_boost_expires; + unsigned long boost_freq; + unsigned long state; +}; + +struct df_boost_drv { + struct boost_dev devices[DEVFREQ_MAX]; + struct notifier_block msm_drm_notif; +}; + +static void devfreq_input_unboost(struct work_struct *work); +static void devfreq_max_unboost(struct work_struct *work); + +#define BOOST_DEV_INIT(b, dev, freq) .devices[dev] = { \ + .input_unboost = \ + __DELAYED_WORK_INITIALIZER((b).devices[dev].input_unboost, \ + devfreq_input_unboost, 0), \ + .max_unboost = \ + __DELAYED_WORK_INITIALIZER((b).devices[dev].max_unboost, \ + devfreq_max_unboost, 0), \ + .boost_waitq = \ + __WAIT_QUEUE_HEAD_INITIALIZER((b).devices[dev].boost_waitq), \ + .boost_freq = freq \ +} + +static struct df_boost_drv df_boost_drv_g __read_mostly = { + BOOST_DEV_INIT(df_boost_drv_g, DEVFREQ_MSM_LLCCBW_DDR, + CONFIG_DEVFREQ_MSM_LLCCBW_DDR_BOOST_FREQ), + BOOST_DEV_INIT(df_boost_drv_g, DEVFREQ_MSM_CPU_LLCCBW, + CONFIG_DEVFREQ_MSM_CPU_LLCCBW_BOOST_FREQ) +}; + +static void __devfreq_boost_kick(struct boost_dev *b) +{ + if (!READ_ONCE(b->df) || test_bit(SCREEN_OFF, &b->state)) + return; + + set_bit(INPUT_BOOST, &b->state); + if (!mod_delayed_work(system_unbound_wq, &b->input_unboost, + msecs_to_jiffies(CONFIG_DEVFREQ_INPUT_BOOST_DURATION_MS))) + wake_up(&b->boost_waitq); +} + +void devfreq_boost_kick(enum df_device device) +{ + struct df_boost_drv *d = &df_boost_drv_g; + + __devfreq_boost_kick(d->devices + device); +} + +static void __devfreq_boost_kick_max(struct boost_dev *b, + unsigned int duration_ms) +{ + unsigned long boost_jiffies = msecs_to_jiffies(duration_ms); + unsigned long curr_expires, new_expires; + + if (!READ_ONCE(b->df) || test_bit(SCREEN_OFF, &b->state)) + return; + + do { + curr_expires = atomic_long_read(&b->max_boost_expires); + new_expires = jiffies + boost_jiffies; + + /* Skip this boost if there's a longer boost in effect */ + if (time_after(curr_expires, new_expires)) + return; + } while (atomic_long_cmpxchg(&b->max_boost_expires, curr_expires, + new_expires) != curr_expires); + + set_bit(MAX_BOOST, &b->state); + if (!mod_delayed_work(system_unbound_wq, &b->max_unboost, + boost_jiffies)) + wake_up(&b->boost_waitq); +} + +void devfreq_boost_kick_max(enum df_device device, unsigned int duration_ms) +{ + struct df_boost_drv *d = &df_boost_drv_g; + + __devfreq_boost_kick_max(d->devices + device, duration_ms); +} + +void devfreq_register_boost_device(enum df_device device, struct devfreq *df) +{ + struct df_boost_drv *d = &df_boost_drv_g; + struct boost_dev *b; + + df->is_boost_device = true; + b = d->devices + device; + WRITE_ONCE(b->df, df); +} + +static void devfreq_input_unboost(struct work_struct *work) +{ + struct boost_dev *b = container_of(to_delayed_work(work), + typeof(*b), input_unboost); + + clear_bit(INPUT_BOOST, &b->state); + wake_up(&b->boost_waitq); +} + +static void devfreq_max_unboost(struct work_struct *work) +{ + struct boost_dev *b = container_of(to_delayed_work(work), + typeof(*b), max_unboost); + + clear_bit(MAX_BOOST, &b->state); + wake_up(&b->boost_waitq); +} + +static void devfreq_update_boosts(struct boost_dev *b, unsigned long state) +{ + struct devfreq *df = b->df; + + mutex_lock(&df->lock); + if (test_bit(SCREEN_OFF, &state)) { + df->min_freq = df->profile->freq_table[0]; + df->max_boost = false; + } else { + df->min_freq = test_bit(INPUT_BOOST, &state) ? + min(b->boost_freq, df->max_freq) : + df->profile->freq_table[0]; + df->max_boost = test_bit(MAX_BOOST, &state); + } + update_devfreq(df); + mutex_unlock(&df->lock); +} + +static int devfreq_boost_thread(void *data) +{ + static const struct sched_param sched_max_rt_prio = { + .sched_priority = MAX_RT_PRIO - 1 + }; + struct boost_dev *b = data; + unsigned long old_state = 0; + + sched_setscheduler_nocheck(current, SCHED_FIFO, &sched_max_rt_prio); + + while (1) { + bool should_stop = false; + unsigned long curr_state; + + wait_event(b->boost_waitq, + (curr_state = READ_ONCE(b->state)) != old_state || + (should_stop = kthread_should_stop())); + + if (should_stop) + break; + + old_state = curr_state; + devfreq_update_boosts(b, curr_state); + } + + return 0; +} + +static int msm_drm_notifier_cb(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct df_boost_drv *d = container_of(nb, typeof(*d), msm_drm_notif); + int i; + struct msm_drm_notifier *evdata = data; + int *blank = evdata->data; + + /* Parse framebuffer blank events as soon as they occur */ + if (action != MSM_DRM_EARLY_EVENT_BLANK) + return NOTIFY_OK; + + /* Boost when the screen turns on and unboost when it turns off */ + for (i = 0; i < DEVFREQ_MAX; i++) { + struct boost_dev *b = d->devices + i; + + if (*blank == MSM_DRM_BLANK_UNBLANK) { + clear_bit(SCREEN_OFF, &b->state); + __devfreq_boost_kick_max(b, + CONFIG_DEVFREQ_WAKE_BOOST_DURATION_MS); + } else { + set_bit(SCREEN_OFF, &b->state); + wake_up(&b->boost_waitq); + } + } + + return NOTIFY_OK; +} + +static void devfreq_boost_input_event(struct input_handle *handle, + unsigned int type, unsigned int code, + int value) +{ + struct df_boost_drv *d = handle->handler->private; + int i; + + for (i = 0; i < DEVFREQ_MAX; i++) + __devfreq_boost_kick(d->devices + i); +} + +static int devfreq_boost_input_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int ret; + + handle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "devfreq_boost_handle"; + + ret = input_register_handle(handle); + if (ret) + goto free_handle; + + ret = input_open_device(handle); + if (ret) + goto unregister_handle; + + return 0; + +unregister_handle: + input_unregister_handle(handle); +free_handle: + kfree(handle); + return ret; +} + +static void devfreq_boost_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id devfreq_boost_ids[] = { + /* Multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) } + }, + /* Touchpad */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) } + }, + /* Keypad */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) } + }, + { } +}; + +static struct input_handler devfreq_boost_input_handler = { + .event = devfreq_boost_input_event, + .connect = devfreq_boost_input_connect, + .disconnect = devfreq_boost_input_disconnect, + .name = "devfreq_boost_handler", + .id_table = devfreq_boost_ids +}; + +static int __init devfreq_boost_init(void) +{ + struct df_boost_drv *d = &df_boost_drv_g; + struct task_struct *thread[DEVFREQ_MAX]; + int i, ret; + + for (i = 0; i < DEVFREQ_MAX; i++) { + struct boost_dev *b = d->devices + i; + + thread[i] = kthread_run_perf_critical(cpu_perf_mask, + devfreq_boost_thread, b, + "devfreq_boostd/%d", i); + if (IS_ERR(thread[i])) { + ret = PTR_ERR(thread[i]); + pr_err("Failed to create kthread, err: %d\n", ret); + goto stop_kthreads; + } + } + + devfreq_boost_input_handler.private = d; + ret = input_register_handler(&devfreq_boost_input_handler); + if (ret) { + pr_err("Failed to register input handler, err: %d\n", ret); + goto stop_kthreads; + } + + d->msm_drm_notif.notifier_call = msm_drm_notifier_cb; + d->msm_drm_notif.priority = INT_MAX; + ret = msm_drm_register_client(&d->msm_drm_notif); + if (ret) { + pr_err("Failed to register fb notifier, err: %d\n", ret); + goto unregister_handler; + } + + return 0; + +unregister_handler: + input_unregister_handler(&devfreq_boost_input_handler); +stop_kthreads: + while (i--) + kthread_stop(thread[i]); + return ret; +} +late_initcall(devfreq_boost_init); diff --git a/drivers/devfreq/devfreq_devbw.c b/drivers/devfreq/devfreq_devbw.c index af8440bc0ba8..159ff6f3beb7 100644 --- a/drivers/devfreq/devfreq_devbw.c +++ b/drivers/devfreq/devfreq_devbw.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Has to be ULL to prevent overflow where this macro is used. */ #define MBYTE (1ULL << 20) @@ -178,6 +179,12 @@ int devfreq_add_devbw(struct device *dev) msm_bus_scale_unregister_client(d->bus_client); return PTR_ERR(d->df); } + + if (!strcmp(dev_name(dev), "soc:qcom,cpu-llcc-ddr-bw")) + devfreq_register_boost_device(DEVFREQ_MSM_LLCCBW_DDR, d->df); + + if (!strcmp(dev_name(dev), "soc:qcom,cpu-cpu-llcc-bw")) + devfreq_register_boost_device(DEVFREQ_MSM_CPU_LLCCBW, d->df); return 0; } diff --git a/drivers/devfreq/governor_msm_adreno_tz.c b/drivers/devfreq/governor_msm_adreno_tz.c index 3cd103b71c26..cd04f107e8e0 100644 --- a/drivers/devfreq/governor_msm_adreno_tz.c +++ b/drivers/devfreq/governor_msm_adreno_tz.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -413,10 +414,14 @@ static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq) priv->bin.busy_time > CEILING) { val = -1 * level; } else { + unsigned int refresh_rate = dsi_panel_get_refresh_rate(); scm_data[0] = level; scm_data[1] = priv->bin.total_time; - scm_data[2] = priv->bin.busy_time; + if (refresh_rate > 60) + scm_data[2] = priv->bin.busy_time * refresh_rate / 60; + else + scm_data[2] = priv->bin.busy_time; scm_data[3] = context_count; __secure_tz_update_entry3(scm_data, sizeof(scm_data), &val, sizeof(val), priv); diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 3520e6115039..22deb616599e 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -50,6 +50,17 @@ #include static atomic_long_t name_counter; +static struct kmem_cache *kmem_attach_pool; +static struct kmem_cache *kmem_dma_buf_pool; + +void __init init_dma_buf_kmem_pool(void) +{ + kmem_attach_pool = KMEM_CACHE(dma_buf_attachment, SLAB_HWCACHE_ALIGN | SLAB_PANIC); + kmem_dma_buf_pool = kmem_cache_create("dma_buf", + (sizeof(struct dma_buf) + sizeof(struct reservation_object)), + (sizeof(struct dma_buf) + sizeof(struct reservation_object)), + SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); +} static inline int is_dma_buf_file(struct file *); @@ -77,7 +88,10 @@ static void dmabuf_dent_put(struct dma_buf *dmabuf) { if (atomic_dec_and_test(&dmabuf->dent_count)) { kfree(dmabuf->name); - kfree(dmabuf); + if (dmabuf->from_kmem) + kmem_cache_free(kmem_dma_buf_pool, dmabuf); + else + kfree(dmabuf); } } @@ -598,7 +612,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) char *bufname; int ret; long cnt; - pid_t tgid = task_tgid_nr(current); + pid_t tgid = task_tgid_nr(current); + bool from_kmem; if (!exp_info->resv) alloc_size += sizeof(struct reservation_object); @@ -626,7 +641,16 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) goto err_module; } - dmabuf = kzalloc(alloc_size, GFP_KERNEL); + from_kmem = (alloc_size == + (sizeof(struct dma_buf) + sizeof(struct reservation_object))); + + if (from_kmem) { + dmabuf = kmem_cache_zalloc(kmem_dma_buf_pool, GFP_KERNEL); + dmabuf->from_kmem = true; + } else { + dmabuf = kzalloc(alloc_size, GFP_KERNEL); + } + if (!dmabuf) { ret = -ENOMEM; goto err_name; @@ -675,7 +699,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) return dmabuf; err_dmabuf: - kfree(dmabuf); + if (from_kmem) + kmem_cache_free(kmem_dma_buf_pool, dmabuf); + else + kfree(dmabuf); err_name: kfree(bufname); err_module: @@ -784,8 +811,8 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, if (WARN_ON(!dmabuf || !dev)) return ERR_PTR(-EINVAL); - attach = kzalloc(sizeof(*attach), GFP_KERNEL); - if (!attach) + attach = kmem_cache_zalloc(kmem_attach_pool, GFP_KERNEL); + if (attach == NULL) return ERR_PTR(-ENOMEM); attach->dev = dev; @@ -804,7 +831,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, return attach; err_attach: - kfree(attach); + kmem_cache_free(kmem_attach_pool, attach); mutex_unlock(&dmabuf->lock); return ERR_PTR(ret); } @@ -829,7 +856,7 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) dmabuf->ops->detach(dmabuf, attach); mutex_unlock(&dmabuf->lock); - kfree(attach); + kmem_cache_free(kmem_attach_pool, attach); } EXPORT_SYMBOL_GPL(dma_buf_detach); diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 91d620994123..af45dd0e50fb 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -27,12 +27,18 @@ #include static const struct file_operations sync_file_fops; +static struct kmem_cache *kmem_sync_file_pool; + +void __init init_sync_kmem_pool(void) +{ + kmem_sync_file_pool = KMEM_CACHE(sync_file, SLAB_HWCACHE_ALIGN | SLAB_PANIC); +} static struct sync_file *sync_file_alloc(void) { struct sync_file *sync_file; - sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL); + sync_file = kmem_cache_zalloc(kmem_sync_file_pool, GFP_KERNEL); if (!sync_file) return NULL; @@ -48,7 +54,7 @@ static struct sync_file *sync_file_alloc(void) return sync_file; err: - kfree(sync_file); + kmem_cache_free(kmem_sync_file_pool, sync_file); return NULL; } @@ -124,36 +130,6 @@ struct dma_fence *sync_file_get_fence(int fd) } EXPORT_SYMBOL(sync_file_get_fence); -/** - * sync_file_get_name - get the name of the sync_file - * @sync_file: sync_file to get the fence from - * @buf: destination buffer to copy sync_file name into - * @len: available size of destination buffer. - * - * Each sync_file may have a name assigned either by the user (when merging - * sync_files together) or created from the fence it contains. In the latter - * case construction of the name is deferred until use, and so requires - * sync_file_get_name(). - * - * Returns: a string representing the name. - */ -char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len) -{ - if (sync_file->user_name[0]) { - strlcpy(buf, sync_file->user_name, len); - } else { - struct dma_fence *fence = sync_file->fence; - - snprintf(buf, len, "%s-%s%llu-%d", - fence->ops->get_driver_name(fence), - fence->ops->get_timeline_name(fence), - fence->context, - fence->seqno); - } - - return buf; -} - static int sync_file_set_fence(struct sync_file *sync_file, struct dma_fence **fences, int num_fences) { @@ -216,7 +192,7 @@ static void add_fence(struct dma_fence **fences, * @a and @b. @a and @b remain valid, independent sync_file. Returns the * new merged sync_file or NULL in case of error. */ -static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, +static struct sync_file *sync_file_merge(struct sync_file *a, struct sync_file *b) { struct sync_file *sync_file; @@ -291,7 +267,6 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, goto err; } - strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name)); return sync_file; err: @@ -307,7 +282,7 @@ static int sync_file_release(struct inode *inode, struct file *file) if (test_bit(POLL_ENABLED, &sync_file->flags)) dma_fence_remove_callback(sync_file->fence, &sync_file->cb); dma_fence_put(sync_file->fence); - kfree(sync_file); + kmem_cache_free(kmem_sync_file_pool, sync_file); return 0; } @@ -335,11 +310,14 @@ static long sync_file_ioctl_merge(struct sync_file *sync_file, int err; struct sync_file *fence2, *fence3; struct sync_merge_data data; + size_t len; if (fd < 0) return fd; - if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { + arg += offsetof(typeof(data), fd2); + len = sizeof(data) - offsetof(typeof(data), fd2); + if (copy_from_user(&data.fd2, (void __user *)arg, len)) { err = -EFAULT; goto err_put_fd; } @@ -355,15 +333,14 @@ static long sync_file_ioctl_merge(struct sync_file *sync_file, goto err_put_fd; } - data.name[sizeof(data.name) - 1] = '\0'; - fence3 = sync_file_merge(data.name, sync_file, fence2); + fence3 = sync_file_merge(sync_file, fence2); if (!fence3) { err = -ENOMEM; goto err_put_fence2; } data.fence = fd; - if (copy_to_user((void __user *)arg, &data, sizeof(data))) { + if (copy_to_user((void __user *)arg, &data.fd2, len)) { err = -EFAULT; goto err_put_fence3; } @@ -386,11 +363,6 @@ static long sync_file_ioctl_merge(struct sync_file *sync_file, static int sync_fill_fence_info(struct dma_fence *fence, struct sync_fence_info *info) { - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), - sizeof(info->obj_name)); - strlcpy(info->driver_name, fence->ops->get_driver_name(fence), - sizeof(info->driver_name)); - info->status = dma_fence_get_status(fence); while (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) && !test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags)) @@ -407,12 +379,13 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, unsigned long arg) { struct sync_file_info info; - struct sync_fence_info *fence_info = NULL; struct dma_fence **fences; - __u32 size; - int num_fences, ret, i; + size_t len, offset; + int num_fences, i; - if (copy_from_user(&info, (void __user *)arg, sizeof(info))) + arg += offsetof(typeof(info), status); + len = sizeof(info) - offsetof(typeof(info), status); + if (copy_from_user(&info.status, (void __user *)arg, len)) return -EFAULT; if (info.flags || info.pad) @@ -436,35 +409,31 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (info.num_fences < num_fences) return -EINVAL; - size = num_fences * sizeof(*fence_info); - fence_info = kzalloc(size, GFP_KERNEL); - if (!fence_info) - return -ENOMEM; - + offset = offsetof(struct sync_fence_info, status); for (i = 0; i < num_fences; i++) { - int status = sync_fill_fence_info(fences[i], &fence_info[i]); + struct { + __s32 status; + __u32 flags; + __u64 timestamp_ns; + } fence_info; + struct sync_fence_info *finfo = (void *)&fence_info - offset; + int status = sync_fill_fence_info(fences[i], finfo); + u64 dest; + + /* Don't leak kernel memory to userspace via finfo->flags */ + finfo->flags = 0; info.status = info.status <= 0 ? info.status : status; - } - - if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info, - size)) { - ret = -EFAULT; - goto out; + dest = info.sync_fence_info + i * sizeof(*finfo) + offset; + if (copy_to_user(u64_to_user_ptr(dest), &fence_info, + sizeof(fence_info))) + return -EFAULT; } no_fences: - sync_file_get_name(sync_file, info.name, sizeof(info.name)); info.num_fences = num_fences; - - if (copy_to_user((void __user *)arg, &info, sizeof(info))) - ret = -EFAULT; - else - ret = 0; - -out: - kfree(fence_info); - - return ret; + if (copy_to_user((void __user *)arg, &info.status, len)) + return -EFAULT; + return 0; } static long sync_file_ioctl(struct file *file, unsigned int cmd, diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 86427f6ba78c..c52718b37f8f 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1683,9 +1683,11 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - atslave = kzalloc(sizeof(*atslave), GFP_KERNEL); - if (!atslave) + atslave = kmalloc(sizeof(*atslave), GFP_KERNEL); + if (!atslave) { + put_device(&dmac_pdev->dev); return NULL; + } atslave->cfg = ATC_DST_H2SEL_HW | ATC_SRC_H2SEL_HW; /* @@ -1714,8 +1716,11 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec, atslave->dma_dev = &dmac_pdev->dev; chan = dma_request_channel(mask, at_dma_filter, atslave); - if (!chan) + if (!chan) { + put_device(&dmac_pdev->dev); + kfree(atslave); return NULL; + } atchan = to_at_dma_chan(chan); atchan->per_if = dma_spec->args[0] & 0xff; diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 8a52a5efee4f..abf10d894fb6 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1082,6 +1082,9 @@ int dma_async_device_register(struct dma_device *device) dma_channel_rebalance(); mutex_unlock(&dma_list_mutex); + if (!chancnt) + kfree(idr_ref); + return 0; err_out: diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig index 04b9728c1d26..070860ec0ef1 100644 --- a/drivers/dma/dw/Kconfig +++ b/drivers/dma/dw/Kconfig @@ -8,6 +8,7 @@ config DW_DMAC_CORE config DW_DMAC tristate "Synopsys DesignWare AHB DMA platform driver" + depends on HAS_IOMEM select DW_DMAC_CORE help Support the Synopsys DesignWare AHB DMA controller. This @@ -16,6 +17,7 @@ config DW_DMAC config DW_DMAC_PCI tristate "Synopsys DesignWare AHB DMA PCI driver" depends on PCI + depends on HAS_IOMEM select DW_DMAC_CORE help Support the Synopsys DesignWare AHB DMA controller on the diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 1117b5123a6f..e7ca3175dbc3 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1218,6 +1218,7 @@ static int fsldma_of_probe(struct platform_device *op) { struct fsldma_device *fdev; struct device_node *child; + unsigned int i; int err; fdev = kzalloc(sizeof(*fdev), GFP_KERNEL); @@ -1296,6 +1297,10 @@ static int fsldma_of_probe(struct platform_device *op) return 0; out_free_fdev: + for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) { + if (fdev->chan[i]) + fsl_dma_chan_remove(fdev->chan[i]); + } irq_dispose_mapping(fdev->irq); iounmap(fdev->regs); out_free: @@ -1318,6 +1323,7 @@ static int fsldma_of_remove(struct platform_device *op) if (fdev->chan[i]) fsl_dma_chan_remove(fdev->chan[i]); } + irq_dispose_mapping(fdev->irq); iounmap(fdev->regs); kfree(fdev); diff --git a/drivers/dma/hsu/pci.c b/drivers/dma/hsu/pci.c index ad45cd344bba..78836526d2e0 100644 --- a/drivers/dma/hsu/pci.c +++ b/drivers/dma/hsu/pci.c @@ -29,22 +29,12 @@ static irqreturn_t hsu_pci_irq(int irq, void *dev) { struct hsu_dma_chip *chip = dev; - struct pci_dev *pdev = to_pci_dev(chip->dev); u32 dmaisr; u32 status; unsigned short i; int ret = 0; int err; - /* - * On Intel Tangier B0 and Anniedale the interrupt line, disregarding - * to have different numbers, is shared between HSU DMA and UART IPs. - * Thus on such SoCs we are expecting that IRQ handler is called in - * UART driver only. - */ - if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA) - return IRQ_HANDLED; - dmaisr = readl(chip->regs + HSU_PCI_DMAISR); for (i = 0; i < chip->hsu->nr_channels; i++) { if (dmaisr & 0x1) { @@ -108,6 +98,17 @@ static int hsu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_register_irq; + /* + * On Intel Tangier B0 and Anniedale the interrupt line, disregarding + * to have different numbers, is shared between HSU DMA and UART IPs. + * Thus on such SoCs we are expecting that IRQ handler is called in + * UART driver only. Instead of handling the spurious interrupt + * from HSU DMA here and waste CPU time and delay HSU UART interrupt + * handling, disable the interrupt entirely. + */ + if (pdev->device == PCI_DEVICE_ID_INTEL_MRFLD_HSU_DMA) + disable_irq_nosync(chip->irq); + pci_set_drvdata(pdev, chip); return 0; diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c index fca232b1d4a6..1d44b02831a0 100644 --- a/drivers/dma/mediatek/mtk-hsdma.c +++ b/drivers/dma/mediatek/mtk-hsdma.c @@ -1007,6 +1007,7 @@ static int mtk_hsdma_probe(struct platform_device *pdev) return 0; err_free: + mtk_hsdma_hw_deinit(hsdma); of_dma_controller_free(pdev->dev.of_node); err_unregister: dma_async_device_unregister(dd); diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c index 8dc0aa4d73ab..462adf7e4e95 100644 --- a/drivers/dma/mv_xor_v2.c +++ b/drivers/dma/mv_xor_v2.c @@ -777,8 +777,10 @@ static int mv_xor_v2_probe(struct platform_device *pdev) goto disable_clk; msi_desc = first_msi_entry(&pdev->dev); - if (!msi_desc) + if (!msi_desc) { + ret = -ENODEV; goto free_msi_irqs; + } xor_dev->msi_desc = msi_desc; ret = devm_request_irq(&pdev->dev, msi_desc->irq, diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c index 7ff04bf04b31..da5050ab7f38 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -932,6 +932,7 @@ static int owl_dma_remove(struct platform_device *pdev) owl_dma_free(od); clk_disable_unprepare(od->clk); + dma_pool_destroy(od->lli_pool); return 0; } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index c564df713efc..15b30d2d8f7e 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2774,7 +2774,7 @@ pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, * If burst size is smaller than bus width then make sure we only * transfer one at a time to avoid a burst stradling an MFIFO entry. */ - if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width) + if (burst * 8 < pl330->pcfg.data_bus_width) desc->rqcfg.brst_len = 1; desc->bytes_requested = len; diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index d56b6b0e22a8..0c5668e897fe 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -453,8 +453,8 @@ struct xilinx_dma_device { #define to_dma_tx_descriptor(tx) \ container_of(tx, struct xilinx_dma_tx_descriptor, async_tx) #define xilinx_dma_poll_timeout(chan, reg, val, cond, delay_us, timeout_us) \ - readl_poll_timeout(chan->xdev->regs + chan->ctrl_offset + reg, val, \ - cond, delay_us, timeout_us) + readl_poll_timeout_atomic(chan->xdev->regs + chan->ctrl_offset + reg, \ + val, cond, delay_us, timeout_us) /* IO accessors */ static inline u32 dma_read(struct xilinx_dma_chan *chan, u32 reg) @@ -2426,7 +2426,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, has_dre = false; if (!has_dre) - xdev->common.copy_align = fls(width - 1); + xdev->common.copy_align = (enum dmaengine_alignment)fls(width - 1); if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel") || of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") || @@ -2529,7 +2529,8 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev, static int xilinx_dma_child_probe(struct xilinx_dma_device *xdev, struct device_node *node) { - int ret, i, nr_channels = 1; + int ret, i; + u32 nr_channels = 1; ret = of_property_read_u32(node, "dma-channels", &nr_channels); if ((ret < 0) && xdev->mcdma) @@ -2713,7 +2714,11 @@ static int xilinx_dma_probe(struct platform_device *pdev) } /* Register the DMA engine with the core */ - dma_async_device_register(&xdev->common); + err = dma_async_device_register(&xdev->common); + if (err) { + dev_err(xdev->dev, "failed to register the dma device\n"); + goto error; + } err = of_dma_controller_register(node, of_dma_xilinx_xlate, xdev); diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index cbe415853197..fe25c98380ad 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -18,6 +18,9 @@ static struct msr __percpu *msrs; /* Per-node stuff */ static struct ecc_settings **ecc_stngs; +/* Device for the PCI component */ +static struct device *pci_ctl_dev; + /* * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching- @@ -2563,6 +2566,9 @@ reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2) return -ENODEV; } + if (!pci_ctl_dev) + pci_ctl_dev = &pvt->F0->dev; + edac_dbg(1, "F0: %s\n", pci_name(pvt->F0)); edac_dbg(1, "F3: %s\n", pci_name(pvt->F3)); edac_dbg(1, "F6: %s\n", pci_name(pvt->F6)); @@ -2587,6 +2593,9 @@ reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 pci_id1, u16 pci_id2) return -ENODEV; } + if (!pci_ctl_dev) + pci_ctl_dev = &pvt->F2->dev; + edac_dbg(1, "F1: %s\n", pci_name(pvt->F1)); edac_dbg(1, "F2: %s\n", pci_name(pvt->F2)); edac_dbg(1, "F3: %s\n", pci_name(pvt->F3)); @@ -3441,21 +3450,10 @@ static void remove_one_instance(unsigned int nid) static void setup_pci_device(void) { - struct mem_ctl_info *mci; - struct amd64_pvt *pvt; - if (pci_ctl) return; - mci = edac_mc_find(0); - if (!mci) - return; - - pvt = mci->pvt_info; - if (pvt->umc) - pci_ctl = edac_pci_create_generic_ctl(&pvt->F0->dev, EDAC_MOD_STR); - else - pci_ctl = edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); + pci_ctl = edac_pci_create_generic_ctl(pci_ctl_dev, EDAC_MOD_STR); if (!pci_ctl) { pr_warn("%s(): Unable to create PCI control\n", __func__); pr_warn("%s(): PCI error report via EDAC not set\n", __func__); @@ -3535,6 +3533,8 @@ static int __init amd64_edac_init(void) return 0; err_pci: + pci_ctl_dev = NULL; + msrs_free(msrs); msrs = NULL; @@ -3566,6 +3566,8 @@ static void __exit amd64_edac_exit(void) kfree(ecc_stngs); ecc_stngs = NULL; + pci_ctl_dev = NULL; + msrs_free(msrs); msrs = NULL; } diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index 227651ff9666..c221a0aec0f3 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c @@ -1275,4 +1275,4 @@ module_platform_driver(max77693_muic_driver); MODULE_DESCRIPTION("Maxim MAX77693 Extcon driver"); MODULE_AUTHOR("Chanwoo Choi "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:extcon-max77693"); +MODULE_ALIAS("platform:max77693-muic"); diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 35ef9cd78a46..4b68aa9ac9ca 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -1314,6 +1314,7 @@ int extcon_dev_register(struct extcon_dev *edev) sizeof(*edev->nh), GFP_KERNEL); if (!edev->nh) { ret = -ENOMEM; + device_unregister(&edev->dev); goto err_dev; } @@ -1324,8 +1325,10 @@ int extcon_dev_register(struct extcon_dev *edev) goto err_dev; } - for (index = 0; index < edev->max_supported; index++) + for (index = 0; index < edev->max_supported; index++) { RAW_INIT_NOTIFIER_HEAD(&edev->nh[index]); + BLOCKING_INIT_NOTIFIER_HEAD(&edev->bnh[index]); + } RAW_INIT_NOTIFIER_HEAD(&edev->nh_all); diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index a128dd1126ae..ac85e03e88e1 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -359,6 +359,7 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct client *client = file->private_data; spinlock_t *client_list_lock = &client->lynx->client_list_lock; struct nosy_stats stats; + int ret; switch (cmd) { case NOSY_IOC_GET_STATS: @@ -373,11 +374,15 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case NOSY_IOC_START: + ret = -EBUSY; spin_lock_irq(client_list_lock); - list_add_tail(&client->link, &client->lynx->client_list); + if (list_empty(&client->link)) { + list_add_tail(&client->link, &client->lynx->client_list); + ret = 0; + } spin_unlock_irq(client_list_lock); - return 0; + return ret; case NOSY_IOC_STOP: spin_lock_irq(client_list_lock); diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 4935cda5301e..4f1af323ec03 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -599,7 +599,7 @@ static int sprd_eic_probe(struct platform_device *pdev) */ res = platform_get_resource(pdev, IORESOURCE_MEM, i); if (!res) - continue; + break; sprd_eic->base[i] = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(sprd_eic->base[i])) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index adc768f908f1..874caed72390 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -650,9 +650,8 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, spin_lock_irqsave(&mvpwm->lock, flags); - val = (unsigned long long) - readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); - val *= NSEC_PER_SEC; + u = readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm)); + val = (unsigned long long) u * NSEC_PER_SEC; do_div(val, mvpwm->clk_rate); if (val > UINT_MAX) state->duty_cycle = UINT_MAX; @@ -661,21 +660,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip, else state->duty_cycle = 1; - val = (unsigned long long) - readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); + val = (unsigned long long) u; /* on duration */ + /* period = on + off duration */ + val += readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm)); val *= NSEC_PER_SEC; do_div(val, mvpwm->clk_rate); - if (val < state->duty_cycle) { + if (val > UINT_MAX) + state->period = UINT_MAX; + else if (val) + state->period = val; + else state->period = 1; - } else { - val -= state->duty_cycle; - if (val > UINT_MAX) - state->period = UINT_MAX; - else if (val) - state->period = val; - else - state->period = 1; - } regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u); if (u) @@ -1191,6 +1186,13 @@ static int mvebu_gpio_probe(struct platform_device *pdev) devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip); + /* Some MVEBU SoCs have simple PWM support for GPIO lines */ + if (IS_ENABLED(CONFIG_PWM)) { + err = mvebu_pwm_probe(pdev, mvchip, id); + if (err) + return err; + } + /* Some gpio controllers do not provide irq support */ if (!have_irqs) return 0; @@ -1200,7 +1202,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev) if (!mvchip->domain) { dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", mvchip->chip.label); - return -ENODEV; + err = -ENODEV; + goto err_pwm; } err = irq_alloc_domain_generic_chips( @@ -1248,14 +1251,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev) mvchip); } - /* Some MVEBU SoCs have simple PWM support for GPIO lines */ - if (IS_ENABLED(CONFIG_PWM)) - return mvebu_pwm_probe(pdev, mvchip, id); - return 0; err_domain: irq_domain_remove(mvchip->domain); +err_pwm: + pwmchip_remove(&mvchip->mvpwm->chip); return err; } diff --git a/drivers/gpio/gpio-pcf857x.c b/drivers/gpio/gpio-pcf857x.c index 68a35b65925a..d3fcc0d15eb8 100644 --- a/drivers/gpio/gpio-pcf857x.c +++ b/drivers/gpio/gpio-pcf857x.c @@ -357,7 +357,7 @@ static int pcf857x_probe(struct i2c_client *client, * reset state. Otherwise it flags pins to be driven low. */ gpio->out = ~n_latch; - gpio->status = gpio->out; + gpio->status = gpio->read(gpio->client); status = devm_gpiochip_add_data(&client->dev, &gpio->chip, gpio); if (status < 0) diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c index f953541e7890..634125747a03 100644 --- a/drivers/gpio/gpio-pcie-idio-24.c +++ b/drivers/gpio/gpio-pcie-idio-24.c @@ -28,6 +28,47 @@ #include #include +/* + * PLX PEX8311 PCI LCS_INTCSR Interrupt Control/Status + * + * Bit: Description + * 0: Enable Interrupt Sources (Bit 0) + * 1: Enable Interrupt Sources (Bit 1) + * 2: Generate Internal PCI Bus Internal SERR# Interrupt + * 3: Mailbox Interrupt Enable + * 4: Power Management Interrupt Enable + * 5: Power Management Interrupt + * 6: Slave Read Local Data Parity Check Error Enable + * 7: Slave Read Local Data Parity Check Error Status + * 8: Internal PCI Wire Interrupt Enable + * 9: PCI Express Doorbell Interrupt Enable + * 10: PCI Abort Interrupt Enable + * 11: Local Interrupt Input Enable + * 12: Retry Abort Enable + * 13: PCI Express Doorbell Interrupt Active + * 14: PCI Abort Interrupt Active + * 15: Local Interrupt Input Active + * 16: Local Interrupt Output Enable + * 17: Local Doorbell Interrupt Enable + * 18: DMA Channel 0 Interrupt Enable + * 19: DMA Channel 1 Interrupt Enable + * 20: Local Doorbell Interrupt Active + * 21: DMA Channel 0 Interrupt Active + * 22: DMA Channel 1 Interrupt Active + * 23: Built-In Self-Test (BIST) Interrupt Active + * 24: Direct Master was the Bus Master during a Master or Target Abort + * 25: DMA Channel 0 was the Bus Master during a Master or Target Abort + * 26: DMA Channel 1 was the Bus Master during a Master or Target Abort + * 27: Target Abort after internal 256 consecutive Master Retrys + * 28: PCI Bus wrote data to LCS_MBOX0 + * 29: PCI Bus wrote data to LCS_MBOX1 + * 30: PCI Bus wrote data to LCS_MBOX2 + * 31: PCI Bus wrote data to LCS_MBOX3 + */ +#define PLX_PEX8311_PCI_LCS_INTCSR 0x68 +#define INTCSR_INTERNAL_PCI_WIRE BIT(8) +#define INTCSR_LOCAL_INPUT BIT(11) + /** * struct idio_24_gpio_reg - GPIO device registers structure * @out0_7: Read: FET Outputs 0-7 @@ -92,6 +133,7 @@ struct idio_24_gpio_reg { struct idio_24_gpio { struct gpio_chip chip; raw_spinlock_t lock; + __u8 __iomem *plx; struct idio_24_gpio_reg __iomem *reg; unsigned long irq_mask; }; @@ -360,13 +402,13 @@ static void idio_24_irq_mask(struct irq_data *data) unsigned long flags; const unsigned long bit_offset = irqd_to_hwirq(data) - 24; unsigned char new_irq_mask; - const unsigned long bank_offset = bit_offset/8 * 8; + const unsigned long bank_offset = bit_offset / 8; unsigned char cos_enable_state; raw_spin_lock_irqsave(&idio24gpio->lock, flags); - idio24gpio->irq_mask &= BIT(bit_offset); - new_irq_mask = idio24gpio->irq_mask >> bank_offset; + idio24gpio->irq_mask &= ~BIT(bit_offset); + new_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; if (!new_irq_mask) { cos_enable_state = ioread8(&idio24gpio->reg->cos_enable); @@ -389,12 +431,12 @@ static void idio_24_irq_unmask(struct irq_data *data) unsigned long flags; unsigned char prev_irq_mask; const unsigned long bit_offset = irqd_to_hwirq(data) - 24; - const unsigned long bank_offset = bit_offset/8 * 8; + const unsigned long bank_offset = bit_offset / 8; unsigned char cos_enable_state; raw_spin_lock_irqsave(&idio24gpio->lock, flags); - prev_irq_mask = idio24gpio->irq_mask >> bank_offset; + prev_irq_mask = idio24gpio->irq_mask >> bank_offset * 8; idio24gpio->irq_mask |= BIT(bit_offset); if (!prev_irq_mask) { @@ -481,6 +523,7 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) struct device *const dev = &pdev->dev; struct idio_24_gpio *idio24gpio; int err; + const size_t pci_plx_bar_index = 1; const size_t pci_bar_index = 2; const char *const name = pci_name(pdev); @@ -494,12 +537,13 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) return err; } - err = pcim_iomap_regions(pdev, BIT(pci_bar_index), name); + err = pcim_iomap_regions(pdev, BIT(pci_plx_bar_index) | BIT(pci_bar_index), name); if (err) { dev_err(dev, "Unable to map PCI I/O addresses (%d)\n", err); return err; } + idio24gpio->plx = pcim_iomap_table(pdev)[pci_plx_bar_index]; idio24gpio->reg = pcim_iomap_table(pdev)[pci_bar_index]; idio24gpio->chip.label = name; @@ -520,6 +564,12 @@ static int idio_24_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Software board reset */ iowrite8(0, &idio24gpio->reg->soft_reset); + /* + * enable PLX PEX8311 internal PCI wire interrupt and local interrupt + * input + */ + iowrite8((INTCSR_INTERNAL_PCI_WIRE | INTCSR_LOCAL_INPUT) >> 8, + idio24gpio->plx + PLX_PEX8311_PCI_LCS_INTCSR + 1); err = devm_gpiochip_add_data(dev, &idio24gpio->chip, idio24gpio); if (err) { diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 18f5973b9697..4ad34c6803ad 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -177,7 +177,7 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio, int ret, value; ret = request_threaded_irq(event->irq, NULL, event->handler, - event->irqflags, "ACPI:Event", event); + event->irqflags | IRQF_ONESHOT, "ACPI:Event", event); if (ret) { dev_err(acpi_gpio->chip->parent, "Failed to setup interrupt handler for %d\n", diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 3dbaf489a8a5..e0ccc79b239a 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -462,6 +462,8 @@ static ssize_t export_store(struct class *class, long gpio; struct gpio_desc *desc; int status; + struct gpio_chip *gc; + int offset; status = kstrtol(buf, 0, &gpio); if (status < 0) @@ -473,6 +475,12 @@ static ssize_t export_store(struct class *class, pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); return -EINVAL; } + gc = desc->gdev->chip; + offset = gpio_chip_hwgpio(desc); + if (!gpiochip_line_is_valid(gc, offset)) { + pr_warn("%s: GPIO %ld masked\n", __func__, gpio); + return -EINVAL; + } /* No extra locking here; FLAG_SYSFS just signifies that the * request and export were done by on behalf of userspace, so diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 2aeddd0c68b1..ab909515b3fa 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -193,6 +193,7 @@ source "drivers/gpu/drm/arm/Kconfig" config DRM_RADEON tristate "ATI Radeon" depends on DRM && PCI && MMU + depends on AGP || !AGP select FW_LOADER select DRM_KMS_HELPER select DRM_TTM diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index a90e83e5ab57..ee4a0b7cb452 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -239,7 +239,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, while (size) { uint32_t value; - value = RREG32_PCIE(*pos >> 2); + value = RREG32_PCIE(*pos); r = put_user(value, (uint32_t *)buf); if (r) return r; @@ -282,7 +282,7 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user if (r) return r; - WREG32_PCIE(*pos >> 2, value); + WREG32_PCIE(*pos, value); result += 4; buf += 4; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index e63a253eb425..cbb969a870f6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -617,7 +617,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) { int ret; - long level; + unsigned long level; char *sub_str = NULL; char *tmp; char buf_cpy[AMDGPU_MASK_BUF_MAX + 1]; @@ -633,8 +633,8 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) while (tmp[0]) { sub_str = strsep(&tmp, delimiter); if (strlen(sub_str)) { - ret = kstrtol(sub_str, 0, &level); - if (ret) + ret = kstrtoul(sub_str, 0, &level); + if (ret || level > 31) return -EINVAL; *mask |= 1 << level; } else diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h index 7206a0025b17..db9907fb99f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h @@ -21,7 +21,7 @@ * */ -#if !defined(_AMDGPU_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#if !defined(_AMDGPU_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) #define _AMDGPU_TRACE_H_ #include diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f67c332b16a4..6a1f5df4bc07 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2076,8 +2076,8 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, uint64_t eaddr; /* validate the parameters */ - if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK || - size == 0 || size & AMDGPU_GPU_PAGE_MASK) + if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || + size == 0 || size & ~PAGE_MASK) return -EINVAL; /* make sure object fit at this offset */ @@ -2141,8 +2141,8 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, int r; /* validate the parameters */ - if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK || - size == 0 || size & AMDGPU_GPU_PAGE_MASK) + if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || + size == 0 || size & ~PAGE_MASK) return -EINVAL; /* make sure object fit at this offset */ @@ -2286,7 +2286,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, after->start = eaddr + 1; after->last = tmp->last; after->offset = tmp->offset; - after->offset += after->start - tmp->start; + after->offset += (after->start - tmp->start) << PAGE_SHIFT; after->flags = tmp->flags; after->bo_va = tmp->bo_va; list_add(&after->list, &tmp->bo_va->invalids); diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c index d0fa2aac2388..ca66c2f79758 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c @@ -1086,22 +1086,19 @@ static int cik_sdma_soft_reset(void *handle) { u32 srbm_soft_reset = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - u32 tmp = RREG32(mmSRBM_STATUS2); + u32 tmp; - if (tmp & SRBM_STATUS2__SDMA_BUSY_MASK) { - /* sdma0 */ - tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET); - tmp |= SDMA0_F32_CNTL__HALT_MASK; - WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp); - srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK; - } - if (tmp & SRBM_STATUS2__SDMA1_BUSY_MASK) { - /* sdma1 */ - tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET); - tmp |= SDMA0_F32_CNTL__HALT_MASK; - WREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET, tmp); - srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK; - } + /* sdma0 */ + tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET); + tmp |= SDMA0_F32_CNTL__HALT_MASK; + WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp); + srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK; + + /* sdma1 */ + tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET); + tmp |= SDMA0_F32_CNTL__HALT_MASK; + WREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET, tmp); + srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA1_MASK; if (srbm_soft_reset) { tmp = RREG32(mmSRBM_SOFT_RESET); 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 3b07a316680c..62a2f0491117 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -668,8 +668,8 @@ static void emulated_link_detect(struct dc_link *link) link->type = dc_connection_none; prev_sink = link->local_sink; - if (prev_sink != NULL) - dc_sink_retain(prev_sink); + if (prev_sink) + dc_sink_release(prev_sink); switch (link->connector_signal) { case SIGNAL_TYPE_HDMI_TYPE_A: { @@ -4732,14 +4732,14 @@ static int dm_force_atomic_commit(struct drm_connector *connector) ret = PTR_ERR_OR_ZERO(conn_state); if (ret) - goto err; + goto out; /* Attach crtc to drm_atomic_state*/ crtc_state = drm_atomic_get_crtc_state(state, &disconnected_acrtc->base); ret = PTR_ERR_OR_ZERO(crtc_state); if (ret) - goto err; + goto out; /* force a restore */ crtc_state->mode_changed = true; @@ -4749,17 +4749,15 @@ static int dm_force_atomic_commit(struct drm_connector *connector) ret = PTR_ERR_OR_ZERO(plane_state); if (ret) - goto err; - + goto out; /* Call commit internally with the state we just constructed */ ret = drm_atomic_commit(state); - if (!ret) - return 0; -err: - DRM_ERROR("Restoring old state failed with %i\n", ret); +out: drm_atomic_state_put(state); + if (ret) + DRM_ERROR("Restoring old state failed with %i\n", ret); return ret; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fa0e6c8e2447..e3bedf4cc9c0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1124,6 +1124,11 @@ static bool construct( goto ddc_create_fail; } + if (!link->ddc->ddc_pin) { + DC_ERROR("Failed to get I2C info for connector!\n"); + goto ddc_create_fail; + } + link->ddc_hw_inst = dal_ddc_get_line( dal_ddc_service_get_ddc_pin(link->ddc)); diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c index ab63d0d0304c..6fd57cfb112f 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_transform.c @@ -429,12 +429,12 @@ static void set_clamp( clamp_max = 0x3FC0; break; case COLOR_DEPTH_101010: - /* 10bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ - clamp_max = 0x3FFC; + /* 10bit MSB aligned on 14 bit bus '11 1111 1111 0000' */ + clamp_max = 0x3FF0; break; case COLOR_DEPTH_121212: - /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1111' */ - clamp_max = 0x3FFF; + /* 12bit MSB aligned on 14 bit bus '11 1111 1111 1100' */ + clamp_max = 0x3FFC; break; default: clamp_max = 0x3FC0; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 058898b321b8..d8e624d64ae3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -1531,6 +1531,10 @@ int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr) PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to reset to default!", result = tmp_result); + tmp_result = smum_stop_smc(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop smc!", result = tmp_result); + tmp_result = smu7_force_switch_to_arbf0(hwmgr); PP_ASSERT_WITH_CODE((tmp_result == 0), "Failed to force to switch arbf0!", result = tmp_result); diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 6ee864455a12..f59e1e737735 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -216,6 +216,7 @@ struct pp_smumgr_func { bool (*is_hw_avfs_present)(struct pp_hwmgr *hwmgr); int (*update_dpm_settings)(struct pp_hwmgr *hwmgr, void *profile_setting); int (*smc_table_manager)(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); /*rw: true for read, false for write */ + int (*stop_smc)(struct pp_hwmgr *hwmgr); }; struct pp_hwmgr_func { diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index 82550a8a3a3f..ef4f2392e2e7 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -113,4 +113,6 @@ extern int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_settin extern int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); +extern int smum_stop_smc(struct pp_hwmgr *hwmgr); + #endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c index db87cb8930d2..c05bec5effb2 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -2723,10 +2723,7 @@ static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) { - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, - VOLTAGE_CONTROLLER_ON)) - ? true : false; + return ci_is_smc_ram_running(hwmgr); } static int ci_smu_init(struct pp_hwmgr *hwmgr) @@ -2934,6 +2931,29 @@ static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) return 0; } +static void ci_reset_smc(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, + rst_reg, 1); +} + + +static void ci_stop_smc_clock(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, + ck_disable, 1); +} + +static int ci_stop_smc(struct pp_hwmgr *hwmgr) +{ + ci_reset_smc(hwmgr); + ci_stop_smc_clock(hwmgr); + + return 0; +} + const struct pp_smumgr_func ci_smu_funcs = { .smu_init = ci_smu_init, .smu_fini = ci_smu_fini, @@ -2957,4 +2977,5 @@ const struct pp_smumgr_func ci_smu_funcs = { .is_dpm_running = ci_is_dpm_running, .update_dpm_settings = ci_update_dpm_settings, .update_smc_table = ci_update_smc_table, + .stop_smc = ci_stop_smc, }; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c index a6edd5df33b0..20ecf994d47f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -213,3 +213,11 @@ int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t tabl return -EINVAL; } + +int smum_stop_smc(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->smumgr_funcs->stop_smc) + return hwmgr->smumgr_funcs->stop_smc(hwmgr); + + return 0; +} diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index cb3cc5a2d2ef..ab7d4ee84d3a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -30,8 +30,10 @@ #include #include #include +#include #include #include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -1706,27 +1708,6 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state, struct drm_connector *connector = conn_state->connector; struct drm_crtc_state *crtc_state; - /* - * For compatibility with legacy users, we want to make sure that - * we allow DPMS On<->Off modesets on unregistered connectors, since - * legacy modesetting users will not be expecting these to fail. We do - * not however, want to allow legacy users to assign a connector - * that's been unregistered from sysfs to another CRTC, since doing - * this with a now non-existent connector could potentially leave us - * in an invalid state. - * - * Since the connector can be unregistered at any point during an - * atomic check or commit, this is racy. But that's OK: all we care - * about is ensuring that userspace can't use this connector for new - * configurations after it's been notified that the connector is no - * longer present. - */ - if (!READ_ONCE(connector->registered) && crtc) { - DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n", - connector->base.id, connector->name); - return -EINVAL; - } - if (conn_state->crtc == crtc) return 0; @@ -2556,8 +2537,8 @@ static void complete_signaling(struct drm_device *dev, kfree(fence_state); } -int drm_mode_atomic_ioctl(struct drm_device *dev, - void *data, struct drm_file *file_priv) +static int __drm_mode_atomic_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_mode_atomic *arg = data; uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr); @@ -2597,6 +2578,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) return -EINVAL; + if (!(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) { + devfreq_boost_kick(DEVFREQ_MSM_CPU_LLCCBW); + devfreq_boost_kick(DEVFREQ_MSM_LLCCBW_DDR); + } + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); state = drm_atomic_state_alloc(dev); @@ -2713,3 +2699,25 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, return ret; } + +int drm_mode_atomic_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + /* + * Optimistically assume the current task won't migrate to another CPU + * and restrict the current CPU to shallow idle states so that it won't + * take too long to finish running the ioctl whenever the ioctl runs a + * command that sleeps, such as for an "atomic" commit. + */ + struct pm_qos_request req = { + .type = PM_QOS_REQ_AFFINE_CORES, + .cpus_affine = ATOMIC_INIT(BIT(raw_smp_processor_id())) + }; + int ret; + + pm_qos_add_request(&req, PM_QOS_CPU_DMA_LATENCY, 100); + ret = __drm_mode_atomic_ioctl(dev, data, file_priv); + pm_qos_remove_request(&req); + + return ret; +} diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index e2350dc56372..cbd5a29d751e 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -307,6 +307,26 @@ update_connector_routing(struct drm_atomic_state *state, return 0; } + crtc_state = drm_atomic_get_new_crtc_state(state, + new_connector_state->crtc); + /* + * For compatibility with legacy users, we want to make sure that + * we allow DPMS On->Off modesets on unregistered connectors. Modesets + * which would result in anything else must be considered invalid, to + * avoid turning on new displays on dead connectors. + * + * Since the connector can be unregistered at any point during an + * atomic check or commit, this is racy. But that's OK: all we care + * about is ensuring that userspace can't do anything but shut off the + * display on a connector that was destroyed after its been notified, + * not before. + */ + if (drm_connector_is_unregistered(connector) && crtc_state->active) { + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n", + connector->base.id, connector->name); + return -EINVAL; + } + funcs = connector->helper_private; if (funcs->atomic_best_encoder) @@ -351,7 +371,6 @@ update_connector_routing(struct drm_atomic_state *state, set_best_encoder(state, new_connector_state, new_encoder); - crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc); crtc_state->connectors_changed = true; DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", @@ -2920,7 +2939,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set, ret = handle_conflicting_encoders(state, true); if (ret) - return ret; + goto fail; ret = drm_atomic_commit(state); diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 42111d7bb18e..4c7a821d6fca 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -392,7 +392,8 @@ void drm_connector_cleanup(struct drm_connector *connector) /* The connector should have been removed from userspace long before * it is finally destroyed. */ - if (WARN_ON(connector->registered)) + if (WARN_ON(connector->registration_state == + DRM_CONNECTOR_REGISTERED)) drm_connector_unregister(connector); if (connector->tile_group) { @@ -449,7 +450,7 @@ int drm_connector_register(struct drm_connector *connector) return 0; mutex_lock(&connector->mutex); - if (connector->registered) + if (connector->registration_state != DRM_CONNECTOR_INITIALIZING) goto unlock; ret = drm_sysfs_connector_add(connector); @@ -469,7 +470,7 @@ int drm_connector_register(struct drm_connector *connector) drm_mode_object_register(connector->dev, &connector->base); - connector->registered = true; + connector->registration_state = DRM_CONNECTOR_REGISTERED; goto unlock; err_debugfs: @@ -491,7 +492,7 @@ EXPORT_SYMBOL(drm_connector_register); void drm_connector_unregister(struct drm_connector *connector) { mutex_lock(&connector->mutex); - if (!connector->registered) { + if (connector->registration_state != DRM_CONNECTOR_REGISTERED) { mutex_unlock(&connector->mutex); return; } @@ -502,7 +503,7 @@ void drm_connector_unregister(struct drm_connector *connector) drm_sysfs_connector_remove(connector); drm_debugfs_connector_remove(connector); - connector->registered = false; + connector->registration_state = DRM_CONNECTOR_UNREGISTERED; mutex_unlock(&connector->mutex); } EXPORT_SYMBOL(drm_connector_unregister); diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c index 0e4f25d63fd2..0b11210c882e 100644 --- a/drivers/gpu/drm/drm_dp_aux_dev.c +++ b/drivers/gpu/drm/drm_dp_aux_dev.c @@ -60,7 +60,7 @@ static struct drm_dp_aux_dev *drm_dp_aux_dev_get_by_minor(unsigned index) mutex_lock(&aux_idr_mutex); aux_dev = idr_find(&aux_idr, index); - if (!kref_get_unless_zero(&aux_dev->refcount)) + if (aux_dev && !kref_get_unless_zero(&aux_dev->refcount)) aux_dev = NULL; mutex_unlock(&aux_idr_mutex); diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 5e253f597798..fc937c0b1a0f 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2881,11 +2881,11 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, { int ret; - port = drm_dp_get_validated_port_ref(mgr, port); - if (!port) + if (slots < 0) return false; - if (slots < 0) + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) return false; if (port->vcpi.vcpi > 0) { @@ -2900,6 +2900,7 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, if (ret) { DRM_DEBUG_KMS("failed to init vcpi slots=%d max=63 ret=%d\n", DIV_ROUND_UP(pbn, mgr->pbn_div), ret); + drm_dp_put_port(port); goto out; } DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n", diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index f8672238d444..ab8847c7dd96 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -96,6 +96,8 @@ static int compat_drm_version(struct file *file, unsigned int cmd, if (copy_from_user(&v32, (void __user *)arg, sizeof(v32))) return -EFAULT; + memset(&v, 0, sizeof(v)); + v = (struct drm_version) { .name_len = v32.name_len, .name = compat_ptr(v32.name), @@ -134,6 +136,9 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, if (copy_from_user(&uq32, (void __user *)arg, sizeof(uq32))) return -EFAULT; + + memset(&uq, 0, sizeof(uq)); + uq = (struct drm_unique){ .unique_len = uq32.unique_len, .unique = compat_ptr(uq32.unique), @@ -260,6 +265,8 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, if (copy_from_user(&c32, argp, sizeof(c32))) return -EFAULT; + memset(&client, 0, sizeof(client)); + client.idx = c32.idx; err = drm_ioctl_kernel(file, drm_getclient, &client, DRM_UNLOCKED); @@ -842,6 +849,8 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, if (copy_from_user(&req32, argp, sizeof(req32))) return -EFAULT; + memset(&req, 0, sizeof(req)); + req.request.type = req32.request.type; req.request.sequence = req32.request.sequence; req.request.signal = req32.request.signal; @@ -879,6 +888,8 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd, struct drm_mode_fb_cmd2 req64; int err; + memset(&req64, 0, sizeof(req64)); + if (copy_from_user(&req64, argp, offsetof(drm_mode_fb_cmd232_t, modifier))) return -EFAULT; diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 3b04c25100ae..3ac2a58424d0 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -101,7 +101,7 @@ int drm_irq_install(struct drm_device *dev, int irq) { int ret; - unsigned long sh_flags = 0; + unsigned long sh_flags = IRQF_PRIME_AFFINE; if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 05eba6dec5eb..3e8b804cf7e7 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -2124,7 +2124,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev DRM_INFO("failed to retrieve link info, disabling eDP\n"); cdv_intel_dp_encoder_destroy(encoder); cdv_intel_dp_destroy(connector); - goto err_priv; + goto err_connector; } else { DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n", intel_dp->dpcd[0], intel_dp->dpcd[1], diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c index e28107061148..fc9a34ed58bd 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi_i2c.c @@ -279,11 +279,8 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev) hdmi_dev = pci_get_drvdata(dev); i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); - if (i2c_dev == NULL) { - DRM_ERROR("Can't allocate interface\n"); - ret = -ENOMEM; - goto exit; - } + if (!i2c_dev) + return -ENOMEM; i2c_dev->adap = &oaktrail_hdmi_i2c_adapter; i2c_dev->status = I2C_STAT_INIT; @@ -300,16 +297,23 @@ int oaktrail_hdmi_i2c_init(struct pci_dev *dev) oaktrail_hdmi_i2c_adapter.name, hdmi_dev); if (ret) { DRM_ERROR("Failed to request IRQ for I2C controller\n"); - goto err; + goto free_dev; } /* Adapter registration */ ret = i2c_add_numbered_adapter(&oaktrail_hdmi_i2c_adapter); - return ret; + if (ret) { + DRM_ERROR("Failed to add I2C adapter\n"); + goto free_irq; + } -err: + return 0; + +free_irq: + free_irq(dev->irq, hdmi_dev); +free_dev: kfree(i2c_dev); -exit: + return ret; } diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index ac32ab5aa002..2fa3c7fc4b6d 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -316,6 +316,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_err; + ret = -ENOMEM; + dev_priv->mmu = psb_mmu_driver_init(dev, 1, 0, 0); if (!dev_priv->mmu) goto out_err; diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 78eb10902809..076b6da44f46 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -350,6 +350,7 @@ int psb_irq_postinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; + unsigned int i; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); @@ -362,20 +363,12 @@ int psb_irq_postinstall(struct drm_device *dev) PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank[0].enabled) - psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank[1].enabled) - psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank[2].enabled) - psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); - else - psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + for (i = 0; i < dev->num_crtcs; ++i) { + if (dev->vblank[i].enabled) + psb_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); + else + psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); + } if (dev_priv->ops->hotplug_enable) dev_priv->ops->hotplug_enable(dev, true); @@ -388,6 +381,7 @@ void psb_irq_uninstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = dev->dev_private; unsigned long irqflags; + unsigned int i; spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); @@ -396,14 +390,10 @@ void psb_irq_uninstall(struct drm_device *dev) PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); - if (dev->vblank[0].enabled) - psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank[1].enabled) - psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); - - if (dev->vblank[2].enabled) - psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); + for (i = 0; i < dev->num_crtcs; ++i) { + if (dev->vblank[i].enabled) + psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); + } dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | _PSB_IRQ_MSVDX_FLAG | diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 52894816167c..8b5b147cdfd1 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -380,7 +380,7 @@ eb_vma_misplaced(const struct drm_i915_gem_exec_object2 *entry, return true; if (!(flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) && - (vma->node.start + vma->node.size - 1) >> 32) + (vma->node.start + vma->node.size + 4095) >> 32) return true; if (flags & __EXEC_OBJECT_NEEDS_MAP && diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index c7d52c66ff29..8a19cfcfc4f1 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, pipe_config->pbn = mst_pbn; /* Zombie connectors can't have VCPI slots */ - if (READ_ONCE(connector->registered)) { + if (!drm_connector_is_unregistered(connector)) { slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, port, @@ -317,7 +317,7 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) struct edid *edid; int ret; - if (!READ_ONCE(connector->registered)) + if (drm_connector_is_unregistered(connector)) return intel_connector_update_modes(connector, NULL); edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); @@ -333,7 +333,7 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force) struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dp *intel_dp = intel_connector->mst_port; - if (!READ_ONCE(connector->registered)) + if (drm_connector_is_unregistered(connector)) return connector_status_disconnected; return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, intel_connector->port); @@ -376,7 +376,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, int bpp = 24; /* MST uses fixed bpp */ int max_rate, mode_rate, max_lanes, max_link_clock; - if (!READ_ONCE(connector->registered)) + if (drm_connector_is_unregistered(connector)) return MODE_ERROR; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 127d81513671..ec01f51437d5 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -170,7 +170,7 @@ static int igt_ppgtt_alloc(void *arg) * This should ensure that we do not run into the oomkiller during * the test and take down the machine wilfully. */ - limit = totalram_pages << PAGE_SHIFT; + limit = totalram_pages() << PAGE_SHIFT; limit = min(ppgtt->vm.total, limit); /* Check we can allocate the entire range */ @@ -1244,7 +1244,7 @@ static int exercise_mock(struct drm_i915_private *i915, u64 hole_start, u64 hole_end, unsigned long end_time)) { - const u64 limit = totalram_pages << PAGE_SHIFT; + const u64 limit = totalram_pages() << PAGE_SHIFT; struct i915_gem_context *ctx; struct i915_hw_ppgtt *ppgtt; IGT_TIMEOUT(end_time); diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 221a8cbc57f9..a4dba034dca4 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -206,6 +206,11 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder) int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); + if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { + dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); + return; + } + drm_panel_prepare(imx_ldb_ch->panel); if (dual) { @@ -264,6 +269,11 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder, int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); u32 bus_format = imx_ldb_ch->bus_format; + if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { + dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); + return; + } + if (mode->clock > 170000) { dev_warn(ldb->dev, "%s: mode exceeds 170 MHz pixel clock\n", __func__); diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 588b3b0c8315..25b06771f238 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -384,6 +384,16 @@ static int meson_probe_remote(struct platform_device *pdev, return count; } +static void meson_drv_shutdown(struct platform_device *pdev) +{ + struct meson_drm *priv = dev_get_drvdata(&pdev->dev); + struct drm_device *drm = priv->drm; + + DRM_DEBUG_DRIVER("\n"); + drm_kms_helper_poll_fini(drm); + drm_atomic_helper_shutdown(drm); +} + static int meson_drv_probe(struct platform_device *pdev) { struct component_match *match = NULL; @@ -428,6 +438,7 @@ MODULE_DEVICE_TABLE(of, dt_match); static struct platform_driver meson_drm_platform_driver = { .probe = meson_drv_probe, + .shutdown = meson_drv_shutdown, .driver = { .name = "meson-drm", .of_match_table = dt_match, diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index d29a58bd2f7a..ba513018534e 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -681,8 +681,6 @@ static int a5xx_hw_init(struct msm_gpu *gpu) if (adreno_gpu->info->quirks & ADRENO_QUIRK_TWO_PASS_USE_WFI) gpu_rmw(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0, (1 << 8)); - gpu_write(gpu, REG_A5XX_PC_DBG_ECO_CNTL, 0xc0200100); - /* Enable USE_RETENTION_FLOPS */ gpu_write(gpu, REG_A5XX_CP_CHICKEN_DBG, 0x02000000); @@ -1196,8 +1194,8 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu) static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { - *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO, - REG_A5XX_RBBM_PERFCTR_CP_0_HI); + *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO, + REG_A5XX_RBBM_ALWAYSON_COUNTER_HI); return 0; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index c629f742a1d1..c280fdc44939 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -713,8 +713,8 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) /* Force the GPU power on so we can read this register */ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); - *value = gpu_read64(gpu, REG_A6XX_RBBM_PERFCTR_CP_0_LO, - REG_A6XX_RBBM_PERFCTR_CP_0_HI); + *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, + REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_GPU_SET); return 0; diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c index 1ca6c69516f5..4c037d855b27 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_20nm.c @@ -147,7 +147,7 @@ const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs = { .disable = dsi_20nm_phy_disable, .init = msm_dsi_phy_init_common, }, - .io_start = { 0xfd998300, 0xfd9a0300 }, + .io_start = { 0xfd998500, 0xfd9a0500 }, .num_dsi_phy = 2, }; diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c index 21a69b046625..d15511b521cb 100644 --- a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c +++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_10nm.c @@ -554,6 +554,7 @@ static int dsi_pll_10nm_restore_state(struct msm_dsi_pll *pll) struct pll_10nm_cached_state *cached = &pll_10nm->cached_state; void __iomem *phy_base = pll_10nm->phy_cmn_mmio; u32 val; + int ret; val = pll_read(pll_10nm->mmio + REG_DSI_10nm_PHY_PLL_PLL_OUTDIV_RATE); val &= ~0x3; @@ -568,6 +569,13 @@ static int dsi_pll_10nm_restore_state(struct msm_dsi_pll *pll) val |= cached->pll_mux; pll_write(phy_base + REG_DSI_10nm_PHY_CMN_CLK_CFG1, val); + ret = dsi_pll_10nm_vco_set_rate(&pll->clk_hw, pll_10nm->vco_current_rate, pll_10nm->vco_ref_clk_rate); + if (ret) { + DRM_DEV_ERROR(&pll_10nm->pdev->dev, + "restore vco rate failed. ret=%d\n", ret); + return ret; + } + DBG("DSI PLL%d", pll_10nm->id); return 0; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index e11299869677..fc602ece335d 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -485,14 +485,14 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) drm_mode_config_init(ddev); - /* Bind all our sub-components: */ - ret = component_bind_all(dev, ddev); + ret = msm_init_vram(ddev); if (ret) goto err_destroy_mdss; - ret = msm_init_vram(ddev); + /* Bind all our sub-components: */ + ret = component_bind_all(dev, ddev); if (ret) - goto err_msm_uninit; + goto err_destroy_mdss; if (!dev->dma_parms) { dev->dma_parms = devm_kzalloc(dev, sizeof(*dev->dma_parms), @@ -1378,6 +1378,10 @@ static int msm_pdev_remove(struct platform_device *pdev) static void msm_pdev_shutdown(struct platform_device *pdev) { struct drm_device *drm = platform_get_drvdata(pdev); + struct msm_drm_private *priv = drm ? drm->dev_private : NULL; + + if (!priv || !priv->kms) + return; drm_atomic_helper_shutdown(drm); } @@ -1398,6 +1402,7 @@ static struct platform_driver msm_platform_driver = { .name = "msm", .of_match_table = dt_match, .pm = &msm_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index 349c12f670eb..6c11be79574e 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -56,7 +56,7 @@ int msm_wait_fence(struct msm_fence_context *fctx, uint32_t fence, int ret; if (fence > fctx->last_fence) { - DRM_ERROR("%s: waiting on invalid fence: %u (of %u)\n", + DRM_ERROR_RATELIMITED("%s: waiting on invalid fence: %u (of %u)\n", fctx->name, fence, fctx->last_fence); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 1bb0a9f6fa73..fbe156302ee8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -131,7 +131,7 @@ nv50_dmac_destroy(struct nv50_dmac *dmac) int nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, - const s32 *oclass, u8 head, void *data, u32 size, u64 syncbuf, + const s32 *oclass, u8 head, void *data, u32 size, s64 syncbuf, struct nv50_dmac *dmac) { struct nouveau_cli *cli = (void *)device->object.client; @@ -166,7 +166,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, if (ret) return ret; - if (!syncbuf) + if (syncbuf < 0) return 0; ret = nvif_object_init(&dmac->base.user, 0xf0000000, NV_DMA_IN_MEMORY, diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.h b/drivers/gpu/drm/nouveau/dispnv50/disp.h index 66c125a6b0b3..55205d23360c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.h @@ -68,7 +68,7 @@ struct nv50_dmac { int nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, const s32 *oclass, u8 head, void *data, u32 size, - u64 syncbuf, struct nv50_dmac *dmac); + s64 syncbuf, struct nv50_dmac *dmac); void nv50_dmac_destroy(struct nv50_dmac *); u32 *evo_wait(struct nv50_dmac *, int nr); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c index f7dbd965e4e7..b49a212af4d8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c @@ -68,7 +68,7 @@ wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, int ret; ret = nv50_dmac_create(&drm->client.device, &disp->disp->object, - &oclass, 0, &args, sizeof(args), 0, + &oclass, 0, &args, sizeof(args), -1, &wndw->wimm); if (ret) { NV_ERROR(drm, "wimm%04x allocation failed: %d\n", oclass, ret); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c index 7deb81b6dbac..4b571cc6bc70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c @@ -75,7 +75,7 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd) nvkm_debug(subdev, "%08x: type %02x, %d bytes\n", image.base, image.type, image.size); - if (!shadow_fetch(bios, mthd, image.size)) { + if (!shadow_fetch(bios, mthd, image.base + image.size)) { nvkm_debug(subdev, "%08x: fetch failed\n", image.base); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c index edb6148cbca0..d0e80ad52684 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/auxgm200.c @@ -33,7 +33,7 @@ static void gm200_i2c_aux_fini(struct gm200_i2c_aux *aux) { struct nvkm_device *device = aux->base.pad->i2c->subdev.device; - nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00310000, 0x00000000); + nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00710000, 0x00000000); } static int @@ -54,10 +54,10 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux) AUX_ERR(&aux->base, "begin idle timeout %08x", ctrl); return -EBUSY; } - } while (ctrl & 0x03010000); + } while (ctrl & 0x07010000); /* set some magic, and wait up to 1ms for it to appear */ - nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00300000, ureq); + nvkm_mask(device, 0x00d954 + (aux->ch * 0x50), 0x00700000, ureq); timeout = 1000; do { ctrl = nvkm_rd32(device, 0x00d954 + (aux->ch * 0x50)); @@ -67,7 +67,7 @@ gm200_i2c_aux_init(struct gm200_i2c_aux *aux) gm200_i2c_aux_fini(aux); return -EBUSY; } - } while ((ctrl & 0x03000000) != urep); + } while ((ctrl & 0x07000000) != urep); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c index d80dbc8f09b2..55a4ea4393c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include static void gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i) @@ -31,7 +32,6 @@ gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i) u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0400)); u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0400)); nvkm_debug(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat); - nvkm_mask(device, 0x122128 + (i * 0x0400), 0x00000200, 0x00000000); } static void @@ -42,7 +42,6 @@ gf100_ibus_intr_rop(struct nvkm_subdev *ibus, int i) u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0400)); u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0400)); nvkm_debug(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat); - nvkm_mask(device, 0x124128 + (i * 0x0400), 0x00000200, 0x00000000); } static void @@ -53,7 +52,6 @@ gf100_ibus_intr_gpc(struct nvkm_subdev *ibus, int i) u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0400)); u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0400)); nvkm_debug(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat); - nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000); } void @@ -90,6 +88,12 @@ gf100_ibus_intr(struct nvkm_subdev *ibus) intr1 &= ~stat; } } + + nvkm_mask(device, 0x121c4c, 0x0000003f, 0x00000002); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x121c4c) & 0x0000003f)) + break; + ); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c index 9025ed1bd2a9..4caf3ef087e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk104.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "priv.h" +#include static void gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i) @@ -31,7 +32,6 @@ gk104_ibus_intr_hub(struct nvkm_subdev *ibus, int i) u32 data = nvkm_rd32(device, 0x122124 + (i * 0x0800)); u32 stat = nvkm_rd32(device, 0x122128 + (i * 0x0800)); nvkm_debug(ibus, "HUB%d: %06x %08x (%08x)\n", i, addr, data, stat); - nvkm_mask(device, 0x122128 + (i * 0x0800), 0x00000200, 0x00000000); } static void @@ -42,7 +42,6 @@ gk104_ibus_intr_rop(struct nvkm_subdev *ibus, int i) u32 data = nvkm_rd32(device, 0x124124 + (i * 0x0800)); u32 stat = nvkm_rd32(device, 0x124128 + (i * 0x0800)); nvkm_debug(ibus, "ROP%d: %06x %08x (%08x)\n", i, addr, data, stat); - nvkm_mask(device, 0x124128 + (i * 0x0800), 0x00000200, 0x00000000); } static void @@ -53,7 +52,6 @@ gk104_ibus_intr_gpc(struct nvkm_subdev *ibus, int i) u32 data = nvkm_rd32(device, 0x128124 + (i * 0x0800)); u32 stat = nvkm_rd32(device, 0x128128 + (i * 0x0800)); nvkm_debug(ibus, "GPC%d: %06x %08x (%08x)\n", i, addr, data, stat); - nvkm_mask(device, 0x128128 + (i * 0x0800), 0x00000200, 0x00000000); } void @@ -90,6 +88,12 @@ gk104_ibus_intr(struct nvkm_subdev *ibus) intr1 &= ~stat; } } + + nvkm_mask(device, 0x12004c, 0x0000003f, 0x00000002); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x12004c) & 0x0000003f)) + break; + ); } static int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c index ee11ccaf0563..cb51e248cb41 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c @@ -316,9 +316,9 @@ nvkm_mmu_vram(struct nvkm_mmu *mmu) { struct nvkm_device *device = mmu->subdev.device; struct nvkm_mm *mm = &device->fb->ram->vram; - const u32 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL); - const u32 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP); - const u32 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED); + const u64 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL); + const u64 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP); + const u64 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED); u8 type = NVKM_MEM_KIND * !!mmu->func->kind; u8 heap = NVKM_MEM_VRAM; int heapM, heapN, heapU; diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index e884183c018a..cb5ce73f7269 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c @@ -763,6 +763,7 @@ static int omap_dmm_probe(struct platform_device *dev) &omap_dmm->refill_pa, GFP_KERNEL); if (!omap_dmm->refill_va) { dev_err(&dev->dev, "could not allocate refill memory\n"); + ret = -ENOMEM; goto fail; } diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c index 31875b636434..5073622cbb56 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c @@ -140,6 +140,7 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, phy_node = of_parse_phandle(dev->of_node, "phys", 0); if (!phy_node) { dev_err(dev, "Can't found PHY phandle\n"); + ret = -EINVAL; goto err_disable_clk_tmds; } diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 965088afcfad..03adb4cf325b 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1670,6 +1670,11 @@ static void tegra_dc_commit_state(struct tegra_dc *dc, dev_err(dc->dev, "failed to set clock rate to %lu Hz\n", state->pclk); + + err = clk_set_rate(dc->clk, state->pclk); + if (err < 0) + dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n", + dc->clk, state->pclk, err); } DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk), @@ -1680,11 +1685,6 @@ static void tegra_dc_commit_state(struct tegra_dc *dc, value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1; tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); } - - err = clk_set_rate(dc->clk, state->pclk); - if (err < 0) - dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n", - dc->clk, state->pclk, err); } static void tegra_dc_stop(struct tegra_dc *dc) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index a2bd5876c633..00808a3d6783 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -242,7 +242,7 @@ static int tegra_drm_open(struct drm_device *drm, struct drm_file *filp) if (!fpriv) return -ENOMEM; - idr_init(&fpriv->contexts); + idr_init_base(&fpriv->contexts, 1); mutex_init(&fpriv->lock); filp->driver_priv = fpriv; diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 89cb70da2bfe..83108e243050 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -2668,17 +2668,23 @@ static int tegra_sor_init(struct host1x_client *client) if (err < 0) { dev_err(sor->dev, "failed to deassert SOR reset: %d\n", err); + clk_disable_unprepare(sor->clk); return err; } } err = clk_prepare_enable(sor->clk_safe); - if (err < 0) + if (err < 0) { + clk_disable_unprepare(sor->clk); return err; + } err = clk_prepare_enable(sor->clk_dp); - if (err < 0) + if (err < 0) { + clk_disable_unprepare(sor->clk_safe); + clk_disable_unprepare(sor->clk); return err; + } return 0; } diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index ac344ddb23bc..f93384c23206 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -223,8 +223,8 @@ static int tve200_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (!irq) { - ret = -EINVAL; + if (irq < 0) { + ret = irq; goto clk_disable; } diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 6b6d5ab82ec3..1f6c91496d93 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -410,7 +410,7 @@ static int xen_drm_drv_dumb_create(struct drm_file *filp, args->size = args->pitch * args->height; obj = xen_drm_front_gem_create(dev, args->size); - if (IS_ERR_OR_NULL(obj)) { + if (IS_ERR(obj)) { ret = PTR_ERR(obj); goto fail; } diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index 802662839e7e..cba7852123d6 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -85,7 +85,7 @@ static struct xen_gem_object *gem_create(struct drm_device *dev, size_t size) size = round_up(size, PAGE_SIZE); xen_obj = gem_create_obj(dev, size); - if (IS_ERR_OR_NULL(xen_obj)) + if (IS_ERR(xen_obj)) return xen_obj; if (drm_info->front_info->cfg.be_alloc) { @@ -119,7 +119,7 @@ static struct xen_gem_object *gem_create(struct drm_device *dev, size_t size) */ xen_obj->num_pages = DIV_ROUND_UP(size, PAGE_SIZE); xen_obj->pages = drm_gem_get_pages(&xen_obj->base); - if (IS_ERR_OR_NULL(xen_obj->pages)) { + if (IS_ERR(xen_obj->pages)) { ret = PTR_ERR(xen_obj->pages); xen_obj->pages = NULL; goto fail; @@ -138,7 +138,7 @@ struct drm_gem_object *xen_drm_front_gem_create(struct drm_device *dev, struct xen_gem_object *xen_obj; xen_obj = gem_create(dev, size); - if (IS_ERR_OR_NULL(xen_obj)) + if (IS_ERR(xen_obj)) return ERR_CAST(xen_obj); return &xen_obj->base; @@ -196,7 +196,7 @@ xen_drm_front_gem_import_sg_table(struct drm_device *dev, size = attach->dmabuf->size; xen_obj = gem_create_obj(dev, size); - if (IS_ERR_OR_NULL(xen_obj)) + if (IS_ERR(xen_obj)) return ERR_CAST(xen_obj); ret = gem_alloc_pages_array(xen_obj, size); diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c b/drivers/gpu/drm/xen/xen_drm_front_kms.c index a3479eb72d79..d9700c69e5b7 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_kms.c +++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c @@ -59,7 +59,7 @@ fb_create(struct drm_device *dev, struct drm_file *filp, int ret; fb = drm_gem_fb_create_with_funcs(dev, filp, mode_cmd, &fb_funcs); - if (IS_ERR_OR_NULL(fb)) + if (IS_ERR(fb)) return fb; gem_obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile index 8165e688dcd3..4ad59bcb7ff3 100644 --- a/drivers/gpu/msm/Makefile +++ b/drivers/gpu/msm/Makefile @@ -32,13 +32,8 @@ msm_adreno-y += \ adreno_snapshot.o \ adreno_coresight.o \ adreno_trace.o \ - adreno_a3xx.o \ - adreno_a5xx.o \ adreno_a6xx.o \ - adreno_a3xx_snapshot.o \ - adreno_a5xx_snapshot.o \ adreno_a6xx_snapshot.o \ - adreno_a5xx_preempt.o \ adreno_a6xx_preempt.o \ adreno_a6xx_gmu.o \ adreno_a6xx_rgmu.o \ diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h index 7fd704bce7a2..8369ca8d5a17 100644 --- a/drivers/gpu/msm/adreno-gpulist.h +++ b/drivers/gpu/msm/adreno-gpulist.h @@ -15,597 +15,6 @@ static const struct adreno_gpu_core adreno_gpu_core_##_name = { \ .features = ADRENO_DEPRECATED, \ } -static const struct adreno_reglist a306_vbif_regs[] = { - { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, - { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000A }, - { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000A }, -}; - -static const struct adreno_a3xx_core adreno_gpu_core_a306 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A306, 3, 0, 6, 0), - .features = ADRENO_SOFT_FAULT_DETECT, - .gpudev = &adreno_a3xx_gpudev, - .gmem_size = SZ_128K, - .busy_mask = 0x7ffffffe, - .bus_width = 0, - }, - .pm4fw_name = "a300_pm4.fw", - .pfpfw_name = "a300_pfp.fw", - .vbif = a306_vbif_regs, - .vbif_count = ARRAY_SIZE(a306_vbif_regs), -}; - -static const struct adreno_reglist a306a_vbif_regs[] = { - { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, - { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000010 }, - { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000010 }, -}; - -static const struct adreno_a3xx_core adreno_gpu_core_a306a = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A306A, 3, 0, 6, 0x20), - .features = ADRENO_SOFT_FAULT_DETECT, - .gpudev = &adreno_a3xx_gpudev, - .gmem_size = SZ_128K, - .busy_mask = 0x7ffffffe, - .bus_width = 16, - }, - .pm4fw_name = "a300_pm4.fw", - .pfpfw_name = "a300_pfp.fw", - .vbif = a306a_vbif_regs, - .vbif_count = ARRAY_SIZE(a306a_vbif_regs), -}; - -static const struct adreno_reglist a304_vbif_regs[] = { - { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, -}; - -static const struct adreno_a3xx_core adreno_gpu_core_a304 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A304, 3, 0, 4, 0), - .features = ADRENO_SOFT_FAULT_DETECT, - .gpudev = &adreno_a3xx_gpudev, - .gmem_size = (SZ_64K + SZ_32K), - .busy_mask = 0x7ffffffe, - .bus_width = 0, - }, - .pm4fw_name = "a300_pm4.fw", - .pfpfw_name = "a300_pfp.fw", - .vbif = a304_vbif_regs, - .vbif_count = ARRAY_SIZE(a304_vbif_regs), -}; - -DEFINE_DEPRECATED_CORE(a405, ADRENO_REV_A405, 4, 0, 5, ANY_ID); -DEFINE_DEPRECATED_CORE(a418, ADRENO_REV_A418, 4, 1, 8, ANY_ID); -DEFINE_DEPRECATED_CORE(a420, ADRENO_REV_A420, 4, 2, 0, ANY_ID); -DEFINE_DEPRECATED_CORE(a430, ADRENO_REV_A430, 4, 3, 0, ANY_ID); -DEFINE_DEPRECATED_CORE(a530v1, ADRENO_REV_A530, 5, 3, 0, 0); - -static const struct adreno_reglist a530_hwcg_regs[] = { - {A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220}, - {A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080}, - {A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777}, - {A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111}, - {A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, - {A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444}, - {A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, - {A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222}, - {A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011}, - {A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, - {A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, - {A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, - {A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, - {A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, - {A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, - {A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, -}; - -/* VBIF control registers for a530, a510, a508, a505 and a506 */ -static const struct adreno_reglist a530_vbif_regs[] = { - {A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003}, -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a530v2 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A530, 5, 3, 0, 1), - .features = ADRENO_GPMU | ADRENO_SPTP_PC | ADRENO_LM | - ADRENO_PREEMPTION | ADRENO_64BIT | - ADRENO_CONTENT_PROTECTION, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, - .bus_width = 32, - }, - .gpmu_tsens = 0x00060007, - .max_power = 5448, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .gpmufw_name = "a530_gpmu.fw2", - .regfw_name = "a530v2_seq.fw2", - .zap_name = "a530_zap", - .hwcg = a530_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a530_hwcg_regs), - .vbif = a530_vbif_regs, - .vbif_count = ARRAY_SIZE(a530_vbif_regs), -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a530v3 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A530, 5, 3, 0, ANY_ID), - .features = ADRENO_GPMU | ADRENO_SPTP_PC | ADRENO_LM | - ADRENO_PREEMPTION | ADRENO_64BIT | - ADRENO_CONTENT_PROTECTION, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, - .bus_width = 32, - }, - .gpmu_tsens = 0x00060007, - .max_power = 5448, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .gpmufw_name = "a530v3_gpmu.fw2", - .regfw_name = "a530v3_seq.fw2", - .zap_name = "a530_zap", - .hwcg = a530_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a530_hwcg_regs), - .vbif = a530_vbif_regs, - .vbif_count = ARRAY_SIZE(a530_vbif_regs), -}; - -/* For a505, a506 and a508 */ -static const struct adreno_reglist a50x_hwcg_regs[] = { - {A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, - {A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, - {A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777}, - {A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111}, - {A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_HYST_UCHE, 0x00FFFFF4}, - {A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, - {A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222}, - {A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011}, - {A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, - {A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, - {A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, - {A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, - {A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, - {A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, - {A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222} -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a505 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A505, 5, 0, 5, ANY_ID), - .features = ADRENO_PREEMPTION | ADRENO_64BIT, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, - .bus_width = 16, - }, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .hwcg = a50x_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a50x_hwcg_regs), - .vbif = a530_vbif_regs, - .vbif_count = ARRAY_SIZE(a530_vbif_regs), -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a506 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A506, 5, 0, 6, ANY_ID), - .features = ADRENO_PREEMPTION | ADRENO_64BIT | - ADRENO_CONTENT_PROTECTION | ADRENO_CPZ_RETENTION, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, - .bus_width = 16, - }, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .zap_name = "a506_zap", - .hwcg = a50x_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a50x_hwcg_regs), - .vbif = a530_vbif_regs, - .vbif_count = ARRAY_SIZE(a530_vbif_regs), -}; - -static const struct adreno_reglist a510_hwcg_regs[] = { - {A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220}, - {A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080}, - {A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777}, - {A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111}, - {A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, - {A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444}, - {A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, - {A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222}, - {A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011}, - {A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, - {A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, - {A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, - {A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, - {A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, - {A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, - {A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a510 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A510, 5, 1, 0, ANY_ID), - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = SZ_256K, - .busy_mask = 0xfffffffe, - .bus_width = 16, - }, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .hwcg = a510_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a510_hwcg_regs), - .vbif = a530_vbif_regs, - .vbif_count = ARRAY_SIZE(a530_vbif_regs), -}; - -DEFINE_DEPRECATED_CORE(a540v1, ADRENO_REV_A540, 5, 4, 0, 0); - -static const struct adreno_reglist a540_hwcg_regs[] = { - {A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP2, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP3, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP2, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP3, 0x02222220}, - {A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP2, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP3, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP2, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP3, 0x00000080}, - {A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP2, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP3, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP2, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP3, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP2, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP3, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP2, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP3, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP2, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP3, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP2, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP3, 0x00007777}, - {A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP2, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP3, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP2, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP3, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP2, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP3, 0x00001111}, - {A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, - {A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444}, - {A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, - {A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB2, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB3, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB2, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB3, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU2, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU3, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222}, - {A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU2, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU3, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_2, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_3, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011}, - {A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, - {A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, - {A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, - {A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, - {A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, - {A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, - {A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_GPMU, 0x00000222}, - {A5XX_RBBM_CLOCK_DELAY_GPMU, 0x00000770}, - {A5XX_RBBM_CLOCK_HYST_GPMU, 0x00000004}, -}; - -static const struct adreno_reglist a540_vbif_regs[] = { - {A5XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003}, - {A5XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000009}, -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a540v2 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A540, 5, 4, 0, ANY_ID), - .features = ADRENO_PREEMPTION | ADRENO_64BIT | - ADRENO_CONTENT_PROTECTION | - ADRENO_GPMU | ADRENO_SPTP_PC, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = SZ_1M, - .busy_mask = 0xfffffffe, - .bus_width = 32, - }, - .gpmu_tsens = 0x000c000d, - .max_power = 5448, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .gpmufw_name = "a540_gpmu.fw2", - .zap_name = "a540_zap", - .hwcg = a540_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a540_hwcg_regs), - .vbif = a540_vbif_regs, - .vbif_count = ARRAY_SIZE(a540_vbif_regs), -}; - -static const struct adreno_reglist a512_hwcg_regs[] = { - {A5XX_RBBM_CLOCK_CNTL_SP0, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL_SP1, 0x02222222}, - {A5XX_RBBM_CLOCK_CNTL2_SP0, 0x02222220}, - {A5XX_RBBM_CLOCK_CNTL2_SP1, 0x02222220}, - {A5XX_RBBM_CLOCK_HYST_SP0, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_HYST_SP1, 0x0000F3CF}, - {A5XX_RBBM_CLOCK_DELAY_SP0, 0x00000080}, - {A5XX_RBBM_CLOCK_DELAY_SP1, 0x00000080}, - {A5XX_RBBM_CLOCK_CNTL_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_TP1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_TP0, 0x00002222}, - {A5XX_RBBM_CLOCK_CNTL3_TP1, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP0, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST2_TP1, 0x77777777}, - {A5XX_RBBM_CLOCK_HYST3_TP0, 0x00007777}, - {A5XX_RBBM_CLOCK_HYST3_TP1, 0x00007777}, - {A5XX_RBBM_CLOCK_DELAY_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP0, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY2_TP1, 0x11111111}, - {A5XX_RBBM_CLOCK_DELAY3_TP0, 0x00001111}, - {A5XX_RBBM_CLOCK_DELAY3_TP1, 0x00001111}, - {A5XX_RBBM_CLOCK_CNTL_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL3_UCHE, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL4_UCHE, 0x00222222}, - {A5XX_RBBM_CLOCK_HYST_UCHE, 0x00444444}, - {A5XX_RBBM_CLOCK_DELAY_UCHE, 0x00000002}, - {A5XX_RBBM_CLOCK_CNTL_RB0, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL_RB1, 0x22222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB0, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL2_RB1, 0x00222222}, - {A5XX_RBBM_CLOCK_CNTL_CCU0, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_CCU1, 0x00022220}, - {A5XX_RBBM_CLOCK_CNTL_RAC, 0x05522222}, - {A5XX_RBBM_CLOCK_CNTL2_RAC, 0x00505555}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU0, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RB_CCU1, 0x04040404}, - {A5XX_RBBM_CLOCK_HYST_RAC, 0x07444044}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_0, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RB_CCU_L1_1, 0x00000002}, - {A5XX_RBBM_CLOCK_DELAY_RAC, 0x00010011}, - {A5XX_RBBM_CLOCK_CNTL_TSE_RAS_RBBM, 0x04222222}, - {A5XX_RBBM_CLOCK_MODE_GPC, 0x02222222}, - {A5XX_RBBM_CLOCK_MODE_VFD, 0x00002222}, - {A5XX_RBBM_CLOCK_HYST_TSE_RAS_RBBM, 0x00000000}, - {A5XX_RBBM_CLOCK_HYST_GPC, 0x04104004}, - {A5XX_RBBM_CLOCK_HYST_VFD, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_HLSQ, 0x00000000}, - {A5XX_RBBM_CLOCK_DELAY_TSE_RAS_RBBM, 0x00004000}, - {A5XX_RBBM_CLOCK_DELAY_GPC, 0x00000200}, - {A5XX_RBBM_CLOCK_DELAY_VFD, 0x00002222}, -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a512 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A512, 5, 1, 2, ANY_ID), - .features = ADRENO_PREEMPTION | ADRENO_64BIT | - ADRENO_CONTENT_PROTECTION | ADRENO_CPZ_RETENTION, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = (SZ_256K + SZ_16K), - .busy_mask = 0xfffffffe, - .bus_width = 32, - }, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .zap_name = "a512_zap", - .hwcg = a512_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a512_hwcg_regs), -}; - -static const struct adreno_a5xx_core adreno_gpu_core_a508 = { - .base = { - DEFINE_ADRENO_REV(ADRENO_REV_A508, 5, 0, 8, ANY_ID), - .features = ADRENO_PREEMPTION | ADRENO_64BIT | - ADRENO_CONTENT_PROTECTION | ADRENO_CPZ_RETENTION, - .gpudev = &adreno_a5xx_gpudev, - .gmem_size = (SZ_128K + SZ_8K), - .busy_mask = 0xfffffffe, - .bus_width = 32, - }, - .pm4fw_name = "a530_pm4.fw", - .pfpfw_name = "a530_pfp.fw", - .zap_name = "a508_zap", - .hwcg = a50x_hwcg_regs, - .hwcg_count = ARRAY_SIZE(a50x_hwcg_regs), - .vbif = a530_vbif_regs, - .vbif_count = ARRAY_SIZE(a530_vbif_regs), -}; - DEFINE_DEPRECATED_CORE(a630v1, ADRENO_REV_A630, 6, 3, 0, 0); static const struct adreno_reglist a630_hwcg_regs[] = { @@ -1479,23 +888,6 @@ static const struct adreno_a6xx_core adreno_gpu_core_a702 = { }; static const struct adreno_gpu_core *adreno_gpulist[] = { - &adreno_gpu_core_a306.base, - &adreno_gpu_core_a306a.base, - &adreno_gpu_core_a304.base, - &adreno_gpu_core_a405, /* Deprecated */ - &adreno_gpu_core_a418, /* Deprecated */ - &adreno_gpu_core_a420, /* Deprecated */ - &adreno_gpu_core_a430, /* Deprecated */ - &adreno_gpu_core_a530v1, /* Deprecated */ - &adreno_gpu_core_a530v2.base, - &adreno_gpu_core_a530v3.base, - &adreno_gpu_core_a505.base, - &adreno_gpu_core_a506.base, - &adreno_gpu_core_a510.base, - &adreno_gpu_core_a540v1, /* Deprecated */ - &adreno_gpu_core_a540v2.base, - &adreno_gpu_core_a512.base, - &adreno_gpu_core_a508.base, &adreno_gpu_core_a630v1, /* Deprecated */ &adreno_gpu_core_a630v2.base, &adreno_gpu_core_a615.base, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 957abd446ec7..58af0a1d3558 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1026,7 +1026,6 @@ static void adreno_of_get_initial_pwrlevel(struct adreno_device *adreno_dev, init_level = 1; pwr->active_pwrlevel = init_level; - pwr->default_pwrlevel = init_level; } static void adreno_of_get_limits(struct adreno_device *adreno_dev, @@ -1199,11 +1198,6 @@ static int adreno_of_get_power(struct adreno_device *adreno_dev, &device->pwrctrl.pm_qos_active_latency)) device->pwrctrl.pm_qos_active_latency = 501; - /* get pm-qos-cpu-mask-latency, set it to default if not found */ - if (of_property_read_u32(node, "qcom,l2pc-cpu-mask-latency", - &device->pwrctrl.pm_qos_cpu_mask_latency)) - device->pwrctrl.pm_qos_cpu_mask_latency = 501; - /* get pm-qos-wakeup-latency, set it to default if not found */ if (of_property_read_u32(node, "qcom,pm-qos-wakeup-latency", &device->pwrctrl.pm_qos_wakeup_latency)) @@ -1979,13 +1973,6 @@ int adreno_set_unsecured_mode(struct adreno_device *adreno_dev, if (!adreno_is_a5xx(adreno_dev) && !adreno_is_a6xx(adreno_dev)) return -EINVAL; - if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_CRITICAL_PACKETS) && - adreno_is_a5xx(adreno_dev)) { - ret = a5xx_critical_packet_submit(adreno_dev, rb); - if (ret) - return ret; - } - /* GPU comes up in secured mode, make it unsecured by default */ if (adreno_dev->zap_loaded) ret = adreno_switch_to_unsecure_mode(adreno_dev, rb); @@ -2032,10 +2019,6 @@ static int _adreno_start(struct adreno_device *adreno_dev) /* make sure ADRENO_DEVICE_STARTED is not set here */ WARN_ON(test_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv)); - /* disallow l2pc during wake up to improve GPU wake up time */ - kgsl_pwrctrl_update_l2pc(&adreno_dev->dev, - KGSL_L2PC_WAKEUP_TIMEOUT); - pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, pmqos_wakeup_vote); @@ -3414,7 +3397,11 @@ int adreno_gmu_fenced_write(struct adreno_device *adreno_dev, break; /* Wait a small amount of time before trying again */ - udelay(GMU_CORE_WAKEUP_DELAY_US); + if (in_atomic()) + udelay(GMU_CORE_WAKEUP_DELAY_US); + else + usleep_range(GMU_CORE_WAKEUP_DELAY_US, + 3 * GMU_CORE_WAKEUP_DELAY_US); /* Try to write the fenced register again */ adreno_writereg(adreno_dev, offset, val); @@ -4103,6 +4090,7 @@ static struct platform_driver adreno_platform_driver = { .name = DEVICE_3D_NAME, .pm = &kgsl_pm_ops, .of_match_table = adreno_match_table, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, } }; diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 1423135b1089..aba2864e5d47 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -1038,8 +1038,6 @@ extern unsigned int *adreno_ft_regs; extern unsigned int adreno_ft_regs_num; extern unsigned int *adreno_ft_regs_val; -extern struct adreno_gpudev adreno_a3xx_gpudev; -extern struct adreno_gpudev adreno_a5xx_gpudev; extern struct adreno_gpudev adreno_a6xx_gpudev; extern int adreno_wake_nice; @@ -1054,8 +1052,6 @@ long adreno_ioctl_helper(struct kgsl_device_private *dev_priv, unsigned int cmd, unsigned long arg, const struct kgsl_ioctl *cmds, int len); -int a5xx_critical_packet_submit(struct adreno_device *adreno_dev, - struct adreno_ringbuffer *rb); int adreno_set_unsecured_mode(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb); void adreno_spin_idle_debug(struct adreno_device *adreno_dev, const char *str); diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 157a0682c7b8..781aebaae9d8 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -876,7 +876,7 @@ static int a6xx_gmu_gfx_rail_on(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - unsigned int perf_idx = pwr->num_pwrlevels - pwr->default_pwrlevel - 1; + unsigned int perf_idx = pwr->num_pwrlevels - 1; uint32_t default_opp = gmu->rpmh_votes.gx_votes[perf_idx]; gmu_core_regwrite(device, A6XX_GMU_BOOT_SLUMBER_OPTION, @@ -1297,8 +1297,8 @@ static int a6xx_gmu_notify_slumber(struct kgsl_device *device) struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct gmu_device *gmu = KGSL_GMU_DEVICE(device); - int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq; - int perf_idx = gmu->num_gpupwrlevels - pwr->default_pwrlevel - 1; + int bus_level = pwr->pwrlevels[pwr->num_pwrlevels - 1].bus_freq; + int perf_idx = gmu->num_gpupwrlevels - 1; int ret, state; /* Disable the power counter so that the GMU is not busy */ diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c index 1d53237fda4c..b6a75a67e486 100644 --- a/drivers/gpu/msm/adreno_a6xx_preempt.c +++ b/drivers/gpu/msm/adreno_a6xx_preempt.c @@ -26,6 +26,8 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) { struct adreno_ringbuffer *rb = adreno_dev->cur_rb; unsigned long flags; + bool write = false; + unsigned int val; int ret = 0; struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -52,9 +54,8 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) gmu_core_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 0x0, 0x2); - ret = adreno_gmu_fenced_write(adreno_dev, - ADRENO_REG_CP_RB_WPTR, rb->wptr, - FENCE_STATUS_WRITEDROPPED0_MASK); + write = true; + val = rb->wptr; /* Clear the keep alive */ if (gmu_core_isenabled(device)) @@ -81,6 +82,10 @@ static void _update_wptr(struct adreno_device *adreno_dev, bool reset_timer) spin_unlock_irqrestore(&rb->preempt_lock, flags); + if (write) + ret = adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_RB_WPTR, + val, FENCE_STATUS_WRITEDROPPED0_MASK); + if (in_interrupt() == 0) { /* If WPTR update fails, set the fault and trigger recovery */ if (ret) { diff --git a/drivers/gpu/msm/adreno_cp_parser.h b/drivers/gpu/msm/adreno_cp_parser.h index 1c5b0e0281eb..edb7bb33a088 100644 --- a/drivers/gpu/msm/adreno_cp_parser.h +++ b/drivers/gpu/msm/adreno_cp_parser.h @@ -8,9 +8,6 @@ #include "adreno.h" -extern const unsigned int a3xx_cp_addr_regs[]; -extern const unsigned int a4xx_cp_addr_regs[]; - /* * struct adreno_ib_object - Structure containing information about an * address range found in an IB @@ -127,12 +124,7 @@ static inline void adreno_ib_init_ib_obj(uint64_t gpuaddr, static inline int adreno_cp_parser_getreg(struct adreno_device *adreno_dev, enum adreno_cp_addr_regs reg_enum) { - if (reg_enum == ADRENO_CP_ADDR_MAX) - return -EEXIST; - - if (!adreno_is_a3xx(adreno_dev)) - return -EEXIST; - return a3xx_cp_addr_regs[reg_enum]; + return -EEXIST; } /* @@ -150,17 +142,6 @@ static inline int adreno_cp_parser_regindex(struct adreno_device *adreno_dev, enum adreno_cp_addr_regs start, enum adreno_cp_addr_regs end) { - int i; - const unsigned int *regs; - - if (!adreno_is_a3xx(adreno_dev)) - return -EEXIST; - - regs = a3xx_cp_addr_regs; - - for (i = start; i <= end && i < ADRENO_CP_ADDR_MAX; i++) - if (regs[i] == offset) - return i; return -EEXIST; } diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index d67945724643..f9e4a0b8a691 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -147,11 +147,6 @@ static void sync_event_print(struct seq_file *s, break; } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { - int i; - - for (i = 0; i < sync_event->info.num_fences; i++) - seq_printf(s, "sync: %s", - sync_event->info.fences[i].name); break; } default: diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 055afd6d6816..5c957b0d4639 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -521,12 +521,8 @@ static int sendcmd(struct adreno_device *adreno_dev, struct kgsl_drawobj *drawobj = DRAWOBJ(cmdobj); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - struct adreno_context *drawctxt = ADRENO_CONTEXT(drawobj->context); struct adreno_dispatcher_drawqueue *dispatch_q = ADRENO_DRAWOBJ_DISPATCH_DRAWQUEUE(drawobj); - struct adreno_submit_time time; - uint64_t secs = 0; - unsigned long nsecs = 0; int ret; mutex_lock(&device->mutex); @@ -535,8 +531,6 @@ static int sendcmd(struct adreno_device *adreno_dev, return -EBUSY; } - memset(&time, 0x0, sizeof(time)); - dispatcher->inflight++; dispatch_q->inflight++; @@ -562,7 +556,7 @@ static int sendcmd(struct adreno_device *adreno_dev, ADRENO_DRAWOBJ_PROFILE_COUNT; } - ret = adreno_ringbuffer_submitcmd(adreno_dev, cmdobj, &time); + ret = adreno_ringbuffer_submitcmd(adreno_dev, cmdobj, NULL); /* * On the first command, if the submission was successful, then read the @@ -622,9 +616,6 @@ static int sendcmd(struct adreno_device *adreno_dev, return ret; } - secs = time.ktime; - nsecs = do_div(secs, 1000000000); - /* * For the first submission in any given command queue update the * expected expire time - this won't actually be used / updated until @@ -636,14 +627,8 @@ static int sendcmd(struct adreno_device *adreno_dev, dispatch_q->expires = jiffies + msecs_to_jiffies(adreno_drawobj_timeout); - trace_adreno_cmdbatch_submitted(drawobj, (int) dispatcher->inflight, - time.ticks, (unsigned long) secs, nsecs / 1000, drawctxt->rb, - adreno_get_rptr(drawctxt->rb)); - mutex_unlock(&device->mutex); - cmdobj->submit_ticks = time.ticks; - dispatch_q->cmd_q[dispatch_q->tail] = cmdobj; dispatch_q->tail = (dispatch_q->tail + 1) % ADRENO_DISPATCH_DRAWQUEUE_SIZE; @@ -1452,10 +1437,6 @@ int adreno_dispatcher_queue_cmds(struct kgsl_device_private *dev_priv, spin_unlock(&drawctxt->lock); - if (device->pwrctrl.l2pc_update_queue) - kgsl_pwrctrl_update_l2pc(&adreno_dev->dev, - KGSL_L2PC_QUEUE_TIMEOUT); - /* Add the context to the dispatcher pending list */ dispatcher_queue_context(adreno_dev, drawctxt); @@ -2360,12 +2341,6 @@ static void retire_cmdobj(struct adreno_device *adreno_dev, ADRENO_DRAWOBJ_RB(drawobj), adreno_get_rptr(drawctxt->rb), cmdobj->fault_recovery); - drawctxt->submit_retire_ticks[drawctxt->ticks_index] = - end - cmdobj->submit_ticks; - - drawctxt->ticks_index = (drawctxt->ticks_index + 1) % - SUBMIT_RETIRE_TICKS_SIZE; - kgsl_drawobj_destroy(drawobj); } diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index c6c3a33a6745..9f6270881d85 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -40,8 +40,6 @@ void adreno_drawctxt_dump(struct kgsl_device *device, { unsigned int queue, start, retire; struct adreno_context *drawctxt = ADRENO_CONTEXT(context); - int index, pos; - char buf[120]; kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_QUEUED, &queue); kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_CONSUMED, &start); @@ -102,25 +100,6 @@ void adreno_drawctxt_dump(struct kgsl_device *device, } stats: - memset(buf, 0, sizeof(buf)); - - pos = 0; - - for (index = 0; index < SUBMIT_RETIRE_TICKS_SIZE; index++) { - uint64_t msecs; - unsigned int usecs; - - if (!drawctxt->submit_retire_ticks[index]) - continue; - msecs = drawctxt->submit_retire_ticks[index] * 10; - usecs = do_div(msecs, 192); - usecs = do_div(msecs, 1000); - pos += scnprintf(buf + pos, sizeof(buf) - pos, "%u.%0u ", - (unsigned int)msecs, usecs); - } - dev_err(device->dev, " context[%u]: submit times: %s\n", - context->id, buf); - spin_unlock_bh(&drawctxt->lock); } diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h index 436c5a27b935..f2e6865629cc 100644 --- a/drivers/gpu/msm/adreno_drawctxt.h +++ b/drivers/gpu/msm/adreno_drawctxt.h @@ -15,7 +15,6 @@ struct adreno_context_type { }; #define ADRENO_CONTEXT_DRAWQUEUE_SIZE 128 -#define SUBMIT_RETIRE_TICKS_SIZE 7 struct kgsl_device; struct adreno_device; @@ -42,10 +41,6 @@ struct kgsl_device_private; * @queued_timestamp: The last timestamp that was queued on this context * @rb: The ringbuffer in which this context submits commands. * @submitted_timestamp: The last timestamp that was submitted for this context - * @submit_retire_ticks: Array to hold command obj execution times from submit - * to retire - * @ticks_index: The index into submit_retire_ticks[] where the new delta will - * be written. * @active_node: Linkage for nodes in active_list * @active_time: Time when this context last seen */ @@ -72,8 +67,6 @@ struct adreno_context { unsigned int queued_timestamp; struct adreno_ringbuffer *rb; unsigned int submitted_timestamp; - uint64_t submit_retire_ticks[SUBMIT_RETIRE_TICKS_SIZE]; - int ticks_index; struct list_head active_node; unsigned long active_time; diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index fb026a15314d..2e5f82d7ab6b 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -77,6 +77,8 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev, struct kgsl_device *device = KGSL_DEVICE(adreno_dev); struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); unsigned long flags; + bool write = false; + unsigned int val; int ret = 0; spin_lock_irqsave(&rb->preempt_lock, flags); @@ -100,13 +102,8 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev, if (gpudev->gpu_keepalive) gpudev->gpu_keepalive(adreno_dev, true); - /* - * Ensure the write posted after a possible - * GMU wakeup (write could have dropped during wakeup) - */ - ret = adreno_gmu_fenced_write(adreno_dev, - ADRENO_REG_CP_RB_WPTR, rb->_wptr, - FENCE_STATUS_WRITEDROPPED0_MASK); + write = true; + val = rb->_wptr; rb->skip_inline_wptr = false; if (gpudev->gpu_keepalive) gpudev->gpu_keepalive(adreno_dev, false); @@ -125,6 +122,14 @@ static void adreno_ringbuffer_wptr(struct adreno_device *adreno_dev, rb->wptr = rb->_wptr; spin_unlock_irqrestore(&rb->preempt_lock, flags); + /* + * Ensure the write posted after a possible + * GMU wakeup (write could have dropped during wakeup) + */ + if (write) + ret = adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_RB_WPTR, + val, FENCE_STATUS_WRITEDROPPED0_MASK); + if (ret) { /* * If WPTR update fails, take inline snapshot and trigger @@ -945,6 +950,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, struct kgsl_memobj_node *ib; unsigned int numibs = 0; unsigned int *link; + unsigned int link_onstack[SZ_256] __aligned(sizeof(long)); unsigned int *cmds; struct kgsl_context *context; struct adreno_context *drawctxt; @@ -1072,10 +1078,14 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, if (gpudev->ccu_invalidate) dwords += 4; - link = kcalloc(dwords, sizeof(unsigned int), GFP_KERNEL); - if (!link) { - ret = -ENOMEM; - goto done; + if (dwords <= ARRAY_SIZE(link_onstack)) { + link = link_onstack; + } else { + link = kcalloc(dwords, sizeof(unsigned int), GFP_KERNEL); + if (!link) { + ret = -ENOMEM; + goto done; + } } cmds = link; @@ -1205,7 +1215,8 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, trace_kgsl_issueibcmds(device, context->id, numibs, drawobj->timestamp, drawobj->flags, ret, drawctxt->type); - kfree(link); + if (link != link_onstack) + kfree(link); return ret; } diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index 07cc11b2b7d4..76a3625ce415 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -43,51 +43,6 @@ TRACE_EVENT(adreno_cmdbatch_queued, ) ); -TRACE_EVENT(adreno_cmdbatch_submitted, - TP_PROTO(struct kgsl_drawobj *drawobj, int inflight, uint64_t ticks, - unsigned long secs, unsigned long usecs, - struct adreno_ringbuffer *rb, unsigned int rptr), - TP_ARGS(drawobj, inflight, ticks, secs, usecs, rb, rptr), - TP_STRUCT__entry( - __field(unsigned int, id) - __field(unsigned int, timestamp) - __field(int, inflight) - __field(unsigned int, flags) - __field(uint64_t, ticks) - __field(unsigned long, secs) - __field(unsigned long, usecs) - __field(int, prio) - __field(int, rb_id) - __field(unsigned int, rptr) - __field(unsigned int, wptr) - __field(int, q_inflight) - ), - TP_fast_assign( - __entry->id = drawobj->context->id; - __entry->timestamp = drawobj->timestamp; - __entry->inflight = inflight; - __entry->flags = drawobj->flags; - __entry->ticks = ticks; - __entry->secs = secs; - __entry->usecs = usecs; - __entry->prio = drawobj->context->priority; - __entry->rb_id = rb->id; - __entry->rptr = rptr; - __entry->wptr = rb->wptr; - __entry->q_inflight = rb->dispatch_q.inflight; - ), - TP_printk( - "ctx=%u ctx_prio=%d ts=%u inflight=%d flags=%s ticks=%lld time=%lu.%0lu rb_id=%d r/w=%x/%x, q_inflight=%d", - __entry->id, __entry->prio, __entry->timestamp, - __entry->inflight, - __entry->flags ? __print_flags(__entry->flags, "|", - KGSL_DRAWOBJ_FLAGS) : "none", - __entry->ticks, __entry->secs, __entry->usecs, - __entry->rb_id, __entry->rptr, __entry->wptr, - __entry->q_inflight - ) -); - TRACE_EVENT(adreno_cmdbatch_retired, TP_PROTO(struct kgsl_drawobj *drawobj, int inflight, uint64_t start, uint64_t retire, diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index c365b3e49e98..0699710ff308 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2340,7 +2340,7 @@ static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, } handle = kgsl_sync_fence_async_wait(event.fd, - gpuobj_free_fence_func, entry, NULL); + gpuobj_free_fence_func, entry); if (IS_ERR(handle)) { kgsl_mem_entry_unset_pend(entry); @@ -5116,8 +5116,8 @@ int kgsl_request_irq(struct platform_device *pdev, const char *name, if (num < 0) return num; - ret = devm_request_irq(&pdev->dev, num, handler, IRQF_TRIGGER_HIGH, - name, data); + ret = devm_request_irq(&pdev->dev, num, handler, IRQF_TRIGGER_HIGH | + IRQF_PERF_AFFINE, name, data); if (ret) dev_err(&pdev->dev, "Unable to get interrupt %s: %d\n", @@ -5155,7 +5155,6 @@ int kgsl_of_property_read_ddrtype(struct device_node *node, const char *base, int kgsl_device_platform_probe(struct kgsl_device *device) { int status = -EINVAL; - int cpu; status = _register_device(device); if (status) @@ -5239,22 +5238,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device) PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); - if (device->pwrctrl.l2pc_cpus_mask) { - struct pm_qos_request *qos = &device->pwrctrl.l2pc_cpus_qos; - - qos->type = PM_QOS_REQ_AFFINE_CORES; - - cpumask_empty(&qos->cpus_affine); - for_each_possible_cpu(cpu) { - if ((1 << cpu) & device->pwrctrl.l2pc_cpus_mask) - cpumask_set_cpu(cpu, &qos->cpus_affine); - } - - pm_qos_add_request(&device->pwrctrl.l2pc_cpus_qos, - PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - } - device->events_wq = alloc_workqueue("kgsl-events", WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS | WQ_HIGHPRI, 0); @@ -5291,8 +5274,6 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_pwrctrl_uninit_sysfs(device); pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma); - if (device->pwrctrl.l2pc_cpus_mask) - pm_qos_remove_request(&device->pwrctrl.l2pc_cpus_qos); idr_destroy(&device->context_idr); @@ -5346,7 +5327,7 @@ static void kgsl_core_exit(void) static int __init kgsl_core_init(void) { int result = 0; - struct sched_param param = { .sched_priority = 2 }; + struct sched_param param = { .sched_priority = 16 }; /* alloc major and minor device numbers */ result = alloc_chrdev_region(&kgsl_driver.major, 0, @@ -5409,7 +5390,7 @@ static int __init kgsl_core_init(void) INIT_LIST_HEAD(&kgsl_driver.pagetable_list); kgsl_driver.workqueue = alloc_workqueue("kgsl-workqueue", - WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); + WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); kgsl_driver.mem_workqueue = alloc_workqueue("kgsl-mementry", WQ_UNBOUND | WQ_MEM_RECLAIM, 0); @@ -5418,8 +5399,8 @@ static int __init kgsl_core_init(void) kthread_init_worker(&kgsl_driver.worker); - kgsl_driver.worker_thread = kthread_run(kthread_worker_fn, - &kgsl_driver.worker, "kgsl_worker_thread"); + kgsl_driver.worker_thread = kthread_run_perf_critical(cpu_perf_mask, + kthread_worker_fn, &kgsl_driver.worker, "kgsl_worker_thread"); if (IS_ERR(kgsl_driver.worker_thread)) { pr_err("kgsl: unable to start kgsl thread\n"); diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c index ce3fd4b0972f..9cd827275e57 100644 --- a/drivers/gpu/msm/kgsl_drawobj.c +++ b/drivers/gpu/msm/kgsl_drawobj.c @@ -34,17 +34,9 @@ static struct kmem_cache *memobjs_cache; static struct kmem_cache *sparseobjs_cache; -static void free_fence_names(struct kgsl_drawobj_sync *syncobj) -{ - unsigned int i; - - for (i = 0; i < syncobj->numsyncs; i++) { - struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i]; - - if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) - kfree(event->info.fences); - } -} +static struct kmem_cache *drawobj_sparse_cache; +static struct kmem_cache *drawobj_sync_cache; +static struct kmem_cache *drawobj_cmd_cache; void kgsl_drawobj_destroy_object(struct kref *kref) { @@ -57,16 +49,15 @@ void kgsl_drawobj_destroy_object(struct kref *kref) switch (drawobj->type) { case SYNCOBJ_TYPE: syncobj = SYNCOBJ(drawobj); - free_fence_names(syncobj); kfree(syncobj->synclist); - kfree(syncobj); + kmem_cache_free(drawobj_sync_cache, syncobj); break; case CMDOBJ_TYPE: case MARKEROBJ_TYPE: - kfree(CMDOBJ(drawobj)); + kmem_cache_free(drawobj_cmd_cache, CMDOBJ(drawobj)); break; case SPARSEOBJ_TYPE: - kfree(SPARSEOBJ(drawobj)); + kmem_cache_free(drawobj_sparse_cache, SPARSEOBJ(drawobj)); break; } } @@ -98,12 +89,6 @@ void kgsl_dump_syncpoints(struct kgsl_device *device, break; } case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { - int j; - struct event_fence_info *info = &event->info; - - for (j = 0; j < info->num_fences; j++) - dev_err(device->dev, "[%d] fence: %s\n", - i, info->fences[j].name); break; } } @@ -155,12 +140,6 @@ static void syncobj_timer(struct timer_list *t) i, event->context->id, event->timestamp); break; case KGSL_CMD_SYNCPOINT_TYPE_FENCE: { - int j; - struct event_fence_info *info = &event->info; - - for (j = 0; j < info->num_fences; j++) - dev_err(device->dev, " [%u] FENCE %s\n", - i, info->fences[j].name); break; } } @@ -349,11 +328,6 @@ EXPORT_SYMBOL(kgsl_drawobj_destroy); static bool drawobj_sync_fence_func(void *priv) { struct kgsl_drawobj_sync_event *event = priv; - int i; - - for (i = 0; i < event->info.num_fences; i++) - trace_syncpoint_fence_expire(event->syncobj, - event->info.fences[i].name); /* * Only call kgsl_drawobj_put() if it's not marked for cancellation @@ -379,7 +353,7 @@ static int drawobj_add_sync_fence(struct kgsl_device *device, struct kgsl_cmd_syncpoint_fence *sync = priv; struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj); struct kgsl_drawobj_sync_event *event; - unsigned int id, i; + unsigned int id; kref_get(&drawobj->refcount); @@ -396,8 +370,7 @@ static int drawobj_add_sync_fence(struct kgsl_device *device, set_bit(event->id, &syncobj->pending); event->handle = kgsl_sync_fence_async_wait(sync->fd, - drawobj_sync_fence_func, event, - &event->info); + drawobj_sync_fence_func, event); if (IS_ERR_OR_NULL(event->handle)) { int ret = PTR_ERR(event->handle); @@ -417,9 +390,6 @@ static int drawobj_add_sync_fence(struct kgsl_device *device, return ret; } - for (i = 0; i < event->info.num_fences; i++) - trace_syncpoint_fence(syncobj, event->info.fences[i].name); - return 0; } @@ -511,8 +481,12 @@ int kgsl_drawobj_sync_add_sync(struct kgsl_device *device, struct kgsl_drawobj_sync *syncobj, struct kgsl_cmd_syncpoint *sync) { + union { + struct kgsl_cmd_syncpoint_timestamp sync_timestamp; + struct kgsl_cmd_syncpoint_fence sync_fence; + } data; void *priv; - int ret, psize; + int psize; struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj); int (*func)(struct kgsl_device *device, struct kgsl_drawobj_sync *syncobj, @@ -522,10 +496,12 @@ int kgsl_drawobj_sync_add_sync(struct kgsl_device *device, case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: psize = sizeof(struct kgsl_cmd_syncpoint_timestamp); func = drawobj_add_sync_timestamp; + priv = &data.sync_timestamp; break; case KGSL_CMD_SYNCPOINT_TYPE_FENCE: psize = sizeof(struct kgsl_cmd_syncpoint_fence); func = drawobj_add_sync_fence; + priv = &data.sync_fence; break; default: dev_err(device->dev, @@ -541,14 +517,10 @@ int kgsl_drawobj_sync_add_sync(struct kgsl_device *device, return -EINVAL; } - priv = memdup_user(sync->priv, sync->size); - if (IS_ERR(priv)) - return PTR_ERR(priv); - - ret = func(device, syncobj, priv); - kfree(priv); + if (copy_from_user(priv, sync->priv, sync->size)) + return -EFAULT; - return ret; + return func(device, syncobj, priv); } static void add_profiling_buffer(struct kgsl_device *device, @@ -674,12 +646,27 @@ int kgsl_drawobj_cmd_add_ibdesc(struct kgsl_device *device, } static void *_drawobj_create(struct kgsl_device *device, - struct kgsl_context *context, unsigned int size, - unsigned int type) + struct kgsl_context *context, unsigned int type) { - void *obj = kzalloc(size, GFP_KERNEL); + void *obj; struct kgsl_drawobj *drawobj; + switch (type) { + case SYNCOBJ_TYPE: + obj = kmem_cache_zalloc(drawobj_sync_cache, GFP_KERNEL); + break; + case CMDOBJ_TYPE: + case MARKEROBJ_TYPE: + obj = kmem_cache_zalloc(drawobj_cmd_cache, GFP_KERNEL); + break; + case SPARSEOBJ_TYPE: + obj = kmem_cache_zalloc(drawobj_sparse_cache, GFP_KERNEL); + break; + default: + // noop + return ERR_PTR(-ENOMEM); + } + if (obj == NULL) return ERR_PTR(-ENOMEM); @@ -688,7 +675,18 @@ static void *_drawobj_create(struct kgsl_device *device, * during the lifetime of this object */ if (!_kgsl_context_get(context)) { - kfree(obj); + switch (type) { + case SYNCOBJ_TYPE: + kmem_cache_free(drawobj_sync_cache, obj); + break; + case CMDOBJ_TYPE: + case MARKEROBJ_TYPE: + kmem_cache_free(drawobj_cmd_cache, obj); + break; + case SPARSEOBJ_TYPE: + kmem_cache_free(drawobj_sparse_cache, obj); + break; + } return ERR_PTR(-ENOENT); } @@ -716,7 +714,7 @@ struct kgsl_drawobj_sparse *kgsl_drawobj_sparse_create( struct kgsl_context *context, unsigned int flags) { struct kgsl_drawobj_sparse *sparseobj = _drawobj_create(device, - context, sizeof(*sparseobj), SPARSEOBJ_TYPE); + context, SPARSEOBJ_TYPE); if (!IS_ERR(sparseobj)) INIT_LIST_HEAD(&sparseobj->sparselist); @@ -736,7 +734,7 @@ struct kgsl_drawobj_sync *kgsl_drawobj_sync_create(struct kgsl_device *device, struct kgsl_context *context) { struct kgsl_drawobj_sync *syncobj = _drawobj_create(device, - context, sizeof(*syncobj), SYNCOBJ_TYPE); + context, SYNCOBJ_TYPE); /* Add a timer to help debug sync deadlocks */ if (!IS_ERR(syncobj)) @@ -760,8 +758,7 @@ struct kgsl_drawobj_cmd *kgsl_drawobj_cmd_create(struct kgsl_device *device, unsigned int type) { struct kgsl_drawobj_cmd *cmdobj = _drawobj_create(device, - context, sizeof(*cmdobj), - (type & (CMDOBJ_TYPE | MARKEROBJ_TYPE))); + context, (type & (CMDOBJ_TYPE | MARKEROBJ_TYPE))); if (!IS_ERR(cmdobj)) { /* sanitize our flags for drawobj's */ @@ -1159,14 +1156,23 @@ void kgsl_drawobjs_cache_exit(void) { kmem_cache_destroy(memobjs_cache); kmem_cache_destroy(sparseobjs_cache); + + kmem_cache_destroy(drawobj_sparse_cache); + kmem_cache_destroy(drawobj_sync_cache); + kmem_cache_destroy(drawobj_cmd_cache); } int kgsl_drawobjs_cache_init(void) { - memobjs_cache = KMEM_CACHE(kgsl_memobj_node, 0); - sparseobjs_cache = KMEM_CACHE(kgsl_sparseobj_node, 0); + memobjs_cache = KMEM_CACHE(kgsl_memobj_node, SLAB_HWCACHE_ALIGN); + sparseobjs_cache = KMEM_CACHE(kgsl_sparseobj_node, SLAB_HWCACHE_ALIGN); + + drawobj_sparse_cache = KMEM_CACHE(kgsl_drawobj_sparse, SLAB_HWCACHE_ALIGN); + drawobj_sync_cache = KMEM_CACHE(kgsl_drawobj_sync, SLAB_HWCACHE_ALIGN); + drawobj_cmd_cache = KMEM_CACHE(kgsl_drawobj_cmd, SLAB_HWCACHE_ALIGN); - if (!memobjs_cache || !sparseobjs_cache) + if (!memobjs_cache || !sparseobjs_cache || + !drawobj_sparse_cache || !drawobj_sync_cache || !drawobj_cmd_cache) return -ENOMEM; return 0; diff --git a/drivers/gpu/msm/kgsl_drawobj.h b/drivers/gpu/msm/kgsl_drawobj.h index 7f3dd2624a5f..d2ac7c4acb48 100644 --- a/drivers/gpu/msm/kgsl_drawobj.h +++ b/drivers/gpu/msm/kgsl_drawobj.h @@ -61,8 +61,6 @@ struct kgsl_drawobj { * for easy access * @profile_index: Index to store the start/stop ticks in the kernel profiling * buffer - * @submit_ticks: Variable to hold ticks at the time of - * command obj submit. */ struct kgsl_drawobj_cmd { @@ -77,7 +75,6 @@ struct kgsl_drawobj_cmd { struct kgsl_mem_entry *profiling_buf_entry; uint64_t profiling_buffer_gpuaddr; unsigned int profile_index; - uint64_t submit_ticks; }; /** @@ -100,17 +97,6 @@ struct kgsl_drawobj_sync { unsigned long timeout_jiffies; }; -#define KGSL_FENCE_NAME_LEN 74 - -struct fence_info { - char name[KGSL_FENCE_NAME_LEN]; -}; - -struct event_fence_info { - struct fence_info *fences; - int num_fences; -}; - /** * struct kgsl_drawobj_sync_event * @id: identifer (positiion within the pending bitmap) @@ -131,7 +117,6 @@ struct kgsl_drawobj_sync_event { unsigned int timestamp; struct kgsl_sync_fence_cb *handle; struct kgsl_device *device; - struct event_fence_info info; }; /** diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c index a9fe84909352..22207f326284 100644 --- a/drivers/gpu/msm/kgsl_gmu.c +++ b/drivers/gpu/msm/kgsl_gmu.c @@ -1612,7 +1612,7 @@ static int gmu_start(struct kgsl_device *device) /* Vote for minimal DDR BW for GMU to init */ ret = msm_bus_scale_client_update_request(gmu->pcl, - pwr->pwrlevels[pwr->default_pwrlevel].bus_min); + pwr->pwrlevels[pwr->num_pwrlevels - 1].bus_min); if (ret) dev_err(&gmu->pdev->dev, "Failed to allocate gmu b/w: %d\n", ret); diff --git a/drivers/gpu/msm/kgsl_ioctl.c b/drivers/gpu/msm/kgsl_ioctl.c index 8df9166bec50..38e2b39a0274 100644 --- a/drivers/gpu/msm/kgsl_ioctl.c +++ b/drivers/gpu/msm/kgsl_ioctl.c @@ -148,7 +148,8 @@ long kgsl_ioctl_helper(struct file *filep, unsigned int cmd, unsigned long arg, return ret; } -long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +static long __kgsl_ioctl(struct file *filep, unsigned int cmd, + unsigned long arg) { struct kgsl_device_private *dev_priv = filep->private_data; struct kgsl_device *device = dev_priv->device; @@ -173,3 +174,24 @@ long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) return ret; } + +long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + /* + * Optimistically assume the current task won't migrate to another CPU + * and restrict the current CPU to shallow idle states so that it won't + * take too long to finish running the ioctl whenever the ioctl runs a + * command that sleeps, such as for memory allocation. + */ + struct pm_qos_request req = { + .type = PM_QOS_REQ_AFFINE_CORES, + .cpus_affine = ATOMIC_INIT(BIT(raw_smp_processor_id())) + }; + long ret; + + pm_qos_add_request(&req, PM_QOS_CPU_DMA_LATENCY, 100); + ret = __kgsl_ioctl(filep, cmd, arg); + pm_qos_remove_request(&req); + + return ret; +} diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c index 9c768458a7c7..57bea26888b9 100644 --- a/drivers/gpu/msm/kgsl_pool.c +++ b/drivers/gpu/msm/kgsl_pool.c @@ -30,12 +30,12 @@ */ struct kgsl_page_pool { unsigned int pool_order; - int page_count; + atomic_t page_count; unsigned int reserved_pages; bool allocation_allowed; unsigned int max_pages; spinlock_t list_lock; - struct list_head page_list; + struct llist_head page_list; }; static struct kgsl_page_pool kgsl_pools[KGSL_MAX_POOLS]; @@ -63,10 +63,8 @@ _kgsl_pool_add_page(struct kgsl_page_pool *pool, struct page *p) { kgsl_zero_page(p, pool->pool_order); - spin_lock(&pool->list_lock); - list_add_tail(&p->lru, &pool->page_list); - pool->page_count++; - spin_unlock(&pool->list_lock); + llist_add((struct llist_node *)&p->lru, &pool->page_list); + atomic_inc(&pool->page_count); mod_node_page_state(page_pgdat(p), NR_KERNEL_MISC_RECLAIMABLE, (1 << pool->pool_order)); } @@ -75,35 +73,28 @@ _kgsl_pool_add_page(struct kgsl_page_pool *pool, struct page *p) static struct page * _kgsl_pool_get_page(struct kgsl_page_pool *pool) { + struct llist_node *node; struct page *p = NULL; spin_lock(&pool->list_lock); - if (pool->page_count) { - p = list_first_entry(&pool->page_list, struct page, lru); - pool->page_count--; - list_del(&p->lru); - } + node = llist_del_first(&pool->page_list); spin_unlock(&pool->list_lock); - if (p != NULL) + if (node) { + atomic_dec(&pool->page_count); + p = container_of((struct list_head *)node, typeof(*p), lru); mod_node_page_state(page_pgdat(p), NR_KERNEL_MISC_RECLAIMABLE, -(1 << pool->pool_order)); - + } return p; } /* Returns the number of pages in specified pool */ static int -kgsl_pool_size(struct kgsl_page_pool *kgsl_pool) +kgsl_pool_size(struct kgsl_page_pool *pool) { - int size; - - spin_lock(&kgsl_pool->list_lock); - size = kgsl_pool->page_count * (1 << kgsl_pool->pool_order); - spin_unlock(&kgsl_pool->list_lock); - - return size; + return atomic_read(&pool->page_count) * (1 << pool->pool_order); } /* Returns the number of pages in all kgsl page pools */ @@ -374,7 +365,7 @@ void kgsl_pool_free_page(struct page *page) if (!kgsl_pool_max_pages || (kgsl_pool_size_total() < kgsl_pool_max_pages)) { pool = _kgsl_get_pool_from_order(page_order); - if (pool && (pool->page_count < pool->max_pages)) { + if (pool && (atomic_read(&pool->page_count) < pool->max_pages)) { _kgsl_pool_add_page(pool, page); return; } @@ -432,12 +423,16 @@ kgsl_pool_shrink_scan_objects(struct shrinker *shrinker, /* nr represents number of pages to be removed*/ int nr = sc->nr_to_scan; int total_pages = kgsl_pool_size_total(); + unsigned long ret; /* Target pages represents new pool size */ int target_pages = (nr > total_pages) ? 0 : (total_pages - nr); /* Reduce pool size to target_pages */ - return kgsl_pool_reduce(target_pages, false); + ret = kgsl_pool_reduce(target_pages, false); + + /* If we are unable to shrink more, stop trying */ + return (ret == 0) ? SHRINK_STOP : ret; } static unsigned long @@ -477,7 +472,7 @@ static void kgsl_pool_config(unsigned int order, unsigned int reserved_pages, kgsl_pools[kgsl_num_pools].allocation_allowed = allocation_allowed; kgsl_pools[kgsl_num_pools].max_pages = max_pages; spin_lock_init(&kgsl_pools[kgsl_num_pools].list_lock); - INIT_LIST_HEAD(&kgsl_pools[kgsl_num_pools].page_list); + init_llist_head(&kgsl_pools[kgsl_num_pools].page_list); kgsl_num_pools++; } @@ -524,7 +519,7 @@ static void kgsl_of_get_mempools(struct device_node *parent) * low memory configuration is not specified * then fallback to default pool configuration. */ - if (totalram_pages < (SZ_2G >> PAGE_SHIFT)) + if (totalram_pages() < (SZ_2G >> PAGE_SHIFT)) node = of_find_compatible_node(parent, NULL, "qcom,gpu-mempools-lowmem"); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 0832f1993047..4f07f70e5ad4 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1,4 +1,3 @@ -// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2010-2021, The Linux Foundation. All rights reserved. */ @@ -15,7 +14,6 @@ #include "kgsl_device.h" #include "kgsl_pwrscale.h" #include "kgsl_trace.h" -#include "kgsl_trace_power.h" #define KGSL_PWRFLAGS_POWER_ON 0 #define KGSL_PWRFLAGS_CLK_ON 1 @@ -166,8 +164,7 @@ static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr, * constraint if one exists. */ static unsigned int _adjust_pwrlevel(struct kgsl_pwrctrl *pwr, int level, - struct kgsl_pwr_constraint *pwrc, - int popp) + struct kgsl_pwr_constraint *pwrc) { unsigned int max_pwrlevel = max_t(unsigned int, pwr->thermal_pwrlevel, pwr->max_pwrlevel); @@ -195,9 +192,6 @@ static unsigned int _adjust_pwrlevel(struct kgsl_pwrctrl *pwr, int level, break; } - if (popp && (max_pwrlevel < pwr->active_pwrlevel)) - max_pwrlevel = pwr->active_pwrlevel; - if (level < max_pwrlevel) return max_pwrlevel; if (level > min_pwrlevel) @@ -578,8 +572,7 @@ unsigned int kgsl_pwrctrl_adjust_pwrlevel(struct kgsl_device *device, * Adjust the power level if required by thermal, max/min, * constraints, etc */ - return _adjust_pwrlevel(pwr, new_level, &pwr->constraint, - device->pwrscale.popp_level); + return _adjust_pwrlevel(pwr, new_level, &pwr->constraint); } /** @@ -658,8 +651,6 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, pwr->previous_pwrlevel, pwr->pwrlevels[old_level].gpu_freq); - trace_gpu_frequency(pwrlevel->gpu_freq/1000, 0); - /* * Some targets do not support the bandwidth requirement of * GPU at TURBO, for such targets we need to set GPU-BIMC @@ -722,7 +713,7 @@ void kgsl_pwrctrl_set_constraint(struct kgsl_device *device, if (device == NULL || pwrc == NULL) return; constraint = _adjust_pwrlevel(&device->pwrctrl, - device->pwrctrl.active_pwrlevel, pwrc, 0); + device->pwrctrl.active_pwrlevel, pwrc); pwrc_old = &device->pwrctrl.constraint; /* @@ -748,35 +739,6 @@ void kgsl_pwrctrl_set_constraint(struct kgsl_device *device, } EXPORT_SYMBOL(kgsl_pwrctrl_set_constraint); -/** - * kgsl_pwrctrl_update_l2pc() - Update existing qos request - * @device: Pointer to the kgsl_device struct - * @timeout_us: the effective duration of qos request in usecs. - * - * Updates an existing qos request to avoid L2PC on the - * CPUs (which are selected through dtsi) on which GPU - * thread is running. This would help for performance. - */ -void kgsl_pwrctrl_update_l2pc(struct kgsl_device *device, - unsigned long timeout_us) -{ - int cpu; - - if (device->pwrctrl.l2pc_cpus_mask == 0) - return; - - cpu = get_cpu(); - put_cpu(); - - if ((1 << cpu) & device->pwrctrl.l2pc_cpus_mask) { - pm_qos_update_request_timeout( - &device->pwrctrl.l2pc_cpus_qos, - device->pwrctrl.pm_qos_cpu_mask_latency, - timeout_us); - } -} -EXPORT_SYMBOL(kgsl_pwrctrl_update_l2pc); - static ssize_t thermal_pwrlevel_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1326,75 +1288,6 @@ static ssize_t bus_split_store(struct device *dev, return count; } -static ssize_t default_pwrlevel_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct kgsl_device *device = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%d\n", - device->pwrctrl.default_pwrlevel); -} - -static ssize_t default_pwrlevel_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct kgsl_device *device = dev_get_drvdata(dev); - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - struct kgsl_pwrscale *pwrscale = &device->pwrscale; - int ret; - unsigned int level = 0; - - ret = kgsl_sysfs_store(buf, &level); - if (ret) - return ret; - - if (level > pwr->num_pwrlevels - 2) - goto done; - - mutex_lock(&device->mutex); - pwr->default_pwrlevel = level; - pwrscale->gpu_profile.profile.initial_freq - = pwr->pwrlevels[level].gpu_freq; - - mutex_unlock(&device->mutex); -done: - return count; -} - - -static ssize_t popp_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned int val = 0; - struct kgsl_device *device = dev_get_drvdata(dev); - int ret; - - ret = kgsl_sysfs_store(buf, &val); - if (ret) - return ret; - - mutex_lock(&device->mutex); - if (val) - set_bit(POPP_ON, &device->pwrscale.popp_state); - else - clear_bit(POPP_ON, &device->pwrscale.popp_state); - mutex_unlock(&device->mutex); - - return count; -} - -static ssize_t popp_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct kgsl_device *device = dev_get_drvdata(dev); - - return scnprintf(buf, PAGE_SIZE, "%d\n", - test_bit(POPP_ON, &device->pwrscale.popp_state)); -} - static ssize_t gpu_model_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1599,8 +1492,6 @@ static DEVICE_ATTR_RW(force_clk_on); static DEVICE_ATTR_RW(force_bus_on); static DEVICE_ATTR_RW(force_rail_on); static DEVICE_ATTR_RW(bus_split); -static DEVICE_ATTR_RW(default_pwrlevel); -static DEVICE_ATTR_RW(popp); static DEVICE_ATTR_RW(force_no_nap); static DEVICE_ATTR_RO(gpu_model); static DEVICE_ATTR_RO(gpu_busy_percentage); @@ -1628,8 +1519,6 @@ static const struct attribute *pwrctrl_attr_list[] = { &dev_attr_force_rail_on.attr, &dev_attr_force_no_nap.attr, &dev_attr_bus_split.attr, - &dev_attr_default_pwrlevel.attr, - &dev_attr_popp.attr, &dev_attr_gpu_model.attr, &dev_attr_gpu_busy_percentage.attr, &dev_attr_min_clock_mhz.attr, @@ -2318,13 +2207,6 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->power_flags = 0; - of_property_read_u32(device->pdev->dev.of_node, "qcom,l2pc-cpu-mask", - &pwr->l2pc_cpus_mask); - - pwr->l2pc_update_queue = of_property_read_bool( - device->pdev->dev.of_node, - "qcom,l2pc-update-queue"); - pm_runtime_enable(&pdev->dev); gpu_cfg_node = @@ -2605,10 +2487,8 @@ static int kgsl_pwrctrl_enable(struct kgsl_device *device) if (pwr->wakeup_maxpwrlevel) { level = pwr->max_pwrlevel; pwr->wakeup_maxpwrlevel = 0; - } else if (kgsl_popp_check(device)) { - level = pwr->active_pwrlevel; } else { - level = pwr->default_pwrlevel; + level = pwr->num_pwrlevels - 1; } kgsl_pwrctrl_pwrlevel_change(device, level); @@ -2720,7 +2600,6 @@ static int _wake(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; int status = 0; - unsigned int state = device->state; switch (device->state) { case KGSL_STATE_SUSPEND: @@ -2747,9 +2626,6 @@ static int _wake(struct kgsl_device *device) /* Turn on the core clocks */ kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE); - if (state == KGSL_STATE_SLUMBER || state == KGSL_STATE_SUSPEND) - trace_gpu_frequency( - pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq/1000, 0); /* * No need to turn on/off irq here as it no longer affects * power collapse @@ -2909,14 +2785,9 @@ _slumber(struct kgsl_device *device) kgsl_pwrctrl_clk_set_options(device, false); kgsl_pwrctrl_disable(device); kgsl_pwrscale_sleep(device); - trace_gpu_frequency(0, 0); kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER); pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); - if (device->pwrctrl.l2pc_cpus_mask) - pm_qos_update_request( - &device->pwrctrl.l2pc_cpus_qos, - PM_QOS_DEFAULT_VALUE); break; case KGSL_STATE_SUSPEND: complete_all(&device->hwaccess_gate); @@ -2925,7 +2796,6 @@ _slumber(struct kgsl_device *device) break; case KGSL_STATE_AWARE: kgsl_pwrctrl_disable(device); - trace_gpu_frequency(0, 0); kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER); break; case KGSL_STATE_RESET: @@ -3408,7 +3278,7 @@ EXPORT_SYMBOL(kgsl_pwr_limits_get_freq); int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; - unsigned int new_level = pwr->default_pwrlevel; + unsigned int new_level = pwr->num_pwrlevels - 1; unsigned int old_level = pwr->active_pwrlevel; /* diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 72577d32246c..6138388f3c31 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -48,19 +48,6 @@ #define KGSL_PWR_DEL_LIMIT 1 #define KGSL_PWR_SET_LIMIT 2 -/* - * The effective duration of qos request in usecs at queue time. - * After timeout, qos request is cancelled automatically. - * Kept 80ms default, inline with default GPU idle time. - */ -#define KGSL_L2PC_QUEUE_TIMEOUT (80 * 1000) - -/* - * The effective duration of qos request in usecs at wakeup time. - * After timeout, qos request is cancelled automatically. - */ -#define KGSL_L2PC_WAKEUP_TIMEOUT (10 * 1000) - enum kgsl_pwrctrl_timer_type { KGSL_PWR_IDLE_TIMER, }; @@ -139,7 +126,6 @@ struct gpu_cx_ipeak_client { * @previous_pwrlevel - The power level before transition * @thermal_pwrlevel - maximum powerlevel constraint from thermal * @thermal_pwrlevel_floor - minimum powerlevel constraint from thermal - * @default_pwrlevel - device wake up power level * @max_pwrlevel - maximum allowable powerlevel per the user * @min_pwrlevel - minimum allowable powerlevel per the user * @num_pwrlevels - number of available power levels @@ -151,9 +137,6 @@ struct gpu_cx_ipeak_client { * @gpu_cfg - CPU to GPU AHB path bus scale identifier * @irq_name - resource name for the IRQ * @clk_stats - structure of clock statistics - * @l2pc_cpus_mask - mask to avoid L2PC on masked CPUs - * @l2pc_update_queue - Boolean flag to avoid L2PC on masked CPUs at queue time - * @l2pc_cpus_qos - qos structure to avoid L2PC on CPUs * @pm_qos_req_dma - the power management quality of service structure * @pm_qos_active_latency - allowed CPU latency in microseconds when active * @pm_qos_cpu_mask_latency - allowed CPU mask latency in microseconds @@ -197,7 +180,6 @@ struct kgsl_pwrctrl { unsigned int previous_pwrlevel; unsigned int thermal_pwrlevel; unsigned int thermal_pwrlevel_floor; - unsigned int default_pwrlevel; unsigned int wakeup_maxpwrlevel; unsigned int max_pwrlevel; unsigned int min_pwrlevel; @@ -210,9 +192,6 @@ struct kgsl_pwrctrl { uint32_t gpu_cfg; const char *irq_name; struct kgsl_clk_stats clk_stats; - unsigned int l2pc_cpus_mask; - bool l2pc_update_queue; - struct pm_qos_request l2pc_cpus_qos; struct pm_qos_request pm_qos_req_dma; unsigned int pm_qos_active_latency; unsigned int pm_qos_cpu_mask_latency; @@ -284,8 +263,6 @@ int kgsl_active_count_wait(struct kgsl_device *device, int count); void kgsl_pwrctrl_busy_time(struct kgsl_device *device, u64 time, u64 busy); void kgsl_pwrctrl_set_constraint(struct kgsl_device *device, struct kgsl_pwr_constraint *pwrc, uint32_t id); -void kgsl_pwrctrl_update_l2pc(struct kgsl_device *device, - unsigned long timeout_us); int kgsl_pwrctrl_set_default_gpu_pwrlevel(struct kgsl_device *device); void kgsl_pwrctrl_disable_unused_opp(struct kgsl_device *device, struct device *dev); diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 4fdb5e2edaff..20ab59e696e2 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -10,24 +10,6 @@ #include "kgsl_pwrscale.h" #include "kgsl_trace.h" -/* - * "SLEEP" is generic counting both NAP & SLUMBER - * PERIODS generally won't exceed 9 for the relavent 150msec - * window, but can be significantly smaller and still POPP - * pushable in cases where SLUMBER is involved. Hence the - * additional reliance on PERCENT to make sure a reasonable - * amount of down-time actually exists. - */ -#define MIN_SLEEP_PERIODS 3 -#define MIN_SLEEP_PERCENT 5 - -static struct kgsl_popp popp_param[POPP_MAX] = { - {0, 0}, - {-5, 20}, - {-5, 0}, - {0, 0}, -}; - /** * struct kgsl_midframe_info - midframe power stats sampling info * @timer - midframe sampling timer @@ -59,15 +41,10 @@ static struct devfreq_dev_status last_status = { .private_data = &last_xstats }; */ void kgsl_pwrscale_sleep(struct kgsl_device *device) { - struct kgsl_pwrscale *psc = &device->pwrscale; - if (!device->pwrscale.enabled) return; device->pwrscale.on_time = 0; - psc->popp_level = 0; - clear_bit(POPP_PUSH, &device->pwrscale.popp_state); - /* to call devfreq_suspend_device() from a kernel thread */ queue_work(device->pwrscale.devfreq_wq, &device->pwrscale.devfreq_suspend_ws); @@ -141,18 +118,6 @@ void kgsl_pwrscale_update_stats(struct kgsl_device *device) struct kgsl_power_stats stats; device->ftbl->power_stats(device, &stats); - if (psc->popp_level) { - u64 x = stats.busy_time; - u64 y = stats.ram_time; - - do_div(x, 100); - do_div(y, 100); - x *= popp_param[psc->popp_level].gpu_x; - y *= popp_param[psc->popp_level].ddr_y; - trace_kgsl_popp_mod(device, x, y); - stats.busy_time += x; - stats.ram_time += y; - } device->pwrscale.accum_stats.busy_time += stats.busy_time; device->pwrscale.accum_stats.ram_time += stats.ram_time; device->pwrscale.accum_stats.ram_wait += stats.ram_wait; @@ -286,7 +251,7 @@ void kgsl_pwrscale_enable(struct kgsl_device *device) * run at default level; */ kgsl_pwrctrl_pwrlevel_change(device, - device->pwrctrl.default_pwrlevel); + device->pwrctrl.num_pwrlevels - 1); device->pwrscale.enabled = false; } } @@ -307,194 +272,6 @@ static int _thermal_adjust(struct kgsl_pwrctrl *pwr, int level) return level; } -/* - * Use various metrics including level stability, NAP intervals, and - * overall GPU freq / DDR freq combination to decide if POPP should - * be activated. - */ -static bool popp_stable(struct kgsl_device *device) -{ - s64 t; - s64 nap_time = 0; - s64 go_time = 0; - int i, index; - int nap = 0; - s64 percent_nap = 0; - struct kgsl_pwr_event *e; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - struct kgsl_pwrscale *psc = &device->pwrscale; - - if (!test_bit(POPP_ON, &psc->popp_state)) - return false; - - /* If already pushed or running naturally at min don't push further */ - if (test_bit(POPP_PUSH, &psc->popp_state)) - return false; - if (!psc->popp_level && - (pwr->active_pwrlevel == pwr->min_pwrlevel)) - return false; - if (psc->history[KGSL_PWREVENT_STATE].events == NULL) - return false; - - t = ktime_to_ms(ktime_get()); - /* Check for recent NAP statistics: NAPping regularly and well? */ - if (pwr->active_pwrlevel == 0) { - index = psc->history[KGSL_PWREVENT_STATE].index; - i = index > 0 ? (index - 1) : - (psc->history[KGSL_PWREVENT_STATE].size - 1); - while (i != index) { - e = &psc->history[KGSL_PWREVENT_STATE].events[i]; - if (e->data == KGSL_STATE_NAP || - e->data == KGSL_STATE_SLUMBER) { - if (ktime_to_ms(e->start) + STABLE_TIME > t) { - nap++; - nap_time += e->duration; - } - } else if (e->data == KGSL_STATE_ACTIVE) { - if (ktime_to_ms(e->start) + STABLE_TIME > t) - go_time += e->duration; - } - if (i == 0) - i = psc->history[KGSL_PWREVENT_STATE].size - 1; - else - i--; - } - if (nap_time && go_time) { - percent_nap = 100 * nap_time; - div64_s64(percent_nap, nap_time + go_time); - } - trace_kgsl_popp_nap(device, (int)nap_time / 1000, nap, - percent_nap); - /* If running high at turbo, don't push */ - if (nap < MIN_SLEEP_PERIODS || percent_nap < MIN_SLEEP_PERCENT) - return false; - } - - /* Finally check that there hasn't been a recent change */ - if ((device->pwrscale.freq_change_time + STABLE_TIME) < t) { - device->pwrscale.freq_change_time = t; - return true; - } - return false; -} - -bool kgsl_popp_check(struct kgsl_device *device) -{ - int i; - unsigned int index; - struct kgsl_pwrscale *psc = &device->pwrscale; - struct kgsl_pwr_event *e; - - if (!test_bit(POPP_ON, &psc->popp_state)) - return false; - if (!test_bit(POPP_PUSH, &psc->popp_state)) - return false; - if (psc->history[KGSL_PWREVENT_STATE].events == NULL) { - clear_bit(POPP_PUSH, &psc->popp_state); - return false; - } - index = psc->history[KGSL_PWREVENT_STATE].index; - - e = &psc->history[KGSL_PWREVENT_STATE].events[index]; - if (e->data == KGSL_STATE_SLUMBER) - e->duration = ktime_us_delta(ktime_get(), e->start); - - /* If there's been a long SLUMBER in recent history, clear the _PUSH */ - for (i = 0; i < psc->history[KGSL_PWREVENT_STATE].size; i++) { - e = &psc->history[KGSL_PWREVENT_STATE].events[i]; - if ((e->data == KGSL_STATE_SLUMBER) && - (e->duration > POPP_RESET_TIME)) { - clear_bit(POPP_PUSH, &psc->popp_state); - return false; - } - } - return true; -} - -/* - * The GPU has been running at the current frequency for a while. Attempt - * to lower the frequency for boarderline cases. - */ -static void popp_trans1(struct kgsl_device *device) -{ - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - struct kgsl_pwrlevel *pl = &pwr->pwrlevels[pwr->active_pwrlevel]; - struct kgsl_pwrscale *psc = &device->pwrscale; - int old_level = psc->popp_level; - - switch (old_level) { - case 0: - psc->popp_level = 2; - /* If the current level has a high default bus don't push it */ - if (pl->bus_freq == pl->bus_max) - pwr->bus_mod = 1; - kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel + 1); - break; - case 1: - case 2: - psc->popp_level++; - break; - case 3: - set_bit(POPP_PUSH, &psc->popp_state); - psc->popp_level = 0; - break; - case POPP_MAX: - default: - psc->popp_level = 0; - break; - } - - trace_kgsl_popp_level(device, old_level, psc->popp_level); -} - -/* - * The GPU DCVS algorithm recommends a level change. Apply any - * POPP restrictions and update the level accordingly - */ -static int popp_trans2(struct kgsl_device *device, int level) -{ - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - struct kgsl_pwrscale *psc = &device->pwrscale; - int old_level = psc->popp_level; - - if (!test_bit(POPP_ON, &psc->popp_state)) - return level; - - clear_bit(POPP_PUSH, &psc->popp_state); - /* If the governor recommends going down, do it! */ - if (pwr->active_pwrlevel < level) { - psc->popp_level = 0; - trace_kgsl_popp_level(device, old_level, psc->popp_level); - return level; - } - - switch (psc->popp_level) { - case 0: - /* If the feature isn't engaged, go up immediately */ - break; - case 1: - /* Turn off mitigation, and go up a level */ - psc->popp_level = 0; - break; - case 2: - case 3: - /* Try a more aggressive mitigation */ - psc->popp_level--; - level++; - /* Update the stable timestamp */ - device->pwrscale.freq_change_time = ktime_to_ms(ktime_get()); - break; - case POPP_MAX: - default: - psc->popp_level = 0; - break; - } - - trace_kgsl_popp_level(device, old_level, psc->popp_level); - - return level; -} - #ifdef DEVFREQ_FLAG_WAKEUP_MAXFREQ static inline bool _check_maxfreq(u32 flags) { @@ -561,13 +338,11 @@ int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) if (pwr->thermal_cycle == CYCLE_ACTIVE) level = _thermal_adjust(pwr, i); else - level = popp_trans2(device, i); + level = i; break; } if (level != pwr->active_pwrlevel) kgsl_pwrctrl_pwrlevel_change(device, level); - } else if (popp_stable(device)) { - popp_trans1(device); } *freq = kgsl_pwrctrl_active_freq(pwr); @@ -947,7 +722,7 @@ int kgsl_pwrscale_init(struct device *dev, const char *governor) srcu_init_notifier_head(&pwrscale->nh); profile->initial_freq = - pwr->pwrlevels[pwr->default_pwrlevel].gpu_freq; + pwr->pwrlevels[pwr->num_pwrlevels - 1].gpu_freq; /* Let's start with 10 ms and tune in later */ profile->polling_ms = 10; diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h index af07d5b85a08..8072f6c0abd4 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.h +++ b/drivers/gpu/msm/kgsl_pwrscale.h @@ -16,8 +16,7 @@ #define KGSL_PWREVENT_STATE 0 #define KGSL_PWREVENT_GPU_FREQ 1 #define KGSL_PWREVENT_BUS_FREQ 2 -#define KGSL_PWREVENT_POPP 3 -#define KGSL_PWREVENT_MAX 4 +#define KGSL_PWREVENT_MAX 3 /** * Amount of time running at a level to be considered @@ -25,21 +24,6 @@ */ #define STABLE_TIME 150 -/* Amount of idle time needed to re-set stability in usec */ -#define POPP_RESET_TIME 1000000 - -/* Number of POPP levels */ -#define POPP_MAX 4 - -/* POPP state bits */ -#define POPP_ON BIT(0) -#define POPP_PUSH BIT(1) - -struct kgsl_popp { - int gpu_x; - int ddr_y; -}; - struct kgsl_power_stats { u64 busy_time; u64 ram_time; @@ -70,7 +54,7 @@ struct kgsl_pwr_history { * @enabled - Whether or not power scaling is enabled * @time - Last submitted sample timestamp * @on_time - Timestamp when gpu busy begins - * @freq_change_time - Timestamp of last freq change or popp update + * @freq_change_time - Timestamp of last freq change * @nh - Notifier for the partner devfreq bus device * @devfreq_wq - Main devfreq workqueue * @devfreq_suspend_ws - Pass device suspension to devfreq @@ -79,8 +63,6 @@ struct kgsl_pwr_history { * @next_governor_call - Timestamp after which the governor may be notified of * a new sample * @history - History of power events with timestamps and durations - * @popp_level - Current level of POPP mitigation - * @popp_state - Control state for POPP, on/off, recently pushed, etc * @cooling_dev - Thermal cooling device handle * @ctxt_aware_enable - Whether or not ctxt aware DCVS feature is enabled * @ctxt_aware_busy_penalty - The time in microseconds required to trigger @@ -106,8 +88,6 @@ struct kgsl_pwrscale { struct work_struct devfreq_notify_ws; ktime_t next_governor_call; struct kgsl_pwr_history history[KGSL_PWREVENT_MAX]; - int popp_level; - unsigned long popp_state; struct thermal_cooling_device *cooling_dev; bool ctxt_aware_enable; unsigned int ctxt_aware_target_pwrlevel; @@ -139,9 +119,6 @@ int kgsl_busmon_get_dev_status(struct device *dev, struct devfreq_dev_status *stat); int kgsl_busmon_get_cur_freq(struct device *dev, unsigned long *freq); -bool kgsl_popp_check(struct kgsl_device *device); - - #define KGSL_PWRSCALE_INIT(_priv_data) { \ .enabled = true, \ .gpu_profile = { \ @@ -161,6 +138,5 @@ bool kgsl_popp_check(struct kgsl_device *device); .history[KGSL_PWREVENT_STATE].size = 20, \ .history[KGSL_PWREVENT_GPU_FREQ].size = 3, \ .history[KGSL_PWREVENT_BUS_FREQ].size = 5, \ - .history[KGSL_PWREVENT_POPP].size = 5, \ } #endif diff --git a/drivers/gpu/msm/kgsl_rgmu.c b/drivers/gpu/msm/kgsl_rgmu.c index ff89170831be..d449dfa6f392 100644 --- a/drivers/gpu/msm/kgsl_rgmu.c +++ b/drivers/gpu/msm/kgsl_rgmu.c @@ -174,7 +174,7 @@ static int rgmu_enable_clks(struct kgsl_device *device) /* Let us set gpu clk to default power level */ ret = rgmu_clk_set_rate(rgmu->gpu_clk, - rgmu->gpu_freqs[pwr->default_pwrlevel]); + rgmu->gpu_freqs[pwr->num_pwrlevels - 1]); if (ret) return ret; diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c index a90b9e359571..68a89fd17aab 100644 --- a/drivers/gpu/msm/kgsl_sync.c +++ b/drivers/gpu/msm/kgsl_sync.c @@ -404,54 +404,8 @@ static void kgsl_sync_fence_callback(struct dma_fence *fence, } } -static void kgsl_get_fence_names(struct dma_fence *fence, - struct event_fence_info *info_ptr) -{ - unsigned int num_fences; - struct dma_fence **fences; - struct dma_fence_array *array; - int i; - - if (!info_ptr) - return; - - array = to_dma_fence_array(fence); - - if (array != NULL) { - num_fences = array->num_fences; - fences = array->fences; - } else { - num_fences = 1; - fences = &fence; - } - - info_ptr->fences = kcalloc(num_fences, sizeof(struct fence_info), - GFP_ATOMIC); - if (info_ptr->fences == NULL) - return; - - info_ptr->num_fences = num_fences; - - for (i = 0; i < num_fences; i++) { - struct dma_fence *f = fences[i]; - struct fence_info *fi = &info_ptr->fences[i]; - int len; - - len = scnprintf(fi->name, sizeof(fi->name), "%s %s", - f->ops->get_driver_name(f), - f->ops->get_timeline_name(f)); - - if (f->ops->fence_value_str) { - len += scnprintf(fi->name + len, sizeof(fi->name) - len, - ": "); - f->ops->fence_value_str(f, fi->name + len, - sizeof(fi->name) - len); - } - } -} - struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, - bool (*func)(void *priv), void *priv, struct event_fence_info *info_ptr) + bool (*func)(void *priv), void *priv) { struct kgsl_sync_fence_cb *kcb; struct dma_fence *fence; @@ -461,6 +415,11 @@ struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, if (fence == NULL) return ERR_PTR(-EINVAL); + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + dma_fence_put(fence); + return NULL; + } + /* create the callback */ kcb = kzalloc(sizeof(*kcb), GFP_ATOMIC); if (kcb == NULL) { @@ -472,8 +431,6 @@ struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, kcb->priv = priv; kcb->func = func; - kgsl_get_fence_names(fence, info_ptr); - /* if status then error or signaled */ status = dma_fence_add_callback(fence, &kcb->fence_cb, kgsl_sync_fence_callback); diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h index 43209b1532cb..c5a6cccbe3af 100644 --- a/drivers/gpu/msm/kgsl_sync.h +++ b/drivers/gpu/msm/kgsl_sync.h @@ -85,8 +85,7 @@ void kgsl_sync_timeline_destroy(struct kgsl_context *context); void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline); struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, - bool (*func)(void *priv), void *priv, - struct event_fence_info *info_ptr); + bool (*func)(void *priv), void *priv); void kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb); @@ -128,8 +127,7 @@ static inline void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline) static inline struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd, - bool (*func)(void *priv), void *priv, - struct event_fence_info *info_ptr) + bool (*func)(void *priv), void *priv) { return NULL; } diff --git a/drivers/gpu/msm/kgsl_trace.c b/drivers/gpu/msm/kgsl_trace.c index 2ba50fe1b7a9..30a7bcbfb212 100644 --- a/drivers/gpu/msm/kgsl_trace.c +++ b/drivers/gpu/msm/kgsl_trace.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2011,2013,2015,2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2011,2013,2015,2019 The Linux Foundation. All rights reserved. */ #include @@ -10,11 +10,8 @@ /* Instantiate tracepoints */ #define CREATE_TRACE_POINTS #include "kgsl_trace.h" -#include "kgsl_trace_power.h" EXPORT_TRACEPOINT_SYMBOL(kgsl_regwrite); EXPORT_TRACEPOINT_SYMBOL(kgsl_issueibcmds); EXPORT_TRACEPOINT_SYMBOL(kgsl_user_pwrlevel_constraint); EXPORT_TRACEPOINT_SYMBOL(kgsl_constraint); - -EXPORT_TRACEPOINT_SYMBOL(gpu_frequency); diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h index 501d97eb0e3a..566d299823de 100644 --- a/drivers/gpu/msm/kgsl_trace.h +++ b/drivers/gpu/msm/kgsl_trace.h @@ -866,78 +866,6 @@ TRACE_EVENT(kgsl_regwrite, ) ); -TRACE_EVENT(kgsl_popp_level, - - TP_PROTO(struct kgsl_device *device, int level1, int level2), - - TP_ARGS(device, level1, level2), - - TP_STRUCT__entry( - __string(device_name, device->name) - __field(int, level1) - __field(int, level2) - ), - - TP_fast_assign( - __assign_str(device_name, device->name); - __entry->level1 = level1; - __entry->level2 = level2; - ), - - TP_printk( - "d_name=%s old level=%d new level=%d", - __get_str(device_name), __entry->level1, __entry->level2) -); - -TRACE_EVENT(kgsl_popp_mod, - - TP_PROTO(struct kgsl_device *device, int x, int y), - - TP_ARGS(device, x, y), - - TP_STRUCT__entry( - __string(device_name, device->name) - __field(int, x) - __field(int, y) - ), - - TP_fast_assign( - __assign_str(device_name, device->name); - __entry->x = x; - __entry->y = y; - ), - - TP_printk( - "d_name=%s GPU busy mod=%d bus busy mod=%d", - __get_str(device_name), __entry->x, __entry->y) -); - -TRACE_EVENT(kgsl_popp_nap, - - TP_PROTO(struct kgsl_device *device, int t, int nap, int percent), - - TP_ARGS(device, t, nap, percent), - - TP_STRUCT__entry( - __string(device_name, device->name) - __field(int, t) - __field(int, nap) - __field(int, percent) - ), - - TP_fast_assign( - __assign_str(device_name, device->name); - __entry->t = t; - __entry->nap = nap; - __entry->percent = percent; - ), - - TP_printk( - "d_name=%s nap time=%d number of naps=%d percentage=%d", - __get_str(device_name), __entry->t, __entry->nap, - __entry->percent) -); - TRACE_EVENT(kgsl_register_event, TP_PROTO(unsigned int id, unsigned int timestamp, void *func), TP_ARGS(id, timestamp, func), diff --git a/drivers/gpu/msm/kgsl_trace_power.h b/drivers/gpu/msm/kgsl_trace_power.h deleted file mode 100644 index 971beb271713..000000000000 --- a/drivers/gpu/msm/kgsl_trace_power.h +++ /dev/null @@ -1,41 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2020, The Linux Foundation. All rights reserved. - */ - -#if !defined(_KGSL_TRACE_POWER_H) || defined(TRACE_HEADER_MULTI_READ) -#define _KGSL_TRACE_POWER_H - -#undef TRACE_SYSTEM -#define TRACE_SYSTEM power -#undef TRACE_INCLUDE_FILE -#define TRACE_INCLUDE_FILE kgsl_trace_power - -#include - -/** - * gpu_frequency - Reports frequency changes in GPU clock domains - * @state: New frequency (in KHz) - * @gpu_id: GPU clock domain - */ -TRACE_EVENT(gpu_frequency, - TP_PROTO(unsigned int state, unsigned int gpu_id), - TP_ARGS(state, gpu_id), - TP_STRUCT__entry( - __field(unsigned int, state) - __field(unsigned int, gpu_id) - ), - TP_fast_assign( - __entry->state = state; - __entry->gpu_id = gpu_id; - ), - - TP_printk("state=%lu gpu_id=%lu", - (unsigned long)__entry->state, - (unsigned long)__entry->gpu_id) -); - -#endif /* _KGSL_TRACE_POWER_H */ - -/* This part must be outside protection */ -#include diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c index f4cf541d13e0..3eddd8f73b57 100644 --- a/drivers/hid/hid-alps.c +++ b/drivers/hid/hid-alps.c @@ -766,6 +766,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi) if (input_register_device(data->input2)) { input_free_device(input2); + ret = -ENOENT; goto exit; } } diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 05122167d9d8..9b66eb1d42c2 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -93,7 +93,7 @@ EXPORT_SYMBOL_GPL(hid_register_report); * Register a new field for this report. */ -static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages, unsigned values) +static struct hid_field *hid_register_field(struct hid_report *report, unsigned usages) { struct hid_field *field; @@ -104,7 +104,7 @@ static struct hid_field *hid_register_field(struct hid_report *report, unsigned field = kzalloc((sizeof(struct hid_field) + usages * sizeof(struct hid_usage) + - values * sizeof(unsigned)), GFP_KERNEL); + usages * sizeof(unsigned)), GFP_KERNEL); if (!field) return NULL; @@ -300,7 +300,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign usages = max_t(unsigned, parser->local.usage_index, parser->global.report_count); - field = hid_register_field(report, usages, parser->global.report_count); + field = hid_register_field(report, usages); if (!field) return 0; @@ -1128,6 +1128,9 @@ EXPORT_SYMBOL_GPL(hid_open_report); static s32 snto32(__u32 value, unsigned n) { + if (!value || !n) + return 0; + switch (n) { case 8: return ((__s8)value); case 16: return ((__s16)value); diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 1689568b597d..12c5d7c96527 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -26,19 +26,17 @@ #define CP_2WHEEL_MOUSE_HACK 0x02 #define CP_2WHEEL_MOUSE_HACK_ON 0x04 +#define VA_INVAL_LOGICAL_BOUNDARY 0x08 + /* * Some USB barcode readers from cypress have usage min and usage max in * the wrong order */ -static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static __u8 *cp_rdesc_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { - unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); unsigned int i; - if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX)) - return rdesc; - if (*rsize < 4) return rdesc; @@ -51,6 +49,40 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } +static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + /* + * Varmilo VA104M (with VID Cypress and device ID 07B1) incorrectly + * reports Logical Minimum of its Consumer Control device as 572 + * (0x02 0x3c). Fix this by setting its Logical Minimum to zero. + */ + if (*rsize == 25 && + rdesc[0] == 0x05 && rdesc[1] == 0x0c && + rdesc[2] == 0x09 && rdesc[3] == 0x01 && + rdesc[6] == 0x19 && rdesc[7] == 0x00 && + rdesc[11] == 0x16 && rdesc[12] == 0x3c && rdesc[13] == 0x02) { + hid_info(hdev, + "fixing up varmilo VA104M consumer control report descriptor\n"); + rdesc[12] = 0x00; + rdesc[13] = 0x00; + } + return rdesc; +} + +static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + + if (quirks & CP_RDESC_SWAPPED_MIN_MAX) + rdesc = cp_rdesc_fixup(hdev, rdesc, rsize); + if (quirks & VA_INVAL_LOGICAL_BOUNDARY) + rdesc = va_logical_boundary_fixup(hdev, rdesc, rsize); + + return rdesc; +} + static int cp_input_mapped(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) @@ -131,6 +163,8 @@ static const struct hid_device_id cp_devices[] = { .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), .driver_data = CP_2WHEEL_MOUSE_HACK }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1), + .driver_data = VA_INVAL_LOGICAL_BOUNDARY }, { } }; MODULE_DEVICE_TABLE(hid, cp_devices); diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index fab8fd7082e0..3e58d4c3cf2c 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -118,6 +118,8 @@ static int hammer_input_configured(struct hid_device *hdev, } static const struct hid_device_id hammer_devices[] = { + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 5791b01296e0..cc56bd6bb37c 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -330,6 +330,8 @@ #define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 +#define USB_DEVICE_ID_CYPRESS_VARMILO_VA104M_07B1 0X07b1 + #define USB_VENDOR_ID_DATA_MODUL 0x7374 #define USB_VENDOR_ID_DATA_MODUL_EASYMAXTOUCH 0x1201 @@ -356,6 +358,7 @@ #define USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR 0x1803 #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE1 0x1843 #define USB_DEVICE_ID_DRAGONRISE_GAMECUBE2 0x1844 +#define USB_DEVICE_ID_DRAGONRISE_GAMECUBE3 0x1846 #define USB_VENDOR_ID_DWAV 0x0eef #define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 @@ -384,6 +387,7 @@ #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 #define USB_DEVICE_ID_HP_X2 0x074d #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 +#define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 #define USB_VENDOR_ID_ELECOM 0x056e #define USB_DEVICE_ID_ELECOM_BM084 0x0061 @@ -442,6 +446,10 @@ #define USB_VENDOR_ID_FRUCTEL 0x25B6 #define USB_DEVICE_ID_GAMETEL_MT_MODE 0x0002 +#define USB_VENDOR_ID_GAMEVICE 0x27F8 +#define USB_DEVICE_ID_GAMEVICE_GV186 0x0BBE +#define USB_DEVICE_ID_GAMEVICE_KISHI 0x0BBF + #define USB_VENDOR_ID_GAMERON 0x0810 #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR 0x0001 #define USB_DEVICE_ID_GAMERON_DUAL_PCS_ADAPTOR 0x0002 @@ -470,6 +478,7 @@ #define USB_DEVICE_ID_GOOGLE_MASTERBALL 0x503c #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 +#define USB_DEVICE_ID_GOOGLE_DON 0x5050 #define USB_VENDOR_ID_GOTOP 0x08f2 #define USB_DEVICE_ID_SUPER_Q2 0x007f @@ -477,6 +486,7 @@ #define USB_DEVICE_ID_PENPOWER 0x00f4 #define USB_VENDOR_ID_GREENASIA 0x0e8f +#define USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR 0x3010 #define USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD 0x3013 #define USB_VENDOR_ID_GRETAGMACBETH 0x0971 @@ -726,6 +736,7 @@ #define USB_VENDOR_ID_LOGITECH 0x046d #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_T651 0xb00c +#define USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD 0xb309 #define USB_DEVICE_ID_LOGITECH_C007 0xc007 #define USB_DEVICE_ID_LOGITECH_C077 0xc077 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 11bd2ca22a2e..4dd151b2924e 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -331,6 +331,11 @@ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100CHI_KEYBOARD), HID_BATTERY_QUIRK_IGNORE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, + USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), + HID_BATTERY_QUIRK_IGNORE }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), + HID_BATTERY_QUIRK_IGNORE }, {} }; diff --git a/drivers/hid/hid-mf.c b/drivers/hid/hid-mf.c index 03f10516131d..a41202d38509 100644 --- a/drivers/hid/hid-mf.c +++ b/drivers/hid/hid-mf.c @@ -161,6 +161,8 @@ static const struct hid_device_id mf_devices[] = { .driver_data = HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2), .driver_data = 0 }, /* No quirk required */ + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3), + .driver_data = HID_QUIRK_MULTI_INPUT }, { } }; MODULE_DEVICE_TABLE(hid, mf_devices); diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 8ae357bf5a09..43d5f01ffa4a 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -74,6 +74,7 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_REDRAGON_SEYMUR2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1), HID_QUIRK_MULTI_INPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_PS3), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER), HID_QUIRK_MULTI_INPUT | HID_QUIRK_NOGET }, @@ -85,7 +86,12 @@ static const struct hid_device_id hid_quirks[] = { { HID_USB_DEVICE(USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER), HID_QUIRK_NO_INIT_REPORTS }, { HID_USB_DEVICE(USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28), HID_QUIRK_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_FUTABA, USB_DEVICE_ID_LED_DISPLAY), HID_QUIRK_NO_INIT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_SAT_ADAPTOR), HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD), HID_QUIRK_MULTI_INPUT }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_GV186), + HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, + { HID_USB_DEVICE(USB_VENDOR_ID_GAMEVICE, USB_DEVICE_ID_GAMEVICE_KISHI), + HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING), HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, @@ -496,6 +502,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_DOLPHINBAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE1) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_GAMECUBE3) }, #endif #if IS_ENABLED(CONFIG_HID_MICROSOFT) { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 4256fdc5cd6d..21fbdcde1faa 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -496,7 +496,8 @@ static int sensor_hub_raw_event(struct hid_device *hdev, return 1; ptr = raw_data; - ptr++; /* Skip report id */ + if (report->id) + ptr++; /* Skip report id */ spin_lock_irqsave(&pdata->lock, flags); diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c index f98c1e1b1dbd..58a753ef2717 100644 --- a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c @@ -397,6 +397,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = { }, .driver_data = (void *)&sipodev_desc }, + { + .ident = "Vero K147", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VERO"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "K147"), + }, + .driver_data = (void *)&sipodev_desc + }, { } /* Terminate list */ }; diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 8249ff3a5a8d..8006732b8f42 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -150,9 +150,9 @@ static int wacom_wac_pen_serial_enforce(struct hid_device *hdev, } if (flush) - wacom_wac_queue_flush(hdev, &wacom_wac->pen_fifo); + wacom_wac_queue_flush(hdev, wacom_wac->pen_fifo); else if (insert) - wacom_wac_queue_insert(hdev, &wacom_wac->pen_fifo, + wacom_wac_queue_insert(hdev, wacom_wac->pen_fifo, raw_data, report_size); return insert && !flush; @@ -1241,6 +1241,38 @@ static int wacom_devm_sysfs_create_group(struct wacom *wacom, group); } +static void wacom_devm_kfifo_release(struct device *dev, void *res) +{ + struct kfifo_rec_ptr_2 *devres = res; + + kfifo_free(devres); +} + +static int wacom_devm_kfifo_alloc(struct wacom *wacom) +{ + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct kfifo_rec_ptr_2 *pen_fifo; + int error; + + pen_fifo = devres_alloc(wacom_devm_kfifo_release, + sizeof(struct kfifo_rec_ptr_2), + GFP_KERNEL); + + if (!pen_fifo) + return -ENOMEM; + + error = kfifo_alloc(pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL); + if (error) { + devres_free(pen_fifo); + return error; + } + + devres_add(&wacom->hdev->dev, pen_fifo); + wacom_wac->pen_fifo = pen_fifo; + + return 0; +} + enum led_brightness wacom_leds_brightness_get(struct wacom_led *led) { struct wacom *wacom = led->wacom; @@ -2697,7 +2729,7 @@ static int wacom_probe(struct hid_device *hdev, goto fail; } - error = kfifo_alloc(&wacom_wac->pen_fifo, WACOM_PKGLEN_MAX, GFP_KERNEL); + error = wacom_devm_kfifo_alloc(wacom); if (error) goto fail; @@ -2764,8 +2796,6 @@ static void wacom_remove(struct hid_device *hdev) if (wacom->wacom_wac.features.type != REMOTE) wacom_release_resources(wacom); - kfifo_free(&wacom_wac->pen_fifo); - hid_set_drvdata(hdev, NULL); } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index da83884b90d2..10524c93f8b6 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2496,7 +2496,7 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, !wacom_wac->shared->is_touch_on) { if (!wacom_wac->shared->touch_down) return; - prox = 0; + prox = false; } wacom_wac->hid_data.num_received++; @@ -2557,7 +2557,12 @@ static void wacom_wac_finger_event(struct hid_device *hdev, wacom_wac->hid_data.tipswitch = value; break; case HID_DG_CONTACTMAX: - features->touch_max = value; + if (!features->touch_max) { + features->touch_max = value; + } else { + hid_warn(hdev, "%s: ignoring attempt to overwrite non-zero touch_max " + "%d -> %d\n", __func__, features->touch_max, value); + } return; } @@ -3523,8 +3528,6 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, { struct wacom_features *features = &wacom_wac->features; - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - if (!(features->device_type & WACOM_DEVICETYPE_PEN)) return -ENODEV; @@ -3539,6 +3542,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, return 0; } + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(ABS_MISC, input_dev->absbit); @@ -3689,8 +3693,6 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, { struct wacom_features *features = &wacom_wac->features; - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - if (!(features->device_type & WACOM_DEVICETYPE_TOUCH)) return -ENODEV; @@ -3703,6 +3705,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, /* setup has already been done */ return 0; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); __set_bit(BTN_TOUCH, input_dev->keybit); if (features->touch_max == 1) { diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index f67d871841c0..46da97162ef4 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -344,7 +344,7 @@ struct wacom_wac { struct input_dev *pen_input; struct input_dev *touch_input; struct input_dev *pad_input; - struct kfifo_rec_ptr_2 pen_fifo; + struct kfifo_rec_ptr_2 *pen_fifo; int pid; int num_contacts_left; u8 bt_features; diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c index 41a09f506803..129c5e6bc654 100644 --- a/drivers/hsi/controllers/omap_ssi_core.c +++ b/drivers/hsi/controllers/omap_ssi_core.c @@ -389,7 +389,7 @@ static int ssi_add_controller(struct hsi_controller *ssi, err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL); if (err < 0) - goto out_err; + return err; ssi->id = err; ssi->owner = THIS_MODULE; diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 7920b0d7e35a..ac9617671757 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -1001,8 +1001,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) vmbus_device_unregister(channel->device_obj); put_device(dev); } - } - if (channel->primary_channel != NULL) { + } else if (channel->primary_channel != NULL) { /* * Sub-channel is being rescinded. Following is the channel * close sequence when initiated from the driveri (refer to diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index 9ca0706a9d40..325b402b1f3f 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c @@ -1104,16 +1104,16 @@ static unsigned long compute_balloon_floor(void) * 8192 744 (1/16) * 32768 1512 (1/32) */ - if (totalram_pages < MB2PAGES(128)) - min_pages = MB2PAGES(8) + (totalram_pages >> 1); - else if (totalram_pages < MB2PAGES(512)) - min_pages = MB2PAGES(40) + (totalram_pages >> 2); - else if (totalram_pages < MB2PAGES(2048)) - min_pages = MB2PAGES(104) + (totalram_pages >> 3); - else if (totalram_pages < MB2PAGES(8192)) - min_pages = MB2PAGES(232) + (totalram_pages >> 4); + if (totalram_pages() < MB2PAGES(128)) + min_pages = MB2PAGES(8) + (totalram_pages() >> 1); + else if (totalram_pages() < MB2PAGES(512)) + min_pages = MB2PAGES(40) + (totalram_pages() >> 2); + else if (totalram_pages() < MB2PAGES(2048)) + min_pages = MB2PAGES(104) + (totalram_pages() >> 3); + else if (totalram_pages() < MB2PAGES(8192)) + min_pages = MB2PAGES(232) + (totalram_pages() >> 4); else - min_pages = MB2PAGES(488) + (totalram_pages >> 5); + min_pages = MB2PAGES(488) + (totalram_pages() >> 5); #undef MB2PAGES return min_pages; } @@ -1275,7 +1275,7 @@ static void balloon_up(struct work_struct *dummy) /* Refuse to balloon below the floor. */ if (avail_pages < num_pages || avail_pages - num_pages < floor) { - pr_warn("Balloon request will be partially fulfilled. %s\n", + pr_info("Balloon request will be partially fulfilled. %s\n", avail_pages < num_pages ? "Not enough memory." : "Balloon floor reached."); diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index c2f411c290bf..c187e557678e 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -187,6 +187,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, #define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ #define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ #define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ +#define LM90_PAUSE_FOR_CONFIG (1 << 8) /* Pause conversion for config */ /* LM90 status */ #define LM90_STATUS_LTHRM (1 << 0) /* local THERM limit tripped */ @@ -380,6 +381,7 @@ static const struct lm90_params lm90_params[] = { .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, [max6657] = { + .flags = LM90_PAUSE_FOR_CONFIG, .alert_alarms = 0x7c, .max_convrate = 8, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, @@ -580,6 +582,38 @@ static inline int lm90_select_remote_channel(struct i2c_client *client, return 0; } +static int lm90_write_convrate(struct i2c_client *client, + struct lm90_data *data, int val) +{ + int err; + int config_orig, config_stop; + + /* Save config and pause conversion */ + if (data->flags & LM90_PAUSE_FOR_CONFIG) { + config_orig = lm90_read_reg(client, LM90_REG_R_CONFIG1); + if (config_orig < 0) + return config_orig; + config_stop = config_orig | 0x40; + if (config_orig != config_stop) { + err = i2c_smbus_write_byte_data(client, + LM90_REG_W_CONFIG1, + config_stop); + if (err < 0) + return err; + } + } + + /* Set conv rate */ + err = i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, val); + + /* Revert change to config */ + if (data->flags & LM90_PAUSE_FOR_CONFIG && config_orig != config_stop) + i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, + config_orig); + + return err; +} + /* * Set conversion rate. * client->update_lock must be held when calling this function (unless we are @@ -600,7 +634,7 @@ static int lm90_set_convrate(struct i2c_client *client, struct lm90_data *data, if (interval >= update_interval * 3 / 4) break; - err = i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, i); + err = lm90_write_convrate(client, data, i); data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64); return err; } @@ -1606,8 +1640,7 @@ static void lm90_restore_conf(void *_data) struct i2c_client *client = data->client; /* Restore initial configuration */ - i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, - data->convrate_orig); + lm90_write_convrate(client, data, data->convrate_orig); i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, data->config_orig); } @@ -1624,12 +1657,13 @@ static int lm90_init_client(struct i2c_client *client, struct lm90_data *data) /* * Start the conversions. */ - lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ config = lm90_read_reg(client, LM90_REG_R_CONFIG1); if (config < 0) return config; data->config_orig = config; + lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ + /* Check Temperature Range Select */ if (data->kind == adt7461 || data->kind == tmp451) { if (config & 0x04) diff --git a/drivers/hwtracing/Kconfig b/drivers/hwtracing/Kconfig index f68e025c5131..d3c46e534e37 100644 --- a/drivers/hwtracing/Kconfig +++ b/drivers/hwtracing/Kconfig @@ -4,4 +4,6 @@ source "drivers/hwtracing/stm/Kconfig" source "drivers/hwtracing/intel_th/Kconfig" +source "drivers/hwtracing/google/Kconfig" + endmenu diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 8bc9b50b4510..b73c80ec47f9 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -211,6 +211,8 @@ static int tmc_pages_alloc(struct tmc_pages *tmc_pages, } else { page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, 0); + if (!page) + goto err; } paddr = dma_map_page(dev, page, 0, PAGE_SIZE, dir); if (dma_mapping_error(dev, paddr)) diff --git a/drivers/hwtracing/google/Kconfig b/drivers/hwtracing/google/Kconfig new file mode 100644 index 000000000000..8eabf3564432 --- /dev/null +++ b/drivers/hwtracing/google/Kconfig @@ -0,0 +1,15 @@ +config CORESIGHT_PLACEHOLDER + tristate "Coresight device placeholder driver" + default n + depends on !CORESIGHT + help + For targets which do not use coresight, this option enables a placeholder + which probes coresight devices to turn down clocks to save power. + +config CORESIGHT_AMBA_PLACEHOLDER + tristate "Coresight primecell device placeholder driver" + default n + depends on !CORESIGHT + help + For targets which do not use coresight, this option enables a placeholder + which probes coresight AMBA devices to turn down clocks to save power. diff --git a/drivers/hwtracing/google/Makefile b/drivers/hwtracing/google/Makefile new file mode 100644 index 000000000000..5234112456cd --- /dev/null +++ b/drivers/hwtracing/google/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_CORESIGHT_PLACEHOLDER) += coresight-clk-placeholder.o +obj-$(CONFIG_CORESIGHT_AMBA_PLACEHOLDER) += coresight-clk-amba-placeholder.o diff --git a/drivers/hwtracing/google/coresight-clk-amba-placeholder.c b/drivers/hwtracing/google/coresight-clk-amba-placeholder.c new file mode 100644 index 000000000000..f221212febc5 --- /dev/null +++ b/drivers/hwtracing/google/coresight-clk-amba-placeholder.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Google LLC. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int coresight_clk_disable_amba_probe(struct amba_device *adev, + const struct amba_id *id) +{ + pm_runtime_put(&adev->dev); + return 0; +} + +#define ETM4x_AMBA_ID(pid) \ + { \ + .id = pid, .mask = 0x000fffff, \ + } + +#define TMC_ETR_AXI_ARCACHE (0x1U << 1) +#define TMC_ETR_SAVE_RESTORE (0x1U << 2) +#define CORESIGHT_SOC_600_ETR_CAPS (TMC_ETR_SAVE_RESTORE | TMC_ETR_AXI_ARCACHE) + +static const struct amba_id coresight_ids[] = { + /* ETM4 IDs */ + ETM4x_AMBA_ID(0x000bb95d), /* Cortex-A53 */ + ETM4x_AMBA_ID(0x000bb95e), /* Cortex-A57 */ + ETM4x_AMBA_ID(0x000bb95a), /* Cortex-A72 */ + ETM4x_AMBA_ID(0x000bb959), /* Cortex-A73 */ + ETM4x_AMBA_ID(0x000bb9da), /* Cortex-A35 */ + /* dynamic-replicator IDs */ + { + .id = 0x000bb909, + .mask = 0x000fffff, + }, + { + /* Coresight SoC-600 */ + .id = 0x000bb9ec, + .mask = 0x000fffff, + }, + /* dynamic-funnel IDs */ + { + .id = 0x000bb908, + .mask = 0x000fffff, + }, + { + /* Coresight SoC-600 */ + .id = 0x000bb9eb, + .mask = 0x000fffff, + }, + /* coresight-tmc IDs */ + { + .id = 0x000bb961, + .mask = 0x000fffff, + }, + { + /* Coresight SoC 600 TMC-ETR/ETS */ + .id = 0x000bb9e8, + .mask = 0x000fffff, + .data = (void *)(unsigned long)CORESIGHT_SOC_600_ETR_CAPS, + }, + { + /* Coresight SoC 600 TMC-ETB */ + .id = 0x000bb9e9, + .mask = 0x000fffff, + }, + { + /* Coresight SoC 600 TMC-ETF */ + .id = 0x000bb9ea, + .mask = 0x000fffff, + }, + { 0, 0 }, +}; + +static struct amba_driver coresight_clk_disable_amba_driver = { + .drv = { + .name = "coresight-clk-disable-amba", + .suppress_bind_attrs = true, + }, + .probe = coresight_clk_disable_amba_probe, + .id_table = coresight_ids, +}; + +module_amba_driver(coresight_clk_disable_amba_driver); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("CoreSight DEBUGv8 and ETMv4 clock disable AMBA driver stub"); +MODULE_AUTHOR("J. Avila "); diff --git a/drivers/hwtracing/google/coresight-clk-placeholder.c b/drivers/hwtracing/google/coresight-clk-placeholder.c new file mode 100644 index 000000000000..8ac1a9df0a1e --- /dev/null +++ b/drivers/hwtracing/google/coresight-clk-placeholder.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, Google LLC. All rights reserved. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static int coresight_clk_disable_probe(struct platform_device *pdev) +{ + return 0; +} + +static int coresight_clk_disable_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id coresight_clk_disable_match[] = { + { .compatible = "qcom,coresight-csr" }, + {} +}; + +static struct platform_driver coresight_clk_disable_driver = { + .probe = coresight_clk_disable_probe, + .remove = coresight_clk_disable_remove, + .driver = { + .name = "coresight-clk-disable", + .of_match_table = coresight_clk_disable_match, + }, +}; + +module_platform_driver(coresight_clk_disable_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("CoreSight DEBUGv8 and ETMv4 clock disable driver stub"); +MODULE_AUTHOR("J. Avila "); diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index a775d7acfa47..2a1617103394 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -230,6 +230,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { + /* Alder Lake-P */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x51a6), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { /* Emmitsburg PCH */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x1bcc), diff --git a/drivers/hwtracing/stm/heartbeat.c b/drivers/hwtracing/stm/heartbeat.c index 7db42395e131..825c59a77a0e 100644 --- a/drivers/hwtracing/stm/heartbeat.c +++ b/drivers/hwtracing/stm/heartbeat.c @@ -64,7 +64,7 @@ static void stm_heartbeat_unlink(struct stm_source_data *data) static int stm_heartbeat_init(void) { - int i, ret = -ENOMEM; + int i, ret; if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX) return -EINVAL; @@ -72,8 +72,10 @@ static int stm_heartbeat_init(void) for (i = 0; i < nr_devs; i++) { stm_heartbeat[i].data.name = kasprintf(GFP_KERNEL, "heartbeat.%d", i); - if (!stm_heartbeat[i].data.name) + if (!stm_heartbeat[i].data.name) { + ret = -ENOMEM; goto fail_unregister; + } stm_heartbeat[i].data.nr_chans = 1; stm_heartbeat[i].data.link = stm_heartbeat_link; diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c index 826d32049996..2086a96307bf 100644 --- a/drivers/i2c/busses/i2c-brcmstb.c +++ b/drivers/i2c/busses/i2c-brcmstb.c @@ -318,7 +318,7 @@ static int brcmstb_send_i2c_cmd(struct brcmstb_i2c_dev *dev, goto cmd_out; } - if ((CMD_RD || CMD_WR) && + if ((cmd == CMD_RD || cmd == CMD_WR) && bsc_readl(dev, iic_enable) & BSC_IIC_EN_NOACK_MASK) { rc = -EREMOTEIO; dev_dbg(dev->device, "controller received NOACK intr for %s\n", diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 0e7f9bd17a91..83c246e30399 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -404,6 +404,19 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx) dma->chan_using = NULL; } +static void i2c_imx_clear_irq(struct imx_i2c_struct *i2c_imx, unsigned int bits) +{ + unsigned int temp; + + /* + * i2sr_clr_opcode is the value to clear all interrupts. Here we want to + * clear only , so we write ~i2sr_clr_opcode with just + * toggled. This is required because i.MX needs W0C and Vybrid uses W1C. + */ + temp = ~i2c_imx->hwdata->i2sr_clr_opcode ^ bits; + imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); +} + static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) { unsigned long orig_jiffies = jiffies; @@ -416,8 +429,7 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) /* check for arbitration lost */ if (temp & I2SR_IAL) { - temp &= ~I2SR_IAL; - imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); + i2c_imx_clear_irq(i2c_imx, I2SR_IAL); return -EAGAIN; } @@ -448,6 +460,16 @@ static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); return -ETIMEDOUT; } + + /* check for arbitration lost */ + if (i2c_imx->i2csr & I2SR_IAL) { + dev_dbg(&i2c_imx->adapter.dev, "<%s> Arbitration lost\n", __func__); + i2c_imx_clear_irq(i2c_imx, I2SR_IAL); + + i2c_imx->i2csr = 0; + return -EAGAIN; + } + dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); i2c_imx->i2csr = 0; return 0; @@ -557,6 +579,8 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) /* Stop I2C transaction */ dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + if (!(temp & I2CR_MSTA)) + i2c_imx->stopped = 1; temp &= ~(I2CR_MSTA | I2CR_MTX); if (i2c_imx->dma) temp &= ~I2CR_DMAEN; @@ -587,9 +611,7 @@ static irqreturn_t i2c_imx_isr(int irq, void *dev_id) if (temp & I2SR_IIF) { /* save status register */ i2c_imx->i2csr = temp; - temp &= ~I2SR_IIF; - temp |= (i2c_imx->hwdata->i2sr_clr_opcode & I2SR_IIF); - imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2SR); + i2c_imx_clear_irq(i2c_imx, I2SR_IIF); wake_up(&i2c_imx->queue); return IRQ_HANDLED; } @@ -722,9 +744,12 @@ static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx, */ dev_dbg(dev, "<%s> clear MSTA\n", __func__); temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + if (!(temp & I2CR_MSTA)) + i2c_imx->stopped = 1; temp &= ~(I2CR_MSTA | I2CR_MTX); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); + if (!i2c_imx->stopped) + i2c_imx_bus_busy(i2c_imx, 0); } else { /* * For i2c master receiver repeat restart operation like: @@ -847,9 +872,12 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo dev_dbg(&i2c_imx->adapter.dev, "<%s> clear MSTA\n", __func__); temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR); + if (!(temp & I2CR_MSTA)) + i2c_imx->stopped = 1; temp &= ~(I2CR_MSTA | I2CR_MTX); imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); + if (!i2c_imx->stopped) + i2c_imx_bus_busy(i2c_imx, 0); } else { /* * For i2c master receiver repeat restart operation like: diff --git a/drivers/i2c/busses/i2c-octeon-core.c b/drivers/i2c/busses/i2c-octeon-core.c index d9607905dc2f..845eda70b8ca 100644 --- a/drivers/i2c/busses/i2c-octeon-core.c +++ b/drivers/i2c/busses/i2c-octeon-core.c @@ -347,7 +347,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target, if (result) return result; if (recv_len && i == 0) { - if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) + if (data[i] > I2C_SMBUS_BLOCK_MAX) return -EPROTO; length += data[i]; } diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index e7d4b78a451d..43f3077a7d4d 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -169,6 +169,13 @@ static struct geni_i2c_clk_fld geni_i2c_clk_map[] = { {KHz(1000), 1, 3, 9, 18}, }; +int geni_i2c_get_adap_irq(struct i2c_client *client) +{ + struct geni_i2c_dev *gi2c = i2c_get_adapdata(client->adapter); + + return gi2c->irq; +} + static int geni_i2c_clk_map_idx(struct geni_i2c_dev *gi2c) { int i; @@ -1242,6 +1249,7 @@ static struct platform_driver geni_i2c_driver = { .name = "i2c_geni", .pm = &geni_i2c_pm_ops, .of_match_table = geni_i2c_dt_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c index e09cd0775ae9..3417f7dffa94 100644 --- a/drivers/i2c/busses/i2c-qup.c +++ b/drivers/i2c/busses/i2c-qup.c @@ -806,7 +806,8 @@ static int qup_i2c_bam_schedule_desc(struct qup_i2c_dev *qup) if (ret || qup->bus_err || qup->qup_err) { reinit_completion(&qup->xfer); - if (qup_i2c_change_state(qup, QUP_RUN_STATE)) { + ret = qup_i2c_change_state(qup, QUP_RUN_STATE); + if (ret) { dev_err(qup->dev, "change to run state timed out"); goto desc_err; } diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index f9029800d399..3ea2ceec676c 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -117,6 +117,7 @@ enum rcar_i2c_type { }; struct rcar_i2c_priv { + u32 flags; void __iomem *io; struct i2c_adapter adap; struct i2c_msg *msg; @@ -127,7 +128,6 @@ struct rcar_i2c_priv { int pos; u32 icccr; - u32 flags; u8 recovery_icmcr; /* protected by adapter lock */ enum rcar_i2c_type devtype; struct i2c_client *slave; diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index a94e724f51dc..bb1478e781c4 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -71,6 +71,8 @@ /* timeout (ms) for pm runtime autosuspend */ #define SPRD_I2C_PM_TIMEOUT 1000 +/* timeout (ms) for transfer message */ +#define I2C_XFER_TIMEOUT 1000 /* SPRD i2c data structure */ struct sprd_i2c { @@ -244,6 +246,7 @@ static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg *msg, bool is_last_msg) { struct sprd_i2c *i2c_dev = i2c_adap->algo_data; + unsigned long time_left; i2c_dev->msg = msg; i2c_dev->buf = msg->buf; @@ -273,7 +276,10 @@ static int sprd_i2c_handle_msg(struct i2c_adapter *i2c_adap, sprd_i2c_opt_start(i2c_dev); - wait_for_completion(&i2c_dev->complete); + time_left = wait_for_completion_timeout(&i2c_dev->complete, + msecs_to_jiffies(I2C_XFER_TIMEOUT)); + if (!time_left) + return -ETIMEDOUT; return i2c_dev->err; } diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index eb7e533b0dd4..6feafebf85fe 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -49,6 +49,8 @@ #define STM32F7_I2C_CR1_RXDMAEN BIT(15) #define STM32F7_I2C_CR1_TXDMAEN BIT(14) #define STM32F7_I2C_CR1_ANFOFF BIT(12) +#define STM32F7_I2C_CR1_DNF_MASK GENMASK(11, 8) +#define STM32F7_I2C_CR1_DNF(n) (((n) & 0xf) << 8) #define STM32F7_I2C_CR1_ERRIE BIT(7) #define STM32F7_I2C_CR1_TCIE BIT(6) #define STM32F7_I2C_CR1_STOPIE BIT(5) @@ -147,7 +149,7 @@ #define STM32F7_I2C_MAX_SLAVE 0x2 #define STM32F7_I2C_DNF_DEFAULT 0 -#define STM32F7_I2C_DNF_MAX 16 +#define STM32F7_I2C_DNF_MAX 15 #define STM32F7_I2C_ANALOG_FILTER_ENABLE 1 #define STM32F7_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ @@ -645,6 +647,13 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev) else stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_ANFOFF); + + /* Program the Digital Filter */ + stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_DNF_MASK); + stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, + STM32F7_I2C_CR1_DNF(i2c_dev->setup.dnf)); + stm32f7_i2c_set_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_PE); } diff --git a/drivers/i2c/busses/i2c-tegra-bpmp.c b/drivers/i2c/busses/i2c-tegra-bpmp.c index f6cd35d0a2ac..240bd1e90892 100644 --- a/drivers/i2c/busses/i2c-tegra-bpmp.c +++ b/drivers/i2c/busses/i2c-tegra-bpmp.c @@ -91,7 +91,7 @@ static int tegra_bpmp_xlate_flags(u16 flags, u16 *out) flags &= ~I2C_M_RECV_LEN; } - return (flags != 0) ? -EINVAL : 0; + return 0; } /** diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 41dd0a08a625..db6851eb251d 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -262,13 +262,14 @@ EXPORT_SYMBOL_GPL(i2c_recover_bus); static void i2c_init_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - char *err_str; + char *err_str, *err_level = KERN_ERR; if (!bri) return; if (!bri->recover_bus) { - err_str = "no recover_bus() found"; + err_str = "no suitable method provided"; + err_level = KERN_DEBUG; goto err; } @@ -298,7 +299,7 @@ static void i2c_init_recovery(struct i2c_adapter *adap) return; err: - dev_err(&adap->dev, "Not using recovery: %s\n", err_str); + dev_printk(err_level, &adap->dev, "Not using recovery: %s\n", err_str); adap->bus_recovery_info = NULL; } @@ -778,6 +779,9 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.of_node = of_node_get(info->of_node); client->dev.fwnode = info->fwnode; + if (client->flags & I2C_CLIENT_ASYNC_SUSPEND) + device_enable_async_suspend(&client->dev); + i2c_dev_set_name(adap, client, info); if (info->properties) { diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 5f489a5fa3aa..1103762c79f9 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -78,6 +78,9 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, if (ret) return ERR_PTR(ret); + if (of_property_read_bool(node, "async-suspend")) + info.flags |= I2C_CLIENT_ASYNC_SUSPEND; + client = i2c_new_device(adap, &info); if (!client) { dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node); diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 8b2b72b93885..4224c4dd8963 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -213,7 +213,6 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) sense_rq->rq_disk = rq->rq_disk; sense_rq->cmd_flags = REQ_OP_DRV_IN; ide_req(sense_rq)->type = ATA_PRIV_SENSE; - sense_rq->rq_flags |= RQF_PREEMPT; req->cmd[0] = GPCMD_REQUEST_SENSE; req->cmd[4] = cmd_len; diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 0d93e0cfbeaf..438176084610 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -527,11 +527,6 @@ void do_ide_request(struct request_queue *q) * above to return us whatever is in the queue. Since we call * ide_do_request() ourselves, we end up taking requests while * the queue is blocked... - * - * We let requests forced at head of queue with ide-preempt - * though. I hope that doesn't happen too much, hopefully not - * unless the subdriver triggers such a thing in its own PM - * state machine. */ if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && ata_pm_request(rq) == 0 && diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index e5fdca74a630..c22afc979206 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -134,6 +134,12 @@ enum kx_chipset { KX_MAX_CHIPS /* this must be last */ }; +enum kx_acpi_type { + ACPI_GENERIC, + ACPI_SMO8500, + ACPI_KIOX010A, +}; + struct kxcjk1013_data { struct i2c_client *client; struct iio_trigger *dready_trig; @@ -150,7 +156,7 @@ struct kxcjk1013_data { bool motion_trigger_on; int64_t timestamp; enum kx_chipset chipset; - bool is_smo8500_device; + enum kx_acpi_type acpi_type; }; enum kxcjk1013_axis { @@ -277,6 +283,32 @@ static const struct { {19163, 1, 0}, {38326, 0, 1} }; +#ifdef CONFIG_ACPI +enum kiox010a_fn_index { + KIOX010A_SET_LAPTOP_MODE = 1, + KIOX010A_SET_TABLET_MODE = 2, +}; + +static int kiox010a_dsm(struct device *dev, int fn_index) +{ + acpi_handle handle = ACPI_HANDLE(dev); + guid_t kiox010a_dsm_guid; + union acpi_object *obj; + + if (!handle) + return -ENODEV; + + guid_parse("1f339696-d475-4e26-8cad-2e9f8e6d7a91", &kiox010a_dsm_guid); + + obj = acpi_evaluate_dsm(handle, &kiox010a_dsm_guid, 1, fn_index, NULL); + if (!obj) + return -EIO; + + ACPI_FREE(obj); + return 0; +} +#endif + static int kxcjk1013_set_mode(struct kxcjk1013_data *data, enum kxcjk1013_mode mode) { @@ -354,6 +386,13 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) { int ret; +#ifdef CONFIG_ACPI + if (data->acpi_type == ACPI_KIOX010A) { + /* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */ + kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE); + } +#endif + ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_WHO_AM_I); if (ret < 0) { dev_err(&data->client->dev, "Error reading who_am_i\n"); @@ -1241,7 +1280,7 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private) static const char *kxcjk1013_match_acpi_device(struct device *dev, enum kx_chipset *chipset, - bool *is_smo8500_device) + enum kx_acpi_type *acpi_type) { const struct acpi_device_id *id; @@ -1250,7 +1289,9 @@ static const char *kxcjk1013_match_acpi_device(struct device *dev, return NULL; if (strcmp(id->id, "SMO8500") == 0) - *is_smo8500_device = true; + *acpi_type = ACPI_SMO8500; + else if (strcmp(id->id, "KIOX010A") == 0) + *acpi_type = ACPI_KIOX010A; *chipset = (enum kx_chipset)id->driver_data; @@ -1286,7 +1327,7 @@ static int kxcjk1013_probe(struct i2c_client *client, } else if (ACPI_HANDLE(&client->dev)) { name = kxcjk1013_match_acpi_device(&client->dev, &data->chipset, - &data->is_smo8500_device); + &data->acpi_type); } else return -ENODEV; @@ -1304,7 +1345,7 @@ static int kxcjk1013_probe(struct i2c_client *client, indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &kxcjk1013_info; - if (client->irq > 0 && !data->is_smo8500_device) { + if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) { ret = devm_request_threaded_irq(&client->dev, client->irq, kxcjk1013_data_rdy_trig_poll, kxcjk1013_event_handler, diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 94bfb0980355..c17c48916b6b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -702,6 +702,7 @@ config STM32_ADC_CORE depends on ARCH_STM32 || COMPILE_TEST depends on OF depends on REGULATOR + depends on HAS_IOMEM select IIO_BUFFER select MFD_STM32_TIMERS select IIO_STM32_TIMER_TRIGGER diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c index 3680e0d47412..d27246cb3cb6 100644 --- a/drivers/iio/adc/qcom-spmi-vadc.c +++ b/drivers/iio/adc/qcom-spmi-vadc.c @@ -1,14 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * Copyright (c) 2012-2016,2021, The Linux Foundation. All rights reserved. */ #include @@ -560,19 +552,19 @@ static const struct vadc_channels vadc_chans[] = { VADC_CHAN_NO_SCALE(SPARE1_03, 1) VADC_CHAN_NO_SCALE(USB_ID_MV, 1) VADC_CHAN_VOLT(VCOIN, 1, SCALE_DEFAULT) - VADC_CHAN_NO_SCALE(VBAT_SNS, 1) + VADC_CHAN_VOLT(VBAT_SNS, 1, SCALE_DEFAULT) VADC_CHAN_VOLT(VSYS, 1, SCALE_DEFAULT) VADC_CHAN_TEMP(DIE_TEMP, 0, SCALE_PMIC_THERM) VADC_CHAN_VOLT(REF_625MV, 0, SCALE_DEFAULT) VADC_CHAN_VOLT(REF_1250MV, 0, SCALE_DEFAULT) VADC_CHAN_NO_SCALE(CHG_TEMP, 0) - VADC_CHAN_NO_SCALE(SPARE1, 0) + VADC_CHAN_VOLT(SPARE1, 0, SCALE_DEFAULT) VADC_CHAN_TEMP(SPARE2, 0, SCALE_PMI_CHG_TEMP) VADC_CHAN_VOLT(GND_REF, 0, SCALE_DEFAULT) VADC_CHAN_VOLT(VDD_VADC, 0, SCALE_DEFAULT) VADC_CHAN_NO_SCALE(P_MUX1_1_1, 0) - VADC_CHAN_NO_SCALE(P_MUX2_1_1, 0) + VADC_CHAN_TEMP(P_MUX2_1_1, 0, SCALE_THERM_100K_PULLUP) VADC_CHAN_NO_SCALE(P_MUX3_1_1, 0) VADC_CHAN_NO_SCALE(P_MUX4_1_1, 0) VADC_CHAN_NO_SCALE(P_MUX5_1_1, 0) @@ -606,18 +598,18 @@ static const struct vadc_channels vadc_chans[] = { VADC_CHAN_NO_SCALE(P_MUX16_1_3, 1) VADC_CHAN_NO_SCALE(LR_MUX1_BAT_THERM, 0) - VADC_CHAN_NO_SCALE(LR_MUX2_BAT_ID, 0) - VADC_CHAN_NO_SCALE(LR_MUX3_XO_THERM, 0) + VADC_CHAN_VOLT(LR_MUX2_BAT_ID, 0, SCALE_DEFAULT) + VADC_CHAN_TEMP(LR_MUX3_XO_THERM, 0, SCALE_THERM_100K_PULLUP) VADC_CHAN_NO_SCALE(LR_MUX4_AMUX_THM1, 0) VADC_CHAN_NO_SCALE(LR_MUX5_AMUX_THM2, 0) VADC_CHAN_NO_SCALE(LR_MUX6_AMUX_THM3, 0) - VADC_CHAN_NO_SCALE(LR_MUX7_HW_ID, 0) + VADC_CHAN_TEMP(LR_MUX7_HW_ID, 0, SCALE_THERM_100K_PULLUP) VADC_CHAN_NO_SCALE(LR_MUX8_AMUX_THM4, 0) VADC_CHAN_NO_SCALE(LR_MUX9_AMUX_THM5, 0) VADC_CHAN_NO_SCALE(LR_MUX10_USB_ID, 0) VADC_CHAN_NO_SCALE(AMUX_PU1, 0) VADC_CHAN_NO_SCALE(AMUX_PU2, 0) - VADC_CHAN_NO_SCALE(LR_MUX3_BUF_XO_THERM, 0) + VADC_CHAN_TEMP(LR_MUX3_BUF_XO_THERM, 0, SCALE_THERM_100K_PULLUP) VADC_CHAN_NO_SCALE(LR_MUX1_PU1_BAT_THERM, 0) VADC_CHAN_NO_SCALE(LR_MUX2_PU1_BAT_ID, 0) @@ -735,6 +727,12 @@ static int vadc_get_dt_channel_data(struct device *dev, else prop->calibration = VADC_CALIB_ABSOLUTE; + prop->scale_fn_type = -EINVAL; + ret = of_property_read_u32(node, "qcom,scale-fn-type", &value); + + if (!ret && value < SCALE_HW_CALIB_MAX) + prop->scale_fn_type = value; + dev_dbg(dev, "%02x name %s\n", chan, name); return 0; @@ -747,6 +745,7 @@ static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node) struct vadc_channel_prop prop; struct device_node *child; unsigned int index = 0; + bool scale_fn_type_from_dt = false; int ret; vadc->nchannels = of_get_available_child_count(node); @@ -772,14 +771,24 @@ static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node) return ret; } - prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type; + if (prop.scale_fn_type == -EINVAL) { + prop.scale_fn_type = + vadc_chans[prop.channel].scale_fn_type; + } else { + scale_fn_type_from_dt = true; + } + vadc->chan_props[index] = prop; vadc_chan = &vadc_chans[prop.channel]; iio_chan->channel = prop.channel; iio_chan->datasheet_name = vadc_chan->datasheet_name; - iio_chan->info_mask_separate = vadc_chan->info_mask; + if (!scale_fn_type_from_dt) + iio_chan->info_mask_separate = vadc_chan->info_mask; + else + iio_chan->info_mask_separate = + vadc_chan->info_mask | BIT(IIO_CHAN_INFO_PROCESSED); iio_chan->type = vadc_chan->type; iio_chan->indexed = 1; iio_chan->address = index++; diff --git a/drivers/iio/adc/qcom-vadc-common.c b/drivers/iio/adc/qcom-vadc-common.c index 1b2b6f003169..8467d0fbddf4 100644 --- a/drivers/iio/adc/qcom-vadc-common.c +++ b/drivers/iio/adc/qcom-vadc-common.c @@ -759,6 +759,61 @@ static const struct vadc_map_pt adcmap7_100k[] = { { 2420, 130048 } }; +/* Voltage to temperature */ +static const struct vadc_map_pt adcmap_batt_therm_qrd_215[] = { + {1575, -200}, + {1549, -180}, + {1522, -160}, + {1493, -140}, + {1463, -120}, + {1431, -100}, + {1398, -80}, + {1364, -60}, + {1329, -40}, + {1294, -20}, + {1258, 0}, + {1222, 20}, + {1187, 40}, + {1151, 60}, + {1116, 80}, + {1082, 100}, + {1049, 120}, + {1016, 140}, + {985, 160}, + {955, 180}, + {926, 200}, + {899, 220}, + {873, 240}, + {849, 260}, + {825, 280}, + {804, 300}, + {783, 320}, + {764, 340}, + {746, 360}, + {729, 380}, + {714, 400}, + {699, 420}, + {686, 440}, + {673, 460}, + {662, 480}, + {651, 500}, + {641, 520}, + {632, 540}, + {623, 560}, + {615, 580}, + {608, 600}, + {601, 620}, + {595, 640}, + {589, 660}, + {583, 680}, + {578, 700}, + {574, 720}, + {569, 740}, + {565, 760}, + {562, 780}, + {558, 800} +}; + static int qcom_vadc_map_voltage_temp(const struct vadc_map_pt *pts, u32 tablesize, s32 input, s64 *output) { @@ -830,6 +885,10 @@ static int qcom_vadc_scale_volt(const struct vadc_linear_graph *calib_graph, voltage = voltage * prescale->den; result = div64_s64(voltage, prescale->num); + + if (!absolute) + result *= 1000; + *result_uv = result; return 0; @@ -860,6 +919,29 @@ static int qcom_vadc_scale_therm(const struct vadc_linear_graph *calib_graph, return 0; } +static int qcom_vadc_scale_therm_qrd_215( + const struct vadc_linear_graph *calib_graph, + const struct vadc_prescale_ratio *prescale, + bool absolute, u16 adc_code, + int *result_mdec) +{ + s64 voltage = 0, result = 0; + int ret; + + qcom_vadc_scale_calib(calib_graph, adc_code, absolute, &voltage); + + ret = qcom_vadc_map_voltage_temp(adcmap_batt_therm_qrd_215, + ARRAY_SIZE(adcmap_batt_therm_qrd_215), + voltage, &result); + if (ret) + return ret; + + *result_mdec = result; + + return 0; +} + + static int qcom_vadc_scale_die_temp(const struct vadc_linear_graph *calib_graph, const struct vadc_prescale_ratio *prescale, bool absolute, @@ -1307,6 +1389,10 @@ int qcom_vadc_scale(enum vadc_scale_fn_type scaletype, return qcom_vadc_scale_therm(calib_graph, prescale, absolute, adc_code, result); + case SCALE_BATT_THERM_QRD_215: + return qcom_vadc_scale_therm_qrd_215(calib_graph, prescale, + absolute, adc_code, + result); case SCALE_PMIC_THERM: return qcom_vadc_scale_die_temp(calib_graph, prescale, absolute, adc_code, diff --git a/drivers/iio/adc/qcom-vadc-common.h b/drivers/iio/adc/qcom-vadc-common.h index ccebabb5a4f2..e0ff98bf5f15 100644 --- a/drivers/iio/adc/qcom-vadc-common.h +++ b/drivers/iio/adc/qcom-vadc-common.h @@ -198,6 +198,7 @@ enum vadc_scale_fn_type { SCALE_HW_CALIB_PM2250_S3_DIE_TEMP, SCALE_HW_CALIB_THERM_100K_PU_PM7, SCALE_HW_CALIB_PMIC_THERM_PM7, + SCALE_BATT_THERM_QRD_215, SCALE_HW_CALIB_MAX, }; diff --git a/drivers/iio/adc/rockchip_saradc.c b/drivers/iio/adc/rockchip_saradc.c index 1f98566d5b3c..5ae3ce60a33f 100644 --- a/drivers/iio/adc/rockchip_saradc.c +++ b/drivers/iio/adc/rockchip_saradc.c @@ -383,7 +383,7 @@ static int rockchip_saradc_resume(struct device *dev) ret = clk_prepare_enable(info->clk); if (ret) - return ret; + clk_disable_unprepare(info->pclk); return ret; } diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index d9037ea59168..97b9ce305a68 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c @@ -189,9 +189,9 @@ static ssize_t ad5504_write_dac_powerdown(struct iio_dev *indio_dev, return ret; if (pwr_down) - st->pwr_down_mask |= (1 << chan->channel); - else st->pwr_down_mask &= ~(1 << chan->channel); + else + st->pwr_down_mask |= (1 << chan->channel); ret = ad5504_spi_write(st, AD5504_ADDR_CTRL, AD5504_DAC_PWRDWN_MODE(st->pwr_down_mode) | diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c index 5ddebede31a6..33120ccff87f 100644 --- a/drivers/iio/gyro/mpu3050-core.c +++ b/drivers/iio/gyro/mpu3050-core.c @@ -549,6 +549,8 @@ static irqreturn_t mpu3050_trigger_handler(int irq, void *p) MPU3050_FIFO_R, &fifo_values[offset], toread); + if (ret) + goto out_trigger_unlock; dev_dbg(mpu3050->dev, "%04x %04x %04x %04x %04x\n", diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c index 4bc95f31c730..d8c30d94d742 100644 --- a/drivers/iio/humidity/hid-sensor-humidity.c +++ b/drivers/iio/humidity/hid-sensor-humidity.c @@ -28,7 +28,10 @@ struct hid_humidity_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info humidity_attr; - s32 humidity_data; + struct { + s32 humidity_data; + u64 timestamp __aligned(8); + } scan; int scale_pre_decml; int scale_post_decml; int scale_precision; @@ -138,9 +141,8 @@ static int humidity_proc_event(struct hid_sensor_hub_device *hsdev, struct hid_humidity_state *humid_st = iio_priv(indio_dev); if (atomic_read(&humid_st->common_attributes.data_ready)) - iio_push_to_buffers_with_timestamp(indio_dev, - &humid_st->humidity_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_timestamp(indio_dev, &humid_st->scan, + iio_get_time_ns(indio_dev)); return 0; } @@ -155,7 +157,7 @@ static int humidity_capture_sample(struct hid_sensor_hub_device *hsdev, switch (usage_id) { case HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY: - humid_st->humidity_data = *(s32 *)raw_data; + humid_st->scan.humidity_data = *(s32 *)raw_data; return 0; default: diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c index 46a569005a13..ec0f50ec813e 100644 --- a/drivers/iio/imu/adis16400_core.c +++ b/drivers/iio/imu/adis16400_core.c @@ -288,8 +288,7 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev) if (ret) goto err_ret; - ret = sscanf(indio_dev->name, "adis%u\n", &device_id); - if (ret != 1) { + if (sscanf(indio_dev->name, "adis%u\n", &device_id) != 1) { ret = -EINVAL; goto err_ret; } diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c index c85659ca9507..1e413bb233ae 100644 --- a/drivers/iio/imu/bmi160/bmi160_core.c +++ b/drivers/iio/imu/bmi160/bmi160_core.c @@ -110,6 +110,13 @@ enum bmi160_sensor_type { struct bmi160_data { struct regmap *regmap; + /* + * Ensure natural alignment for timestamp if present. + * Max length needed: 2 * 3 channels + 4 bytes padding + 8 byte ts. + * If fewer channels are enabled, less space may be needed, as + * long as the timestamp is still aligned to 8 bytes. + */ + __le16 buf[12] __aligned(8); }; const struct regmap_config bmi160_regmap_config = { @@ -385,8 +392,6 @@ static irqreturn_t bmi160_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct bmi160_data *data = iio_priv(indio_dev); - __le16 buf[16]; - /* 3 sens x 3 axis x __le16 + 3 x __le16 pad + 4 x __le16 tstamp */ int i, ret, j = 0, base = BMI160_REG_DATA_MAGN_XOUT_L; __le16 sample; @@ -396,10 +401,10 @@ static irqreturn_t bmi160_trigger_handler(int irq, void *p) &sample, sizeof(sample)); if (ret < 0) goto done; - buf[j++] = sample; + data->buf[j++] = sample; } - iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_push_to_buffers_with_timestamp(indio_dev, data->buf, iio_get_time_ns(indio_dev)); done: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c index 631360b14ca7..4d89de0be58b 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c @@ -475,13 +475,29 @@ static irqreturn_t st_lsm6dsx_handler_irq(int irq, void *private) static irqreturn_t st_lsm6dsx_handler_thread(int irq, void *private) { struct st_lsm6dsx_hw *hw = private; - int count; + int fifo_len = 0, len; - mutex_lock(&hw->fifo_lock); - count = st_lsm6dsx_read_fifo(hw); - mutex_unlock(&hw->fifo_lock); + /* + * If we are using edge IRQs, new samples can arrive while + * processing current interrupt since there are no hw + * guarantees the irq line stays "low" long enough to properly + * detect the new interrupt. In this case the new sample will + * be missed. + * Polling FIFO status register allow us to read new + * samples even if the interrupt arrives while processing + * previous data and the timeslot where the line is "low" is + * too short to be properly detected. + */ + do { + mutex_lock(&hw->fifo_lock); + len = st_lsm6dsx_read_fifo(hw); + mutex_unlock(&hw->fifo_lock); + + if (len > 0) + fifo_len += len; + } while (len > 0); - return !count ? IRQ_NONE : IRQ_HANDLED; + return fifo_len ? IRQ_HANDLED : IRQ_NONE; } static int st_lsm6dsx_buffer_preenable(struct iio_dev *iio_dev) diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c index a0d089afa1a2..61b9e1bbcc31 100644 --- a/drivers/iio/industrialio-buffer.c +++ b/drivers/iio/industrialio-buffer.c @@ -850,12 +850,12 @@ static int iio_buffer_update_demux(struct iio_dev *indio_dev, indio_dev->masklength, in_ind + 1); while (in_ind != out_ind) { - in_ind = find_next_bit(indio_dev->active_scan_mask, - indio_dev->masklength, - in_ind + 1); length = iio_storage_bytes_for_si(indio_dev, in_ind); /* Make sure we are aligned */ in_loc = roundup(in_loc, length) + length; + in_ind = find_next_bit(indio_dev->active_scan_mask, + indio_dev->masklength, + in_ind + 1); } length = iio_storage_bytes_for_si(indio_dev, in_ind); out_loc = roundup(out_loc, length); diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index cf5a0c242609..3c25d6bb3764 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -37,6 +37,9 @@ struct prox_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info prox_attr; u32 human_presence; + int scale_pre_decml; + int scale_post_decml; + int scale_precision; }; /* Channel definitions */ @@ -107,8 +110,9 @@ static int prox_read_raw(struct iio_dev *indio_dev, ret_type = IIO_VAL_INT; break; case IIO_CHAN_INFO_SCALE: - *val = prox_state->prox_attr.units; - ret_type = IIO_VAL_INT; + *val = prox_state->scale_pre_decml; + *val2 = prox_state->scale_post_decml; + ret_type = prox_state->scale_precision; break; case IIO_CHAN_INFO_OFFSET: *val = hid_sensor_convert_exponent( @@ -248,6 +252,11 @@ static int prox_parse_report(struct platform_device *pdev, HID_USAGE_SENSOR_HUMAN_PRESENCE, &st->common_attributes.sensitivity); + st->scale_precision = hid_sensor_format_scale( + hsdev->usage, + &st->prox_attr, + &st->scale_pre_decml, &st->scale_post_decml); + return ret; } diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c index ffe9ce798ea2..d61c0645244e 100644 --- a/drivers/iio/light/rpr0521.c +++ b/drivers/iio/light/rpr0521.c @@ -197,6 +197,17 @@ struct rpr0521_data { bool pxs_need_dis; struct regmap *regmap; + + /* + * Ensure correct naturally aligned timestamp. + * Note that the read will put garbage data into + * the padding but this should not be a problem + */ + struct { + __le16 channels[3]; + u8 garbage; + s64 ts __aligned(8); + } scan; }; static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL); @@ -452,8 +463,6 @@ static irqreturn_t rpr0521_trigger_consumer_handler(int irq, void *p) struct rpr0521_data *data = iio_priv(indio_dev); int err; - u8 buffer[16]; /* 3 16-bit channels + padding + ts */ - /* Use irq timestamp when reasonable. */ if (iio_trigger_using_own(indio_dev) && data->irq_timestamp) { pf->timestamp = data->irq_timestamp; @@ -464,11 +473,11 @@ static irqreturn_t rpr0521_trigger_consumer_handler(int irq, void *p) pf->timestamp = iio_get_time_ns(indio_dev); err = regmap_bulk_read(data->regmap, RPR0521_REG_PXS_DATA, - &buffer, + data->scan.channels, (3 * 2) + 1); /* 3 * 16-bit + (discarded) int clear reg. */ if (!err) iio_push_to_buffers_with_timestamp(indio_dev, - buffer, pf->timestamp); + &data->scan, pf->timestamp); else dev_err(&data->client->dev, "Trigger consumer can't read from sensor.\n"); diff --git a/drivers/iio/light/st_uvis25.h b/drivers/iio/light/st_uvis25.h index 5e970ab480cd..f9bb7a5755dd 100644 --- a/drivers/iio/light/st_uvis25.h +++ b/drivers/iio/light/st_uvis25.h @@ -28,6 +28,11 @@ struct st_uvis25_hw { struct iio_trigger *trig; bool enabled; int irq; + /* Ensure timestamp is naturally aligned */ + struct { + u8 chan; + s64 ts __aligned(8); + } scan; }; extern const struct dev_pm_ops st_uvis25_pm_ops; diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c index 302635836e6b..815211e024a8 100644 --- a/drivers/iio/light/st_uvis25_core.c +++ b/drivers/iio/light/st_uvis25_core.c @@ -235,17 +235,19 @@ static const struct iio_buffer_setup_ops st_uvis25_buffer_ops = { static irqreturn_t st_uvis25_buffer_handler_thread(int irq, void *p) { - u8 buffer[ALIGN(sizeof(u8), sizeof(s64)) + sizeof(s64)]; struct iio_poll_func *pf = p; struct iio_dev *iio_dev = pf->indio_dev; struct st_uvis25_hw *hw = iio_priv(iio_dev); + unsigned int val; int err; - err = regmap_read(hw->regmap, ST_UVIS25_REG_OUT_ADDR, (int *)buffer); + err = regmap_read(hw->regmap, ST_UVIS25_REG_OUT_ADDR, &val); if (err < 0) goto out; - iio_push_to_buffers_with_timestamp(iio_dev, buffer, + hw->scan.chan = val; + + iio_push_to_buffers_with_timestamp(iio_dev, &hw->scan, iio_get_time_ns(iio_dev)); out: diff --git a/drivers/iio/magnetometer/mag3110.c b/drivers/iio/magnetometer/mag3110.c index f063355480ba..57fbe5bfe883 100644 --- a/drivers/iio/magnetometer/mag3110.c +++ b/drivers/iio/magnetometer/mag3110.c @@ -56,6 +56,12 @@ struct mag3110_data { struct mutex lock; u8 ctrl_reg1; int sleep_val; + /* Ensure natural alignment of timestamp */ + struct { + __be16 channels[3]; + u8 temperature; + s64 ts __aligned(8); + } scan; }; static int mag3110_request(struct mag3110_data *data) @@ -387,10 +393,9 @@ static irqreturn_t mag3110_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct mag3110_data *data = iio_priv(indio_dev); - u8 buffer[16]; /* 3 16-bit channels + 1 byte temp + padding + ts */ int ret; - ret = mag3110_read(data, (__be16 *) buffer); + ret = mag3110_read(data, data->scan.channels); if (ret < 0) goto done; @@ -399,10 +404,10 @@ static irqreturn_t mag3110_trigger_handler(int irq, void *p) MAG3110_DIE_TEMP); if (ret < 0) goto done; - buffer[6] = ret; + data->scan.temperature = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: diff --git a/drivers/iio/pressure/mpl3115.c b/drivers/iio/pressure/mpl3115.c index 7537547fb7ee..bd001062dc65 100644 --- a/drivers/iio/pressure/mpl3115.c +++ b/drivers/iio/pressure/mpl3115.c @@ -147,7 +147,14 @@ static irqreturn_t mpl3115_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct mpl3115_data *data = iio_priv(indio_dev); - u8 buffer[16]; /* 32-bit channel + 16-bit channel + padding + ts */ + /* + * 32-bit channel + 16-bit channel + padding + ts + * Note that it is possible for only one of the first 2 + * channels to be enabled. If that happens, the first element + * of the buffer may be either 16 or 32-bits. As such we cannot + * use a simple structure definition to express this data layout. + */ + u8 buffer[16] __aligned(8); int ret, pos = 0; mutex_lock(&data->lock); diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c index b592fc4f007e..d710a1a66817 100644 --- a/drivers/iio/temperature/hid-sensor-temperature.c +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -28,7 +28,10 @@ struct temperature_state { struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info temperature_attr; - s32 temperature_data; + struct { + s32 temperature_data; + u64 timestamp __aligned(8); + } scan; int scale_pre_decml; int scale_post_decml; int scale_precision; @@ -45,7 +48,7 @@ static const struct iio_chan_spec temperature_channels[] = { BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_HYSTERESIS), }, - IIO_CHAN_SOFT_TIMESTAMP(3), + IIO_CHAN_SOFT_TIMESTAMP(1), }; /* Adjust channel real bits based on report descriptor */ @@ -136,9 +139,8 @@ static int temperature_proc_event(struct hid_sensor_hub_device *hsdev, struct temperature_state *temp_st = iio_priv(indio_dev); if (atomic_read(&temp_st->common_attributes.data_ready)) - iio_push_to_buffers_with_timestamp(indio_dev, - &temp_st->temperature_data, - iio_get_time_ns(indio_dev)); + iio_push_to_buffers_with_timestamp(indio_dev, &temp_st->scan, + iio_get_time_ns(indio_dev)); return 0; } @@ -153,7 +155,7 @@ static int temperature_capture_sample(struct hid_sensor_hub_device *hsdev, switch (usage_id) { case HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE: - temp_st->temperature_data = *(s32 *)raw_data; + temp_st->scan.temperature_data = *(s32 *)raw_data; return 0; default: return -EINVAL; diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 4ebf63360a69..9bdb3fd97d26 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1443,6 +1443,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, id.local_id); if (IS_ERR(cm_id_priv->timewait_info)) { ret = PTR_ERR(cm_id_priv->timewait_info); + cm_id_priv->timewait_info = NULL; goto out; } @@ -1969,6 +1970,7 @@ static int cm_req_handler(struct cm_work *work) id.local_id); if (IS_ERR(cm_id_priv->timewait_info)) { ret = PTR_ERR(cm_id_priv->timewait_info); + cm_id_priv->timewait_info = NULL; goto destroy; } cm_id_priv->timewait_info->work.remote_id = req_msg->local_comm_id; diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index a18f3f8ad77f..471a824be86c 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -366,6 +366,11 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, mutex_lock(&file->mutex); + if (file->agents_dead) { + mutex_unlock(&file->mutex); + return -EIO; + } + while (list_empty(&file->recv_list)) { mutex_unlock(&file->mutex); @@ -379,6 +384,11 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf, mutex_lock(&file->mutex); } + if (file->agents_dead) { + mutex_unlock(&file->mutex); + return -EIO; + } + packet = list_entry(file->recv_list.next, struct ib_umad_packet, list); list_del(&packet->list); @@ -508,7 +518,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf, agent = __get_agent(file, packet->mad.hdr.id); if (!agent) { - ret = -EINVAL; + ret = -EIO; goto err_up; } @@ -637,10 +647,14 @@ static __poll_t ib_umad_poll(struct file *filp, struct poll_table_struct *wait) /* we will always be able to post a MAD send */ __poll_t mask = EPOLLOUT | EPOLLWRNORM; + mutex_lock(&file->mutex); poll_wait(filp, &file->recv_wait, wait); if (!list_empty(&file->recv_list)) mask |= EPOLLIN | EPOLLRDNORM; + if (file->agents_dead) + mask = EPOLLERR; + mutex_unlock(&file->mutex); return mask; } @@ -1257,6 +1271,7 @@ static void ib_umad_kill_port(struct ib_umad_port *port) list_for_each_entry(file, &port->file_list, port_list) { mutex_lock(&file->mutex); file->agents_dead = 1; + wake_up_interruptible(&file->recv_wait); mutex_unlock(&file->mutex); for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index 957da3ffe593..f8c9caa8aad6 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -1838,6 +1838,7 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, goto out; } qp_attr->qp_state = __to_ib_qp_state(qplib_qp->state); + qp_attr->cur_qp_state = __to_ib_qp_state(qplib_qp->cur_qp_state); qp_attr->en_sqd_async_notify = qplib_qp->en_sqd_async_notify ? 1 : 0; qp_attr->qp_access_flags = __to_ib_access_flags(qplib_qp->access); qp_attr->pkey_index = qplib_qp->pkey_index; diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 3fd3dfa3478b..6c1a093b164e 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -3517,13 +3517,14 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) ep->com.local_addr.ss_family == AF_INET) { err = cxgb4_remove_server_filter( ep->com.dev->rdev.lldi.ports[0], ep->stid, - ep->com.dev->rdev.lldi.rxq_ids[0], 0); + ep->com.dev->rdev.lldi.rxq_ids[0], false); } else { struct sockaddr_in6 *sin6; c4iw_init_wr_wait(ep->com.wr_waitp); err = cxgb4_remove_server( ep->com.dev->rdev.lldi.ports[0], ep->stid, - ep->com.dev->rdev.lldi.rxq_ids[0], 0); + ep->com.dev->rdev.lldi.rxq_ids[0], + ep->com.local_addr.ss_family == AF_INET6); if (err) goto done; err = c4iw_wait_for_reply(&ep->com.dev->rdev, ep->com.wr_waitp, diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index 1fd8798d91a7..43c611aa068c 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -1012,6 +1012,9 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, rhp = to_c4iw_dev(ibdev); + if (entries < 1 || entries > ibdev->attrs.max_cqe) + return ERR_PTR(-EINVAL); + if (vector >= rhp->rdev.lldi.nciq) return ERR_PTR(-EINVAL); diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index a9e3a11bea54..caa6a502c37e 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -2485,7 +2485,7 @@ int c4iw_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, init_attr->cap.max_send_wr = qhp->attr.sq_num_entries; init_attr->cap.max_recv_wr = qhp->attr.rq_num_entries; init_attr->cap.max_send_sge = qhp->attr.sq_max_sges; - init_attr->cap.max_recv_sge = qhp->attr.sq_max_sges; + init_attr->cap.max_recv_sge = qhp->attr.rq_max_sges; init_attr->cap.max_inline_data = T4_MAX_SEND_INLINE; init_attr->sq_sig_type = qhp->sq_sig_all ? IB_SIGNAL_ALL_WR : 0; return 0; diff --git a/drivers/infiniband/hw/i40iw/i40iw_main.c b/drivers/infiniband/hw/i40iw/i40iw_main.c index 68095f00d08f..41227d956871 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_main.c +++ b/drivers/infiniband/hw/i40iw/i40iw_main.c @@ -54,10 +54,6 @@ #define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \ __stringify(DRV_VERSION_MINOR) "." __stringify(DRV_VERSION_BUILD) -static int push_mode; -module_param(push_mode, int, 0644); -MODULE_PARM_DESC(push_mode, "Low latency mode: 0=disabled (default), 1=enabled)"); - static int debug; module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "debug flags: 0=disabled (default), 0x7fffffff=all"); @@ -1584,7 +1580,6 @@ static enum i40iw_status_code i40iw_setup_init_state(struct i40iw_handler *hdl, if (status) goto exit; iwdev->obj_next = iwdev->obj_mem; - iwdev->push_mode = push_mode; init_waitqueue_head(&iwdev->vchnl_waitq); init_waitqueue_head(&dev->vf_reqs); diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c index a5e3349b8a7c..314d19153c99 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c +++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c @@ -201,38 +201,16 @@ static int i40iw_dealloc_ucontext(struct ib_ucontext *context) */ static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) { - struct i40iw_ucontext *ucontext; - u64 db_addr_offset; - u64 push_offset; - - ucontext = to_ucontext(context); - if (ucontext->iwdev->sc_dev.is_pf) { - db_addr_offset = I40IW_DB_ADDR_OFFSET; - push_offset = I40IW_PUSH_OFFSET; - if (vma->vm_pgoff) - vma->vm_pgoff += I40IW_PF_FIRST_PUSH_PAGE_INDEX - 1; - } else { - db_addr_offset = I40IW_VF_DB_ADDR_OFFSET; - push_offset = I40IW_VF_PUSH_OFFSET; - if (vma->vm_pgoff) - vma->vm_pgoff += I40IW_VF_FIRST_PUSH_PAGE_INDEX - 1; - } + struct i40iw_ucontext *ucontext = to_ucontext(context); + u64 dbaddr; - vma->vm_pgoff += db_addr_offset >> PAGE_SHIFT; + if (vma->vm_pgoff || vma->vm_end - vma->vm_start != PAGE_SIZE) + return -EINVAL; - if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) { - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - vma->vm_private_data = ucontext; - } else { - if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2) - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - else - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); - } + dbaddr = I40IW_DB_ADDR_OFFSET + pci_resource_start(ucontext->iwdev->ldev->pcidev, 0); - if (io_remap_pfn_range(vma, vma->vm_start, - vma->vm_pgoff + (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >> PAGE_SHIFT), - PAGE_SIZE, vma->vm_page_prot)) + if (io_remap_pfn_range(vma, vma->vm_start, dbaddr >> PAGE_SHIFT, PAGE_SIZE, + pgprot_noncached(vma->vm_page_prot))) return -EAGAIN; return 0; diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c index 4c90a007e09d..c89aec834972 100644 --- a/drivers/infiniband/hw/mlx5/devx.c +++ b/drivers/infiniband/hw/mlx5/devx.c @@ -572,7 +572,9 @@ static void devx_obj_build_destroy_cmd(void *in, void *out, void *din, MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT); break; case MLX5_CMD_OP_CREATE_TIR: - MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR); + *obj_id = MLX5_GET(create_tir_out, out, tirn); + MLX5_SET(destroy_tir_in, din, opcode, MLX5_CMD_OP_DESTROY_TIR); + MLX5_SET(destroy_tir_in, din, tirn, *obj_id); break; case MLX5_CMD_OP_CREATE_TIS: MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS); diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index f41f3ff689c5..1695605eeb52 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -6094,7 +6094,7 @@ int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev) err = mlx5_alloc_bfreg(dev->mdev, &dev->fp_bfreg, false, true); if (err) - mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg); + mlx5_free_bfreg(dev->mdev, &dev->bfreg); return err; } diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index a6531ffe29a6..098653b8157e 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -609,7 +609,7 @@ static inline int mthca_poll_one(struct mthca_dev *dev, entry->byte_len = MTHCA_ATOMIC_BYTE_LEN; break; default: - entry->opcode = MTHCA_OPCODE_INVALID; + entry->opcode = 0xFF; break; } } else { @@ -808,8 +808,10 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, } mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); - if (IS_ERR(mailbox)) + if (IS_ERR(mailbox)) { + err = PTR_ERR(mailbox); goto err_out_arm; + } cq_context = mailbox->buf; @@ -851,9 +853,9 @@ int mthca_init_cq(struct mthca_dev *dev, int nent, } spin_lock_irq(&dev->cq_table.lock); - if (mthca_array_set(&dev->cq_table.cq, - cq->cqn & (dev->limits.num_cqs - 1), - cq)) { + err = mthca_array_set(&dev->cq_table.cq, + cq->cqn & (dev->limits.num_cqs - 1), cq); + if (err) { spin_unlock_irq(&dev->cq_table.lock); goto err_out_free_mr; } diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 220a3e4717a3..e23575861f28 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -105,7 +105,6 @@ enum { MTHCA_OPCODE_ATOMIC_CS = 0x11, MTHCA_OPCODE_ATOMIC_FA = 0x12, MTHCA_OPCODE_BIND_MW = 0x18, - MTHCA_OPCODE_INVALID = 0xff }; enum { diff --git a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c index e611f133aa97..e6c11b5a1669 100644 --- a/drivers/infiniband/hw/usnic/usnic_ib_verbs.c +++ b/drivers/infiniband/hw/usnic/usnic_ib_verbs.c @@ -212,6 +212,7 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev, } usnic_uiom_free_dev_list(dev_list); + dev_list = NULL; } /* Try to find resources on an unused vf */ @@ -236,6 +237,8 @@ find_free_vf_and_create_qp_grp(struct usnic_ib_dev *us_ibdev, qp_grp_check: if (IS_ERR_OR_NULL(qp_grp)) { usnic_err("Failed to allocate qp_grp\n"); + if (usnic_ib_share_vf) + usnic_uiom_free_dev_list(dev_list); return ERR_PTR(qp_grp ? PTR_ERR(qp_grp) : -ENOMEM); } return qp_grp; diff --git a/drivers/infiniband/sw/rxe/Kconfig b/drivers/infiniband/sw/rxe/Kconfig index 67ae960ab523..1fa19a77583e 100644 --- a/drivers/infiniband/sw/rxe/Kconfig +++ b/drivers/infiniband/sw/rxe/Kconfig @@ -3,6 +3,7 @@ config RDMA_RXE depends on INET && PCI && INFINIBAND depends on !64BIT || ARCH_DMA_ADDR_T_64BIT select NET_UDP_TUNNEL + select CRYPTO select CRYPTO_CRC32 select DMA_VIRT_OPS ---help--- diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 7903bd5c639e..04bfc36cc8d7 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -500,6 +500,11 @@ int rxe_send(struct rxe_pkt_info *pkt, struct sk_buff *skb) void rxe_loopback(struct sk_buff *skb) { + if (skb->protocol == htons(ETH_P_IP)) + skb_pull(skb, sizeof(struct iphdr)); + else + skb_pull(skb, sizeof(struct ipv6hdr)); + rxe_rcv(skb); } diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c index b8f3e65402d1..d94e2c5bc317 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -36,21 +36,26 @@ #include "rxe.h" #include "rxe_loc.h" +/* check that QP matches packet opcode type and is in a valid state */ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct rxe_qp *qp) { + unsigned int pkt_type; + if (unlikely(!qp->valid)) goto err1; + pkt_type = pkt->opcode & 0xe0; + switch (qp_type(qp)) { case IB_QPT_RC: - if (unlikely((pkt->opcode & IB_OPCODE_RC) != 0)) { + if (unlikely(pkt_type != IB_OPCODE_RC)) { pr_warn_ratelimited("bad qp type\n"); goto err1; } break; case IB_QPT_UC: - if (unlikely(!(pkt->opcode & IB_OPCODE_UC))) { + if (unlikely(pkt_type != IB_OPCODE_UC)) { pr_warn_ratelimited("bad qp type\n"); goto err1; } @@ -58,7 +63,7 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, case IB_QPT_UD: case IB_QPT_SMI: case IB_QPT_GSI: - if (unlikely(!(pkt->opcode & IB_OPCODE_UD))) { + if (unlikely(pkt_type != IB_OPCODE_UD)) { pr_warn_ratelimited("bad qp type\n"); goto err1; } diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index 1c1eae0ef8c2..63db49144f62 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -664,7 +664,8 @@ int rxe_requester(void *arg) } if (unlikely(qp_type(qp) == IB_QPT_RC && - qp->req.psn > (qp->comp.psn + RXE_MAX_UNACKED_PSNS))) { + psn_compare(qp->req.psn, (qp->comp.psn + + RXE_MAX_UNACKED_PSNS)) > 0)) { qp->req.wait_psn = 1; goto exit; } diff --git a/drivers/input/fingerprint/goodix/gf_spi.c b/drivers/input/fingerprint/goodix/gf_spi.c index ccb97ae6de54..474b01cb402b 100644 --- a/drivers/input/fingerprint/goodix/gf_spi.c +++ b/drivers/input/fingerprint/goodix/gf_spi.c @@ -650,7 +650,7 @@ static int gf_open(struct inode *inode, struct file *filp) gpio_direction_input(gf_dev->irq_gpio); rc = request_threaded_irq(gf_dev->irq, NULL, gf_irq, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, + IRQF_TRIGGER_RISING | IRQF_ONESHOT | IRQF_PERF_AFFINE, "gf", gf_dev); if (!rc) { diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 4c1e427dfabb..7ef6e1c165e3 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -460,7 +460,7 @@ static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, if (IS_ERR(abspam)) return PTR_ERR(abspam); - for (i = 0; i < joydev->nabs; i++) { + for (i = 0; i < len && i < joydev->nabs; i++) { if (abspam[i] > ABS_MAX) { retval = -EINVAL; goto out; @@ -484,6 +484,9 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, int i; int retval = 0; + if (len % sizeof(*keypam)) + return -EINVAL; + len = min(len, sizeof(joydev->keypam)); /* Validate the map. */ @@ -491,7 +494,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, if (IS_ERR(keypam)) return PTR_ERR(keypam); - for (i = 0; i < joydev->nkey; i++) { + for (i = 0; i < (len / 2) && i < joydev->nkey; i++) { if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { retval = -EINVAL; goto out; diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 9adc72d65c63..eacb8af8b4fc 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -229,9 +229,17 @@ static const struct xpad_device { { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE }, - { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a0, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a1, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a2, "PDP Wired Controller for Xbox One - Crimson Red", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x02a6, "PDP Wired Controller for Xbox One - Camo Series", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a7, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a8, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02ad, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02b3, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02b8, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, @@ -255,6 +263,7 @@ static const struct xpad_device { { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 }, { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, + { 0x1209, 0x2882, "Ardwiino Controller", 0, XTYPE_XBOX360 }, { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, { 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, @@ -309,6 +318,10 @@ static const struct xpad_device { { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, + { 0x20d6, 0x2001, "BDA Xbox Series X Wired Controller", 0, XTYPE_XBOXONE }, + { 0x20d6, 0x2009, "PowerA Enhanced Wired Controller for Xbox Series X|S", 0, XTYPE_XBOXONE }, + { 0x20d6, 0x281f, "PowerA Wired Controller For Xbox 360", 0, XTYPE_XBOX360 }, + { 0x2e24, 0x0652, "Hyperkin Duke X-Box One pad", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, @@ -432,6 +445,7 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ XPAD_XBOX360_VENDOR(0x1038), /* SteelSeries Controllers */ XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ + XPAD_XBOX360_VENDOR(0x1209), /* Ardwiino Controllers */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ @@ -441,8 +455,12 @@ static const struct usb_device_id xpad_table[] = { XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ + XPAD_XBOX360_VENDOR(0x20d6), /* PowerA Controllers */ + XPAD_XBOXONE_VENDOR(0x20d6), /* PowerA Controllers */ XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */ + XPAD_XBOXONE_VENDOR(0x2e24), /* Hyperkin Duke X-Box One pad */ + XPAD_XBOX360_VENDOR(0x2f24), /* GameSir Controllers */ { } }; diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index d56001181598..1edf0e8322cc 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -183,6 +183,7 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev, "changed: [r%d c%d]: byte %02x\n", row, col, new_state); + input_event(idev, EV_MSC, MSC_SCAN, pos); input_report_key(idev, keycodes[pos], new_state); } diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index c7f26fa3034c..cf138d836eec 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -96,9 +96,15 @@ static irqreturn_t nspire_keypad_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int nspire_keypad_chip_init(struct nspire_keypad *keypad) +static int nspire_keypad_open(struct input_dev *input) { + struct nspire_keypad *keypad = input_get_drvdata(input); unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles; + int error; + + error = clk_prepare_enable(keypad->clk); + if (error) + return error; cycles_per_us = (clk_get_rate(keypad->clk) / 1000000); if (cycles_per_us == 0) @@ -124,30 +130,6 @@ static int nspire_keypad_chip_init(struct nspire_keypad *keypad) keypad->int_mask = 1 << 1; writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK); - /* Disable GPIO interrupts to prevent hanging on touchpad */ - /* Possibly used to detect touchpad events */ - writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); - /* Acknowledge existing interrupts */ - writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); - - return 0; -} - -static int nspire_keypad_open(struct input_dev *input) -{ - struct nspire_keypad *keypad = input_get_drvdata(input); - int error; - - error = clk_prepare_enable(keypad->clk); - if (error) - return error; - - error = nspire_keypad_chip_init(keypad); - if (error) { - clk_disable_unprepare(keypad->clk); - return error; - } - return 0; } @@ -155,6 +137,11 @@ static void nspire_keypad_close(struct input_dev *input) { struct nspire_keypad *keypad = input_get_drvdata(input); + /* Disable interrupts */ + writel(0, keypad->reg_base + KEYPAD_INTMSK); + /* Acknowledge existing interrupts */ + writel(~0, keypad->reg_base + KEYPAD_INT); + clk_disable_unprepare(keypad->clk); } @@ -215,6 +202,25 @@ static int nspire_keypad_probe(struct platform_device *pdev) return -ENOMEM; } + error = clk_prepare_enable(keypad->clk); + if (error) { + dev_err(&pdev->dev, "failed to enable clock\n"); + return error; + } + + /* Disable interrupts */ + writel(0, keypad->reg_base + KEYPAD_INTMSK); + /* Acknowledge existing interrupts */ + writel(~0, keypad->reg_base + KEYPAD_INT); + + /* Disable GPIO interrupts to prevent hanging on touchpad */ + /* Possibly used to detect touchpad events */ + writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); + /* Acknowledge existing GPIO interrupts */ + writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); + + clk_disable_unprepare(keypad->clk); + input_set_drvdata(input, keypad); input->id.bustype = BUS_HOST; diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index aeeef50cef9b..adb1ecc969ee 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -199,12 +199,8 @@ static int omap4_keypad_open(struct input_dev *input) return 0; } -static void omap4_keypad_close(struct input_dev *input) +static void omap4_keypad_stop(struct omap4_keypad *keypad_data) { - struct omap4_keypad *keypad_data = input_get_drvdata(input); - - disable_irq(keypad_data->irq); - /* Disable interrupts and wake-up events */ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQENABLE, OMAP4_VAL_IRQDISABLE); @@ -213,7 +209,15 @@ static void omap4_keypad_close(struct input_dev *input) /* clear pending interrupts */ kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS, kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); +} + +static void omap4_keypad_close(struct input_dev *input) +{ + struct omap4_keypad *keypad_data; + keypad_data = input_get_drvdata(input); + disable_irq(keypad_data->irq); + omap4_keypad_stop(keypad_data); enable_irq(keypad_data->irq); pm_runtime_put_sync(input->dev.parent); @@ -236,13 +240,37 @@ static int omap4_keypad_parse_dt(struct device *dev, return 0; } +static int omap4_keypad_check_revision(struct device *dev, + struct omap4_keypad *keypad_data) +{ + unsigned int rev; + + rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION); + rev &= 0x03 << 30; + rev >>= 30; + switch (rev) { + case KBD_REVISION_OMAP4: + keypad_data->reg_offset = 0x00; + keypad_data->irqreg_offset = 0x00; + break; + case KBD_REVISION_OMAP5: + keypad_data->reg_offset = 0x10; + keypad_data->irqreg_offset = 0x0c; + break; + default: + dev_err(dev, "Keypad reports unsupported revision %d", rev); + return -EINVAL; + } + + return 0; +} + static int omap4_keypad_probe(struct platform_device *pdev) { struct omap4_keypad *keypad_data; struct input_dev *input_dev; struct resource *res; unsigned int max_keys; - int rev; int irq; int error; @@ -282,41 +310,33 @@ static int omap4_keypad_probe(struct platform_device *pdev) goto err_release_mem; } + pm_runtime_enable(&pdev->dev); /* * Enable clocks for the keypad module so that we can read * revision register. */ - pm_runtime_enable(&pdev->dev); error = pm_runtime_get_sync(&pdev->dev); if (error) { dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); - goto err_unmap; - } - rev = __raw_readl(keypad_data->base + OMAP4_KBD_REVISION); - rev &= 0x03 << 30; - rev >>= 30; - switch (rev) { - case KBD_REVISION_OMAP4: - keypad_data->reg_offset = 0x00; - keypad_data->irqreg_offset = 0x00; - break; - case KBD_REVISION_OMAP5: - keypad_data->reg_offset = 0x10; - keypad_data->irqreg_offset = 0x0c; - break; - default: - dev_err(&pdev->dev, - "Keypad reports unsupported revision %d", rev); - error = -EINVAL; - goto err_pm_put_sync; + pm_runtime_put_noidle(&pdev->dev); + } else { + error = omap4_keypad_check_revision(&pdev->dev, + keypad_data); + if (!error) { + /* Ensure device does not raise interrupts */ + omap4_keypad_stop(keypad_data); + } + pm_runtime_put_sync(&pdev->dev); } + if (error) + goto err_pm_disable; /* input device allocation */ keypad_data->input = input_dev = input_allocate_device(); if (!input_dev) { error = -ENOMEM; - goto err_pm_put_sync; + goto err_pm_disable; } input_dev->name = pdev->name; @@ -362,28 +382,25 @@ static int omap4_keypad_probe(struct platform_device *pdev) goto err_free_keymap; } - device_init_wakeup(&pdev->dev, true); - pm_runtime_put_sync(&pdev->dev); - error = input_register_device(keypad_data->input); if (error < 0) { dev_err(&pdev->dev, "failed to register input device\n"); - goto err_pm_disable; + goto err_free_irq; } + device_init_wakeup(&pdev->dev, true); platform_set_drvdata(pdev, keypad_data); + return 0; -err_pm_disable: - pm_runtime_disable(&pdev->dev); +err_free_irq: free_irq(keypad_data->irq, keypad_data); err_free_keymap: kfree(keypad_data->keymap); err_free_input: input_free_device(input_dev); -err_pm_put_sync: - pm_runtime_put_sync(&pdev->dev); -err_unmap: +err_pm_disable: + pm_runtime_disable(&pdev->dev); iounmap(keypad_data->base); err_release_mem: release_mem_region(res->start, resource_size(res)); diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c index ad5d7f94f95a..1c7aa86c92ab 100644 --- a/drivers/input/keyboard/sunkbd.c +++ b/drivers/input/keyboard/sunkbd.c @@ -111,7 +111,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio, switch (data) { case SUNKBD_RET_RESET: - schedule_work(&sunkbd->tq); + if (sunkbd->enabled) + schedule_work(&sunkbd->tq); sunkbd->reset = -1; break; @@ -212,16 +213,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) } /* - * sunkbd_reinit() sets leds and beeps to a state the computer remembers they - * were in. + * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers + * they were in. */ -static void sunkbd_reinit(struct work_struct *work) +static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd) { - struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); - - wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); - serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); serio_write(sunkbd->serio, (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | @@ -234,11 +231,39 @@ static void sunkbd_reinit(struct work_struct *work) SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); } + +/* + * sunkbd_reinit() wait for the keyboard reset to complete and restores state + * of leds and beeps. + */ + +static void sunkbd_reinit(struct work_struct *work) +{ + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); + + /* + * It is OK that we check sunkbd->enabled without pausing serio, + * as we only want to catch true->false transition that will + * happen once and we will be woken up for it. + */ + wait_event_interruptible_timeout(sunkbd->wait, + sunkbd->reset >= 0 || !sunkbd->enabled, + HZ); + + if (sunkbd->reset >= 0 && sunkbd->enabled) + sunkbd_set_leds_beeps(sunkbd); +} + static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) { serio_pause_rx(sunkbd->serio); sunkbd->enabled = enable; serio_continue_rx(sunkbd->serio); + + if (!enable) { + wake_up_interruptible(&sunkbd->wait); + cancel_work_sync(&sunkbd->tq); + } } /* diff --git a/drivers/input/misc/adxl34x.c b/drivers/input/misc/adxl34x.c index a3e79bf5a04b..3695dd7dbb9b 100644 --- a/drivers/input/misc/adxl34x.c +++ b/drivers/input/misc/adxl34x.c @@ -696,7 +696,7 @@ struct adxl34x *adxl34x_probe(struct device *dev, int irq, struct input_dev *input_dev; const struct adxl34x_platform_data *pdata; int err, range, i; - unsigned char revid; + int revid; if (!irq) { dev_err(dev, "no IRQ?\n"); diff --git a/drivers/input/misc/aw8697_haptic/aw8697.c b/drivers/input/misc/aw8697_haptic/aw8697.c index f2cc799c14f1..a1e98bb850f0 100755 --- a/drivers/input/misc/aw8697_haptic/aw8697.c +++ b/drivers/input/misc/aw8697_haptic/aw8697.c @@ -878,7 +878,6 @@ static int aw8697_haptic_softreset(struct aw8697 *aw8697) static int aw8697_haptic_active(struct aw8697 *aw8697) { - pr_debug("%s enter\n", __func__); aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSCTRL, AW8697_BIT_SYSCTRL_WORK_MODE_MASK, @@ -893,11 +892,9 @@ static int aw8697_haptic_active(struct aw8697 *aw8697) static int aw8697_haptic_play_mode(struct aw8697 *aw8697, unsigned char play_mode) { - pr_debug("%s enter\n", __func__); switch (play_mode) { case AW8697_HAPTIC_STANDBY_MODE: - aw_dev_info(aw8697->dev, "%s: enter standby mode\n", __func__); aw8697->play_mode = AW8697_HAPTIC_STANDBY_MODE; if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSINTM, @@ -911,7 +908,6 @@ static int aw8697_haptic_play_mode(struct aw8697 *aw8697, } break; case AW8697_HAPTIC_RAM_MODE: - aw_dev_info(aw8697->dev, "%s: enter ram mode\n", __func__); aw8697->play_mode = AW8697_HAPTIC_RAM_MODE; if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSCTRL, @@ -933,7 +929,6 @@ static int aw8697_haptic_play_mode(struct aw8697 *aw8697, break; case AW8697_HAPTIC_RAM_LOOP_MODE: - aw_dev_info(aw8697->dev, "%s: enter ram loop mode\n", __func__); aw8697->play_mode = AW8697_HAPTIC_RAM_LOOP_MODE; if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSCTRL, @@ -954,7 +949,6 @@ static int aw8697_haptic_play_mode(struct aw8697 *aw8697, break; case AW8697_HAPTIC_RTP_MODE: - aw_dev_info(aw8697->dev, "%s: enter rtp mode\n", __func__); aw8697->play_mode = AW8697_HAPTIC_RTP_MODE; if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSCTRL, @@ -975,7 +969,6 @@ static int aw8697_haptic_play_mode(struct aw8697 *aw8697, } break; case AW8697_HAPTIC_TRIG_MODE: - aw_dev_info(aw8697->dev, "%s: enter trig mode\n", __func__); aw8697->play_mode = AW8697_HAPTIC_TRIG_MODE; if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSCTRL, @@ -990,7 +983,6 @@ static int aw8697_haptic_play_mode(struct aw8697 *aw8697, break; case AW8697_HAPTIC_CONT_MODE: - aw_dev_info(aw8697->dev, "%s: enter cont mode\n", __func__); aw8697->play_mode = AW8697_HAPTIC_CONT_MODE; if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write_bits(aw8697, AW8697_REG_SYSCTRL, @@ -1049,8 +1041,6 @@ static int aw8697_haptic_stop_delay(struct aw8697 *aw8697) return 0; } msleep(2); - pr_debug("%s wait for standby, reg glb_state=0x%02x\n", - __func__, reg_val); } pr_err("%s do not enter standby automatically\n", __func__); @@ -1063,7 +1053,6 @@ static int aw8697_haptic_stop(struct aw8697 *aw8697) unsigned char reg_val = 0; bool force_flag = true; - aw_dev_info(aw8697->dev, "%s enter\n", __func__); if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_haptic_play_go(aw8697, false); aw8697_haptic_stop_delay(aw8697); @@ -1115,7 +1104,6 @@ static int aw8697_haptic_stop(struct aw8697 *aw8697) static int aw8697_haptic_start(struct aw8697 *aw8697) { - pr_debug("%s enter\n", __func__); aw8697_haptic_play_go(aw8697, true); @@ -2047,8 +2035,6 @@ static int aw869xx_haptic_rtp_init(struct aw8697 *aw8697) } static int16_t aw8697_haptic_effect_strength(struct aw8697 *aw8697) { - pr_debug("%s enter\n", __func__); - pr_debug("%s: aw8697->play.vmax_mv =0x%x\n", __func__, aw8697->play.vmax_mv); #if 0 switch (aw8697->play.vmax_mv) { case AW8697_LIGHT_MAGNITUDE: @@ -2068,13 +2054,12 @@ static int16_t aw8697_haptic_effect_strength(struct aw8697 *aw8697) aw8697->level = 0x80; /*128*/ else if (aw8697->play.vmax_mv <= 0x3FFF) aw8697->level = 0x1E; /*30*/ - else + else aw8697->level = (aw8697->play.vmax_mv - 16383) / 128; - if( aw8697->level < 0x1E) + if (aw8697->level < 0x1E) aw8697->level = 0x1E; /*30*/ #endif - pr_info("%s: aw8697->level =0x%x\n", __func__, aw8697->level); return 0; } @@ -2114,7 +2099,6 @@ static void aw8697_haptic_upload_lra(struct aw8697 *aw8697, unsigned char flag) { switch (flag) { case WRITE_ZERO: - pr_info("%s write zero to trim_lra!\n", __func__); if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write(aw8697, AW8697_REG_TRIM_LRA, 0x00); } else { @@ -2125,8 +2109,6 @@ static void aw8697_haptic_upload_lra(struct aw8697 *aw8697, unsigned char flag) break; case F0_CALI: - pr_info("%s write f0_calib_data to trim_lra = 0x%02X\n", - __func__, aw8697->f0_calib_data); if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write(aw8697, AW8697_REG_TRIM_LRA, (char)aw8697->f0_calib_data); @@ -2137,8 +2119,6 @@ static void aw8697_haptic_upload_lra(struct aw8697 *aw8697, unsigned char flag) } break; case OSC_CALI: - pr_info("%s write lra_calib_data to trim_lra = 0x%02X\n", - __func__, aw8697->lra_calib_data); if (aw8697->chip_version == AW8697_CHIP_9X) { aw8697_i2c_write(aw8697, AW8697_REG_TRIM_LRA, (char)aw8697->lra_calib_data); @@ -3745,9 +3725,6 @@ static void aw8697_vibrator_work_routine(struct work_struct *work) struct aw8697 *aw8697 = container_of(work, struct aw8697, vibrator_work); - pr_debug("%s enter\n", __func__); - pr_info("%s: effect_id = %d state=%d activate_mode = %d duration = %d\n", __func__, - aw8697->effect_id, aw8697->state, aw8697->activate_mode, aw8697->duration); mutex_lock(&aw8697->lock); aw8697_haptic_upload_lra(aw8697, F0_CALI); aw8697_haptic_stop(aw8697); @@ -4212,7 +4189,7 @@ static int aw8697_parse_dt_common(struct device *dev, struct aw8697 *aw8697, __func__); } printk("%s %d effect->pattern_length=%d effect->pattern=%d \n", __func__, __LINE__, - effect->pattern_length, (int)effect->pattern); + effect->pattern_length, (uintptr_t)effect->pattern); effect->play_rate_us = config->play_rate_us; rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us", @@ -4614,19 +4591,13 @@ static int aw8697_haptics_upload_effect(struct input_dev *dev, if (hrtimer_active(&aw8697->timer)) { rem = hrtimer_get_remaining(&aw8697->timer); time_us = ktime_to_us(rem); - printk("waiting for playing clear sequence: %lld us\n", - time_us); usleep_range(time_us, time_us + 100); } - pr_debug("%s: effect->type=0x%x,FF_CONSTANT=0x%x,FF_PERIODIC=0x%x\n", - __func__, effect->type, FF_CONSTANT, FF_PERIODIC); aw8697->effect_type = effect->type; mutex_lock(&aw8697->lock); while (atomic_read(&aw8697->exit_in_rtp_loop)) { - pr_info("%s goint to waiting rtp exit\n", __func__); mutex_unlock(&aw8697->lock); ret = wait_event_interruptible(aw8697->stop_wait_q, atomic_read(&aw8697->exit_in_rtp_loop) == 0); - pr_info("%s wakeup \n", __func__); if (ret == -ERESTARTSYS) { mutex_unlock(&aw8697->lock); pr_err("%s wake up by signal return erro\n", __func__); @@ -4636,7 +4607,6 @@ static int aw8697_haptics_upload_effect(struct input_dev *dev, } if (aw8697->effect_type == FF_CONSTANT) { - pr_debug("%s: effect_type is FF_CONSTANT! \n", __func__); /*cont mode set duration */ aw8697->duration = effect->replay.length; aw8697->activate_mode = AW8697_HAPTIC_ACTIVATE_RAM_LOOP_MODE; @@ -4648,7 +4618,6 @@ static int aw8697_haptics_upload_effect(struct input_dev *dev, return -EINVAL; } - pr_debug("%s: effect_type is FF_PERIODIC! \n", __func__); if (copy_from_user(data, effect->u.periodic.custom_data, sizeof(s16) * CUSTOM_DATA_LEN)) { mutex_unlock(&aw8697->lock); @@ -4656,7 +4625,6 @@ static int aw8697_haptics_upload_effect(struct input_dev *dev, } aw8697->effect_id = data[0]; - pr_debug("%s: aw8697->effect_id =%d \n", __func__, aw8697->effect_id); play->vmax_mv = effect->u.periodic.magnitude; /*vmax level*/ if (aw8697->effect_id < 0 || @@ -4668,22 +4636,16 @@ static int aw8697_haptics_upload_effect(struct input_dev *dev, if (aw8697->effect_id < aw8697->info.effect_id_boundary) { aw8697->activate_mode = AW8697_HAPTIC_ACTIVATE_RAM_MODE; - pr_debug("%s: aw8697->effect_id=%d , aw8697->activate_mode = %d\n", - __func__, aw8697->effect_id, aw8697->activate_mode); data[1] = aw8697->predefined[aw8697->effect_id].play_rate_us/1000000; /*second data*/ data[2] = aw8697->predefined[aw8697->effect_id].play_rate_us/1000; /*millisecond data*/ } if (aw8697->effect_id >= aw8697->info.effect_id_boundary) { aw8697->activate_mode = AW8697_HAPTIC_ACTIVATE_RTP_MODE; - pr_debug("%s: aw8697->effect_id=%d , aw8697->activate_mode = %d\n", - __func__, aw8697->effect_id, aw8697->activate_mode); data[1] = aw8697->info.rtp_time[aw8697->effect_id]/1000; /*second data*/ data[2] = aw8697->info.rtp_time[aw8697->effect_id]; /*millisecond data*/ } if (aw8697->effect_id == CUSTOME_WAVE_ID) { aw8697->activate_mode = AW8697_HAPTIC_ACTIVATE_RTP_MODE; - pr_debug("%s: aw8697->effect_id=%d , aw8697->activate_mode = %d\n", - __func__, aw8697->effect_id, aw8697->activate_mode); data[1] = aw8697->info.rtp_time[aw8697->effect_id]/1000; /*second data*/ data[2] = aw8697->info.rtp_time[aw8697->effect_id]; /*millisecond data*/ aw8697->is_custom_wave = 1; @@ -4715,8 +4677,6 @@ static int aw8697_haptics_playback(struct input_dev *dev, int effect_id, //printk("%s aw8697->effect_id=%d , aw8697->activate_mode = %d\n", // __func__, aw8697->effect_id, aw8697->activate_mode); - pr_debug("%s: effect_id=%d , activate_mode = %d val = %d\n", - __func__, aw8697->effect_id, aw8697->activate_mode, val); /*for osc calibration*/ if (aw8697->osc_cali_run != 0) return 0; @@ -4729,17 +4689,14 @@ static int aw8697_haptics_playback(struct input_dev *dev, int effect_id, if (aw8697->effect_type == FF_CONSTANT && aw8697->activate_mode == AW8697_HAPTIC_ACTIVATE_RAM_LOOP_MODE) { - pr_debug("%s: enter ram_loop_mode \n", __func__); //schedule_work(&aw8697->vibrator_work); queue_work(aw8697->work_queue, &aw8697->vibrator_work); } else if (aw8697->effect_type == FF_PERIODIC && aw8697->activate_mode == AW8697_HAPTIC_ACTIVATE_RAM_MODE) { - pr_debug("%s: enter ram_mode\n", __func__); //schedule_work(&aw8697->vibrator_work) queue_work(aw8697->work_queue, &aw8697->vibrator_work);; } else if ((aw8697->effect_type == FF_PERIODIC) && aw8697->activate_mode == AW8697_HAPTIC_ACTIVATE_RTP_MODE) { - pr_debug("%s: enter rtp_mode\n", __func__); //schedule_work(&aw8697->rtp_work); queue_work(aw8697->work_queue, &aw8697->rtp_work); //if we are in the play mode, force to exit @@ -4764,7 +4721,6 @@ static int aw8697_haptics_erase(struct input_dev *dev, int effect_id) if (aw8697->osc_cali_run != 0) return 0; - pr_debug("%s: enter\n", __func__); aw8697->effect_type = 0; aw8697->is_custom_wave = 0; aw8697->duration = 0; @@ -6827,3 +6783,4 @@ module_exit(aw8697_i2c_exit); MODULE_DESCRIPTION("AW8697 Haptic Driver"); MODULE_LICENSE("GPL v2"); + diff --git a/drivers/input/misc/cm109.c b/drivers/input/misc/cm109.c index 23c191a2a071..cf4d507efaf6 100644 --- a/drivers/input/misc/cm109.c +++ b/drivers/input/misc/cm109.c @@ -571,12 +571,15 @@ static int cm109_input_open(struct input_dev *idev) dev->ctl_data->byte[HID_OR2] = dev->keybit; dev->ctl_data->byte[HID_OR3] = 0x00; + dev->ctl_urb_pending = 1; error = usb_submit_urb(dev->urb_ctl, GFP_KERNEL); - if (error) + if (error) { + dev->ctl_urb_pending = 0; dev_err(&dev->intf->dev, "%s: usb_submit_urb (urb_ctl) failed %d\n", __func__, error); - else + } else { dev->open = 1; + } mutex_unlock(&dev->pm_mutex); diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c index 5763989a39ba..bc67bd6bf556 100644 --- a/drivers/input/misc/qpnp-power-on.c +++ b/drivers/input/misc/qpnp-power-on.c @@ -170,6 +170,7 @@ enum pon_type { PON_RESIN = PON_POWER_ON_TYPE_RESIN, PON_CBLPWR = PON_POWER_ON_TYPE_CBLPWR, PON_KPDPWR_RESIN = PON_POWER_ON_TYPE_KPDPWR_RESIN, + PON_KEY_MAX }; struct qpnp_pon_config { @@ -220,6 +221,7 @@ struct qpnp_pon { int pon_trigger_reason; int pon_power_off_reason; u32 dbc_time_us; + u32 sw_dbc_time_us; u32 uvlo; int warm_reset_poff_type; int hard_reset_poff_type; @@ -233,10 +235,10 @@ struct qpnp_pon { bool resin_shutdown_disable; bool ps_hold_hard_reset_disable; bool ps_hold_shutdown_disable; - bool kpdpwr_dbc_enable; bool resin_pon_reset; - ktime_t kpdpwr_last_release_time; ktime_t time_kpdpwr_bark; + bool sw_dbc_enable; + ktime_t sw_dbc_last_release_time[PON_KEY_MAX]; }; int in_long_press; @@ -1079,10 +1081,10 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) if (!cfg->key_code) return 0; - if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) { + if (pon->sw_dbc_enable) { elapsed_us = ktime_us_delta(ktime_get(), - pon->kpdpwr_last_release_time); - if (elapsed_us < pon->dbc_time_us) { + pon->sw_dbc_last_release_time[cfg->pon_type]); + if (elapsed_us < pon->sw_dbc_time_us) { pr_debug("Ignoring kpdpwr event; within debounce time\n"); return 0; } @@ -1127,10 +1129,8 @@ static int qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type) pon_rt_sts); key_status = pon_rt_sts & pon_rt_bit; - if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) { - if (!key_status) - pon->kpdpwr_last_release_time = ktime_get(); - } + if (pon->sw_dbc_enable && !key_status) + pon->sw_dbc_last_release_time[cfg->pon_type] = ktime_get(); /* * Simulate a press event in case release event occurred without a press @@ -2662,8 +2662,22 @@ static int qpnp_pon_probe(struct platform_device *pdev) if (rc) return rc; - pon->kpdpwr_dbc_enable = of_property_read_bool(dev->of_node, - "qcom,kpdpwr-sw-debounce"); + pon->sw_dbc_enable = of_property_read_bool(dev->of_node, + "qcom,pon-sw-debounce"); + if (pon->sw_dbc_enable) { + rc = of_property_read_u32(dev->of_node, + "qcom,pon-sw-dbc-delay", + &pon->sw_dbc_time_us); + if (rc) { + if (rc == -EINVAL) { + pon->sw_dbc_time_us = pon->dbc_time_us; + } else { + dev_err(dev, "Unable to read software debounce delay rc: %d\n", + rc); + return rc; + } + } + } pon->store_hard_reset_reason = of_property_read_bool(dev->of_node, "qcom,store-hard-reset-reason"); diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c index c1b524ab4623..ba50f5713423 100644 --- a/drivers/input/mouse/cyapa_gen6.c +++ b/drivers/input/mouse/cyapa_gen6.c @@ -573,7 +573,7 @@ static int cyapa_pip_retrieve_data_structure(struct cyapa *cyapa, memset(&cmd, 0, sizeof(cmd)); put_unaligned_le16(PIP_OUTPUT_REPORT_ADDR, &cmd.head.addr); - put_unaligned_le16(sizeof(cmd), &cmd.head.length - 2); + put_unaligned_le16(sizeof(cmd) - 2, &cmd.head.length); cmd.head.report_id = PIP_APP_CMD_REPORT_ID; cmd.head.cmd_code = PIP_RETRIEVE_DATA_STRUCTURE; put_unaligned_le16(read_offset, &cmd.read_offset); diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 51bd2ebaa342..f20e54f41dde 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -224,6 +224,12 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "C15B"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ByteSpeed LLC"), + DMI_MATCH(DMI_PRODUCT_NAME, "ByteSpeed Laptop C15B"), + }, + }, { } }; @@ -586,6 +592,11 @@ static const struct dmi_system_id i8042_dmi_noselftest_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ }, + }, { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */ + }, }, { } }; @@ -611,6 +622,48 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A114-31"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A314-31"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A315-31"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-132"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-332"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire ES1-432"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate Spin B118-RN"), + }, + }, { /* Advent 4211 */ .matches = { diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 95a78ccbd847..c60593c8d2be 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -125,6 +125,7 @@ module_param_named(unmask_kbd_data, i8042_unmask_kbd_data, bool, 0600); MODULE_PARM_DESC(unmask_kbd_data, "Unconditional enable (may reveal sensitive data) of normally sanitize-filtered kbd data traffic debug log [pre-condition: i8042.debug=1 enabled]"); #endif +static bool i8042_present; static bool i8042_bypass_aux_irq_test; static char i8042_kbd_firmware_id[128]; static char i8042_aux_firmware_id[128]; @@ -345,6 +346,9 @@ int i8042_command(unsigned char *param, int command) unsigned long flags; int retval; + if (!i8042_present) + return -1; + spin_lock_irqsave(&i8042_lock, flags); retval = __i8042_command(param, command); spin_unlock_irqrestore(&i8042_lock, flags); @@ -1468,7 +1472,8 @@ static int __init i8042_setup_aux(void) if (error) goto err_free_ports; - if (aux_enable()) + error = aux_enable(); + if (error) goto err_free_irq; i8042_aux_irq_registered = true; @@ -1613,12 +1618,15 @@ static int __init i8042_init(void) err = i8042_platform_init(); if (err) - return err; + return (err == -ENODEV) ? 0 : err; err = i8042_controller_check(); if (err) goto err_platform_exit; + /* Set this before creating the dev to allow i8042_command to work right away */ + i8042_present = true; + pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); if (IS_ERR(pdev)) { err = PTR_ERR(pdev); @@ -1637,6 +1645,9 @@ static int __init i8042_init(void) static void __exit i8042_exit(void) { + if (!i8042_present) + return; + platform_device_unregister(i8042_platform_device); platform_driver_unregister(&i8042_driver); i8042_platform_exit(); diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index e091f49874a0..1058af6753dd 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -97,6 +97,7 @@ config TOUCHSCREEN_AD7879_SPI config TOUCHSCREEN_ADC tristate "Generic ADC based resistive touchscreen" depends on IIO + select IIO_BUFFER select IIO_BUFFER_CB help Say Y here if you want to use the generic ADC diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index a2f45aefce08..b536768234b7 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -35,6 +35,7 @@ #include #include #include +#include /* * This code has been heavily tested on a Nokia 770, and lightly @@ -199,6 +200,26 @@ struct ads7846 { #define REF_ON (READ_12BIT_DFR(x, 1, 1)) #define REF_OFF (READ_12BIT_DFR(y, 0, 0)) +static int get_pendown_state(struct ads7846 *ts) +{ + if (ts->get_pendown_state) + return ts->get_pendown_state(); + + return !gpio_get_value(ts->gpio_pendown); +} + +static void ads7846_report_pen_up(struct ads7846 *ts) +{ + struct input_dev *input = ts->input; + + input_report_key(input, BTN_TOUCH, 0); + input_report_abs(input, ABS_PRESSURE, 0); + input_sync(input); + + ts->pendown = false; + dev_vdbg(&ts->spi->dev, "UP\n"); +} + /* Must be called with ts->lock held */ static void ads7846_stop(struct ads7846 *ts) { @@ -215,6 +236,10 @@ static void ads7846_stop(struct ads7846 *ts) static void ads7846_restart(struct ads7846 *ts) { if (!ts->disabled && !ts->suspended) { + /* Check if pen was released since last stop */ + if (ts->pendown && !get_pendown_state(ts)) + ads7846_report_pen_up(ts); + /* Tell IRQ thread that it may poll the device. */ ts->stopped = false; mb(); @@ -410,7 +435,7 @@ static int ads7845_read12_ser(struct device *dev, unsigned command) if (status == 0) { /* BE12 value, then padding */ - status = be16_to_cpu(*((u16 *)&req->sample[1])); + status = get_unaligned_be16(&req->sample[1]); status = status >> 3; status &= 0x0fff; } @@ -605,14 +630,6 @@ static const struct attribute_group ads784x_attr_group = { /*--------------------------------------------------------------------------*/ -static int get_pendown_state(struct ads7846 *ts) -{ - if (ts->get_pendown_state) - return ts->get_pendown_state(); - - return !gpio_get_value(ts->gpio_pendown); -} - static void null_wait_for_sync(void) { } @@ -785,10 +802,11 @@ static void ads7846_report_state(struct ads7846 *ts) /* compute touch pressure resistance using equation #2 */ Rt = z2; Rt -= z1; - Rt *= x; Rt *= ts->x_plate_ohms; + Rt = DIV_ROUND_CLOSEST(Rt, 16); + Rt *= x; Rt /= z1; - Rt = (Rt + 2047) >> 12; + Rt = DIV_ROUND_CLOSEST(Rt, 256); } else { Rt = 0; } @@ -871,16 +889,8 @@ static irqreturn_t ads7846_irq(int irq, void *handle) msecs_to_jiffies(TS_POLL_PERIOD)); } - if (ts->pendown && !ts->stopped) { - struct input_dev *input = ts->input; - - input_report_key(input, BTN_TOUCH, 0); - input_report_abs(input, ABS_PRESSURE, 0); - input_sync(input); - - ts->pendown = false; - dev_vdbg(&ts->spi->dev, "UP\n"); - } + if (ts->pendown && !ts->stopped) + ads7846_report_pen_up(ts); return IRQ_HANDLED; } diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 7f2942f3cec6..0f3146bcfcd0 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c @@ -345,8 +345,10 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) switch (elo->id) { case 0: /* 10-byte protocol */ - if (elo_setup_10(elo)) + if (elo_setup_10(elo)) { + err = -EIO; goto fail3; + } break; diff --git a/drivers/input/touchscreen/focaltech_touch/include/firmware/fw_ft3518_j11.i b/drivers/input/touchscreen/focaltech_touch/include/firmware/fw_ft3518_j11.i deleted file mode 100644 index a89a4b9af99e..000000000000 --- a/drivers/input/touchscreen/focaltech_touch/include/firmware/fw_ft3518_j11.i +++ /dev/null @@ -1,3362 +0,0 @@ -0x2, 0x1c,0x2d,0x2, 0xc9,0x27,0xe4,0x2, 0x15,0xb, 0x22,0x2, 0x0, 0x71,0x12,0x12, -0xe4,0x2, 0x17,0x2c,0x22,0xeb,0xaa,0x8, 0x22,0x22,0x22,0x2, 0x58,0x17,0x1, 0x2, -0x4, 0x8, 0x10,0x20,0x40,0x80,0x0, 0xd, 0x19,0x23,0x22,0x2, 0x6f,0xcb,0x7f,0x60, -0xa9,0xc2,0xea,0x74,0x1, 0x12,0x18,0x0, 0x7f,0x6, 0x12,0xa, 0x32,0x7f,0x6, 0x2, -0x10,0x0, 0x22,0x2, 0x6f,0xe7,0x7f,0x20,0x2, 0x3d,0xac,0x2, 0x0, 0x72,0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x74,0xff,0x7a,0xb3,0x3c,0xe1,0x22,0x2, 0x13,0xfe,0x12,0x5e, -0xa0,0x74,0x1, 0x7a,0xb3,0x3b,0xf5,0x22,0xe4,0x22,0x22,0x2, 0x0, 0xff,0xa2,0x1c, -0x22,0x32,0x32,0x2, 0x15,0x62,0xca,0xf8,0x7c,0xfb,0x7e,0x34,0x0, 0x1, 0x7e,0xf, -0x37,0xf9,0x79,0x30,0x0, 0x10,0xc2,0x21,0xe4,0x7a,0xb3,0x37,0xf0,0x5e,0xf0,0x3, -0x74,0x3, 0x12,0x17,0x81,0x74,0x1, 0x12,0x15,0xb, 0xa, 0x2f,0x5e,0x24,0x0, 0x3, -0x3e,0x24,0x7e,0xf, 0x3d,0xd8,0xb, 0xa, 0x30,0x5e,0x70,0xf9,0x4d,0x32,0x1b,0xa, -0x30,0x7e,0xf, 0x3d,0xd8,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x7e,0xf, -0x3d,0xd8,0xb, 0xa, 0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x2e,0x14,0x0, 0x9e,0xb, -0xa, 0x30,0x4e,0x70,0x20,0x1b,0xa, 0x30,0x74,0x1, 0x12,0x17,0x81,0x7e,0xf, 0x37, -0xf9,0xb, 0xa, 0x30,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xa9,0xd3,0xcd,0x7e,0xf, 0x37, -0xf9,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0xda,0xf8,0x22,0x32, -0xd2,0x18,0x2d,0xe7,0x7, 0x4a,0xf8,0xb5,0x5b,0x11,0xa4,0xee,0x48,0xb7,0x10,0xef, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0, 0xf, -0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, -0x7c,0x7b,0x7f,0x70,0xbe,0x78,0x0, 0x0, 0x78,0x2, 0x61,0x9e,0xbe,0x70,0x3, 0x40, -0x2, 0x61,0x9e,0xa5,0xbf,0x0, 0x2, 0x80,0x2, 0x41,0xa, 0xb, 0x7a,0x30,0x7e,0xf, -0x3d,0xe0,0x79,0x30,0x0, 0x46,0x69,0x37,0x0, 0x2, 0x7e,0xf, 0x3d,0xe0,0x79,0x30, -0x0, 0x40,0x29,0x77,0x0, 0x4, 0xa, 0x27,0x5e,0x24,0x0, 0x3, 0x7e,0xf, 0x3d,0xe0, -0x2e,0x14,0x0, 0x4c,0xb, 0xa, 0x30,0x5e,0x70,0xfc,0x4d,0x32,0x1b,0xa, 0x30,0x29, -0x77,0x0, 0x5, 0xa, 0x27,0x5e,0x24,0x0, 0x7f,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3d, -0xe0,0x2e,0x14,0x0, 0x12,0xb, 0xa, 0x30,0x5e,0x60,0x80,0x4d,0x32,0x1b,0xa, 0x30, -0x29,0x77,0x0, 0xe, 0xa, 0x27,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3d,0xe0,0x2e,0x14, -0x0, 0x16,0xb, 0xa, 0x30,0x6c,0x66,0x4d,0x32,0x1b,0xa, 0x30,0x29,0x77,0x0, 0xf, -0xa, 0x27,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x22,0xb, 0xa, -0x30,0x6c,0x66,0x4d,0x32,0x1b,0xa, 0x30,0x69,0x37,0x0, 0x6, 0x7e,0xf, 0x3d,0xe0, -0x79,0x30,0x0, 0x50,0x69,0x37,0x0, 0x8, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x56, -0x69,0x37,0x0, 0xa, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x5c,0x69,0x37,0x0, 0xc, -0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x62,0x61,0x66,0xa5,0xbf,0x1, 0x2, 0x80,0x2, -0x41,0xd1,0xb, 0x7a,0x30,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x48,0x69,0x37,0x0, -0x2, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x42,0x29,0x77,0x0, 0x4, 0xa, 0x27,0x5e, -0x24,0x0, 0x3, 0x3e,0x24,0x3e,0x24,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x4c,0xb, -0xa, 0x30,0x5e,0x70,0xf3,0x4d,0x32,0x1b,0xa, 0x30,0x29,0x77,0x0, 0x5, 0xa, 0x27, -0x5e,0x24,0x0, 0x7f,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x4e,0xb, 0xa, 0x30,0x5e, -0x70,0x80,0x4d,0x32,0x1b,0xa, 0x30,0x29,0x77,0x0, 0xe, 0xa, 0x27,0x7c,0x45,0x6c, -0x55,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x16,0xb, 0xa, 0x30,0x6c,0x66,0x4d,0x32, -0x1b,0xa, 0x30,0x29,0x77,0x0, 0xf, 0xa, 0x27,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3d, -0xe0,0x2e,0x14,0x0, 0x22,0xb, 0xa, 0x30,0x6c,0x66,0x4d,0x32,0x1b,0xa, 0x30,0x69, -0x37,0x0, 0x6, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x52,0x69,0x37,0x0, 0x8, 0x7e, -0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x58,0x69,0x37,0x0, 0xa, 0x7e,0xf, 0x3d,0xe0,0x79, -0x30,0x0, 0x5e,0x69,0x37,0x0, 0xc, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x64,0x61, -0x66,0xa5,0xbf,0x2, 0x2, 0x80,0x2, 0x61,0x66,0xb, 0x7a,0x30,0x7e,0xf, 0x3d,0xe0, -0x79,0x30,0x0, 0x4a,0x69,0x37,0x0, 0x2, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x44, -0x29,0x77,0x0, 0x4, 0xa, 0x27,0x5e,0x24,0x0, 0x3, 0x3e,0x24,0x3e,0x24,0x3e,0x24, -0x3e,0x24,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x4c,0xb, 0xa, 0x30,0x5e,0x70,0xcf, -0x4d,0x32,0x1b,0xa, 0x30,0x29,0x77,0x0, 0x5, 0xa, 0x27,0x5e,0x24,0x0, 0x7f,0x7c, -0x45,0x6c,0x55,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x4e,0xb, 0xa, 0x30,0x5e,0x60, -0x80,0x4d,0x32,0x1b,0xa, 0x30,0x69,0x37,0x0, 0x6, 0x7e,0xf, 0x3d,0xe0,0x79,0x30, -0x0, 0x54,0x69,0x37,0x0, 0x8, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x5a,0x69,0x37, -0x0, 0xa, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x60,0x69,0x37,0x0, 0xc, 0x7e,0xf, -0x3d,0xe0,0x79,0x30,0x0, 0x66,0x29,0x77,0x0, 0xe, 0xa, 0x27,0x7c,0x45,0x6c,0x55, -0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x16,0xb, 0xa, 0x30,0x6c,0x66,0x4d,0x32,0x1b, -0xa, 0x30,0x29,0x77,0x0, 0xf, 0xa, 0x27,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3d,0xe0, -0x2e,0x14,0x0, 0x22,0xb, 0xa, 0x30,0x6c,0x66,0x4d,0x32,0x1b,0xa, 0x30,0x22,0xca, -0xd8,0xca,0x79,0x7f,0x70,0x74,0x1, 0x12,0x18,0x1b,0x29,0xd7,0x1, 0xf, 0x29,0xa7, -0x0, 0xb5,0x29,0x87,0x0, 0xb6,0x29,0xb7,0x1, 0x10,0x7a,0xb3,0x3d,0xe9,0x29,0xb7, -0x1, 0x12,0x7a,0xb3,0x3d,0xf7,0x29,0xb7,0x1, 0x11,0x7a,0xb3,0x3d,0xea,0xbe,0xa0, -0x3, 0x28,0x2, 0x6c,0xaa,0xbe,0x80,0x40,0x28,0x3, 0x7e,0x80,0x40,0xa, 0x3d,0x7e, -0xf, 0x3d,0xe0,0x79,0x30,0x0, 0xa, 0xa, 0x5a,0x9, 0xf5,0x3d,0xe4,0xa, 0x18,0x5e, -0x14,0x0, 0x7f,0x7e,0x1f,0x3d,0xe0,0x2e,0x34,0x0, 0x12,0xb, 0x1a,0x50,0x54,0x80, -0x4d,0x51,0x1b,0x1a,0x50,0x7c,0x7d,0xac,0x7f,0xa, 0x28,0x12,0x1a,0xed,0xa, 0x57, -0x7e,0x1f,0x3d,0xe0,0x79,0x51,0x0, 0x14,0xa, 0x2f,0xa, 0x38,0x12,0x1a,0xed,0x7d, -0x13,0x29,0xb7,0x0, 0xb7,0x60,0x56,0x7c,0x5d,0xac,0x5f,0x29,0x97,0x1, 0x10,0xa, -0x39,0xad,0x32,0xa, 0x28,0x8d,0x32,0x7d,0x3, 0x7c,0x7d,0xac,0x7f,0xa, 0x28,0x12, -0x1a,0xed,0x7c,0x97,0x7c,0x81,0x2c,0x98,0xbe,0x90,0xd, 0x50,0x3, 0x7e,0x90,0xd, -0x7e,0xe0,0xc, 0xa, 0x59,0x9e,0x54,0x0, 0xd, 0x2e,0x54,0x0, 0xc, 0x6c,0xaa,0x7e, -0x1f,0x3d,0xe0,0x2e,0x34,0x0, 0x22,0xb, 0x1a,0x0, 0x6c,0x11,0x4d,0x5, 0x1b,0x1a, -0x0, 0xa, 0x59,0x9e,0x54,0x0, 0xd, 0x2e,0x54,0x0, 0x18,0x80,0x34,0x29,0x77,0x1, -0x12,0xa, 0x47,0x2e,0x44,0x0, 0xd, 0x6c,0xee,0xa, 0x59,0x9e,0x54,0x0, 0xd, 0x2e, -0x54,0x0, 0xc, 0x6c,0xaa,0x7e,0x1f,0x3d,0xe0,0x2e,0x34,0x0, 0x22,0xb, 0x1a,0x0, -0x6c,0x11,0x4d,0x5, 0x1b,0x1a,0x0, 0xa, 0x59,0x9e,0x54,0x0, 0xd, 0x2e,0x54,0x0, -0xc, 0x6c,0xaa,0x7e,0x1f,0x3d,0xe0,0x2e,0x34,0x0, 0x16,0xb, 0x1a,0x0, 0x6c,0x11, -0x4d,0x5, 0x1b,0x1a,0x0, 0xa, 0x39,0xad,0x31,0x7d,0x53,0xb, 0x54,0xbe,0x54,0x2, -0x0, 0x40,0x4, 0x7e,0x54,0x1, 0xff,0x1e,0x54,0x6c,0xaa,0x7e,0x1f,0x3d,0xe0,0x2e, -0x34,0x0, 0xc, 0xb, 0x1a,0x0, 0x6c,0x11,0x4d,0x5, 0x1b,0x1a,0x0, 0x29,0xb7,0x1, -0x11,0x7e,0x80,0x2, 0xac,0xb8,0xa, 0x3e,0xad,0x31,0x2d,0x35,0x29,0x87,0x1, 0x14, -0xa, 0x28,0xb, 0x24,0x3e,0x24,0x2d,0x23,0x69,0x37,0x1, 0x15,0xbe,0x34,0x0, 0x0, -0x28,0x2, 0xb, 0x25,0xb, 0x24,0xbe,0x24,0x2, 0x0, 0x40,0x4, 0x7e,0x24,0x1, 0xff, -0x1e,0x24,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0xc, 0xb, 0xa, -0x30,0x6c,0x66,0x4d,0x32,0x1b,0xa, 0x30,0xda,0x79,0xda,0xd8,0x22,0xca,0x79,0x7c, -0xe7,0x7c,0xfb,0x7f,0x60,0xbe,0xf0,0x3, 0x40,0x2, 0x6c,0xff,0x69,0x46,0x0, 0x4, -0x5e,0x80,0xf, 0x6c,0x77,0x74,0x2, 0xac,0xb7,0x69,0x16,0x0, 0xe, 0x69,0x6, 0x0, -0xc, 0x2d,0x15,0x29,0x60,0x0, 0x1, 0xa, 0x56,0x7c,0xab,0xe4,0x7e,0xb, 0x60,0xa, -0x26,0x4d,0x25,0x7e,0x30,0x34,0xac,0x3e,0x74,0x2, 0xac,0xb7,0x2d,0x51,0xa, 0xf, -0x7e,0x14,0x1, 0x38,0xad,0x10,0x2d,0x51,0x7e,0xf, 0x37,0xf5,0x2d,0x15,0x79,0x20, -0x0, 0x10,0xb, 0x70,0xa5,0xbf,0x6, 0xbd,0x6c,0x77,0x74,0x2, 0xac,0xb7,0x69,0x16, -0x0, 0xa, 0x69,0x6, 0x0, 0x8, 0x2d,0x15,0x29,0x60,0x0, 0x1, 0xa, 0x56,0x7c,0xab, -0xe4,0x7e,0xb, 0x60,0xa, 0x26,0x4d,0x25,0x7e,0x30,0x34,0xac,0x3e,0x74,0x2, 0xac, -0xb7,0x2d,0x51,0xa, 0xf, 0x7e,0x14,0x1, 0x38,0xad,0x10,0x2d,0x51,0x7e,0xf, 0x37, -0xf5,0x2d,0x15,0x79,0x20,0x0, 0x1c,0xb, 0x70,0xa5,0xbf,0xc, 0xbd,0x6c,0x77,0x7e, -0x30,0x2, 0xac,0x37,0x69,0xf6,0x0, 0x2, 0xb, 0x6a,0xe0,0x2d,0xf1,0xb, 0x7a,0x20, -0x74,0x34,0xac,0xbe,0x2d,0x51,0xa, 0xf, 0x7e,0x14,0x1, 0x38,0xad,0x10,0x2d,0x51, -0x7e,0xf, 0x37,0xf5,0x2d,0x15,0x1b,0xa, 0x20,0xb, 0x70,0xbe,0x70,0x5, 0x40,0xcf, -0x6d,0x33,0xa, 0xf, 0x7e,0x14,0x1, 0x38,0xad,0x10,0x7e,0x50,0x34,0xac,0x5e,0x2d, -0x21,0x7e,0xf, 0x37,0xf5,0x2d,0x12,0x79,0x30,0x0, 0xa, 0xa, 0x2f,0x7e,0x34,0x1, -0x38,0xad,0x32,0x74,0x34,0xac,0xbe,0x2d,0x53,0x7e,0x1f,0x37,0xf5,0x2d,0x35,0x79, -0x41,0x0, 0xc, 0x69,0x46,0x0, 0x6, 0xa, 0x2f,0x7e,0x34,0x1, 0x38,0xad,0x32,0x74, -0x34,0xac,0xbe,0x2d,0x53,0x7e,0x1f,0x37,0xf5,0x2d,0x35,0x79,0x41,0x0, 0xe, 0xda, -0x79,0x22,0xca,0x3b,0x7f,0x30,0x7e,0x3b,0xb0,0xf5,0x2a,0x29,0xb3,0x0, 0x1, 0xbe, -0xb1,0x2a,0x28,0x2, 0xf5,0x2a,0x69,0x13,0x0, 0x6, 0x6d,0x0, 0x7e,0x34,0x0, 0xf2, -0x74,0xff,0x12,0x1d,0xd3,0x7f,0x3, 0x12,0x14,0xb3,0xa9,0xd6,0xcb,0x75,0x29,0x0, -0x80,0x2f,0x6c,0x77,0x80,0x21,0x7e,0x11,0x29,0x74,0xb, 0xac,0x1b,0xa, 0x17,0x2d, -0x1, 0x3e,0x4, 0x69,0x13,0x0, 0x6, 0x2d,0x10,0x6d,0x0, 0xb, 0xa, 0x20,0x6e,0x24, -0xff,0xff,0x1b,0xa, 0x20,0xb, 0x70,0x29,0x63,0x0, 0x1, 0xbc,0x67,0x38,0xd7,0x5, -0x29,0x7e,0x3b,0x60,0xbe,0x61,0x29,0x38,0xc9,0x69,0x33,0x0, 0x6, 0x7e,0xf, 0x3e, -0x43,0x79,0x30,0x0, 0x4, 0xe5,0x2a,0xa, 0x2b,0x7d,0x32,0x7c,0x67,0x6c,0x77,0x2d, -0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3e,0x43,0x1b, -0x1a,0x10,0x7e,0x34,0x0, 0xd0,0x12,0x14,0x5a,0x75,0x29,0x0, 0xe5,0x29,0xbe,0xb0, -0x4, 0x50,0x18,0x7e,0x71,0x29,0x74,0x4, 0xac,0xb7,0x7e,0x1f,0x3e,0x43,0x69,0x41, -0x0, 0x26,0x60,0x44,0x1e,0x44,0x14,0x78,0xfb,0x80,0x3d,0xe5,0x29,0xbe,0xb0,0x8, -0x50,0x1b,0xe5,0x29,0xa, 0x5b,0x1b,0x56,0x3e,0x54,0x3e,0x54,0x7e,0x1f,0x3e,0x43, -0x69,0x41,0x0, 0x28,0x60,0x22,0x1e,0x44,0x14,0x78,0xfb,0x80,0x1b,0xe5,0x29,0xa, -0x5b,0x9e,0x54,0x0, 0x8, 0x3e,0x54,0x3e,0x54,0x7e,0x1f,0x3e,0x43,0x69,0x41,0x0, -0x2a,0x60,0x5, 0x1e,0x44,0x14,0x78,0xfb,0x5e,0x44,0x0, 0xf, 0x7e,0x71,0x29,0x74, -0x2, 0xac,0xb7,0x69,0x33,0x0, 0x6, 0x2d,0x35,0x6d,0x22,0x1b,0x1a,0x40,0x5, 0x29, -0xe5,0x29,0xbe,0xb0,0xb, 0x40,0x85,0xa9,0xc6,0xcb,0xda,0x3b,0x22,0x7c,0xa7,0x7f, -0x70,0xa9,0xd6,0xcb,0x69,0x47,0x0, 0x4, 0x7e,0x1f,0x3e,0x43,0x79,0x41,0x0, 0x4, -0x69,0x47,0x0, 0x6, 0x7e,0x1f,0x3e,0x43,0x79,0x41,0x0, 0x6, 0x69,0x47,0x0, 0x8, -0x7e,0x1f,0x3e,0x43,0x79,0x41,0x0, 0x8, 0x6d,0x44,0x7e,0x1f,0x3e,0x43,0x79,0x41, -0x0, 0xe, 0x7c,0x4b,0x6c,0x55,0xa, 0x3a,0x4d,0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30, -0x0, 0x10,0x7e,0xf, 0x3e,0x43,0x2e,0x14,0x0, 0xe, 0x6d,0x33,0x7e,0xf, 0x3e,0x43, -0x79,0x30,0x0, 0xa, 0x7e,0x7b,0x70,0x7c,0x47,0x29,0x77,0x0, 0x1, 0x2d,0x32,0x7e, -0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3e,0x43,0x1b,0x1a,0x10, -0x7e,0x34,0x0, 0x30,0x12,0x14,0x5a,0xa9,0xc6,0xcb,0x22,0x2, 0x4e,0xed,0xff,0xff, -0xca,0x3b,0x7c,0xf7,0x7c,0xeb,0x7f,0x70,0x6c,0x77,0x80,0x16,0x74,0x2, 0xac,0xb7, -0x7e,0xf, 0x37,0xf1,0x2d,0x15,0xb, 0xa, 0x20,0x7f,0x7, 0x2d,0x15,0x1b,0xa, 0x20, -0xb, 0x70,0xbc,0xf7,0x38,0xe6,0x6c,0x77,0x80,0x1f,0x74,0x2, 0xac,0xb7,0x7e,0xf, -0x37,0xf1,0x2d,0x15,0x69,0x20,0x0, 0x48,0xa, 0xf, 0xa, 0x17,0x2d,0x10,0x3e,0x14, -0x2d,0x1f,0x7d,0xe, 0x1b,0xa, 0x20,0xb, 0x70,0xbc,0xe7,0x38,0xdd,0x7e,0xf, 0x37, -0xf9,0x69,0x20,0x0, 0x4, 0x5e,0x24,0x0, 0x1, 0x78,0x2, 0x21,0x17,0xa, 0x3f,0xa, -0x6e,0x2d,0x63,0x7c,0xcd,0x6c,0x77,0x80,0x1f,0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x37, -0xf1,0x2d,0x15,0x69,0x20,0x0, 0x8e,0xa, 0x7, 0xa, 0x1c,0x2d,0x10,0x3e,0x14,0x2d, -0x1f,0x7d,0xe, 0x1b,0xa, 0x20,0xb, 0x70,0xbc,0xf7,0x38,0xdd,0x2c,0xcf,0x6c,0x77, -0x80,0x1f,0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x37,0xf1,0x2d,0x15,0x69,0x20,0x0, 0xd6, -0xa, 0x7, 0xa, 0x1c,0x2d,0x10,0x3e,0x14,0x2d,0x1f,0x7d,0xe, 0x1b,0xa, 0x20,0xb, -0x70,0xbc,0xe7,0x38,0xdd,0x7e,0xf, 0x37,0xf9,0x69,0x20,0x0, 0x4, 0x1e,0x24,0x5e, -0x24,0x0, 0x1, 0x78,0x52,0x2c,0xce,0x6c,0x77,0x80,0x1f,0x74,0x2, 0xac,0xb7,0x7e, -0xf, 0x37,0xf1,0x2d,0x15,0x69,0x20,0x1, 0x1c,0xa, 0x7, 0xa, 0x1c,0x2d,0x10,0x3e, -0x14,0x2d,0x1f,0x7d,0xe, 0x1b,0xa, 0x20,0xb, 0x70,0xbc,0xf7,0x38,0xdd,0x2c,0xcf, -0x6c,0x77,0x80,0x1f,0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x37,0xf1,0x2d,0x15,0x69,0x20, -0x1, 0x64,0xa, 0x7, 0xa, 0x1c,0x2d,0x10,0x3e,0x14,0x2d,0x1f,0x7d,0xe, 0x1b,0xa, -0x20,0xb, 0x70,0xbc,0xe7,0x38,0xdd,0xda,0x3b,0x22,0xca,0x79,0x7e,0x6f,0x3d,0xe0, -0x69,0x36,0x0, 0xa, 0x69,0xe6,0x0, 0x2, 0x1e,0xe4,0x1e,0xe4,0x1e,0xe4,0x1e,0xe4, -0x1e,0xe4,0x1e,0xe4,0x1e,0xe4,0x5e,0xe4,0x0, 0x3, 0x9, 0xe, 0x3d,0xe4,0x69,0x76, -0x0, 0x12,0x5e,0x74,0x0, 0x7f,0x69,0x16,0x0, 0x14,0x7c,0x23,0x69,0xe6,0x0, 0xc, -0x7d,0xae,0x5e,0xa4,0x0, 0xff,0x3e,0xa4,0x7d,0x4e,0xa, 0x48,0x3e,0x44,0x69,0x56, -0x0, 0x16,0x7c,0x1b,0x69,0x56,0x0, 0x22,0x7c,0x3b,0xac,0x70,0x7c,0xbf,0xac,0xb2, -0xbd,0x53,0x68,0x6, 0x7e,0x34,0x0, 0x81,0x41,0x2f,0xa, 0x20,0xa, 0x3f,0x12,0x1a, -0xed,0x4d,0x22,0x68,0x6, 0x7e,0x34,0x0, 0x82,0x41,0x2f,0xa, 0xb0,0xad,0xba,0xa, -0x2f,0x7d,0x3b,0x8d,0x32,0x7c,0x27,0xbe,0x20,0xd, 0x50,0x6, 0x7e,0x34,0x0, 0x83, -0x41,0x2f,0x7c,0xb2,0xac,0xbf,0xbd,0x5b,0x68,0x6, 0x7e,0x34,0x0, 0x84,0x80,0x7f, -0x7e,0x70,0xc, 0xac,0x7f,0xa, 0x20,0x8d,0x32,0x7d,0xe3,0x69,0x56,0x0, 0x2a,0x7d, -0x35,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e,0x34,0x3, -0xff,0xbe,0x34,0x0, 0x0, 0x28,0x6, 0x7e,0xf4,0x0, 0x2, 0x80,0x2, 0x6d,0xff,0x5e, -0x54,0x0, 0x3f,0xb, 0x54,0x3e,0x54,0x2d,0xef,0x2d,0xe5,0xbd,0xe4,0x68,0x6, 0x7e, -0x34,0x0, 0x85,0x80,0x3a,0x7e,0xb3,0x3d,0xd6,0x60,0x12,0xa, 0x32,0x2e,0x34,0x0, -0xb, 0xa, 0xe1,0xbd,0xe3,0x68,0x16,0x7e,0x34,0x0, 0x86,0x80,0x22,0xa, 0xe2,0x1b, -0xe4,0xa, 0x1, 0xbd,0xe, 0x68,0x6, 0x7e,0x34,0x0, 0x87,0x80,0x12,0xa, 0x32,0x1b, -0x34,0xa, 0xe3,0xbd,0xe3,0x68,0x6, 0x7e,0x34,0x0, 0x88,0x80,0x2, 0x6d,0x33,0xda, -0x79,0x22,0x7f,0x70,0x29,0xa7,0x0, 0xa6,0x29,0x77,0x0, 0xa8,0x29,0x87,0x0, 0xa7, -0x29,0x67,0x0, 0x9d,0xbe,0x60,0x4, 0x38,0x4, 0x6c,0x99,0x80,0x21,0xbe,0x60,0x8, -0x38,0x5, 0x7e,0x90,0x1, 0x80,0x17,0xbe,0x60,0x10,0x38,0x5, 0x7e,0x90,0x2, 0x80, -0xd, 0xbe,0x60,0x20,0x38,0x5, 0x7e,0x90,0x3, 0x80,0x3, 0x7e,0x90,0x4, 0xbe,0x70, -0x3, 0x28,0x3, 0x7e,0x70,0x3, 0xbe,0x60,0x3f,0x28,0x3, 0x7e,0x60,0x3f,0xbe,0x80, -0x1, 0x28,0x3, 0x7e,0x80,0x1, 0xbe,0xa0,0x2, 0x28,0x2, 0x6c,0xaa,0xa, 0x26,0x3e, -0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7c,0x67,0x6c,0x77,0x3e,0x34,0x3e, -0x34,0x3e,0x34,0x2d,0x32,0xa, 0x28,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d, -0x23,0xa, 0x3a,0x3e,0x34,0x3e,0x34,0x2d,0x32,0x7e,0xf, 0x37,0xf9,0x79,0x30,0x0, -0x2, 0x29,0x87,0x0, 0x9c,0x7c,0x48,0x6c,0x55,0x29,0x87,0x0, 0x9b,0xa, 0x38,0x2d, -0x32,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0x9a,0x69,0x37,0x0, 0xb2,0x7e,0xf, 0x37, -0xf9,0x79,0x30,0x0, 0xc, 0x69,0x27,0x0, 0xb0,0x7d,0x32,0x7e,0xf, 0x37,0xf9,0x79, -0x30,0x0, 0xe, 0x69,0x37,0x0, 0xae,0x5e,0x34,0xe0,0xf, 0x29,0x87,0x0, 0x9c,0xa, -0x28,0x1b,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x2d,0x32,0x7e,0xf, 0x3d, -0xd8,0x79,0x30,0x0, 0x9c,0xa, 0x29,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29, -0x87,0x0, 0xa9,0xa, 0x38,0x2d,0x32,0x7e,0xf, 0x37,0xf9,0x79,0x30,0x0, 0x6, 0x69, -0x37,0x0, 0xac,0x7e,0xf, 0x37,0xf9,0x79,0x30,0x0, 0x8, 0x69,0x37,0x0, 0xaa,0x7e, -0xf, 0x37,0xf9,0x79,0x30,0x0, 0xa, 0x22,0x7f,0x71,0x7f,0x20,0xa9,0xd6,0xcb,0x69, -0x32,0x0, 0x4, 0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x4, 0x69,0x32,0x0, 0x8, 0x7e, -0xf, 0x3e,0x43,0x79,0x30,0x0, 0x6, 0x69,0x32,0x0, 0x6, 0x7e,0xf, 0x3e,0x43,0x79, -0x30,0x0, 0x8, 0x29,0x72,0x0, 0x1, 0x7c,0x47,0x6c,0x55,0x7e,0x2b,0x70,0xa, 0x37, -0x2d,0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x29,0x72,0x0, 0x2, 0xa, 0x37, -0x1b,0x34,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xa, 0x69,0x32,0x0, 0xa, 0x7e,0xf, -0x3e,0x43,0x79,0x30,0x0, 0xe, 0x69,0x32,0x0, 0xc, 0x7e,0xf, 0x3e,0x43,0x79,0x30, -0x0, 0x10,0x69,0x32,0x0, 0xe, 0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x12,0x69,0x32, -0x0, 0x10,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x30,0x29,0x72,0x0, 0x3, 0x7c,0x27, -0x6c,0x33,0x7e,0x1f,0x3e,0x43,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0xa0,0x12,0x14,0x5a, -0x7e,0x1f,0x3e,0x43,0x69,0x31,0x0, 0x1a,0x7a,0x7b,0x70,0x7e,0x1f,0x3e,0x43,0x69, -0x31,0x0, 0x1c,0x39,0x77,0x0, 0x1, 0x7e,0x1f,0x3e,0x43,0x69,0x31,0x0, 0x16,0x79, -0x37,0x0, 0x2, 0x7e,0x1f,0x3e,0x43,0x69,0x31,0x0, 0x18,0x79,0x37,0x0, 0x4, 0x7e, -0x1f,0x3e,0x43,0x69,0x31,0x0, 0x22,0x79,0x37,0x0, 0x6, 0x7e,0x1f,0x3e,0x43,0x69, -0x31,0x0, 0x24,0x79,0x37,0x0, 0x8, 0x7e,0x1f,0x3e,0x43,0x69,0x31,0x0, 0x1e,0x79, -0x37,0x0, 0xa, 0x7e,0x1f,0x3e,0x43,0x69,0x31,0x0, 0x20,0x79,0x37,0x0, 0xc, 0xa9, -0xc6,0xcb,0x22,0xca,0x3b,0x7f,0x30,0x74,0x1, 0x12,0x18,0x1b,0x29,0x73,0x1, 0xd, -0x2e,0x70,0xff,0x92,0x8, 0x29,0xb3,0x1, 0xe, 0x12,0x17,0xcb,0x7f,0x3, 0x12,0x11, -0xe4,0x7f,0x3, 0x12,0x3, 0x9f,0x29,0x73,0x0, 0xa, 0xa, 0x37,0x7e,0xf, 0x3d,0xe0, -0x79,0x30,0x0, 0x24,0x29,0x73,0x0, 0xb5,0xa, 0x27,0x3e,0x24,0x3e,0x24,0x3e,0x24, -0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x69,0x33,0x1, 0x19,0x4d,0x32,0x7e,0xf, -0x3d,0xe0,0x79,0x30,0x0, 0x2, 0x29,0x73,0x0, 0xa, 0xa, 0x47,0x29,0x73,0x0, 0x1, -0xa, 0x57,0x9d,0x54,0xf5,0x33,0x7f,0x3, 0x12,0x10,0xa9,0x29,0x73,0x0, 0xb7,0x2e, -0x70,0xff,0x92,0x8, 0x7f,0x3, 0xe5,0x33,0x12,0x11,0x4c,0x69,0x23,0x1, 0x15,0x3e, -0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x29,0x73,0x1, 0x14,0xa, -0x37,0x2d,0x32,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x2a,0x29,0x73,0x1, 0x13,0xa, -0x37,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x2c,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3d, -0xe0,0x79,0x30,0x0, 0x34,0x7e,0x34,0x1, 0xb, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, -0x2e,0x29,0x73,0x0, 0x1, 0xa, 0x37,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x10,0x29, -0x73,0x0, 0xb9,0x7e,0x60,0x1, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x1a,0x69,0x33, -0x0, 0xba,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x1c,0x69,0x33,0x0, 0xbc,0x7e,0xf, -0x3d,0xe0,0x79,0x30,0x0, 0x1e,0x7f,0x3, 0x12,0xe, 0x4, 0xda,0x3b,0x22,0x7f,0x71, -0x7f,0x60,0xbe,0x68,0x0, 0x0, 0x78,0x2, 0xc1,0x3, 0xbe,0x78,0x0, 0x0, 0x78,0x2, -0xc1,0x3, 0x29,0x77,0x0, 0x2, 0xbe,0x70,0x3, 0x28,0x5, 0xe4,0x39,0xb7,0x0, 0x2, -0x29,0x77,0x0, 0x3, 0xbe,0x70,0x40,0x28,0x6, 0x74,0x40,0x39,0xb7,0x0, 0x3, 0x29, -0xb7,0x0, 0x2, 0xa, 0x3b,0x9, 0xa3,0x3d,0xe4,0x39,0xb6,0x0, 0x4, 0x29,0xb7,0x0, -0x3, 0x39,0xb6,0x0, 0x5, 0x29,0xb7,0x0, 0x2, 0xb4,0x3, 0xb, 0xb, 0x7a,0x30,0x7e, -0x24,0x0, 0x6, 0x8d,0x32,0x80,0x3, 0xb, 0x7a,0x30,0x79,0x36,0x0, 0x2, 0xb, 0x7a, -0x30,0x1e,0x34,0x29,0xb7,0x0, 0x4, 0xa, 0x2b,0x9d,0x32,0x79,0x36,0x0, 0x6, 0xb, -0x7a,0x30,0x1e,0x34,0x1b,0x35,0x79,0x36,0x0, 0x8, 0xb, 0x7a,0x30,0x1e,0x34,0x69, -0x27,0x0, 0x5, 0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x79,0x36,0x0, 0xa, 0x69,0x37,0x0, -0x5, 0x79,0x36,0x0, 0xc, 0x29,0xb7,0x0, 0x7, 0x39,0xb6,0x0, 0xe, 0x29,0xb7,0x0, -0x7, 0x39,0xb6,0x0, 0xf, 0x29,0xb7,0x0, 0x7, 0xa, 0x3b,0x29,0xb6,0x0, 0xe, 0xa, -0x2b,0x2d,0x23,0x29,0xb6,0x0, 0x5, 0xa, 0x3b,0xad,0x32,0xa, 0x2a,0x12,0x1a,0xed, -0x1b,0x6a,0x30,0x22,0x7f,0x50,0x29,0x75,0x1, 0x1e,0xa, 0x27,0x5e,0x24,0x0, 0x1, -0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7e,0xf, 0x3d,0xe0, -0xb, 0x15,0xb, 0xa, 0x30,0x5e,0x70,0xbf,0x4d,0x32,0x1b,0xa, 0x30,0x29,0x85,0x1, -0x1f,0x7c,0x98,0xbe,0x90,0x3, 0x38,0x4, 0x7c,0x98,0x80,0x3, 0x7e,0x90,0x3, 0xa, -0x39,0x5e,0x34,0x0, 0x3, 0x7d,0x23,0x7c,0x45,0x6c,0x55,0x3e,0x24,0x3e,0x24,0x3e, -0x24,0x7e,0xf, 0x3d,0xe0,0xb, 0x15,0xb, 0xa, 0x30,0x5e,0x60,0xe7,0x4d,0x32,0x1b, -0xa, 0x30,0x29,0x85,0x0, 0xb8,0x7a,0x83,0x2, 0xbc,0x69,0x35,0x1, 0x17,0x7a,0x37, -0x2, 0xbd,0x29,0x85,0x1, 0x31,0x7a,0x83,0x2, 0xbf,0x6c,0x88,0x80,0x46,0x74,0x5, -0xac,0xb8,0x7f,0x15,0x2d,0x35,0x69,0x51,0x1, 0x21,0x7a,0x57,0x2, 0xb8,0x74,0x5, -0xac,0xb8,0x7f,0x15,0x2d,0x35,0x29,0x71,0x1, 0x23,0x7a,0x73,0x2, 0xba,0x74,0x5, -0xac,0xb8,0x7f,0x15,0x2d,0x35,0x29,0x71,0x1, 0x24,0x7a,0x73,0x2, 0xbb,0x7e,0x8, -0x2, 0xa8,0x7e,0x18,0x2, 0xb8,0x12,0xd, 0x3e,0x7e,0x8, 0x2, 0xa8,0x7c,0xb8,0x12, -0x1, 0x30,0xb, 0x80,0xbc,0x98,0x38,0xb6,0x22,0x7f,0x70,0x7c,0xab,0x6c,0x77,0x7e, -0x50,0x3, 0xac,0x57,0x7d,0x12,0x2e,0x14,0x1d,0x51,0x7a,0x31,0x82,0x7a,0x21,0x83, -0xe4,0x93,0xbc,0xba,0x78,0x26,0x2e,0x24,0x1d,0x52,0x7a,0x51,0x82,0x7a,0x41,0x83, -0xe4,0x93,0x7a,0x7b,0xb0,0x7e,0x50,0x3, 0xac,0x57,0x2e,0x24,0x1d,0x53,0x7a,0x51, -0x82,0x7a,0x41,0x83,0xe4,0x93,0x39,0xb7,0x0, 0x1, 0x80,0x7, 0xb, 0x70,0xbe,0x70, -0x2, 0x28,0xbc,0xbe,0x70,0x2, 0x28,0x25,0x7e,0x34,0x1d,0xf, 0x79,0x37,0x0, 0x2, -0x7e,0x34,0x1c,0xc7,0x79,0x37,0x0, 0x4, 0xbe,0xa0,0x81,0x78,0x9, 0x74,0x23,0x7a, -0x7b,0xb0,0x74,0x24,0x80,0x3a,0x74,0x1, 0x7a,0x7b,0xb0,0x80,0x33,0x2e,0xa0,0xf4, -0x68,0x6, 0xb, 0xa0,0x78,0x13,0x80,0x0, 0x7e,0x34,0x1d,0x32,0x79,0x37,0x0, 0x2, -0x7e,0x34,0x1c,0xeb,0x79,0x37,0x0, 0x4, 0x22,0x7e,0x34,0x1d,0xf, 0x79,0x37,0x0, -0x2, 0x7e,0x34,0x1c,0xc7,0x79,0x37,0x0, 0x4, 0x74,0x23,0x7a,0x7b,0xb0,0x74,0x24, -0x39,0xb7,0x0, 0x1, 0x22,0x7f,0x20,0xa9,0xd6,0xcb,0x69,0x32,0x0, 0x6, 0x7e,0xf, -0x3e,0x43,0x79,0x30,0x0, 0x4, 0x69,0x32,0x0, 0x8, 0x7e,0xf, 0x3e,0x43,0x79,0x30, -0x0, 0x8, 0x29,0x72,0x0, 0x2, 0x7c,0x47,0x6c,0x55,0x29,0x72,0x0, 0x3, 0xa, 0x37, -0x2d,0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x7e,0x2b,0x70,0x7c,0x47,0x29, -0x72,0x0, 0x1, 0xa, 0x37,0x2d,0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xa, 0x29, -0x72,0x0, 0x4, 0xa, 0x37,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xe, 0x29,0xb2,0x0, -0x5, 0x54,0x1, 0x7c,0x2b,0x6c,0x33,0x7e,0x1f,0x3e,0x43,0x1b,0x1a,0x10,0x7e,0x34, -0x0, 0xc0,0x12,0x14,0x5a,0xa9,0xc6,0xcb,0x22,0x7c,0x7b,0xa5,0xbf,0x2, 0xa, 0xa9, -0x27,0xea,0x3, 0xd3,0x80,0x6, 0xc3,0x80,0x3, 0x2e,0x70,0xff,0xa9,0x97,0xea,0x22, -0x7f,0x70,0x29,0x77,0x0, 0xb, 0xa, 0x27,0x7e,0x7b,0x70,0xa, 0x37,0x2d,0x32,0x7c, -0x67,0x6d,0x22,0x6c,0x77,0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x3d,0xd8,0x2d,0x15,0x79, -0x20,0x0, 0x2, 0xb, 0x70,0xa5,0xbf,0x23,0xec,0x6c,0x77,0x80,0x4f,0xa, 0x27,0x7f, -0x7, 0x2d,0x12,0x29,0x50,0x0, 0x54,0xbe,0x50,0x23,0x50,0x1d,0x29,0x40,0x0, 0xc6, -0x7c,0x4, 0x6c,0x11,0x7e,0x30,0x2, 0xac,0x35,0x7e,0x2f,0x3d,0xd8,0x2d,0x51,0xb, -0x55,0xb, 0x2a,0x10,0x4d,0x10,0x1b,0x2a,0x10,0xa, 0x17,0x2d,0x1f,0x7d,0xe, 0x29, -0x40,0x0, 0x54,0xa, 0x4, 0x7e,0x30,0x2, 0xac,0x37,0x7e,0x2f,0x3d,0xd8,0x2d,0x51, -0xb, 0x55,0xb, 0x2a,0x10,0x4d,0x10,0x1b,0x2a,0x10,0xb, 0x70,0xbc,0x67,0x38,0xad, -0x6c,0x77,0x80,0x1c,0xa, 0x27,0x7f,0x7, 0x2d,0x12,0x29,0x60,0x0, 0x77,0xa, 0x46, -0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x3d,0xd8,0x2d,0x15,0x79,0x40,0x0, 0x52,0xb, 0x70, -0x29,0x67,0x0, 0x1, 0xbc,0x67,0x38,0xdc,0x22,0xca,0x3b,0x7f,0x30,0xe4,0x12,0x15, -0xb, 0x6c,0x77,0x74,0x2, 0xac,0xb7,0x69,0x13,0x1, 0x1b,0x2d,0x15,0x7e,0x4, 0x0, -0xff,0xb, 0xa, 0x20,0x7e,0xf, 0x37,0xf5,0x2d,0x15,0x79,0x20,0x3, 0xd4,0xb, 0x70, -0xa5,0xbf,0xc, 0xdf,0x29,0x73,0x1, 0x1d,0xa, 0x37,0x7e,0xf, 0x37,0xf5,0x79,0x30, -0x3, 0xf2,0x6c,0x77,0x74,0x2, 0xac,0xb7,0x69,0x13,0x1, 0x2f,0x2d,0x15,0x7e,0x4, -0x0, 0xff,0xb, 0xa, 0x20,0x7e,0xf, 0x37,0xf5,0x2d,0x15,0x79,0x20,0x3, 0xf4,0xb, -0x70,0xa5,0xbf,0xc, 0xdf,0x29,0x73,0x1, 0x31,0xa, 0x37,0x7e,0xf, 0x37,0xf5,0x79, -0x30,0x4, 0x12,0x29,0xb3,0x1, 0x32,0x60,0x16,0x7e,0x34,0xff,0xff,0x7e,0xf, 0x37, -0xf5,0x79,0x30,0x4, 0xc, 0x7e,0xf, 0x37,0xf5,0x79,0x30,0x4, 0xe, 0x80,0x12,0x6d, -0x33,0x7e,0xf, 0x37,0xf5,0x79,0x30,0x4, 0xc, 0x7e,0xf, 0x37,0xf5,0x79,0x30,0x4, -0xe, 0x7e,0xf, 0x37,0xf5,0x79,0x30,0x4, 0x10,0xda,0x3b,0x22,0xca,0x79,0x7c,0xfb, -0x7a,0xd, 0x34,0x7e,0x1f,0x37,0xf5,0x2e,0x34,0x3, 0xec,0x7a,0x1d,0x39,0x7e,0x8, -0x2, 0xa8,0x7e,0x34,0x0, 0x6, 0xe4,0x12,0x1d,0xd3,0xa2,0x8, 0xe4,0x33,0x7e,0x1d, -0x34,0x39,0xb1,0x0, 0xb7,0x7e,0x1d,0x34,0x29,0x71,0x0, 0xb7,0x7a,0x73,0x3d,0xd6, -0x30,0x8, 0x3b,0x6c,0xee,0x80,0x33,0xa, 0x1e,0x1e,0x14,0x1e,0x14,0x1e,0x14,0x1e, -0x14,0xa, 0x3e,0x7e,0x24,0x0, 0x10,0x12,0x1a,0xed,0x7c,0xb5,0x7e,0x44,0x0, 0x1, -0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x50,0x2, 0xac,0x53,0x2e,0x24,0x2, 0xa8, -0xb, 0x28,0x30,0x4d,0x34,0x1b,0x28,0x30,0xb, 0xe0,0xbc,0xfe,0x38,0xc9,0x7e,0xd, -0x34,0x12,0x3, 0x9f,0xe4,0x12,0x15,0xb, 0x6c,0xee,0x74,0x2, 0xac,0xbe,0x49,0x15, -0x2, 0xa8,0x7e,0x1d,0x39,0x2d,0x35,0x1b,0x1a,0x10,0xb, 0xe0,0xbe,0xe0,0x3, 0x40, -0xe9,0xda,0x79,0x22,0x7f,0x70,0x69,0x37,0x0, 0xc0,0x29,0xb7,0x0, 0xb5,0xb4,0x3, -0x12,0x7e,0x4, 0x0, 0x6, 0x7d,0x13,0x8d,0x10,0x7e,0x2f,0x3d,0xe0,0x79,0x12,0x0, -0x6, 0x80,0x8, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x6, 0x29,0x57,0x0, 0xb8,0xa, -0x15,0x7d,0x23,0x1e,0x24,0x9d,0x21,0x7e,0xf, 0x3d,0xe0,0x79,0x20,0x0, 0x18,0x7d, -0x23,0x1e,0x24,0x1b,0x25,0x7e,0xf, 0x3d,0xe0,0x79,0x20,0x0, 0x38,0x69,0x27,0x1, -0x17,0x1e,0x34,0x9d,0x32,0x9e,0x34,0x0, 0xa, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, -0x26,0x69,0x37,0x1, 0x17,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x28,0x29,0x77,0x0, -0xb9,0xa, 0x37,0x7e,0x60,0x1, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x1a,0x29,0x77, -0x0, 0xb, 0xa, 0x27,0x7e,0x7b,0x70,0xa, 0x37,0x2d,0x32,0x7e,0xf, 0x3d,0xe0,0x79, -0x30,0x0, 0x8, 0x7f,0x7, 0x2, 0x10,0x0, 0x7f,0x70,0xa9,0xd6,0xcb,0xc2,0x20,0x69, -0x37,0x0, 0x4, 0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x4, 0x69,0x37,0x0, 0x6, 0x7e, -0xf, 0x3e,0x43,0x79,0x30,0x0, 0x6, 0x69,0x37,0x0, 0x8, 0x7e,0xf, 0x3e,0x43,0x79, -0x30,0x0, 0x8, 0x7e,0x7b,0x70,0x7c,0x47,0x6c,0x55,0x29,0x77,0x0, 0x1, 0xa, 0x37, -0x2d,0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x29,0x77,0x0, 0x2, 0xa, 0x37, -0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xe, 0x29,0xb7,0x0, 0x3, 0x54,0x1, 0x7c,0x2b, -0x6c,0x33,0x7e,0x1f,0x3e,0x43,0x1b,0x1a,0x10,0x69,0x37,0x0, 0xa, 0x12,0x14,0x5a, -0xa9,0xc6,0xcb,0x22,0x74,0x3, 0x12,0x17,0x81,0x74,0x1, 0x12,0x15,0xb, 0xa9,0xd1, -0xc4,0x7e,0xf, 0x3d,0xd8,0x2e,0x14,0x0, 0x9e,0xb, 0xa, 0x30,0x4e,0x70,0x20,0x1b, -0xa, 0x30,0x7e,0xf, 0x3d,0xd8,0xb, 0xa, 0x30,0x5e,0x70,0xf9,0x1b,0xa, 0x30,0x7e, -0xf, 0x3d,0xd8,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x7e,0xf, 0x3d,0xe0, -0xb, 0x16,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0xc2,0x12,0xe4,0x7a,0xb3, -0x3d,0xf8,0x7e,0x1f,0x3d,0xd8,0xb, 0x1a,0x30,0x5e,0x34,0x0, 0x1, 0x78,0xf3,0x74, -0x2, 0x2, 0x17,0x81,0x7d,0xf3,0x7f,0x20,0xa9,0xd6,0xcb,0x69,0xe2,0x0, 0x4, 0x7e, -0x1f,0x3e,0x43,0x79,0xe1,0x0, 0x4, 0x69,0xe2,0x0, 0x8, 0x7e,0x1f,0x3e,0x43,0x79, -0xe1,0x0, 0x8, 0x7e,0x2b,0x60,0x6c,0x77,0x29,0x52,0x0, 0x1, 0xa, 0xe5,0x2d,0xe3, -0x7e,0x1f,0x3e,0x43,0x79,0xe1,0x0, 0xc, 0x29,0x72,0x0, 0x2, 0xa, 0xe7,0x7e,0x1f, -0x3e,0x43,0x79,0xe1,0x0, 0xe, 0x7e,0x1f,0x3e,0x43,0x79,0xf1,0x0, 0xa, 0x6d,0x11, -0x7e,0x1f,0x3e,0x43,0x1b,0x1a,0x10,0x7e,0x34,0x0, 0x40,0x12,0x14,0x5a,0xa9,0xc6, -0xcb,0x22,0x7f,0x60,0x6c,0x77,0x74,0x2, 0xac,0xb7,0x69,0x16,0x0, 0xe, 0x69,0x6, -0x0, 0xc, 0x2d,0x15,0x29,0x60,0x0, 0x1, 0xa, 0x56,0x7c,0xab,0xe4,0x7e,0xb, 0x60, -0xa, 0x46,0x4d,0x45,0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x37,0xf5,0x2d,0x15,0x79,0x40, -0x3, 0xb0,0xb, 0x70,0xbe,0x70,0x12,0x40,0xcd,0x7e,0x34,0xff,0xff,0x7e,0xf, 0x37, -0xf5,0x79,0x30,0x3, 0xa8,0x7e,0xf, 0x37,0xf5,0x79,0x30,0x3, 0xaa,0x7e,0xf, 0x37, -0xf5,0x79,0x30,0x3, 0xac,0x7e,0xf, 0x37,0xf5,0x79,0x30,0x3, 0xae,0x22,0xca,0x7b, -0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83, -0xc0,0x82,0xd2,0x12,0x7e,0xf, 0x3d,0xe0,0x69,0x30,0x0, 0x4, 0x7a,0x73,0x3d,0xf8, -0x7e,0x73,0x3d,0xf8,0xa, 0x37,0x5e,0x34,0x0, 0x4, 0x68,0x4, 0xd2,0x11,0x80,0x2, -0xc2,0x11,0x7e,0x34,0x0, 0x1f,0x79,0x30,0x0, 0x4, 0xc2,0xc3,0x12,0x17,0xe6,0x12, -0x77,0xfa,0xa9,0xc1,0xc4,0xd0,0x82,0xd0,0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda, -0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda,0x7b,0x32,0xa9,0xd7,0xcb,0x7d,0x23,0x4e, -0x50,0x1, 0x7e,0xf, 0x3e,0x43,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x80,0x1e, -0x7e,0xf, 0x3e,0x43,0xb, 0xa, 0x30,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, -0x8, 0x78,0xb, 0xa9,0xd7,0xcb,0x4e,0x70,0x4, 0x1b,0xa, 0x30,0xd2,0x20,0x7e,0xf, -0x3e,0x43,0x69,0x30,0x0, 0x38,0x5e,0x34,0x80,0x0, 0xbe,0x34,0x80,0x0, 0x78,0xd0, -0xb, 0xa, 0x30,0x4e,0x60,0x40,0x1b,0xa, 0x30,0x6d,0x11,0x7e,0x1f,0x3e,0x43,0x1b, -0x1a,0x10,0x22,0x7f,0x20,0xa9,0xd6,0xcb,0x69,0x32,0x0, 0x2, 0x7e,0xf, 0x3e,0x43, -0x79,0x30,0x0, 0x4, 0x69,0x32,0x0, 0x4, 0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x6, -0x69,0x32,0x0, 0x6, 0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x8, 0x7e,0x2b,0x70,0xa, -0x7, 0x7e,0x14,0x1, 0x0, 0xad,0x10,0x29,0x72,0x0, 0x1, 0xa, 0x37,0x2d,0x31,0x7e, -0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x6d,0x11,0x7e,0x1f,0x3e,0x43,0x1b,0x1a,0x10, -0x7e,0x34,0x0, 0x60,0x12,0x14,0x5a,0xa9,0xc6,0xcb,0x22,0x7c,0xab,0xbe,0xa0,0x2, -0x78,0x1b,0x7e,0x1f,0x3d,0xd8,0xb, 0x1a,0x30,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x5e, -0x34,0x0, 0x1, 0x78,0x6, 0x74,0x1, 0x7c,0xab,0x80,0x2, 0x6c,0xaa,0xa, 0x2a,0x5e, -0x24,0x0, 0x1, 0x3e,0x24,0x3e,0x24,0x3e,0x24,0x7e,0xf, 0x3d,0xd8,0xb, 0xa, 0x30, -0x5e,0x70,0xf7,0x4d,0x32,0x1b,0xa, 0x30,0x7e,0x1f,0x3d,0xd8,0xb, 0x1a,0x20,0x1e, -0x24,0x1e,0x24,0x1e,0x24,0x1e,0x24,0x5e,0x24,0x0, 0x1, 0xa, 0x3a,0xbd,0x23,0x78, -0xe7,0x22,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca,0x2b,0xca,0x1b,0xca,0xb, -0xc0,0xd0,0xc0,0x83,0xc0,0x82,0xd2,0x21,0x7e,0xf, 0x37,0xf9,0xb, 0xa, 0x30,0x7c, -0x57,0x7a,0x53,0x37,0xf0,0x4e,0x70,0xc, 0x1b,0xa, 0x30,0xc2,0xc6,0x6d,0x33,0x7e, -0xf, 0x37,0xf9,0x79,0x30,0x0, 0x10,0x12,0x17,0xe6,0x12,0x77,0xfa,0xd0,0x82,0xd0, -0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, -0x7b,0x32,0xca,0x79,0x7c,0xf7,0x7c,0xeb,0x7f,0x70,0x6c,0x77,0x74,0x2, 0xac,0xb7, -0x7f,0x7, 0x2d,0x15,0x29,0x60,0x0, 0x1, 0xa, 0x56,0x7c,0xab,0xe4,0x7e,0xb, 0x60, -0xa, 0x46,0x4d,0x45,0x7e,0x50,0x34,0xac,0x5f,0x74,0x2, 0xac,0xb7,0x2d,0x52,0xa, -0xe, 0x7e,0x14,0x1, 0x38,0xad,0x10,0x2d,0x51,0x7e,0xf, 0x37,0xf5,0x2d,0x15,0x79, -0x40,0x0, 0x1c,0xb, 0x70,0xbe,0x70,0xc, 0x40,0xc2,0xda,0x79,0x22,0x7c,0x9b,0x7f, -0x61,0x7f,0x50,0xe5,0x25,0x7e,0x8, 0x0, 0x26,0x12,0xe, 0xc9,0xbe,0x90,0x23,0x28, -0x3, 0x7e,0x90,0x23,0x6c,0xaa,0x80,0x2a,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c,0x7e,0x1b, -0x80,0xbe,0x81,0x26,0x40,0x4, 0x74,0x23,0x80,0xd, 0xa, 0x38,0x2e,0x35,0x28,0x7a, -0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x3a,0x2d,0x3b,0x7d,0x2a,0x7a,0x1b,0xb0, -0xb, 0xa0,0xbc,0x9a,0x38,0xd2,0x22,0x7c,0x9b,0x7f,0x61,0x7f,0x50,0xe5,0x25,0x7e, -0x8, 0x0, 0x26,0x12,0xe, 0xc9,0x6c,0xaa,0x80,0x2a,0xa, 0x3a,0x2d,0x3d,0x7d,0x2c, -0x7e,0x1b,0x80,0xbe,0x81,0x27,0x40,0x4, 0x74,0x24,0x80,0xd, 0xa, 0x38,0x2e,0x35, -0x2a,0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0xa, 0x3a,0x2d,0x3b,0x7d,0x2a,0x7a, -0x1b,0xb0,0xb, 0xa0,0xbc,0x9a,0x38,0xd2,0x22,0x7d,0x42,0x7c,0xa7,0x7c,0x5b,0xa9, -0xd6,0xcb,0xbe,0x50,0x23,0x28,0x3, 0x7e,0x50,0x23,0xbe,0xa0,0x24,0x28,0x3, 0x7e, -0xa0,0x24,0x7e,0x34,0x0, 0x5, 0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x2, 0x7c,0x65, -0x6c,0x77,0xa, 0x5a,0x2d,0x53,0x7e,0x1f,0x3e,0x43,0x79,0x51,0x0, 0x32,0x7e,0x1f, -0x3e,0x43,0x79,0x41,0x0, 0x14,0xa9,0xc6,0xcb,0x22,0x2e,0x34,0x4, 0x0, 0x7e,0xf, -0x3d,0xe0,0x79,0x30,0x0, 0x80,0x7e,0x34,0x4, 0x0, 0x9d,0x32,0x7e,0xf, 0x3d,0xe0, -0x79,0x30,0x0, 0x82,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x84, -0xa, 0x3b,0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x86,0x22,0x7c,0xa5,0x7c,0x5b,0x7d, -0x13,0xbe,0x14,0x0, 0x0, 0x28,0x10,0xa, 0x35,0x3e,0x34,0x7d,0x21,0x7c,0x45,0x6c, -0x55,0x2d,0x23,0xa, 0x3a,0x80,0xa, 0xa, 0x25,0x3e,0x24,0x7d,0x31,0x7c,0x67,0x6c, -0x77,0x2d,0x32,0x7e,0xf, 0x37,0xf9,0x79,0x30,0x0, 0x4, 0x22,0x7e,0x34,0x0, 0x1f, -0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x4, 0xa9,0xd2,0xcd,0x7e,0xb3,0x3d,0xe8,0xb4, -0x1, 0x7, 0x12,0x9, 0x1a,0x7a,0x73,0x3d,0xd7,0x7e,0xf, 0x3d,0xe0,0xb, 0xa, 0x30, -0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x22,0x7c,0xa7,0x7e,0x1f,0x3d,0xd8,0x69,0x41,0x0, -0xa4,0x5e,0x44,0x10,0xf, 0xa, 0x1a,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x3e,0x14,0xa, -0x5b,0xc4,0x23,0x54,0xe0,0x7c,0xab,0xe4,0x2d,0x51,0x4d,0x45,0x79,0x41,0x0, 0xa4, -0x22,0x7c,0x3b,0x7e,0x2f,0x3d,0xd8,0x69,0x32,0x0, 0x9e,0x5e,0x70,0xe7,0x1b,0x31, -0x68,0xd, 0x1b,0x30,0x68,0xe, 0xb, 0x31,0x78,0x7, 0x4e,0x70,0x10,0x80,0x5, 0x80, -0x0, 0x4e,0x70,0x8, 0x79,0x32,0x0, 0x9e,0x22,0x7c,0x7b,0xa, 0x57,0x5e,0x54,0x0, -0x1, 0xc4,0x54,0xf0,0x7c,0xab,0xe4,0x7e,0xf, 0x3d,0xd8,0x2e,0x14,0x0, 0xa4,0xb, -0xa, 0x30,0x5e,0x60,0xef,0x4d,0x35,0x1b,0xa, 0x30,0x22,0x7c,0x7b,0x30,0x8, 0xb, -0x5e,0x70,0x3, 0xa, 0x37,0x2e,0x34,0x2, 0x0, 0x80,0x2, 0x6d,0x33,0x7e,0xf, 0x3d, -0xe0,0x79,0x30,0x0, 0x3a,0x22,0x7e,0xf, 0x3d,0xd8,0x2e,0x14,0x0, 0x9e,0xb, 0xa, -0x30,0x5e,0x70,0xdf,0x1b,0xa, 0x30,0x74,0x3, 0x12,0x17,0x81,0xe4,0x2, 0x17,0x81, -0x7c,0x7b,0xbe,0x70,0x0, 0x28,0xa, 0xa9,0xd7,0xca,0xa9,0xd3,0xcb,0xa9,0xd2,0xcb, -0x22,0xa9,0xc7,0xca,0xa9,0xc3,0xcb,0xa9,0xc2,0xcb,0x22,0x7c,0x7b,0xbe,0x70,0x0, -0x28,0x9, 0xa9,0xd6,0xca,0xd2,0xcd,0xa9,0xd1,0xcb,0x22,0xa9,0xc6,0xca,0xc2,0xcd, -0xa9,0xc1,0xcb,0x22,0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x3d,0xe0,0x79,0x30,0x0, 0x4, -0xc2,0xc3,0xd2,0xeb,0x22,0x7d,0x13,0x7e,0x1f,0x37,0xf9,0x1b,0x1a,0x10,0xc2,0xc6, -0xd2,0xee,0x22,0x7e,0xa0,0x20,0x80,0xc, 0x7e,0xa0,0x10,0x80,0x5, 0x7e,0xa0,0x8, -0x6c,0x55,0x6d,0x33,0x33,0x92,0xd5,0x50,0xa, 0x6e,0x34,0xff,0xff,0x6e,0x24,0xff, -0xff,0xb, 0x1c,0xa5,0xec,0x33,0x40,0x6, 0x2f,0x11,0xd5,0xf0,0xf6,0x22,0x7c,0xba, -0x24,0x7e,0xa2,0xd5,0x13,0x7c,0x76,0x7c,0x65,0xa5,0xcc,0x92,0xe7,0x7c,0x5b,0x22, -0x7c,0xb5,0x33,0x7c,0xb4,0x33,0x92,0xd5,0x4e,0x50,0x80,0x24,0x81,0x40,0x3, 0x9f, -0x11,0x22,0x7c,0x45,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x24,0xe0,0x50,0xe, 0x7e,0x1c, -0xff,0xff,0x22,0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x4, 0x78,0xf4,0x30, -0xd5,0xa, 0x6e,0x34,0xff,0xff,0x6e,0x24,0xff,0xff,0xb, 0x1c,0x22,0x7c,0xb5,0xa2, -0xe7,0xd2,0xe7,0x7c,0x1b,0x7c,0xb4,0x33,0x40,0x9, 0x68,0xd, 0xb4,0xff,0xb, 0xa5, -0xbd,0xff,0x3, 0x2, 0x19,0x9a,0x2, 0x19,0xa2,0x22,0x7c,0xb, 0x24,0x81,0xc2,0xe0, -0xf5,0x82,0xf4,0x4, 0x2c,0xb0,0x7c,0x2b,0xc3,0x13,0x7c,0x4b,0x7c,0xb5,0x92,0xe7, -0x7c,0x5b,0x7f,0x41,0x7c,0xb6,0xa2,0xe7,0x7c,0xb1,0xa5,0xba,0x7f,0x2, 0xc3,0x13, -0x34,0x0, 0x94,0x0, 0x7c,0x2b,0x7e,0xa0,0x91,0xa4,0x7c,0xba,0x13,0xf4,0x94,0xfe, -0xac,0xb2,0x33,0x7c,0xba,0x33,0x24,0x8c,0xd3,0x13,0x7c,0x5b,0xe4,0x92,0xe7,0x7c, -0x6b,0x6c,0x77,0x7e,0x40,0x3f,0x75,0x83,0x2, 0x7f,0x51,0x7f,0x1, 0x7f,0x14,0x12, -0x1a,0x6c,0x7f,0x5, 0x12,0x19,0xb4,0x9e,0x24,0x0, 0x80,0xd5,0x83,0xeb,0x7e,0x1, -0x82,0x6c,0x11,0xe, 0x4, 0x1e,0x4, 0x2d,0x20,0x5e,0x40,0x7f,0x22,0x2d,0x0, 0x92, -0xd5,0xe, 0x10,0x4e,0x10,0x80,0x7d,0x42,0x2d,0x44,0x50,0x2, 0xb2,0xd5,0x4e,0x50, -0x80,0x6c,0x44,0x7c,0xb8,0x22,0x2c,0x44,0x50,0x12,0xb, 0x1c,0x7e,0x40,0x0, 0x5e, -0x50,0x7f,0xbe,0x18,0x0, 0x0, 0x78,0x4, 0xb, 0x80,0x68,0x16,0xa2,0xd5,0x7c,0xb8, -0x13,0x7c,0x4b,0x7c,0xb5,0x92,0xe7,0x7c,0x5b,0x22,0x7e,0x1c,0xff,0xff,0x22,0x9f, -0x11,0x22,0x7e,0x24,0xff,0x80,0x20,0xd5,0x2, 0x6c,0x45,0x6d,0x33,0x22,0x2, 0x19, -0x9a,0x6e,0x0, 0x80,0x7c,0xb1,0x33,0x7c,0xb0,0x33,0x68,0xd, 0x4, 0x68,0xef,0x7c, -0xb5,0x33,0x7c,0xb4,0x33,0x78,0x3, 0x7f,0x10,0x22,0x4, 0x68,0xe1,0x7d,0x50,0x92, -0xf7,0x7d,0x45,0x7d,0x51,0xbf,0x21,0x40,0x6, 0x7c,0x80,0x7f,0x1, 0x7f,0x12,0x12, -0x19,0x5d,0x7e,0xa1,0xd0,0x5c,0xb0,0x4, 0x78,0x3, 0x20,0xd5,0xc1,0x7c,0xb0,0x4, -0x78,0x7, 0x50,0x2, 0xb2,0xd5,0x2, 0x19,0xa2,0x92,0xd5,0xbe,0x80,0xff,0x68,0xf6, -0x7c,0xb8,0x9c,0xb0,0x6c,0x0, 0x60,0x2a,0xb4,0x18,0x5, 0x7c,0x41,0x2, 0x19,0x76, -0x50,0xfb,0x80,0x3, 0x2f,0x0, 0x4, 0x7c,0x9b,0x5e,0x90,0x7, 0x78,0xf6,0x30,0xe4, -0x6, 0x7c,0x43,0x7d,0x10,0x6d,0x0, 0x30,0xe3,0x8, 0x7c,0x43,0x7c,0x32,0x7c,0x21, -0xa, 0x0, 0x30,0xf5,0x19,0x9f,0x10,0x78,0xe, 0x22,0x2, 0x19,0x9f,0x1b,0x80,0x68, -0xf9,0x2f,0x11,0x50,0x2, 0xb, 0x70,0x7c,0xb5,0x30,0xe7,0xf1,0x80,0x1b,0x2d,0x31, -0x7c,0xb5,0xa5,0x39,0x7c,0x5b,0x50,0x11,0xb, 0x80,0x78,0x3, 0x2, 0x19,0xa2,0x1e, -0x34,0x13,0x50,0x3, 0x4e,0x60,0x80,0x1a,0x2b,0x2, 0x19,0x76,0xbe,0x24,0xff,0xff, -0x68,0x6, 0xbe,0x4, 0xff,0xff,0x78,0x3, 0x2, 0x19,0x9a,0x12,0x19,0x5d,0x5c,0xb0, -0x4, 0x68,0xf5,0x7c,0xb8,0xa5,0x48,0x68,0xef,0x7c,0xb8,0x70,0x3, 0x9f,0x11,0x22, -0xa5,0xb8,0x0, 0x3, 0x2, 0x19,0xa2,0x2e,0x0, 0x81,0x50,0x7, 0x9c,0x80,0x38,0x7, -0x2, 0x19,0x9f,0x9c,0x80,0x50,0xed,0xa, 0x51,0xc2,0xe7,0x4d,0x51,0x78,0x3, 0x2, -0x19,0x8c,0x7e,0x54,0x0, 0x80,0x7e,0x90,0x1a,0x6c,0x0, 0x80,0x6, 0x1b,0x90,0x68, -0x14,0x2f,0x11,0xbf,0x10,0x40,0x4, 0x9f,0x10,0x4c,0xab,0x3, 0x30,0xe7,0xee,0xca, -0xa8,0x6c,0xaa,0x80,0xe8,0xda,0x39,0xda,0x58,0x7c,0x4a,0xbe,0x50,0x80,0x50,0xa, -0x1b,0x80,0x68,0xbc,0x2f,0x11,0x50,0x2, 0xb, 0x70,0x2, 0x19,0x76,0xc2,0xd5,0x7c, -0xb4,0x30,0xe7,0x8, 0xb2,0xd5,0x6e,0x24,0xff,0xff,0xb, 0x24,0x7c,0xb6,0x30,0xe7, -0x12,0xb2,0xd5,0x6e,0x34,0xff,0xff,0xb, 0x34,0x8d,0x32,0x6e,0x24,0xff,0xff,0xb, -0x24,0x80,0x2, 0x8d,0x32,0x30,0xd5,0x6, 0x6e,0x34,0xff,0xff,0xb, 0x34,0x22,0x7d, -0x51,0xad,0x3, 0x7d,0x2, 0x7d,0x21,0xad,0x5, 0x2d,0x12,0xad,0x35,0x2d,0x21,0x22, -0x7d,0x2, 0xad,0x31,0xad,0x10,0x2d,0x21,0x22,0x6d,0x0, 0x74,0x10,0x4d,0x0, 0x78, -0xb, 0x4d,0x22,0x78,0x27,0x8d,0x31,0x7d,0x12,0x6d,0x22,0x22,0x7d,0x43,0x7d,0x32, -0x6d,0x22,0x2f,0x11,0x2d,0x44,0x50,0x2, 0xa5,0xf, 0xbf,0x10,0x40,0x4, 0x9f,0x10, -0xb, 0x90,0x14,0x78,0xed,0x7f,0x1, 0x6d,0x22,0x7d,0x34,0x22,0x7d,0x41,0x7d,0x13, -0x8d,0x24,0x7d,0x2, 0x2f,0x0, 0x40,0x4, 0xbd,0x4, 0x40,0x4, 0x9d,0x4, 0xb, 0x14, -0x14,0x78,0xf1,0x7d,0x23,0x7d,0x31,0x7d,0x10,0x6d,0x0, 0x22,0xc2,0xd5,0x7c,0xb0, -0x30,0xe7,0x8, 0xb2,0xd5,0x9f,0x22,0x9f,0x20,0x7f,0x2, 0x7c,0xb4,0x30,0xe7,0x13, -0xb2,0xd5,0x9f,0x22,0x9f,0x21,0x7f,0x12,0x12,0x1b,0x3b,0x9f,0x22,0x9f,0x20,0x7f, -0x2, 0x80,0x3, 0x12,0x1b,0x3b,0x30,0xd5,0x6, 0x9f,0x22,0x9f,0x21,0x7f,0x12,0x22, -0x6c,0xaa,0x4d,0x11,0x68,0x1a,0x1e,0x54,0x68,0xe, 0xb, 0x38,0x20,0x1b,0x18,0x20, -0xb, 0x35,0xb, 0x15,0x1b,0x54,0x78,0xf2,0x50,0x6, 0x7e,0x39,0x40,0x7a,0x19,0x40, -0x22,0x6c,0xaa,0x4d,0x11,0x68,0x1e,0x1e,0x54,0x50,0xc, 0x7e,0x1b,0x0, 0x7a,0x19, -0x0, 0x68,0x12,0xb, 0x1c,0xb, 0x14,0xb, 0x1a,0x0, 0x1b,0x18,0x0, 0xb, 0x1d,0xb, -0x15,0x1b,0x54,0x78,0xf2,0x22,0x6c,0xaa,0xbe,0x8, 0x0, 0x0, 0x68,0x1e,0x1e,0x54, -0x50,0xc, 0x7e,0x39,0x40,0x7a,0xb, 0x40,0x68,0x12,0xb, 0x34,0xb, 0xc, 0xb, 0x38, -0x20,0x1b,0xa, 0x20,0xb, 0x35,0xb, 0xd, 0x1b,0x54,0x78,0xf2,0x22,0x75,0x84,0x1, -0x7e,0x44,0x47,0xef,0xe4,0x7a,0x49,0xb0,0x1b,0x44,0x78,0xf9,0x7e,0xf8,0x3e,0x47, -0x75,0xd, 0x0, 0x75,0xe, 0x0, 0x75,0xf, 0x2, 0x75,0x10,0x0, 0xc2,0x9, 0xc2,0xa, -0x75,0x7a,0x0, 0xc2,0x13,0x75,0x74,0x47,0x75,0x75,0xf0,0xd2,0x15,0xc2,0x16,0xc2, -0x17,0xc2,0x18,0x75,0x70,0x3, 0x75,0x71,0x0, 0x75,0x72,0x2, 0x75,0x73,0x58,0xc2, -0x1a,0x75,0x7b,0x0, 0xc2,0x1c,0x75,0x7c,0x0, 0xc2,0x1d,0xc2,0x2, 0xc2,0xe, 0x75, -0x78,0x0, 0x75,0x79,0x64,0xc2,0x1e,0xc2,0x1f,0x75,0x1f,0x0, 0xd2,0x3, 0xd2,0x4, -0xd2,0x5, 0x75,0x7d,0x0, 0xc2,0x11,0xd2,0x12,0xd2,0x21,0x7e,0x4, 0x0, 0xff,0x7e, -0x14,0x1e,0x15,0xb, 0xa, 0x40,0x5d,0x44,0x68,0x1a,0x69,0x20,0x0, 0x2, 0xb, 0xe, -0xb, 0x44,0x80,0xa, 0x7e,0xb, 0xb0,0x7a,0x29,0xb0,0xb, 0x24,0xb, 0xc, 0x1b,0x44, -0x78,0xf2,0x80,0xdf,0x2, 0x21,0xb9,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, -0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, -0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x0, 0x1, 0x2, 0x3, 0x4, -0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14, -0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x0, -0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, -0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20, -0x21,0x22,0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, -0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d, -0x1e,0x0, 0x1, 0x1, 0xb, 0x1f,0x24,0xc, 0x1f,0x24,0x0, 0x0, 0x0, 0x47,0x0, 0xcb, -0x1, 0x0, 0x0, 0x10,0xfd,0xc7,0xfb,0x7e,0xfb,0xfb,0x1, 0xbb,0xc, 0x9e,0x19,0x0, -0x21,0x45,0x7, 0x46,0x15,0x97,0x22,0x68,0x22,0x68,0x15,0x97,0x7, 0x46,0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, -0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10,0x11,0x12,0x13,0x14,0x15, -0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0xca,0xf8, -0x7f,0x20,0x80,0xa, 0x7e,0x1b,0xf0,0x7a,0x2b,0xf0,0xb, 0x34,0xb, 0x54,0x69,0xff, -0xff,0xfc,0x7d,0xef,0x1b,0xe4,0x79,0xef,0xff,0xfc,0x4d,0xff,0x78,0xe6,0x7f,0x10, -0xda,0xf8,0x22,0x7d,0x43,0x7f,0x10,0x80,0x7, 0x1b,0x44,0x7a,0xb, 0xb0,0xb, 0x14, -0x4d,0x44,0x78,0xf5,0x22,0x32,0x1, 0x19,0x1, 0x0, 0x2, 0xf8,0x4, 0xe7,0x5, 0xce, -0x6, 0xc2,0x7, 0xb5,0x8, 0xff,0x0, 0x1, 0x2, 0x0, 0xff,0x1, 0x2, 0x0, 0x1, 0xff, -0x2, 0x0, 0x1, 0x2, 0xff,0x7d,0x23,0xbe,0x24,0x0, 0x0, 0x48,0x3, 0x7d,0x32,0x22, -0x6d,0x33,0x9d,0x32,0x22,0x0, 0x2, 0x26,0xca,0x0, 0x1, 0x0, 0x48,0x26,0xcc,0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x27,0x14,0x0, 0x0, 0x4, 0x2b,0xdf, -0x0, 0x0, 0x0, 0x0, 0x0, 0x48,0x2d,0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x1, 0x3, 0xff,0x1, 0x0, 0x1, 0x18,0xda,0x1, 0x0, 0x1, 0x1d,0xf6,0x0, 0x0, -0x1, 0x3d,0x92,0x0, 0x0, 0x2, 0x3d,0x93,0x0, 0x0, 0x0, 0x2, 0x3d,0x95,0x0, 0x0, -0x0, 0x1, 0x3c,0xe1,0xff,0x0, 0x4, 0x0, 0x15,0x0, 0x0, 0x33,0xe5,0x0, 0x2, 0x0, -0x19,0x39,0x47,0x0, 0x2, 0x0, 0x1b,0x39,0x59,0x0, 0x1, 0x37,0xc6,0x0, 0x0, 0x1, -0x37,0xc7,0x0, 0x0, 0x1, 0x37,0xfd,0x0, 0x0, 0x2, 0x3e,0x3f,0x0, 0x0, 0x0, 0x1, -0x3e,0x20,0x0, 0x0, 0x1, 0x3e,0x23,0x0, 0x0, 0x1, 0x3e,0x24,0x0, 0x0, 0x1, 0x3e, -0x25,0x0, 0x0, 0x1, 0x3e,0x26,0x0, 0x0, 0x1, 0x3e,0x27,0x0, 0x0, 0x1, 0x3e,0x28, -0x0, 0x0, 0x1, 0x3e,0x29,0x0, 0x0, 0x1, 0x31,0x4b,0x0, 0x0, 0x2, 0x31,0x60,0x0, -0x0, 0x0, 0x1, 0x33,0x29,0x0, 0x0, 0x1, 0x33,0x2a,0x0, 0x0, 0x24,0x34,0xc0,0x0, -0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, -0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, 0x0, 0x1, 0x2, -0x0, 0x1, 0x2, 0x0, 0xc, 0x34,0xe4,0x3, 0x84,0x0, 0x64,0x2, 0x58,0x0, 0x50,0x0, -0x0, 0x0, 0x32,0x0, 0x2, 0x36,0x2, 0x0, 0x0, 0x0, 0x2, 0x3e,0x3a,0x0, 0x0, 0x0, -0x1, 0x0, 0x7e,0x0, 0x0, 0x1, 0x0, 0x7f,0x0, 0x0, 0x1, 0x0, 0x80,0x0, 0x0, 0x1, -0x2, 0xa1,0x0, 0x0, 0x1, 0x2, 0xa2,0x0, 0x0, 0x1, 0x2, 0xa7,0x0, 0x0, 0x1, 0x3b, -0xf5,0x1, 0x0, 0x1, 0x37,0xff,0x0, 0x0, 0x6, 0x34,0xba,0x30,0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x1, 0x36,0x4, 0x0, 0x0, 0x1, 0x36,0x5, 0x0, 0x0, 0x1, 0x36,0x6, 0x0, -0x0, 0x1, 0x36,0x7, 0x0, 0x0, 0x1, 0x37,0x3b,0x0, 0x0, 0x1, 0x37,0x3c,0x0, 0x0, -0x2, 0x37,0x65,0x0, 0x0, 0x0, 0x1, 0x37,0xc5,0x0, 0x0, 0x4, 0x3c,0x6e,0x0, 0x0, -0x0, 0x0, 0x0, 0x1, 0x3a,0xd6,0x0, 0x0, 0x1, 0x3a,0xd8,0x0, 0x0, 0x1, 0x3a,0xf4, -0x0, 0x0, 0x14,0x3a,0xf5,0x12,0x74,0x76,0x12,0x0, 0x0, 0x0, 0x0, 0x18,0x2e,0x2f, -0x18,0x18,0x4f,0x50,0x18,0x18,0x74,0x76,0x18,0x0, 0x1, 0x3b,0xe5,0x0, 0x0, 0x1, -0x3b,0xe7,0x0, 0x0, 0x1, 0x3, 0xf5,0xff,0x0, 0x1, 0x3, 0xf6,0x0, 0x0, 0x1, 0x3, -0xf7,0x0, 0x0, 0x1, 0x3, 0xfc,0xff,0x0, 0x1, 0x3e,0x2a,0x0, 0x0, 0x1, 0x3e,0x2b, -0x0, 0x0, 0x2, 0x3e,0x2c,0x0, 0x0, 0x0, 0x2, 0x3e,0x2e,0x0, 0x0, 0x0, 0x1, 0x3e, -0x30,0x64,0x0, 0x1, 0x3e,0x31,0x0, 0x0, 0x2, 0x3e,0x32,0x0, 0x0, 0x0, 0x1, 0x3e, -0x47,0x0, 0x0, 0x1, 0x3, 0xfd,0x0, 0x0, 0x1, 0x3, 0xfe,0x0, 0x0, 0x1, 0x2d,0x5a, -0x0, 0x0, 0x2, 0x2d,0x5b,0x2d,0x61,0x0, 0x1, 0x31,0x21,0x2, 0x0, 0x1, 0x31,0x4a, -0x0, 0x0, 0x1, 0x3e,0x15,0x0, 0x0, 0x4, 0x3e,0x43,0x0, 0x0, 0xb0,0x0, 0x0, 0x1, -0x3d,0xd6,0x1, 0x0, 0x1, 0x3d,0xd7,0x0, 0x0, 0x4, 0x3d,0xd8,0x0, 0x0, 0xbc,0x0, -0x0, 0x4, 0x3d,0xdc,0x0, 0x0, 0xb8,0xc0,0x0, 0x4, 0x3d,0xe0,0x0, 0x0, 0xb8,0x0, -0x0, 0x4, 0x3d,0xe4,0x4, 0x8, 0x10,0x6, 0x0, 0x1, 0x3d,0xe8,0x0, 0x0, 0x4, 0x3d, -0xf9,0x0, 0x0, 0x80,0x0, 0x0, 0x4, 0x37,0xf1,0x0, 0x0, 0x80,0x0, 0x0, 0x4, 0x37, -0xf5,0x0, 0x0, 0x90,0x0, 0x0, 0x4, 0x37,0xf9,0x0, 0x0, 0xb4,0x0, 0x0, 0x0, 0x3, -0x20,0x0, 0xd, 0x1, 0xf4,0x2, 0x58,0x0, 0xc, 0x1, 0x2c,0x1, 0xc2,0x0, 0xb, 0x0, -0x96,0x1, 0x40,0x0, 0x8, 0x0, 0x78,0x0, 0xc8,0x0, 0x8, 0x0, 0x64,0x0, 0x78,0x0, -0x6, 0x0, 0x3c,0x0, 0x3c,0x0, 0x6, 0x0, 0x0, 0x74,0x1, 0x7a,0xb3,0x3d,0x9, 0x12, -0x32,0xbe,0x74,0x1, 0xf1,0x7b,0x71,0x30,0x31,0xea,0x21,0x1c,0xca,0x3b,0x7c,0xfb, -0x6c,0xee,0xe4,0x7a,0xb3,0x3c,0x1, 0x6c,0xdd,0x7e,0x73,0x3c,0x1, 0xbe,0x70,0x4, -0x40,0x2, 0x80,0x19,0xbe,0x70,0x0, 0x28,0x19,0x74,0x5, 0xac,0xb7,0x9, 0x65,0x19, -0x17,0xbc,0x6f,0x78,0xd, 0xa, 0x37,0xbe,0x34,0x0, 0x3, 0x78,0x5, 0xe4,0x7a,0xb3, -0x3c,0x1, 0xe4,0x7a,0xb3,0x1f,0xa7,0x7e,0xc3,0x3c,0x1, 0x80,0x43,0x7e,0xb3,0x3c, -0x1, 0x4, 0x7a,0xb3,0x3c,0x1, 0x74,0x5, 0xac,0xbc,0x9, 0x75,0x19,0x17,0xbc,0x7f, -0x68,0x2c,0xa, 0x2d,0x19,0xc2,0x3c,0x5, 0x74,0x5, 0xac,0xbd,0x19,0x75,0x1f,0xa9, -0x74,0x5, 0xac,0xbd,0x9, 0xb5,0x1f,0xa9,0x7c,0x7d,0x12,0x63,0x93,0x74,0x5, 0xac, -0xbd,0x59,0x35,0x1f,0xaa,0xb, 0xd0,0xb, 0xe0,0xbe,0xe0,0x3, 0x50,0x7, 0xb, 0xc0, -0xbe,0xc0,0x4, 0x40,0xb8,0xe4,0x7a,0xb3,0x1f,0xa8,0x7e,0x8, 0x1e,0x89,0x12,0xe, -0x4, 0xe4,0x7a,0xb3,0x3c,0x2, 0xda,0x3b,0x22,0x12,0x0, 0x18,0xd1,0xc6,0x12,0x3d, -0x31,0x12,0x67,0xf1,0x12,0x58,0xa0,0x31,0x9, 0x7e,0xb3,0x3d,0x9, 0x24,0xfd,0x68, -0x8, 0xb, 0xb1,0x78,0xf4,0x71,0x73,0x80,0xf0,0x12,0x40,0xf3,0x80,0xeb,0x12,0x58, -0xe5,0x12,0x5f,0x86,0x12,0x5f,0x59,0xd2,0x15,0x22,0x31,0xde,0x51,0x14,0x12,0x0, -0x5e,0x7e,0xb3,0x1f,0x3d,0x22,0x7e,0x34,0xd, 0xac,0x71,0x51,0x12,0x3d,0x31,0x12, -0x58,0xa0,0x74,0x1, 0x7a,0xb3,0x3d,0x9, 0x12,0x32,0xbe,0x71,0x2a,0x12,0x40,0x2b, -0x31,0xea,0x21,0x1c,0x12,0x5e,0xd1,0xe4,0x7a,0xb3,0x3d,0xff,0x7a,0xb3,0x3d,0xfe, -0x12,0x37,0xcd,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x2, 0x74,0x3, 0x7a,0xb3,0x3d,0xff, -0x22,0xca,0x3b,0xf1,0x70,0x50,0xfc,0x7e,0x73,0x3e,0x14,0x7a,0x73,0x18,0xd1,0x7e, -0xf3,0x1f,0x3d,0x7c,0xbf,0x12,0x4a,0x5a,0x12,0x67,0xb8,0x12,0x66,0x6b,0x7e,0xb3, -0x1f,0x4d,0xf5,0x28,0x7e,0xc3,0x1f,0x4e,0x7e,0xb3,0x3d,0x9, 0xb4,0x1, 0xe, 0x12, -0x85,0xc1,0x7e,0xb3,0x18,0xcf,0x70,0x5, 0x51,0x14,0xc3,0x61,0x27,0x12,0x41,0x81, -0x7a,0x35,0x34,0x7e,0x8, 0x4, 0x72,0x7e,0x18,0x6, 0xb4,0x12,0x69,0x25,0x12,0x41, -0x81,0x7a,0x35,0x34,0x7e,0x8, 0x4, 0x0, 0x7e,0x18,0x8, 0xa, 0x12,0x69,0x25,0x7e, -0xb3,0x3d,0x9, 0xb4,0x3, 0x7, 0x12,0x9f,0x6f,0x7a,0x37,0x3d,0x88,0x74,0x1, 0x7a, -0xb3,0x18,0xce,0x71,0x30,0x12,0x9f,0x16,0x51,0x14,0x7e,0x8, 0x4, 0x72,0x7a,0xd, -0x29,0x7e,0x18,0x6, 0x3a,0x7e,0xb3,0x1f,0xbe,0x12,0x69,0x41,0x7e,0x8, 0x4, 0x0, -0x7a,0xd, 0x29,0x7e,0x18,0x5, 0xc8,0x7e,0xb3,0x18,0xd4,0x12,0x69,0x41,0x7e,0xd3, -0x1f,0x4d,0x7e,0xe3,0x1f,0x4e,0xe5,0x28,0x7a,0xb3,0x1f,0x4d,0x7a,0xc3,0x1f,0x4e, -0x7e,0x34,0x9, 0x74,0x7e,0x4, 0xf, 0x5c,0x7d,0x20,0x7d,0x10,0x12,0x50,0x22,0x7a, -0xd3,0x1f,0x4d,0x7a,0xe3,0x1f,0x4e,0x7c,0xbf,0x12,0x49,0xf6,0x12,0x67,0x27,0x7e, -0xb3,0x3e,0x31,0x4, 0x7a,0xb3,0x3e,0x31,0x7e,0x73,0x3e,0x31,0xbe,0x70,0xfa,0x28, -0x6, 0x74,0x64,0x7a,0xb3,0x3e,0x31,0x7e,0xb3,0x18,0xce,0x60,0x9, 0x7e,0xb3,0x18, -0xcf,0x60,0x3, 0xd3,0x80,0x1, 0xc3,0xda,0x3b,0x22,0x7e,0x34,0xd, 0xac,0x71,0x51, -0x12,0x35,0x5, 0x12,0x49,0x2b,0x61,0x38,0x30,0x17,0x8, 0x12,0x50,0x9b,0x12,0x49, -0x51,0xc2,0x17,0x22,0x74,0x81,0x7a,0xb3,0x3e,0x2a,0xe4,0xf1,0x29,0x7e,0x34,0x0, -0xc8,0x7d,0x23,0x6d,0x33,0x7a,0x37,0x34,0xa9,0x7a,0x27,0x34,0xab,0x22,0xf1,0x70, -0x50,0xfc,0x12,0x40,0x2b,0x6d,0x33,0x7a,0x37,0x3e,0x3c,0x7a,0x37,0x3e,0x2c,0x71, -0x2a,0x41,0x14,0x71,0x5e,0x7e,0xb3,0x3d,0x9, 0xb4,0x1, 0x2, 0x80,0x2, 0x81,0x14, -0x12,0xca,0xf8,0x71,0x4d,0x12,0x88,0x51,0x12,0x80,0x40,0x51,0x31,0x50,0xe6,0x12, -0x9a,0x77,0x7e,0xb3,0x3d,0x6, 0xb4,0x1, 0x4, 0xc2,0x6, 0xf1,0x87,0x12,0x2a,0xbf, -0x12,0x50,0x6, 0xe4,0x33,0xbe,0xb0,0x1, 0x68,0xcb,0x12,0x46,0xa3,0x12,0x50,0x6, -0xe4,0x33,0xbe,0xb0,0x1, 0x68,0xbe,0x12,0x41,0x90,0x12,0x4a,0xeb,0x12,0x78,0x7e, -0x12,0x84,0x38,0x12,0x0, 0x19,0x12,0x6c,0x31,0x12,0x53,0x3e,0x12,0x56,0xde,0x12, -0x0, 0x42,0x12,0xc6,0x6b,0x12,0xc3,0x22,0x7e,0x73,0x3d,0x32,0xbe,0x70,0x0, 0x28, -0x26,0x7e,0x37,0x3e,0x2c,0xbe,0x34,0x1, 0x90,0x50,0x1c,0xf1,0xd7,0x68,0xf, 0xbe, -0xb0,0x4, 0x68,0xa, 0xbe,0xb0,0x5, 0x68,0x5, 0xe4,0x7a,0xb3,0x3d,0x7, 0x6d,0x33, -0x7a,0x37,0x3e,0x3c,0x12,0x52,0x7d,0x12,0x73,0x60,0x12,0x43,0xd3,0xf1,0xdf,0x12, -0x4f,0xe7,0x61,0x75,0x12,0xcd,0xcb,0x81,0x19,0x7e,0xb3,0x3d,0x6, 0xb4,0x1, 0x3, -0xe4,0xe1,0x7b,0x22,0x7e,0xb3,0x3d,0x7, 0x14,0x78,0x2, 0x81,0xad,0x14,0x78,0x2, -0xa1,0x24,0x14,0x78,0x2, 0x81,0xdb,0x14,0x78,0x2, 0x81,0xec,0x14,0x78,0x2, 0xa1, -0xb, 0x24,0x5, 0x68,0x2, 0xa1,0x28,0x12,0x43,0xe7,0xbe,0x34,0x0, 0x0, 0x18,0x10, -0xa2,0x19,0xe4,0x33,0xb4,0x1, 0x16,0x7e,0xb3,0x3d,0x32,0xbe,0xb0,0x1, 0x68,0xd, -0x6d,0x33,0x7a,0x37,0x3e,0x3c,0xe4,0x7a,0xb3,0x3e,0x3e,0xa1,0x35,0x7e,0x73,0x3c, -0xe9,0xa, 0x27,0x7e,0x34,0x4, 0x0, 0xad,0x32,0x7e,0xb3,0x3c,0xe8,0x70,0x4, 0x7e, -0x34,0x1c,0x0, 0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0x8, 0x7e,0x37,0x3a,0x86,0x2e,0x34, -0x4, 0x0, 0xbe,0x37,0x3e,0x3c,0x40,0x2, 0xa1,0x35,0x6d,0x33,0x7a,0x37,0x3e,0x3c, -0x74,0x1, 0x7a,0xb3,0x3d,0x7, 0xe4,0x7a,0xb3,0x3e,0x42,0xa1,0x35,0x12,0x43,0xe7, -0xbe,0x34,0x0, 0x0, 0x18,0x5, 0x12,0xc4,0x5a,0x18,0x75,0xe4,0x7a,0xb3,0x3d,0x7, -0x12,0xc4,0x5a,0x18,0x5, 0xe4,0x7a,0xb3,0x3e,0x3e,0x7e,0xb3,0x3e,0x3e,0xb4,0x1, -0x6, 0x74,0x1, 0x7a,0xb3,0x3d,0x7, 0xd2,0x1f,0x80,0x55,0x12,0x0, 0x54,0xd2,0x18, -0x7e,0x34,0xc, 0x1c,0x7a,0x37,0x3e,0x3f,0x74,0x4, 0x80,0x19,0x12,0x0, 0x54,0xa2, -0x18,0xe4,0x33,0xb4,0x1, 0xe, 0x7e,0x37,0x3e,0x3f,0x4d,0x33,0x78,0x37,0xc2,0x18, -0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x3d,0x7, 0x80,0x2a,0xc2,0x18,0x12,0x0, 0x54, -0x71,0x4d,0x12,0x3d,0xb, 0x31,0xf6,0xe4,0x7a,0xb3,0x3d,0x7, 0x7a,0xb3,0x3e,0x31, -0xd2,0x1f,0x80,0x11,0xc2,0x18,0x80,0xd, 0xc2,0x18,0x74,0x1, 0x7a,0xb3,0x3d,0x7, -0xe4,0x7a,0xb3,0x3e,0x31,0x12,0x77,0xc6,0xa1,0x3a,0xca,0x3b,0x7e,0xb3,0x3d,0x7, -0xb4,0x1, 0x2, 0x80,0x2, 0xc1,0xaa,0x6c,0xdd,0xc2,0x6, 0x7e,0xb3,0x3d,0x32,0xb4, -0x1, 0x8, 0x7e,0xe0,0x10,0x7e,0xf0,0x3e,0x80,0x6, 0x7e,0xe0,0xa, 0x7e,0xf0,0x64, -0x12,0x88,0x4c,0x7d,0x43,0xf1,0x70,0xe4,0x33,0x68,0xfa,0x74,0x1, 0x7a,0xb3,0x3e, -0x41,0x12,0x31,0xaa,0x12,0xd1,0xfd,0x74,0xa, 0x12,0x35,0xa0,0x6d,0x33,0xe4,0x6c, -0x55,0x12,0x16,0xfb,0x7e,0x1f,0x1f,0x39,0x7a,0x1d,0x26,0x7e,0xb3,0x1f,0x26,0xf5, -0x25,0x74,0x4, 0x7a,0xb3,0x1f,0x26,0x7e,0x1f,0x1f,0x39,0x6d,0x22,0x5e,0x60,0x1, -0x7a,0x1f,0x1f,0x39,0x7a,0x47,0x1f,0x33,0x12,0x34,0x83,0x7e,0x70,0x1, 0x12,0x34, -0x49,0xc1,0x85,0xd2,0x7, 0xd1,0xad,0x12,0x49,0x24,0x30,0x16,0x2, 0xc1,0x8f,0x7e, -0xb3,0x3d,0x9, 0xb4,0x1, 0x2, 0x80,0x2, 0xc1,0x8f,0x7c,0xbe,0x12,0x88,0x8e,0xe4, -0x12,0x18,0x1b,0x12,0x36,0xde,0x12,0x33,0x1e,0xa9,0xd1,0xcb,0x7e,0xb3,0x1f,0x28, -0x12,0x0, 0x76,0xc2,0x6, 0x80,0x39,0x30,0x21,0x2b,0x20,0x6, 0x28,0xd2,0x7, 0xd1, -0xad,0x12,0x51,0xbf,0xd2,0x6, 0xd1,0xde,0x68,0x6, 0x7e,0xb3,0x3e,0x3e,0x60,0x30, -0xc2,0x7, 0xd1,0xad,0x80,0xf, 0x74,0x81,0x7a,0xb3,0x3e,0x2a,0xe4,0xf1,0x29,0x20, -0x6, 0x3, 0x20,0x21,0x3, 0x20,0x93,0xee,0x30,0x21,0x3, 0x30,0x6, 0x2, 0xd1,0xe9, -0x7e,0xb3,0x3d,0x9, 0xb4,0x1, 0x6, 0x30,0x1f,0xbd,0x30,0x6, 0xba,0x30,0x21,0xb7, -0x7e,0xa3,0x3e,0x3e,0x4c,0xaa,0x78,0x6, 0x74,0x1, 0x7a,0xb3,0x3e,0x41,0x4c,0xaa, -0x68,0xb, 0x7e,0xb3,0x3d,0x32,0x70,0x5, 0xe4,0x7a,0xb3,0x3e,0x3e,0xd1,0xde,0x78, -0x15,0x7e,0xb3,0x3e,0x3e,0x60,0xf, 0xe4,0x7a,0xb3,0x3e,0x3e,0x7a,0xb3,0x1d,0xea, -0x7a,0xb3,0x1d,0xeb,0x80,0x29,0xd1,0xde,0x68,0x1b,0x7e,0xb3,0x3e,0x3e,0x70,0x15, -0xf1,0xd7,0x68,0x1b,0xbe,0xb0,0x4, 0x68,0x16,0xbe,0xb0,0x5, 0x68,0x11,0xe4,0x7a, -0xb3,0x3d,0x7, 0x80,0xa, 0x7c,0xad,0xb, 0xd0,0xbc,0xaf,0x50,0x2, 0xa1,0xb3,0xe4, -0x7a,0xb3,0x1f,0x30,0x7e,0x1d,0x26,0x7a,0x1f,0x1f,0x39,0xe5,0x25,0x7a,0xb3,0x1f, -0x26,0xd2,0x7, 0xd1,0xad,0xa9,0xd1,0xcb,0x51,0x14,0xda,0x3b,0x22,0x30,0x7, 0x6, -0x12,0xd2,0xb, 0x2, 0x18,0x0, 0x12,0xd2,0x4, 0xc2,0x8, 0xc1,0xbd,0xa9,0xd0,0xce, -0xa2,0x8, 0xa9,0x91,0xc9,0x22,0x7e,0x34,0x2, 0xcb,0xca,0x39,0x7e,0x34,0x60,0x0, -0x7e,0x24,0x0, 0xff,0x7e,0x8, 0x38,0x0, 0x12,0x1d,0xae,0x1b,0xfd,0x22,0x7e,0x73, -0x37,0xf0,0xa, 0x37,0x5e,0x34,0x0, 0x2, 0x22,0x30,0x1f,0x3, 0x20,0x21,0x39,0x30, -0x21,0x4, 0xc2,0x7, 0xd1,0xad,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0xa9,0xd3,0xcd,0xa9, -0xd2,0xcd,0xa9,0xd0,0xce,0xa9,0xc4,0xc9,0x74,0x81,0x7a,0xb3,0x3e,0x2a,0x74,0x2, -0xf1,0x29,0xa9,0xd0,0xce,0xa9,0xd4,0xc9,0xa9,0xc1,0xcd,0xa9,0xc3,0xcd,0xa9,0xc2, -0xcd,0x30,0x21,0x4, 0xc2,0x7, 0xc1,0xad,0x22,0x7c,0xab,0x7e,0xb3,0x3e,0x2a,0xb4, -0x81,0x38,0x4c,0xaa,0x78,0x5, 0xa9,0xd0,0x87,0x80,0x29,0xbe,0xa0,0x1, 0x78,0xf, -0xc2,0xaf,0xa9,0xd0,0xce,0xa9,0xc7,0xc9,0xa9,0xd1,0x87,0xd2,0xaf,0x80,0x15,0xbe, -0xa0,0x2, 0x78,0x16,0xc2,0xaf,0x20,0x93,0x9, 0xa9,0xd0,0xce,0xa9,0xd7,0xc9,0xa9, -0xd1,0x87,0xd2,0xaf,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe4,0x7a,0xb3,0x3e,0x2a,0x22, -0x7e,0xb3,0x3d,0xff,0xb4,0x1, 0x2, 0xc3,0x22,0xd3,0x22,0x7c,0x7b,0xa5,0xbf,0x0, -0x3, 0xd2,0x86,0x22,0xc2,0x86,0x22,0xc2,0xaf,0x30,0x6, 0x3c,0x7e,0xb3,0x34,0x38, -0x60,0x36,0xf1,0xd7,0x68,0x8, 0xbe,0xb0,0x4, 0x68,0x3, 0xb4,0x5, 0x5, 0x12,0x5f, -0xfa,0x80,0x28,0x74,0x1, 0xf1,0x7b,0xd2,0xaf,0x7e,0xb3,0x3d,0x32,0x60,0x1f,0x7e, -0xb3,0x1d,0xeb,0x70,0x19,0x80,0x2, 0x71,0x44,0x7e,0xb3,0x34,0x38,0x60,0xf, 0xe5, -0x1f,0xbe,0xb0,0xfa,0x28,0xf1,0x80,0x6, 0x20,0x6, 0x3, 0xe4,0xf1,0x7b,0xd2,0xaf, -0x22,0x74,0x1, 0x7a,0xb3,0x3e,0x3e,0x7e,0xb3,0x3d,0x7, 0xbe,0xb0,0x3, 0x22,0x91, -0x24,0x7e,0x73,0x3c,0xe1,0xbe,0x70,0xff,0x68,0xf, 0xbe,0x73,0x3d,0x7, 0x68,0x9, -0x7a,0x73,0x3d,0x7, 0x12,0x0, 0x54,0x81,0x24,0x22,0x7c,0x1b,0xa5,0xb9,0xf, 0x5, -0x7e,0xb3,0x2d,0x5, 0x22,0xbe,0x10,0x34,0x38,0x2, 0x21,0x2, 0xa5,0xb9,0x35,0x5, -0x7e,0xb3,0x1f,0x3e,0x22,0xbe,0x10,0x36,0x68,0x4, 0xa5,0xb9,0x37,0x19,0x7e,0x15, -0x8, 0x7d,0x31,0xb, 0x34,0x7a,0x35,0x8, 0x2e,0x17,0x2b,0xdd,0x7e,0x19,0xb0,0xa5, -0xb9,0x37,0x3, 0x75,0x77,0x36,0x22,0xbe,0x10,0x38,0x68,0x4, 0xa5,0xb9,0x39,0x19, -0x7e,0x3, 0x3d,0x65,0x7c,0xb0,0x4, 0x7a,0xb3,0x3d,0x65,0xa5,0xb9,0x39,0x3, 0x75, -0x77,0x38,0xa, 0x30,0x9, 0xb3,0x1f,0x4f,0x22,0xbe,0x10,0x3a,0x68,0x4, 0xa5,0xb9, -0x3b,0x19,0x7e,0x3, 0x3d,0x67,0x7c,0xb0,0x4, 0x7a,0xb3,0x3d,0x67,0xa5,0xb9,0x3b, -0x3, 0x75,0x77,0x3a,0xa, 0x30,0x9, 0xb3,0x1f,0x72,0x22,0xa5,0xb9,0xfb,0x5, 0x7e, -0xb3,0x1f,0x40,0x22,0xa5,0xb9,0xfa,0x3, 0x74,0x2, 0x22,0xa5,0xb9,0x5e,0x25,0x7e, -0x7f,0x3d,0xd8,0x69,0x17,0x0, 0xa8,0xa, 0x32,0x51,0xa, 0x7c,0x17,0x5e,0x10,0x1, -0x7c,0xb1,0x3, 0x3, 0x54,0xc0,0x7c,0x1b,0xa, 0x52,0x54,0x3, 0x4c,0x1b,0x4e,0x10, -0x80,0x7c,0xb1,0x22,0xbe,0x10,0x3c,0x68,0x4, 0xa5,0xb9,0x3d,0x19,0x7e,0x3, 0x3d, -0x69,0x7c,0xb0,0x4, 0x7a,0xb3,0x3d,0x69,0xa5,0xb9,0x3d,0x3, 0x75,0x77,0x3c,0xa, -0x30,0x9, 0xb3,0x1e,0x96,0x22,0xbe,0x10,0x3e,0x68,0x4, 0xa5,0xb9,0x3f,0x19,0x7e, -0x3, 0x3d,0x6b,0x7c,0xb0,0x4, 0x7a,0xb3,0x3d,0x6b,0xa5,0xb9,0x3f,0x3, 0x75,0x77, -0x3e,0xa, 0x30,0x9, 0xb3,0x1e,0xb9,0x22,0xbe,0x10,0x40,0x40,0xc, 0xbe,0x10,0x4d, -0x38,0x7, 0xa, 0x31,0x9, 0xb3,0x3d,0x41,0x22,0xbe,0x10,0x4e,0x68,0x4, 0xa5,0xb9, -0x4f,0x1c,0x7e,0x3, 0x3d,0x86,0x7c,0xb0,0x4, 0x7a,0xb3,0x3d,0x86,0xa5,0xb9,0x4f, -0x3, 0x75,0x77,0x4e,0xa, 0x30,0x2e,0x37,0x2b,0x75,0x7e,0x39,0xb0,0x22,0xbe,0x10, -0x51,0x68,0x4, 0xa5,0xb9,0x52,0x1e,0x7e,0x34,0x38,0x0, 0x7e,0xb3,0x3d,0x91,0xa, -0x1b,0x2d,0x13,0x7e,0x19,0xa0,0x4, 0x7a,0xb3,0x3d,0x91,0xa5,0xb9,0x52,0x3, 0x75, -0x77,0x51,0x7c,0xba,0x22,0xbe,0x10,0x60,0x40,0xc, 0xbe,0x10,0x6c,0x38,0x7, 0xa, -0x31,0x9, 0xb3,0x34,0x4d,0x22,0xa5,0xb9,0x5b,0x3, 0xe5,0xf, 0x22,0xa5,0xb9,0x5a, -0x5, 0x7e,0x57,0x26,0xca,0x22,0xbe,0x10,0x58,0x68,0x4, 0xa5,0xb9,0x59,0x20,0xa5, -0xb9,0x59,0x5, 0x75,0x77,0x58,0x80,0x5, 0xe4,0x7a,0xb3,0x27,0x14,0x7e,0x13,0x27, -0x14,0x7c,0xb1,0x4, 0x7a,0xb3,0x27,0x14,0xa, 0x31,0x9, 0xb3,0x26,0xcc,0x22,0xbe, -0x10,0xf4,0x68,0x4, 0xa5,0xb9,0xf5,0x16,0x7e,0x15,0xb, 0x7d,0x31,0xb, 0x34,0x7a, -0x35,0xb, 0x9, 0xb1,0x2b,0xe3,0xa5,0xb9,0xf5,0x3, 0x75,0x77,0xf4,0x22,0xbe,0x10, -0xf0,0x68,0x4, 0xa5,0xb9,0xf1,0x6, 0x2e,0x10,0x21,0xa5,0xe7,0x22,0xbe,0x10,0xf2, -0x68,0x4, 0xa5,0xb9,0xf3,0x16,0x7e,0x15,0x11,0x3e,0x14,0x7e,0x1f,0x2b,0xdf,0x2d, -0x31,0xb, 0x1a,0x50,0xa5,0xb9,0xf2,0x3, 0xa, 0x5a,0x22,0x22,0xa5,0xb9,0xf6,0x3, -0xe5,0x10,0x22,0xa5,0xb9,0xf7,0x3, 0x74,0x64,0x22,0xa5,0xb9,0xfd,0x2, 0xe4,0x22, -0xa5,0xb9,0xff,0x2, 0xe4,0x22,0xe4,0x22,0x1e,0x34,0x1e,0x34,0x1e,0x34,0x1e,0x34, -0x22,0x51,0x64,0x7e,0xb3,0x3c,0x0, 0xb4,0x1, 0x6, 0x7e,0x34,0x0, 0xdc,0x51,0x57, -0x7e,0xb3,0x1c,0x7c,0xb4,0x1, 0x9, 0x7e,0x34,0x0, 0xe6,0x51,0x57,0x12,0xd1,0x9b, -0x7e,0xb3,0x1d,0xeb,0x70,0x20,0x7e,0x27,0x1e,0x76,0x7d,0x32,0x7e,0x14,0x0, 0x4, -0xad,0x13,0x7d,0x31,0x51,0x8, 0xbe,0x34,0x0, 0x50,0x28,0x4, 0x7e,0x34,0x0, 0x50, -0x2d,0x32,0x7a,0x37,0x1e,0x76,0x22,0x7a,0x37,0x1e,0x76,0x7e,0x34,0x0, 0xbe,0x7a, -0x37,0x1e,0x78,0x22,0x7e,0x73,0x3c,0xe2,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a,0x37, -0x1e,0x76,0x7e,0x73,0x3c,0xe3,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x7a,0x37,0x1e,0x78, -0x6d,0x33,0x9e,0x37,0x1e,0x78,0x7a,0x37,0x1e,0x7a,0x7e,0x73,0x3c,0xe4,0x51,0xb4, -0x7a,0x37,0x1e,0x6b,0x7e,0x73,0x3c,0xe5,0x51,0xb4,0x7a,0x37,0x1e,0x6d,0x7e,0x73, -0x3c,0xe6,0x51,0xb4,0x7a,0x37,0x1e,0x6f,0x22,0x7e,0xf, 0x3d,0xd8,0x69,0x20,0x0, -0xa0,0x5e,0x50,0x1f,0xa, 0x37,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x3e,0x34,0x22,0x51, -0x11,0xe4,0x7a,0xb3,0x3, 0xfd,0x41,0xc8,0xe4,0x7a,0xb3,0x1c,0x67,0x71,0xf, 0x7e, -0xb3,0x18,0xcf,0xb4,0x1, 0x8, 0x7e,0x73,0x1c,0x58,0x7a,0x73,0x1c,0x66,0x7e,0x18, -0x4, 0xe4,0x7a,0x1f,0x6, 0xb0,0x12,0xd1,0x75,0x12,0xcf,0x82,0x12,0x7d,0xc0,0x7e, -0xb3,0x18,0xce,0xb4,0x1, 0x18,0x7e,0x73,0x19,0x67,0x7a,0x73,0x19,0xd7,0x7e,0x73, -0x19,0x69,0x7a,0x73,0x19,0xd9,0x7e,0x73,0x19,0x68,0x7a,0x73,0x19,0xd8,0x22,0xca, -0x3b,0x6c,0xff,0x80,0x9, 0xe4,0xa, 0x3f,0x19,0xb3,0x1a,0xec,0xb, 0xf0,0x7e,0xb3, -0x38,0xa2,0x12,0x7e,0xca,0xb, 0x24,0xa, 0x3f,0xbd,0x32,0x48,0xe8,0xe4,0x7a,0xb3, -0x1c,0x58,0x7a,0xb3,0x1c,0x59,0x6d,0x33,0x7a,0x37,0x1c,0x5a,0x7a,0x37,0x1c,0x5c, -0x7a,0x37,0x1c,0x5e,0x7a,0x37,0x1c,0x62,0x7e,0xd4,0x2, 0xaa,0x5e,0xd4,0xff,0xfe, -0x6d,0xcc,0x7e,0x1f,0x15,0x48,0x7a,0x37,0x2, 0xea,0x7d,0x3d,0x7a,0x37,0x2, 0xee, -0x7e,0x34,0x17,0xdc,0x7a,0x37,0x2, 0xec,0x7e,0x73,0x1e,0x89,0x7a,0x73,0x2, 0xe7, -0x7e,0x73,0x1e,0x8a,0x7a,0x73,0x2, 0xe6,0x7e,0x37,0x1e,0x78,0x7a,0x37,0x2, 0xf0, -0x7e,0x37,0x1e,0x7a,0x7a,0x37,0x2, 0xf2,0x7e,0x37,0x1e,0x7c,0x7a,0x37,0x2, 0xf4, -0x6d,0x33,0x9e,0x37,0x1e,0x7c,0x7a,0x37,0x2, 0xf6,0x7e,0x73,0x38,0xa2,0x7a,0x73, -0x2, 0xe8,0x7e,0x73,0x3, 0xfe,0x7a,0x73,0x2, 0xe9,0x7e,0x8, 0x2, 0xe6,0x7e,0x18, -0x2, 0xf8,0x12,0xb, 0x48,0x7e,0x73,0x2, 0xf8,0x7a,0x73,0x1c,0x58,0x7e,0x73,0x2, -0xf9,0x7a,0x73,0x1c,0x59,0x7e,0x37,0x2, 0xfa,0x7a,0x37,0x1c,0x5a,0x7e,0x37,0x2, -0xfc,0x7a,0x37,0x1c,0x5c,0x7e,0x37,0x3, 0x2, 0x7a,0x37,0x1c,0x5e,0x7e,0x37,0x3, -0x4, 0x7c,0x57,0x7a,0x53,0x1c,0x60,0xa, 0x36,0x7a,0x73,0x1c,0x61,0x7e,0x37,0x2, -0xfe,0x7a,0x37,0x1c,0x62,0x7e,0x37,0x3, 0x0, 0x7c,0x57,0x7a,0x53,0x1c,0x64,0xa, -0x36,0x7a,0x73,0x1c,0x65,0x6c,0xff,0xa1,0x48,0x12,0x4e,0xb6,0x74,0x2, 0xac,0xbf, -0x49,0x35,0x17,0xdc,0xa, 0x26,0x19,0x55,0x19,0xde,0x19,0x75,0x19,0xdf,0x7e,0x70, -0x1, 0x74,0x5, 0xac,0xbf,0x19,0x75,0x1a,0x1a,0x7c,0xbf,0x12,0xaa,0x9e,0x7e,0xf4, -0x0, 0x3c,0x7e,0xe4,0x0, 0x78,0xd1,0x41,0x7d,0xb3,0x80,0x2c,0xa, 0x5d,0x1b,0x54, -0xd1,0x35,0x1b,0x54,0xd1,0x9, 0x58,0xa, 0xd1,0x12,0x48,0x6, 0x1b,0xd0,0x7c,0xec, -0x80,0xa, 0xf1,0xf1,0xbc,0x7d,0x78,0x15,0x1b,0xd0,0x80,0x11,0xbd,0xba,0x8, 0x2, -0x7d,0xba,0xbd,0xea,0x8, 0x2, 0x6d,0xbb,0xbe,0xd0,0x0, 0x38,0xcf,0x74,0x5, 0xac, -0xbf,0x19,0xd5,0x1a,0x1b,0xd1,0x41,0x7d,0xb3,0x80,0x2c,0xa, 0x5d,0xb, 0x54,0xd1, -0x35,0xb, 0x54,0xd1,0x9, 0x58,0xa, 0xd1,0x12,0x48,0x6, 0xb, 0xd0,0x7c,0xec,0x80, -0xa, 0xf1,0xf1,0xbc,0x7d,0x78,0x15,0xb, 0xd0,0x80,0x11,0xbd,0xba,0x8, 0x2, 0x7d, -0xba,0xbd,0xea,0x8, 0x2, 0x6d,0xbb,0x12,0x82,0xa0,0x48,0xcf,0x74,0x5, 0xac,0xbf, -0x19,0xd5,0x1a,0x1c,0xb1,0x79,0x7d,0xb3,0x80,0x34,0x7c,0xbc,0xa, 0x3d,0x1b,0x34, -0x6c,0x66,0xb1,0x8f,0xf5,0x25,0xa, 0x3d,0x1b,0x34,0xd1,0xb, 0x58,0xb, 0xd1,0x12, -0x48,0x7, 0x1b,0xd0,0x7e,0xc1,0x25,0x80,0x9, 0x12,0xd1,0xb0,0x78,0x15,0x1b,0xd0, -0x80,0x11,0xbd,0xba,0x8, 0x2, 0x7d,0xba,0xbd,0xea,0x8, 0x2, 0x6d,0xbb,0xbe,0xd0, -0x0, 0x38,0xc7,0x74,0x5, 0xac,0xbf,0x19,0xd5,0x1a,0x1d,0xb1,0x79,0x7d,0xb3,0x80, -0x34,0x7c,0xbc,0xa, 0x3d,0xb, 0x34,0x6c,0x66,0xb1,0x8f,0xf5,0x26,0xa, 0x3d,0xb, -0x34,0xd1,0xb, 0x58,0xb, 0xd1,0x12,0x48,0x7, 0xb, 0xd0,0x7e,0xc1,0x26,0x80,0x9, -0x12,0xd1,0xb0,0x78,0x19,0xb, 0xd0,0x80,0x15,0xbd,0xba,0x8, 0x2, 0x7d,0xba,0xbd, -0xea,0x8, 0x2, 0x6d,0xbb,0x7e,0x73,0x1e,0x8c,0x12,0x82,0xa4,0x48,0xc3,0x74,0x5, -0xac,0xbf,0x19,0xd5,0x1a,0x1e,0xb, 0xf0,0x12,0x5f,0xe5,0x28,0x2, 0x81,0x9, 0x6c, -0xff,0x80,0x1b,0x74,0x2, 0xac,0xbf,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0x30,0xa, 0x26, -0x19,0x55,0x1a,0xb0,0x74,0x2, 0xac,0xbf,0x19,0x75,0x1a,0xb1,0xb, 0xf0,0x7e,0x73, -0x1c,0x59,0xbc,0x7f,0x38,0xdd,0xda,0x3b,0x22,0x74,0x2, 0xac,0xbf,0x9, 0xc5,0x19, -0xde,0x9, 0xd5,0x19,0xdf,0x7c,0xbc,0x7c,0x7d,0xd1,0x53,0xb, 0x1a,0x30,0x22,0xca, -0x3b,0x7c,0xd6,0x7c,0xf7,0x7c,0xeb,0x4c,0xdd,0x78,0x2f,0x7c,0xce,0xbe,0xe0,0x0, -0x28,0xe, 0xa, 0x5e,0x1b,0x54,0xd1,0x26,0x8, 0x6, 0xa, 0x3e,0x1b,0x34,0x7c,0xc7, -0x7e,0x73,0x1e,0x89,0xa, 0x27,0x1b,0x24,0xa, 0x3e,0xbd,0x32,0x58,0x46,0xa, 0x5e, -0xb, 0x54,0xd1,0x26,0x8, 0x3e,0xa, 0x6e,0x80,0x36,0xbe,0xd0,0x1, 0x78,0x35,0x7c, -0xcf,0xbe,0xf0,0x0, 0x28,0x10,0x7c,0xbe,0xa, 0x3f,0x1b,0x34,0xd1,0x1b,0x8, 0x6, -0xa, 0x6f,0x1b,0x64,0x7c,0xcd,0x7e,0x73,0x1e,0x8a,0xa, 0x27,0x1b,0x24,0xa, 0x3f, -0xbd,0x32,0x58,0x10,0x7c,0xbe,0xa, 0x3f,0xb, 0x34,0xd1,0x1b,0x8, 0x6, 0xa, 0x6f, -0xb, 0x64,0x7c,0xcd,0x7c,0xbc,0xda,0x3b,0x22,0x7c,0x7c,0xb1,0x89,0x7d,0xa3,0xbd, -0xfa,0x22,0x7d,0x3b,0x2e,0x34,0x0, 0x1e,0xbd,0x3a,0x22,0xb1,0x89,0x7d,0x43,0x7c, -0x7c,0xb1,0x89,0xbd,0x43,0x22,0x7c,0x7f,0xb1,0x89,0x7d,0x43,0x7c,0xbc,0x7c,0x7f, -0xb1,0x89,0xbd,0x43,0x22,0x7c,0x7e,0x7e,0x60,0x1, 0xb1,0x8f,0x7c,0xcb,0xa, 0x5d, -0x22,0x74,0x2, 0xac,0xbf,0x9, 0xe5,0x19,0xdf,0x9, 0xd5,0x19,0xde,0x7c,0xbd,0x7c, -0x7e,0xa1,0x89,0x7c,0xa7,0x7c,0x1b,0x7e,0x3, 0x1e,0x8a,0xac,0x10,0x3e,0x4, 0x7e, -0x30,0x2, 0xac,0x3a,0x2d,0x10,0x7e,0x1f,0x15,0x48,0x2d,0x31,0x22,0x7e,0x38,0x0, -0x3e,0xe5,0x34,0x7e,0x71,0x35,0x7e,0x61,0x3d,0x7e,0x51,0x32,0x7f,0x63,0x7c,0xe5, -0x7c,0xf6,0x7c,0xc7,0x7c,0xdb,0x6d,0x33,0x7a,0x35,0x5c,0x7a,0x35,0x5e,0x75,0x63, -0x0, 0x75,0x64,0x0, 0x7e,0xb3,0x3c,0xee,0xf5,0x65,0x7e,0x8, 0x0, 0x66,0x12,0x5f, -0xec,0x4c,0xff,0x78,0x38,0x75,0x60,0x1, 0xbe,0xd0,0x3, 0x38,0x7, 0xe4,0xf1,0xea, -0x74,0x1, 0x80,0xd, 0xbe,0xd0,0xc, 0x50,0x2, 0xe1,0xde,0x74,0xf, 0xf1,0xea,0x74, -0xe, 0x7c,0x7c,0xd1,0x53,0x7f,0x41,0x80,0x2, 0xe1,0xde,0xbe,0xc0,0x1f,0x40,0x3, -0x75,0x66,0x1, 0x7c,0xbc,0x7e,0x70,0x23,0x7e,0x60,0x1, 0x80,0x4f,0x75,0x60,0x23, -0xbe,0xc0,0x3, 0x38,0xd, 0x7c,0xbd,0x6c,0x77,0xd1,0x53,0x7f,0x51,0x7e,0x70,0x1, -0x80,0x13,0xbe,0xc0,0x1f,0x50,0x2, 0xe1,0xde,0x7c,0xbd,0x7e,0x70,0x22,0xd1,0x53, -0x7f,0x51,0x7e,0x70,0x21,0xd1,0x53,0x7f,0x41,0x80,0x2, 0xe1,0xde,0xbe,0xf0,0x2, -0x78,0x5, 0xbe,0xd0,0xd, 0x50,0xa, 0xbe,0xf0,0x1, 0x78,0x8, 0xbe,0xd0,0x2, 0x38, -0x3, 0x75,0x66,0x1, 0x7c,0xbd,0x7e,0x70,0x10,0x7e,0x60,0x23,0x12,0xc1,0x39,0x7a, -0x35,0x61,0xb, 0x5a,0x30,0x7a,0x35,0x6e,0x7e,0x35,0x61,0x3e,0x34,0x9d,0xb3,0x7e, -0x35,0x61,0x3e,0x34,0x9d,0x93,0x6c,0xaa,0xb, 0x5a,0x40,0x9e,0x44,0x0, 0x21,0xb, -0x4a,0x30,0x9e,0x34,0x0, 0x21,0x7d,0x24,0x2e,0x25,0x5c,0x7a,0x25,0x5c,0x7d,0x23, -0x2e,0x25,0x5e,0x7a,0x25,0x5e,0xbe,0x44,0x0, 0xa5,0x8, 0x9, 0x4c,0xee,0x78,0x5, -0xbe,0xf1,0x65,0x68,0x1a,0xbe,0x44,0x0, 0x4d,0x8, 0x8, 0x7d,0x23,0x3e,0x24,0xbd, -0x24,0x48,0xc, 0xbe,0x44,0x0, 0x37,0x8, 0xa, 0xbe,0x34,0x0, 0xb, 0x58,0x4, 0x5, -0x63,0x80,0xe, 0xbe,0x44,0x0, 0x4d,0x58,0x8, 0xbe,0x44,0x0, 0x21,0x8, 0x2, 0x5, -0x64,0x7d,0x24,0x2e,0x24,0x0, 0x42,0xbd,0x23,0x58,0x8, 0xbe,0x44,0x2, 0x26,0x58, -0x2, 0x5, 0x69,0xb, 0xa0,0xe5,0x60,0x1a,0x2b,0x3e,0x24,0x2d,0xb2,0xe5,0x60,0x1a, -0x2b,0x3e,0x24,0x2d,0x92,0xbe,0xa0,0x8, 0x68,0x2, 0xe1,0x48,0x85,0x63,0x67,0x85, -0x64,0x68,0x7e,0x35,0x5c,0x7a,0x35,0x6a,0x7e,0x35,0x5e,0x7a,0x35,0x6c,0x7e,0x70, -0x66,0x7f,0x6, 0xa, 0x37,0x74,0xa, 0x2, 0x1c,0x6, 0x7c,0x7c,0xd1,0x53,0x7f,0x51, -0x22,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x19,0xde,0x22,0x7c,0xa7,0x7c,0xb, 0xa5,0xb8, -0x0, 0x8, 0x7c,0xba,0x12,0x6f,0xee,0xd2,0x9, 0x22,0xa5,0xb8,0x1, 0x44,0x7a,0xa3, -0x3d,0x42,0xbe,0xa0,0xad,0x78,0x2, 0x80,0x35,0xbe,0xa0,0xae,0x78,0x3, 0xd2,0xa, -0x22,0xbe,0xa0,0xaa,0x78,0xa, 0x7e,0x34,0xf, 0x5c,0x7a,0x37,0x2b,0xdd,0x80,0x1e, -0xbe,0xa0,0xab,0x78,0xa, 0x7e,0x34,0x5, 0x56,0x7a,0x37,0x2b,0xdd,0x80,0xf, 0xbe, -0xa0,0xac,0x68,0x2, 0x21,0x52,0x7e,0x34,0x4, 0xe4,0x7a,0x37,0x2b,0xdd,0x6d,0x33, -0x80,0x7d,0xbe,0x0, 0x4, 0x40,0x1c,0xbe,0x0, 0x8, 0x38,0x17,0x31,0x53,0xa5,0xb8, -0x7, 0x6, 0x6d,0x33,0x7a,0x35,0xb, 0x22,0xa5,0xb8,0x8, 0x2, 0x80,0x2, 0x21,0x52, -0x2, 0x38,0x1, 0xa5,0xb8,0xa, 0x8, 0x43,0xd, 0x20,0x7a,0xa3,0x3d,0x4b,0x22,0xa5, -0xb8,0xb, 0x5, 0x31,0x53,0x2, 0x38,0xb, 0xa5,0xb8,0xf, 0x2, 0x80,0x56,0xbe,0x0, -0x1b,0x40,0x7, 0xbe,0x0, 0x1c,0x38,0x2, 0x80,0x4a,0xbe,0x0, 0x1e,0x40,0xb, 0xbe, -0x0, 0x23,0x38,0x6, 0x31,0x55,0x43,0xd, 0x40,0x22,0xbe,0x0, 0x24,0x40,0x7, 0xbe, -0x0, 0x2c,0x38,0x2, 0x80,0x2e,0xa5,0xb8,0x2d,0x19,0x31,0x55,0x20,0xa, 0x2, 0x21, -0x52,0x7e,0xb3,0x3d,0x6d,0x7c,0x4b,0x6c,0x55,0xa, 0x3a,0x2d,0x32,0x3e,0x34,0x7a, -0x35,0x8, 0x22,0xa5,0xb8,0x44,0x4, 0x31,0x55,0x21,0x5c,0xbe,0x0, 0x45,0x68,0x4, -0xa5,0xb8,0x46,0x2, 0x21,0x55,0xa5,0xb8,0x5b,0x4, 0x7a,0xa1,0xf, 0x22,0xbe,0x0, -0x58,0x68,0x4, 0xa5,0xb8,0x59,0x20,0xa5,0xb8,0x59,0x5, 0x75,0x77,0x58,0x80,0x5, -0xe4,0x7a,0xb3,0x27,0x14,0x7e,0x73,0x27,0x14,0x7c,0xb7,0x4, 0x7a,0xb3,0x27,0x14, -0xa, 0x37,0x19,0xa3,0x26,0xcc,0x22,0xa5,0xb8,0x5a,0x7, 0xa, 0x3a,0x7a,0x37,0x26, -0xca,0x22,0xbe,0x0, 0xf0,0x40,0x24,0xbe,0x0, 0xf3,0x38,0x1f,0x7c,0x10,0x2e,0x10, -0x21,0x7c,0xba,0xa5,0xf7,0xa5,0xb8,0xf3,0x19,0x7e,0x15,0x13,0x7e,0x5, 0x11,0x3e, -0x4, 0x7e,0x1f,0x2b,0xdf,0x2d,0x30,0x1b,0x1a,0x10,0x22,0xa5,0xb8,0xf6,0x3, 0x7a, -0xa1,0x10,0x22,0xd2,0x9, 0xa, 0x30,0x19,0xa3,0x3d,0x41,0x22,0x7e,0xb3,0x3d,0x85, -0xb4,0x1, 0x1f,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x18,0x18,0xd2,0x7e,0x8, 0x3d, -0x81,0x12,0x1d,0xae,0x1b,0xfd,0x7e,0x37,0x18,0xd8,0x7a,0x37,0x2b,0x75,0x51,0xea, -0x80,0x1d,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x18,0x1f,0xbc,0x7e,0x8, 0x3d,0x81, -0x12,0x1d,0xae,0x1b,0xfd,0x7e,0x37,0x1f,0xc2,0x7a,0x37,0x2b,0x75,0x71,0xa, 0x21, -0xa1,0x7a,0x1f,0x1f,0x28,0x7a,0xf, 0x1f,0x24,0x22,0x7c,0x7b,0x7a,0x73,0x1f,0x2c, -0xa5,0xbf,0x0, 0x12,0x71,0xa, 0x31,0xa1,0x7e,0x18,0x6, 0x3a,0x7a,0x1f,0x6, 0xac, -0x7e,0x18,0x4, 0x72,0x80,0xf, 0xa5,0xbf,0x1, 0xf, 0x51,0xea,0x31,0xa1,0x12,0xd1, -0x75,0x7e,0x18,0x4, 0x0, 0x7a,0x1f,0x6, 0xb0,0x22,0x74,0x1, 0x12,0x0, 0x6, 0xe4, -0x31,0xaa,0x31,0xee,0xe4,0x12,0x0, 0x6, 0x74,0x1, 0x31,0xaa,0x21,0xee,0xca,0xd8, -0xca,0x79,0x7e,0xd3,0x1e,0x8f,0x7e,0xe3,0x1e,0x90,0x7e,0x8, 0x3, 0x90,0x7e,0x34, -0x0, 0xc, 0xe4,0x12,0x1d,0xd3,0x7e,0x8, 0x3, 0x9c,0x7e,0x34,0x0, 0xc, 0x12,0x1d, -0xd3,0x7e,0xf3,0x1f,0x28,0x51,0xaa,0x7e,0x18,0x3, 0x90,0x51,0xb2,0x12,0xcd,0x30, -0x7e,0x34,0x2, 0xb8,0x74,0x90,0xf1,0x19,0x7e,0x34,0x3, 0x48,0x74,0x48,0x12,0xcd, -0xe1,0x7e,0xb3,0x1f,0x29,0x60,0xd, 0x51,0xaa,0x7e,0x18,0x3, 0xa8,0x51,0xb2,0x12, -0xcc,0x6e,0x80,0xc, 0x7e,0x8, 0x3, 0xa8,0x7e,0x34,0x0, 0x48,0xe4,0x12,0x1d,0xd3, -0x6c,0xee,0x7e,0x70,0xc, 0xac,0x7e,0x2e,0x34,0x3, 0xa8,0x6d,0x22,0x7a,0x1f,0x2, -0xa8,0x74,0x2, 0xac,0xbe,0x49,0x35,0x3, 0x90,0x7a,0x37,0x2, 0xac,0x74,0x2, 0xac, -0xbe,0x49,0x35,0x3, 0x9c,0x7a,0x37,0x2, 0xae,0x7e,0x70,0x18,0xac,0x7e,0x2e,0x34, -0x2, 0xb8,0x7a,0x1f,0x2, 0xb0,0x7e,0x70,0xc, 0xac,0x7e,0x2e,0x34,0x3, 0x48,0x7a, -0x1f,0x2, 0xb4,0x7e,0x8, 0x2, 0xa8,0x7c,0xbf,0x7c,0x7e,0x12,0x5, 0x3d,0xb, 0xe0, -0xbe,0xe0,0x6, 0x40,0xad,0xda,0x79,0xda,0xd8,0x22,0x7e,0x18,0x1f,0x0, 0x7a,0x1d, -0x25,0x22,0x7a,0x1d,0x29,0x7c,0xbd,0x7c,0x7e,0x7e,0x8, 0x1e,0xdd,0x22,0x12,0x3f, -0xcf,0x12,0x0, 0xa, 0x12,0x18,0x34,0x12,0xcb,0xe5,0x7e,0x24,0x3, 0xd4,0x12,0x40, -0x24,0x74,0x1, 0x31,0xaa,0xf1,0xc6,0x7e,0x34,0xd0,0xc, 0x12,0x18,0x45,0x31,0xda, -0x7e,0x34,0x0, 0x1, 0xe4,0x6c,0x55,0x2, 0x16,0xfb,0x7e,0x1f,0x18,0xd6,0x7e,0xf, -0x18,0xd2,0x22,0x7c,0x7b,0x7a,0x73,0x1f,0x2c,0xa5,0xbf,0x0, 0x4, 0x71,0xa, 0x80, -0x6, 0xa5,0xbf,0x1, 0x4, 0x51,0xea,0x31,0xa1,0x22,0x7e,0x1f,0x1f,0xc0,0x7e,0xf, -0x1f,0xbc,0x22,0x7c,0xab,0x51,0xf3,0x7c,0xba,0x12,0xd1,0xfd,0x61,0x1e,0x7e,0x33, -0x1f,0x24,0x7e,0x23,0x1f,0x25,0xa, 0x32,0x6d,0x22,0xa, 0x13,0x6d,0x0, 0x2f,0x1, -0x74,0x4, 0x2f,0x0, 0x14,0x78,0xfb,0x2e,0x8, 0x0, 0x2a,0x12,0x63,0xfe,0x7e,0x24, -0x1, 0xf4,0x8d,0x32,0xbe,0x70,0x7, 0x28,0x3, 0x7e,0x70,0x7, 0x12,0x2a,0xa9,0x3e, -0x34,0x2d,0x32,0x79,0x30,0x0, 0xa0,0x22,0x7c,0xa7,0x31,0xaa,0x7c,0xba,0x12,0x17, -0xa9,0x74,0xa, 0xb1,0xa0,0x61,0x67,0xca,0x3b,0x7e,0xe3,0x1e,0x90,0x7e,0xf3,0x1f, -0x26,0x74,0x1, 0x7a,0xb3,0x1f,0x26,0x91,0x83,0x6c,0x77,0x91,0x49,0x6d,0x33,0xe4, -0x6c,0x55,0x12,0x16,0xfb,0x7e,0x8, 0x2, 0xa8,0x7e,0x34,0x0, 0x72,0x12,0x1d,0xd3, -0x7e,0xd0,0x8, 0x12,0x49,0x24,0x6c,0xcc,0x80,0x1b,0x7e,0x44,0x0, 0x1, 0x7c,0xbd, -0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x50,0x2, 0xac,0x5c,0x91,0x70,0x4d,0x34, -0x1b,0x28,0x30,0xb, 0xc0,0x91,0x8f,0xa, 0x3c,0xbd,0x32,0x48,0xdd,0x7e,0x34,0x0, -0x72,0xca,0x39,0x91,0x78,0x12,0x1d,0xae,0x1b,0xfd,0xb1,0x4e,0xe4,0xd1,0xde,0x71, -0x1e,0x7e,0xb3,0x1f,0x28,0x12,0x0, 0x76,0x30,0x21,0xfd,0x74,0x1, 0x12,0xf, 0xe9, -0x7e,0x8, 0x6, 0xb4,0x7e,0xb3,0x1e,0x8f,0x7c,0x7e,0x12,0x8, 0x0, 0x6c,0xcc,0x80, -0x2b,0x7e,0x50,0x2, 0xac,0x5c,0x49,0x32,0x6, 0xb4,0xbe,0x34,0x15,0x40,0x50,0x1a, -0x7e,0x34,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x7d,0x13,0x6e, -0x14,0xff,0xff,0x91,0x70,0x5d,0x31,0x1b,0x28,0x30,0xb, 0xc0,0x91,0x8f,0xa, 0x3c, -0xbd,0x32,0x48,0xcd,0x1b,0xd0,0xbe,0xd0,0x0, 0x48,0x2, 0x61,0x93,0x7e,0x34,0x0, -0x72,0xca,0x39,0x91,0x78,0x12,0x1d,0xae,0x1b,0xfd,0xb1,0x4e,0x7a,0xf3,0x1f,0x26, -0x91,0x83,0x6c,0x77,0x91,0x49,0xda,0x3b,0x22,0x7c,0xa7,0x4c,0xaa,0x78,0x8, 0x7e, -0x34,0x0, 0x1, 0xb1,0x88,0x80,0x15,0x12,0xcd,0xd1,0x7c,0x7b,0xa, 0x17,0x6d,0x0, -0x7e,0x18,0x80,0x0, 0x12,0x1b,0x3b,0xb1,0x88,0x4e,0x70,0xb0,0x1b,0xa, 0x30,0x22, -0x2e,0x24,0x2, 0xa8,0xb, 0x28,0x30,0x22,0x7e,0x17,0x1f,0x2a,0x6d,0x0, 0x7e,0x18, -0x2, 0xa8,0x22,0x7e,0x8, 0x1e,0x89,0x12,0xa, 0x32,0x7e,0xb3,0x1f,0x26,0x22,0x7e, -0x73,0x1e,0x90,0xa, 0x37,0x7e,0x53,0x1e,0x8f,0xa, 0x25,0x2d,0x23,0x22,0xca,0x3b, -0xf5,0x2d,0x7a,0x1d,0x29,0x7f,0x30,0x7e,0x1d,0x29,0x12,0x68,0xfc,0xf1,0xc6,0xe5, -0x2d,0x7e,0x70,0x1, 0x91,0x49,0x75,0x2e,0x0, 0xe4,0xd1,0xde,0x7e,0xb3,0x1f,0x28, -0x12,0x0, 0x76,0x30,0x21,0xfd,0x74,0x1, 0x12,0xf, 0xe9,0x7f,0x3, 0x12,0x78,0x73, -0x75,0x2f,0x0, 0x80,0x1a,0xb1,0x46,0x7f,0x13,0x2d,0x35,0xb, 0x1a,0x20,0xb1,0x46, -0x7e,0xd, 0x29,0x2d,0x15,0xb, 0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x5, 0x2f,0x91, -0x8f,0xe5,0x2f,0xa, 0x3b,0xbd,0x32,0x48,0xdc,0x5, 0x2e,0xe5,0x2e,0xbe,0xb0,0x1, -0x40,0xb7,0xda,0x3b,0x22,0x7e,0xb3,0x1f,0x2e,0x70,0x3a,0x12,0x27,0x70,0xe4,0x33, -0x68,0xf9,0xe4,0x6c,0x77,0x71,0x58,0x7e,0x8, 0x6, 0xb4,0x7e,0x1f,0x6, 0xac,0x7e, -0xb3,0x1f,0xbe,0x91,0x9e,0x74,0x1, 0x7e,0x70,0x1, 0x71,0x58,0x7e,0x8, 0x8, 0xa, -0x7e,0x1f,0x6, 0xac,0x7e,0xb3,0x18,0xd4,0x91,0x9e,0x74,0x2, 0x7a,0xb3,0x1f,0x2e, -0xe4,0x7a,0xb3,0x18,0xce,0x22,0x7e,0x71,0x2f,0x74,0x2, 0xac,0xb7,0x22,0x74,0x2, -0x12,0x0, 0x6, 0x7e,0xb3,0x1f,0x28,0xb1,0x5e,0x74,0x2, 0x2, 0x0, 0x6, 0xca,0x79, -0x7c,0xfb,0x7e,0x34,0x3, 0x1a,0x74,0x90,0xf1,0x19,0x6c,0xee,0x7e,0x30,0x18,0xac, -0x3e,0x2e,0x14,0x3, 0x1a,0x6d,0x0, 0x7c,0xbf,0x7c,0x7e,0x12,0x15,0xb2,0xb, 0xe0, -0xbe,0xe0,0x6, 0x40,0xe7,0xda,0x79,0x22,0x7e,0xf, 0x37,0xf9,0x79,0x30,0x0, 0x12, -0x7e,0xf, 0x37,0xf9,0x2e,0x14,0x0, 0x6, 0xb, 0xa, 0x30,0x5e,0x34,0xfe,0xf, 0x22, -0x7c,0x7b,0x80,0xe, 0x7e,0x60,0x3, 0x80,0x1, 0x0, 0x7c,0xa6,0x1b,0x60,0x4c,0xaa, -0x78,0xf7,0x7c,0xa7,0x1b,0x70,0x4c,0xaa,0x78,0xea,0x22,0x7e,0x34,0x0, 0x1, 0x7d, -0x23,0x80,0x11,0x7e,0x30,0x4, 0x80,0x4, 0x74,0xfa,0xb1,0xa0,0x7c,0x23,0x1b,0x30, -0xa5,0xba,0x0, 0xf4,0x7d,0x32,0x1b,0x24,0x4d,0x33,0x78,0xe7,0x22,0x7e,0x1d,0x15, -0x29,0x31,0x0, 0x1, 0xbe,0x30,0x0, 0x28,0x68,0x29,0xb1,0x0, 0x1, 0xbe,0xb0,0xff, -0x68,0x5f,0x7e,0xb3,0x1d,0xea,0x70,0x59,0x7e,0xb3,0x1d,0xeb,0x70,0x53,0x7e,0xb3, -0x34,0xa8,0xbe,0xb0,0xff,0x50,0x5, 0x4, 0x7a,0xb3,0x34,0xa8,0x7e,0x33,0x34,0xa8, -0xbe,0x30,0x5, 0x28,0x41,0x7e,0xb3,0x34,0x38,0x70,0x23,0xe4,0x39,0xb1,0x0, 0x1, -0x7e,0xd, 0x15,0xb, 0x15,0xb, 0xa, 0x30,0x5e,0x60,0x3f,0x1b,0xa, 0x30,0x7e,0xd, -0x15,0xb, 0x15,0xb, 0xa, 0x30,0x4e,0x70,0x1, 0x1b,0xa, 0x30,0x80,0x5, 0xe4,0x7a, -0xb3,0x34,0xa8,0xd1,0x57,0xb1,0xbf,0x74,0x1, 0xd1,0x58,0xb1,0xbf,0xd1,0x57,0xa1, -0xbf,0xe4,0x7a,0xb3,0x34,0xa8,0x22,0xe4,0x12,0x27,0x7b,0x7e,0x34,0x0, 0xa, 0x22, -0x7c,0x7b,0x2e,0x70,0xab,0x68,0x13,0x2e,0x70,0xef,0x68,0x1c,0x2e,0x70,0xde,0x68, -0x24,0x2e,0x70,0xde,0x78,0x2a,0x74,0x5, 0x80,0x28,0x7e,0xb3,0x3, 0xff,0xb4,0x5, -0x25,0xb1,0xbb,0x12,0xc9,0xb0,0xe1,0xb7,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0x17,0xb1, -0xbb,0x75,0xe9,0xff,0x22,0x7e,0xb3,0x3, 0xff,0xb4,0x5, 0xa, 0xb1,0xbb,0xe1,0xb2, -0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7c,0x3b,0x7e,0x6f,0x1f,0x39,0xbe,0x30,0x1, -0x28,0x2, 0xe4,0x22,0x7c,0xb3,0x71,0x13,0x91,0x83,0x7e,0x70,0x1, 0x91,0x49,0x7a, -0x6f,0x1f,0x39,0x7e,0x73,0x1f,0x26,0xa, 0x37,0x3e,0x34,0x3e,0x34,0xe4,0x7e,0x50, -0x1, 0x12,0x16,0xfb,0x7e,0xb3,0x1f,0x28,0x12,0x0, 0x76,0x74,0x1, 0x22,0x12,0xf, -0xe9,0x74,0x6, 0x7e,0x70,0x9b,0x12,0x17,0x57,0x6c,0x77,0x80,0x23,0xa, 0x27,0x9, -0x62,0x1f,0x0, 0xa, 0x26,0x2e,0x24,0x1d,0x8a,0x12,0x72,0x77,0x7c,0x6b,0xa, 0x26, -0x74,0x2, 0xac,0xb7,0x7e,0xf, 0x3d,0xd8,0x2d,0x15,0x79,0x20,0x0, 0x52,0xb, 0x70, -0x7e,0x53,0x1e,0x90,0xbc,0x57,0x38,0xd5,0x22,0xca,0x3b,0x7c,0x5b,0x7d,0x83,0x7d, -0x18,0x6d,0x0, 0xa, 0x35,0x74,0x3e,0x12,0x1d,0xd3,0x7e,0xb3,0x1e,0x8f,0xf5,0x29, -0x7e,0xb3,0x1e,0x90,0xf5,0x2a,0x6c,0xcc,0x80,0x35,0x7c,0xfc,0xa, 0x9c,0x9, 0xe9, -0x1f,0x0, 0xa, 0x9e,0x2e,0x94,0x1d,0x8a,0x7d,0x39,0x12,0x4a,0x70,0x7c,0xeb,0xbe, -0xe0,0x24,0x50,0x19,0xa, 0xe, 0x7e,0x24,0x0, 0x3, 0x8d,0x2, 0x7e,0x14,0x0, 0xc, -0xad,0x10,0xa, 0x3e,0x8d,0x32,0x7d,0x93,0x2d,0x91,0x12,0xcb,0x50,0xb, 0xc0,0xe5, -0x2a,0xbc,0xbc,0x38,0xc5,0x6c,0xcc,0x80,0x30,0xa, 0x9c,0xe5,0x2a,0xa, 0x7b,0x2d, -0x79,0x9, 0xe9,0x1e,0xdd,0xbe,0xe0,0x23,0x50,0x1d,0xa, 0x5e,0x7e,0x14,0x0, 0xc, -0x8d,0x51,0x7e,0x34,0x0, 0xc, 0xad,0x35,0xa, 0xe, 0x8d,0x1, 0x7d,0x90,0x2e,0x94, -0x0, 0x24,0x2d,0x93,0x12,0xcb,0x50,0xb, 0xc0,0xe5,0x29,0xbc,0xbc,0x38,0xca,0xda, -0x3b,0x22,0x75,0xe7,0x6b,0xe1,0xb7,0xe4,0x6d,0x33,0x7e,0x24,0x0, 0xff,0x7a,0x1b, -0xb0,0x75,0xe9,0xff,0x80,0xfe,0x7e,0x8, 0x1e,0x89,0x2, 0x0, 0x2e,0x7e,0x73,0x3d, -0xfd,0xbe,0x73,0x3d,0xfe,0x38,0x2, 0xe4,0x22,0x12,0x78,0x6b,0xac,0xb7,0x49,0x55, -0x3e,0x0, 0xbe,0xb0,0x2, 0x38,0x2, 0xc1,0xa7,0xe1,0xeb,0x7c,0x7b,0xa5,0xbf,0x3, -0x5, 0x12,0x57,0x7e,0x80,0x2, 0xe4,0x22,0x12,0x57,0xdf,0x12,0x0, 0xe, 0x74,0x1, -0x22,0x20,0x86,0x3, 0xd3,0x80,0x1, 0xc3,0x92,0x86,0x22,0x20,0x82,0x3, 0xd3,0x80, -0x1, 0xc3,0x92,0x82,0x22,0x30,0x9, 0x33,0xc2,0x9, 0x7e,0x73,0x3d,0x46,0x7a,0x73, -0x1e,0x69,0x7e,0x73,0x3d,0x47,0x7a,0x73,0x1f,0x4b,0x7e,0x73,0x3d,0x47,0x7a,0x73, -0x1f,0x2d,0x7e,0xb3,0x3d,0x47,0xf5,0xa, 0x7e,0x73,0x3d,0x48,0x4c,0x77,0x68,0xb, -0xa, 0x37,0x1b,0x34,0x11,0xc8,0xe4,0x7a,0xb3,0x3d,0x48,0x1, 0x4d,0xe5,0xd, 0x60, -0x76,0xe5,0xd, 0x30,0xe2,0x33,0x53,0xd, 0xfb,0x7e,0xb3,0x1f,0x40,0x60,0x9, 0x7e, -0x8, 0x1e,0x89,0x12,0x3, 0x9f,0x80,0xb, 0x7e,0xb3,0x1f,0x9b,0x7e,0x73,0x1f,0x9a, -0x12,0x0, 0x14,0x7e,0x73,0x1f,0x40,0x2e,0x70,0xff,0x92,0x8, 0x7e,0x8, 0x1e,0x89, -0x74,0x23,0x9e,0xb3,0x1e,0x93,0x12,0x11,0x4c,0xe5,0xd, 0x30,0xe3,0x2a,0x53,0xd, -0xf7,0x7e,0x73,0x3d,0x73,0xd1,0xc5,0x12,0x57,0x77,0x7e,0x73,0x3d,0x74,0xbe,0x73, -0x1f,0x98,0x68,0x6, 0x7a,0x73,0x1f,0x98,0xd2,0x13,0x30,0x13,0x5, 0xf1,0xcd,0x12, -0x0, 0xa, 0x12,0x21,0xee,0x12,0x21,0x1c,0xe5,0xd, 0x30,0xe5,0xa, 0x53,0xd, 0xdf, -0x7e,0xb3,0x3d,0x4b,0x2, 0x40,0x5f,0x22,0xca,0x3b,0x7d,0xf3,0x6c,0xdd,0x12,0x47, -0xdc,0x7e,0x34,0xd, 0xac,0x12,0x23,0x51,0x7e,0x8, 0x2b,0xe3,0x7e,0x34,0x1, 0x22, -0xe4,0x12,0x1d,0xd3,0x12,0x27,0x70,0x50,0xfb,0x7e,0x1f,0x3d,0xd8,0x69,0xc1,0x0, -0x9e,0x69,0xd1,0x0, 0xaa,0x7e,0x1f,0x3d,0xe0,0x69,0xe1,0x0, 0x2e,0xa9,0xd0,0xc4, -0xa9,0xd5,0xcb,0x74,0x7, 0x91,0x9f,0xf5,0x25,0x74,0x7, 0x7e,0x70,0xf, 0x91,0x12, -0x74,0x1, 0x12,0x18,0x1b,0x7e,0x34,0x4, 0xb0,0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, -0x6, 0x7e,0x34,0x0, 0x80,0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, 0x8, 0x7e,0x34,0x0, -0x10,0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, 0x12,0x6d,0x33,0x7e,0xf, 0x3d,0xdc,0x79, -0x30,0x0, 0xe, 0x7e,0xf, 0x3d,0xe0,0x2e,0x14,0x0, 0x2e,0xb, 0xa, 0x30,0x5e,0x60, -0xfe,0x1b,0xa, 0x30,0x6d,0x33,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0x9e,0x91,0x93, -0x4e,0x70,0x20,0x1b,0xa, 0x30,0x91,0x93,0x5e,0x34,0xfe,0x7f,0x1b,0xa, 0x30,0x7e, -0x27,0x26,0xca,0x5e,0x24,0x0, 0x3, 0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e,0x24,0x3e, -0x24,0x3e,0x24,0x3e,0x24,0x91,0x93,0x4d,0x32,0x1b,0xa, 0x30,0x7e,0x34,0xff,0xff, -0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0xac,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0xae, -0x7e,0x34,0x0, 0xf, 0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0xb0,0x91,0x93,0x4e,0x60, -0x88,0x1b,0xa, 0x30,0xbe,0xf4,0x0, 0x3, 0x78,0x11,0x91,0xa7,0x4e,0xf4,0x0, 0x1, -0x1b,0x1a,0xf0,0x91,0xa7,0x5e,0xf4,0x0, 0xf, 0x80,0x18,0xbe,0xf4,0x0, 0x4, 0x78, -0x1d,0x7e,0xf4,0x0, 0x2, 0x7e,0x1f,0x3d,0xdc,0x79,0xf1,0x0, 0xe, 0x91,0xa7,0x4e, -0xf4,0x0, 0x8, 0x1b,0x1a,0xf0,0x71,0x41,0x7a,0x37,0x2b,0xe3,0x41,0xef,0x7e,0x34, -0x0, 0x10,0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, 0xe, 0x7d,0x2f,0x3e,0x24,0x3e,0x24, -0x7e,0xf, 0x3d,0xdc,0x2e,0x14,0x0, 0xe, 0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30, -0xe5,0xf, 0x60,0x7, 0xe5,0xf, 0xbe,0xb0,0x64,0x28,0x6, 0x7e,0x34,0x0, 0x2, 0x80, -0x4, 0xe5,0xf, 0xa, 0x3b,0x12,0x35,0xbf,0x4d,0xff,0x78,0x1b,0x6c,0xdd,0xa, 0x3d, -0x9, 0x73,0x2d,0x7, 0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, 0x10,0x71,0x4b,0x91,0xdf, -0xbe,0xd0,0x33,0x78,0xe9,0x41,0xe2,0xbe,0xf4,0x0, 0x2, 0x78,0x26,0x7e,0xe3,0x26, -0xcc,0x6c,0xdd,0x80,0x18,0xa, 0x3d,0x9, 0xc3,0x26,0xcd,0xa, 0x3c,0x9, 0x73,0x2d, -0x6, 0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, 0x10,0x71,0x4b,0x91,0xdf,0xbc,0xed,0x38, -0xe4,0x80,0x6f,0xbe,0xf4,0x0, 0x1, 0x78,0x69,0x6c,0x99,0x7e,0xe3,0x26,0xcc,0x7e, -0xf0,0x1, 0x80,0x58,0xa, 0xff,0x9, 0xcf,0x26,0xcc,0xb, 0xf4,0x7d,0x3f,0x7c,0xd7, -0x80,0x44,0xa, 0xfd,0x9, 0x8f,0x26,0xcc,0xbc,0x8c,0x68,0x38,0xbe,0x90,0x8f,0x38, -0x39,0xa, 0x5c,0x9, 0x75,0x2d,0x6, 0xa, 0xf7,0x7d,0x3f,0x7c,0x67,0x6c,0x77,0x7d, -0xf3,0xa, 0x58,0x9, 0x75,0x2d,0x6, 0xa, 0x57,0x4d,0x5f,0x7e,0x1f,0x3d,0xdc,0x79, -0x51,0x0, 0x10,0x71,0x4b,0x7c,0x49,0xb, 0x90,0x7e,0x50,0x2, 0x7c,0xb4,0xac,0xb5, -0x59,0x35,0x2b,0xe3,0xb, 0xd0,0xbc,0xed,0x50,0xb8,0xb, 0xf0,0xbc,0xef,0x38,0xa4, -0x7c,0xd9,0x71,0x41,0x7e,0x50,0x2, 0x7c,0xbd,0xac,0xb5,0x59,0x35,0x2b,0xe3,0xa9, -0xd5,0xcb,0x74,0x7, 0x7e,0x71,0x25,0x91,0x12,0xa9,0xc0,0xc4,0x7e,0x1f,0x3d,0xd8, -0x79,0xc1,0x0, 0x9e,0x7e,0x1f,0x3d,0xd8,0x79,0xd1,0x0, 0xaa,0x7e,0x1f,0x3d,0xe0, -0x79,0xe1,0x0, 0x2e,0x6d,0xff,0x7e,0x1f,0x3d,0xdc,0x79,0xf1,0x0, 0x6, 0x7e,0x1f, -0x3d,0xdc,0x79,0xf1,0x0, 0x8, 0x7e,0x1f,0x3d,0xdc,0x79,0xf1,0x0, 0x12,0x7e,0x1f, -0x3d,0xdc,0x79,0xf1,0x0, 0xe, 0x7e,0x1f,0x3d,0xdc,0x79,0xf1,0x0, 0x10,0xda,0x3b, -0x22,0x6d,0xff,0x7e,0x1f,0x3d,0xdc,0x79,0xf1,0x0, 0x10,0x7e,0x34,0x0, 0x2, 0x12, -0x35,0xbf,0x7e,0x34,0x0, 0x1, 0x7e,0xf, 0x3d,0xdc,0x79,0x30,0x0, 0x4, 0x7e,0xf, -0x3d,0xdc,0x69,0x30,0x0, 0x14,0x5e,0x34,0x0, 0x1, 0x68,0xf2,0x7e,0x34,0x0, 0x1, -0x79,0x30,0x0, 0x14,0x7e,0xf, 0x3d,0xdc,0x69,0x30,0x0, 0xa, 0x7d,0x23,0x6d,0x33, -0x69,0x10,0x0, 0xc, 0x6d,0x0, 0x2f,0x10,0x74,0x7, 0x1e,0x34,0x1e,0x24,0x50,0x3, -0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x7c,0xa7,0xf5,0xfd,0x7a,0xa1,0xfe,0x22,0xa9, -0xd5,0xcb,0x74,0x2, 0x7e,0x70,0x3f,0x71,0x97,0x74,0x3, 0x7e,0x70,0x1f,0x71,0x97, -0xa9,0xd0,0xce,0xa9,0xd6,0xc9,0x74,0x5, 0x91,0x9f,0x7c,0x7b,0x5e,0x70,0xe0,0x4e, -0x70,0x1d,0x74,0x5, 0x71,0x97,0x74,0xa, 0x7e,0x70,0x24,0x71,0x97,0x74,0xb, 0x7e, -0x70,0xc, 0x71,0x97,0x74,0xc, 0x7e,0x70,0x2, 0x71,0x97,0x7e,0x71,0xc1,0x5e,0x70, -0xe0,0x4e,0x70,0x2, 0x7a,0x71,0xc1,0x7e,0x71,0xc2,0x5e,0x70,0xe0,0x4e,0x70,0x4, -0x7a,0x71,0xc2,0x74,0xc, 0x91,0x9f,0x54,0x7f,0x68,0x7, 0x74,0xc, 0x7e,0x70,0xf8, -0x71,0x97,0x75,0xcf,0x82,0x74,0x7, 0x91,0x9f,0x7c,0x7b,0x5e,0x70,0xfb,0x74,0x7, -0x81,0x12,0x71,0x97,0x75,0xfd,0xff,0xa9,0xc5,0xcb,0x22,0x6d,0x33,0x7e,0x8, 0x0, -0x25,0x7e,0x24,0x0, 0x12,0x12,0x0, 0x46,0xa9,0xd5,0xcb,0x7e,0x73,0x3d,0x13,0xbe, -0x70,0x5, 0x50,0x14,0x5, 0x2d,0x5, 0x2d,0xe5,0x2e,0xbe,0xb0,0xe, 0x50,0x6, 0x5, -0x2e,0x5, 0x2e,0x80,0x3, 0x75,0x2e,0xf, 0x74,0x8, 0x7e,0x71,0x2d,0x71,0x97,0x74, -0x9, 0x7e,0x71,0x2e,0x71,0x97,0xe5,0x34,0xb4,0x1, 0x15,0x7e,0x71,0x32,0x5e,0x70, -0x1f,0x3e,0x70,0x3e,0x70,0x74,0xa, 0x71,0x97,0x74,0xb, 0x7e,0x71,0x33,0x71,0x97, -0x74,0xc, 0x7e,0x71,0x31,0x71,0x97,0x74,0x2, 0x7e,0x71,0x27,0x71,0x97,0x74,0x3, -0x7e,0x71,0x28,0x71,0x97,0x74,0x4, 0x7e,0x71,0x29,0x71,0x97,0x74,0x5, 0x7e,0x71, -0x2a,0x81,0x12,0x7e,0xf, 0x3d,0xd8,0x2e,0x14,0x0, 0x9e,0xb, 0xa, 0x30,0x22,0x7c, -0x7b,0x7a,0x71,0xfd,0xe5,0xfe,0x22,0x7e,0x1f,0x3d,0xdc,0x2e,0x34,0x0, 0xe, 0xb, -0x1a,0xf0,0x22,0x7f,0x71,0x12,0xd2,0x4, 0xc2,0x6, 0xd1,0xbc,0xc2,0x8, 0x12,0x26, -0xbd,0xc2,0x6, 0xf1,0xdc,0xa9,0xd5,0xcb,0x74,0xf, 0x91,0x9f,0x7a,0x7b,0xb0,0x74, -0xf, 0x6c,0x77,0x71,0x97,0xe5,0xfc,0x7a,0xb, 0xb0,0x43,0xfc,0x10,0x81,0x14,0x74, -0x2, 0xac,0xbd,0x59,0x35,0x2b,0xe3,0xb, 0xd0,0x22,0x7c,0xa7,0x7c,0x6b,0xa9,0xd5, -0xcb,0x74,0xf, 0x7c,0x7a,0x71,0x97,0x7a,0x61,0xfc,0x91,0x14,0xb1,0x73,0xd2,0x6, -0xf1,0xdc,0x12,0xd2,0xb, 0x12,0x18,0x1b,0x2, 0x18,0x0, 0x74,0x81,0x7a,0xb3,0x3e, -0x2a,0x12,0x87,0xe6,0x75,0xcd,0x0, 0xc2,0xce,0x7e,0x8, 0x0, 0x26,0x7e,0x18,0x0, -0x25,0x91,0xb3,0x74,0x1, 0x12,0x27,0x29,0xd2,0xce,0xe5,0x26,0x7e,0x71,0x25,0x81, -0xea,0xe4,0x12,0xc9,0xf8,0x12,0xca,0x93,0x12,0x49,0x24,0x12,0xca,0xf1,0x71,0x9f, -0x12,0xc9,0xa6,0x12,0xca,0xaa,0x12,0x0, 0x1a,0x12,0xca,0xb6,0x12,0x77,0x80,0xc2, -0xae,0x12,0xca,0xc6,0xd2,0xaf,0x12,0xca,0x30,0x12,0xcb,0x3f,0x91,0x1b,0xb1,0x73, -0x7e,0x8, 0x34,0xad,0x12,0xcb,0x11,0x74,0x10,0x7e,0x70,0x23,0x7e,0x24,0xff,0xff, -0x2, 0x16,0x89,0xca,0xf8,0xa2,0xaf,0xe4,0x33,0x7c,0xfb,0xd2,0x6, 0xd1,0xbc,0xa9, -0xd0,0xcb,0xc2,0xaf,0xa9,0xd0,0x9e,0x75,0x9d,0x0, 0xa9,0xd0,0x9e,0x75,0x9c,0x54, -0xa9,0xd0,0x9e,0xa9,0xd4,0x9e,0xa9,0xd0,0xcd,0x74,0x41,0x12,0x35,0xa0,0xa9,0xd0, -0x9e,0xa9,0xd7,0x9e,0x2e,0xf0,0xff,0x92,0xaf,0xda,0xf8,0x22,0x7f,0x70,0x7d,0xd3, -0xd1,0x1c,0x24,0xe4,0x68,0xe, 0x24,0x54,0x68,0x10,0x24,0xd9,0x78,0x12,0x7d,0x3d, -0x7f,0x7, 0xa1,0xd1,0x7d,0x3d,0x7f,0x7, 0xc1,0x87,0x7d,0x3d,0x7f,0x7, 0xc1,0xb, -0x22,0x7d,0xf2,0x7f,0x60,0x6d,0x22,0x2e,0x18,0x10,0x0, 0x12,0xd1,0x51,0x74,0x48, -0xa1,0xe2,0xb1,0xfd,0xe5,0x39,0xb1,0xfd,0xe5,0x38,0xb1,0xfd,0xe5,0x37,0xb1,0xfd, -0xe4,0xb1,0xfd,0x7f,0x6, 0x7d,0x3f,0xd1,0x69,0xa9,0xd2,0xb4,0x22,0x7c,0x7b,0x7a, -0x71,0xb5,0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xd3,0x22,0x7d,0xf2,0x7f,0x60,0x6d, -0x22,0x2e,0x18,0x4, 0x0, 0x12,0xd1,0x51,0x74,0x4b,0xa1,0xe2,0xa9,0xc2,0xb4,0x74, -0x90,0xb1,0xfd,0xe4,0xb1,0xfd,0xb1,0xfd,0xb1,0xfd,0x7e,0x8, 0x0, 0x37,0x7e,0x34, -0x0, 0x1, 0xb1,0xf7,0xe5,0x37,0x22,0x7f,0x70,0x7f,0x1, 0x7d,0x30,0x7d,0x53,0xf5, -0x3b,0x7c,0x72,0x7c,0x61,0xa, 0x20,0x7d,0x53,0xf5,0x3a,0x7d,0x51,0xf5,0x39,0xa9, -0xc2,0xb4,0x74,0x3, 0xb1,0xfd,0xe5,0x3b,0xb1,0xfd,0xe5,0x3a,0xb1,0xfd,0xe5,0x39, -0xb1,0xfd,0x7f,0x7, 0x7e,0x35,0x37,0xa1,0xf7,0x7d,0x43,0x6d,0x33,0x80,0x13,0x75, -0xb5,0x0, 0xa9,0x36,0xb3,0xfc,0xa9,0xc6,0xb3,0xe5,0xb5,0x7a,0xb, 0xb0,0xb, 0x14, -0xb, 0x34,0xbd,0x43,0x38,0xe9,0x22,0x7d,0x42,0x7f,0x70,0x7d,0x53,0x7d,0x15,0x6d, -0x0, 0xb, 0x4, 0x2e,0x8, 0xf0,0x0, 0x74,0x1, 0xd1,0xa7,0x7a,0x45,0x37,0x7f,0x10, -0x7f,0x7, 0xd1,0x37,0xe4,0xc1,0xa7,0x7c,0x7b,0xa9,0xc2,0xb4,0x4c,0x77,0x68,0x4, -0x74,0x3a,0x80,0x2, 0x74,0x4, 0xb1,0xfd,0xa9,0xd2,0xb4,0x22,0xa9,0xd0,0xce,0xa2, -0x6, 0xa9,0x95,0xc9,0x22,0x7a,0x73,0x1f,0x3d,0xd1,0xd0,0x7a,0x37,0x1f,0x49,0x22, -0xca,0x79,0x7e,0x23,0x1f,0x3d,0x7e,0x33,0x3d,0x72,0xac,0x23,0x2e,0x14,0x1, 0xf4, -0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, 0x7e,0xe3,0x1f,0x3e,0xbe,0x14, -0xc, 0x67,0x40,0x4, 0x7e,0x14,0xc, 0x67,0xbe,0x14,0x8, 0x20,0x40,0x3, 0xe4,0x80, -0x16,0xbe,0x14,0x5, 0xdc,0x40,0x4, 0x74,0x3, 0x80,0xc, 0xbe,0x14,0x2, 0xee,0x40, -0x4, 0x74,0x1, 0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x1f,0x3e,0x7e,0xf3,0x1f,0x3e,0xbe, -0xf0,0x3, 0x78,0x5, 0x12,0x64,0x9, 0x80,0x2, 0x74,0x20,0x7a,0xb3,0x1f,0x3f,0xbc, -0xfe,0x68,0x2, 0xd2,0x13,0x7e,0x24,0x1, 0xf4,0x7d,0x31,0x8d,0x32,0x7c,0x17,0xbe, -0x10,0x7, 0x28,0x3, 0x7e,0x10,0x7, 0x7e,0x1f,0x3d,0xd8,0x69,0x51,0x0, 0xa0,0x54, -0x1f,0xa, 0x1, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x3e,0x4, 0x2d,0x5, 0x79, -0x1, 0x0, 0xa0,0x6d,0x0, 0x12,0x63,0xfe,0xda,0x79,0x22,0x7c,0x7b,0xd1,0xc5,0x30, -0x13,0x5, 0xf1,0xcd,0x12,0x0, 0xa, 0xa2,0x7, 0xe4,0x33,0xb4,0x1, 0xa, 0x12,0x5e, -0xa0,0x7e,0xb3,0x1f,0x3d,0x2, 0x21,0x1c,0x22,0xca,0x79,0x7c,0xfb,0x74,0x5, 0xac, -0xfb,0x9, 0x77,0x19,0x17,0x7a,0x73,0x1f,0x3d,0x9, 0x77,0x19,0x18,0x7a,0x73,0x1f, -0x42,0x9, 0x77,0x19,0x19,0x7a,0x73,0x1f,0x4d,0x9, 0x77,0x19,0x1a,0x7a,0x73,0x1f, -0x4e,0xd1,0xc9,0x9, 0xb7,0x19,0x1b,0x12,0xa3,0xca,0x7e,0xb3,0x1f,0x3d,0x12,0x21, -0x1c,0xe4,0x7a,0xb3,0x18,0xcf,0x7a,0xb3,0x3c,0x6b,0xda,0x79,0x22,0xc2,0x13,0x7e, -0x8, 0x1e,0x89,0x12,0xc, 0x43,0x7e,0x8, 0x1e,0x89,0xe4,0x22,0xa2,0x6, 0xa9,0x97, -0xc1,0xa2,0x6, 0xa9,0x95,0xc1,0xa2,0x6, 0xa9,0x97,0xc2,0xa2,0x6, 0xa9,0x96,0xc2, -0x22,0x12,0x27,0x70,0x50,0xfb,0x7e,0x34,0xf, 0x5c,0x7a,0x37,0x2b,0xdd,0x7e,0x37, -0x18,0xd8,0x7a,0x37,0x2b,0x75,0x6d,0x33,0x7a,0x35,0xb, 0x11,0x36,0x74,0x50,0x7a, -0xb3,0x3d,0x75,0x7e,0x24,0x3, 0x20,0x11,0x24,0x11,0x2b,0x6d,0x33,0x7a,0x37,0x3e, -0x2c,0x2, 0x22,0x14,0x7d,0x32,0x74,0xfa,0x2, 0x16,0xca,0x74,0x1, 0x7a,0xb3,0x1f, -0x2d,0x7a,0xb3,0x1f,0x4b,0x22,0x7e,0x73,0x1f,0x3d,0x7a,0x73,0x3d,0x73,0x7e,0x73, -0x1f,0x4d,0x7a,0x73,0x3d,0x63,0x7e,0x73,0x1f,0x4e,0x7a,0x73,0x3d,0x62,0x7e,0x73, -0x1f,0x42,0x7a,0x73,0x3d,0x64,0x7e,0x73,0x1f,0x98,0x7a,0x73,0x3d,0x74,0x22,0xca, -0xd8,0xca,0x79,0x7c,0xfb,0xbe,0xf0,0x80,0x78,0x16,0x7e,0xd0,0xff,0x6c,0xee,0x11, -0xcf,0x38,0x4, 0x7c,0xd7,0x7c,0xfe,0xb, 0xe0,0xbe,0xe0,0x4, 0x78,0xf1,0x80,0x18, -0xbe,0xf0,0x81,0x78,0x13,0x6c,0xdd,0x6c,0xee,0x11,0xcf,0x40,0x4, 0x7c,0xd7,0x7c, -0xfe,0xb, 0xe0,0xbe,0xe0,0x4, 0x78,0xf1,0xbe,0xf0,0x4, 0x40,0x2, 0x6c,0xff,0x7c, -0xbf,0x12,0x3f,0x89,0x7e,0x73,0x1f,0x42,0x7a,0x73,0x3d,0x64,0x7e,0x73,0x1f,0x4d, -0x7a,0x73,0x3d,0x63,0x7e,0x73,0x1f,0x4e,0x7a,0x73,0x3d,0x62,0x7e,0x73,0x1f,0x3d, -0x7a,0x73,0x3d,0x73,0x11,0x56,0x7a,0xf3,0x3d,0x4b,0xda,0x79,0xda,0xd8,0x22,0x74, -0x5, 0xac,0xbe,0x9, 0x75,0x19,0x17,0xbc,0x7d,0x22,0xa2,0x11,0xe4,0x33,0x7a,0xb3, -0x3d,0x6f,0x7e,0x73,0x3d,0x73,0xbe,0x73,0x1f,0x3d,0x68,0x6, 0xe5,0xd, 0x70,0x2, -0x11,0x36,0x22,0xc2,0x6, 0x12,0x3f,0xf1,0x7e,0xb3,0x3d,0x9, 0xb4,0x3, 0x64,0x12, -0xca,0xf8,0x12,0x49,0x24,0x12,0x38,0x15,0xf1,0x1b,0x7e,0xb3,0x3d,0x41,0x30,0xe7, -0xe7,0x12,0x22,0x31,0x31,0x81,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, 0x0, 0x7e,0x8, -0x4, 0xe4,0x12,0x1d,0xae,0x1b,0xfd,0x31,0x81,0x3e,0x34,0xca,0x39,0x7e,0x18,0x4, -0x72,0x7e,0x8, 0x5, 0x56,0x12,0x1d,0xae,0x1b,0xfd,0xe5,0xa, 0xb4,0x1, 0x16,0x12, -0x9a,0x77,0x12,0x2a,0xbf,0x20,0x6, 0x4, 0xd1,0xa3,0x80,0x2, 0xc2,0x6, 0x31,0x90, -0x12,0x48,0x53,0x71,0xd3,0x11,0xda,0x7e,0xb3,0x3d,0x41,0x54,0x7f,0x7a,0xb3,0x3d, -0x41,0x80,0x95,0x12,0xcd,0xcb,0x21,0x68,0x7e,0xb3,0x1d,0xf6,0xb4,0x1, 0x6, 0xe4, -0x7a,0xb3,0x1d,0xf6,0x22,0x21,0x77,0xe4,0x7a,0xb3,0x1f,0x2e,0x7a,0xb3,0x1f,0x4c, -0x22,0x7e,0x73,0x1e,0x90,0xa, 0x27,0x7e,0x73,0x1e,0x8f,0xa, 0x37,0x2d,0x32,0x22, -0x31,0x97,0x7a,0xb3,0x1d,0xf4,0x22,0xca,0x3b,0x6d,0x33,0x7d,0x43,0x7e,0xb3,0x1e, -0x8a,0xf5,0x27,0x7e,0xf3,0x1e,0x89,0x7e,0x25,0x74,0x49,0x52,0x0, 0x1, 0xbe,0x54, -0x4e,0x20,0x38,0x10,0x9, 0xb2,0x0, 0x3, 0xb4,0x12,0x9, 0x9, 0xb2,0x0, 0x4, 0xbe, -0xb0,0x34,0x68,0x4, 0x59,0x32,0x0, 0x1, 0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0x3, 0xe4, -0x61,0xa0,0x7e,0xb3,0x1c,0x58,0x60,0x6, 0x7e,0xb3,0x1d,0xeb,0x60,0x7, 0xe4,0x7a, -0xb3,0x33,0x29,0x61,0xa0,0x6c,0xee,0x61,0x95,0x12,0xd1,0x7e,0x9, 0x75,0x19,0xdf, -0x7a,0x71,0x25,0x6c,0xcc,0x6d,0xee,0x7d,0xfe,0xa, 0xd7,0x80,0x1b,0x71,0xc7,0x8, -0x1d,0xb, 0xc0,0xbe,0xd0,0x0, 0x28,0x2, 0x71,0xbc,0xa, 0xcf,0x1b,0xc4,0xa, 0x5d, -0xbd,0x5c,0x58,0x2, 0x71,0xb1,0x1b,0xd4,0xbe,0xd4,0x0, 0x0, 0x58,0xdf,0xe5,0x25, -0xa, 0xdb,0x80,0x2f,0x71,0xc7,0x8, 0x39,0xb, 0xc0,0xbe,0xd0,0x0, 0x28,0x4, 0x71, -0xbc,0x80,0x8, 0x4c,0xdd,0x78,0x4, 0x7e,0xf4,0x7f,0xf8,0xa, 0xcf,0x1b,0xc4,0xa, -0x5d,0xbd,0x5c,0x58,0x4, 0x71,0xb1,0x80,0xa, 0xa, 0x5d,0xbd,0x5c,0x78,0x4, 0x7e, -0xe4,0x7f,0xf8,0x7d,0xcd,0xb, 0xc4,0x7d,0xdc,0xe5,0x27,0xa, 0x5b,0xbd,0xc5,0x48, -0xc3,0xbe,0xc0,0x3, 0x50,0x2, 0x61,0x93,0xbe,0xc0,0x9, 0x28,0x10,0x71,0xaa,0xbe, -0x34,0x0, 0x50,0x48,0x1d,0x71,0xa3,0xbe,0x34,0x0, 0x50,0x48,0x15,0x7e,0x71,0x27, -0x1e,0x70,0xbc,0x7c,0x50,0x31,0x7e,0xb3,0x19,0x67,0x70,0x2b,0x7e,0xb3,0x1d,0xeb, -0x70,0x25,0x74,0x2, 0x7a,0xb3,0x33,0x29,0x7e,0x34,0x4e,0x20,0x7e,0x25,0x74,0x59, -0x32,0x0, 0x1, 0x74,0x12,0x7e,0x35,0x74,0x19,0xb3,0x0, 0x3, 0x74,0x34,0x7e,0x35, -0x74,0x19,0xb3,0x0, 0x4, 0x61,0x9c,0x7e,0xb3,0x1d,0xeb,0x70,0x2f,0xbe,0xc0,0x6, -0x28,0x2, 0x80,0x22,0xbe,0xc0,0x4, 0x28,0x23,0x71,0xaa,0xbe,0x34,0x0, 0x64,0x58, -0x1b,0x71,0xa3,0xbe,0x34,0x0, 0x64,0x58,0x13,0x7e,0x55,0x74,0x49,0x55,0x0, 0x1, -0xbe,0x54,0x0, 0x0, 0x28,0x6, 0x74,0x2, 0x7a,0xb3,0x33,0x29,0x71,0xaa,0xbe,0x34, -0x0, 0x28,0x8, 0xa, 0x71,0xa3,0xbe,0x34,0x0, 0x28,0x8, 0x2, 0x61,0x93,0x6d,0xcc, -0xbe,0xd0,0x0, 0x28,0xb, 0x7c,0xbd,0x14,0x7e,0x71,0x25,0x12,0x2d,0x89,0x7d,0xc3, -0xa, 0x3f,0x1b,0x34,0xa, 0x5d,0xbd,0x53,0x58,0xb, 0x7c,0xbd,0x4, 0x7e,0x71,0x25, -0x12,0x2d,0x89,0x2d,0xc3,0x75,0x26,0x8, 0x80,0x2e,0x7e,0x71,0x26,0x74,0x2, 0xac, -0x7b,0x7d,0x23,0x2e,0x24,0x1d,0xe5,0x12,0x72,0x77,0x1a,0x2b,0xbd,0x2c,0x8, 0x18, -0x7e,0xb3,0x1c,0x7c,0x70,0x12,0x7d,0x53,0x2e,0x54,0x1d,0xe6,0x7a,0xb1,0x82,0x7a, -0xa1,0x83,0xe4,0x93,0x1a,0x5b,0x2d,0x45,0x7e,0xa1,0x26,0x7c,0xba,0x14,0xf5,0x26, -0x4c,0xaa,0x78,0xc6,0x7c,0xbd,0x7e,0x71,0x25,0x12,0x2d,0x89,0x12,0x1e,0x5, 0xbe, -0x34,0xa, 0xf0,0x8, 0x4, 0x2e,0x44,0x0, 0x28,0xbe,0x44,0x0, 0xfa,0x28,0x4, 0x7e, -0x44,0x0, 0xfa,0x7e,0x73,0x33,0x29,0xa, 0x57,0xbd,0x54,0x50,0x6, 0x7c,0x79,0x7a, -0x73,0x33,0x29,0xb, 0xe0,0x12,0x4f,0xe0,0x28,0x2, 0x21,0xe9,0x7e,0xb3,0x33,0x29, -0xda,0x3b,0x22,0xa, 0x2c,0x7d,0x3e,0x2, 0x1a,0xed,0xa, 0x2c,0x7d,0x3f,0x2, 0x1a, -0xed,0x7c,0xbd,0x4, 0x7d,0x3d,0x12,0x2d,0x89,0x2d,0xe3,0x22,0x7c,0xbd,0x14,0x7d, -0x3d,0x12,0x2d,0x89,0x2d,0xf3,0x22,0x7c,0xbd,0x7d,0x3d,0x12,0x2d,0x89,0xbe,0x34, -0x0, 0x64,0x22,0x71,0xe9,0x7a,0x73,0x1d,0xeb,0x7e,0x73,0x1c,0x67,0x7a,0x73,0x1c, -0x68,0xe4,0x7a,0xb3,0x1d,0xee,0x22,0xc2,0x18,0x7e,0x73,0x3b,0xf2,0xa, 0x27,0x7e, -0x73,0x1d,0xea,0xa, 0x37,0x2d,0x32,0x22,0x7e,0x73,0x0, 0x7e,0xbe,0x70,0x0, 0x38, -0x31,0x74,0x2, 0x7a,0xb3,0x0, 0x7e,0x74,0x1, 0x7a,0xb3,0x1c,0x80,0x31,0x77,0x7e, -0xb3,0x37,0x3a,0x70,0x11,0xe4,0x7a,0xb3,0x18,0xcf,0x7a,0xb3,0x18,0xce,0x7a,0xb3, -0x1c,0x58,0x7a,0xb3,0x19,0x67,0x7e,0xb3,0x2, 0xa0,0x70,0x6, 0x74,0x1, 0x7a,0xb3, -0x2, 0xa0,0x22,0xca,0xf8,0x7e,0x90,0x1, 0x7e,0xf4,0x0, 0x1, 0x7a,0xf7,0x1c,0x75, -0x7a,0xf7,0x1c,0x77,0xe4,0x7a,0xb3,0x1c,0x80,0xd1,0x9c,0x7e,0xb3,0x2, 0xa0,0xbe, -0xb0,0x0, 0x28,0xa, 0xbe,0xb0,0xff,0x50,0x5, 0x4, 0x7a,0xb3,0x2, 0xa0,0x7e,0xb3, -0x0, 0x7e,0x70,0x46,0x7e,0xf7,0x9, 0x70,0xbe,0xf4,0x1, 0xf4,0x8, 0x3c,0x7e,0xf7, -0x9, 0x6a,0xbe,0xf4,0x0, 0xa0,0x8, 0x32,0x7e,0xf7,0x9, 0x6e,0xbe,0xf4,0xff,0x60, -0x8, 0x28,0x7e,0xf7,0x1c,0x5a,0x4d,0xff,0x78,0xc, 0x7e,0xf7,0x1c,0x5c,0xbe,0xf4, -0x1, 0x18,0x28,0x2, 0x80,0x10,0x12,0x9f,0x11,0xbe,0xb0,0x5, 0x40,0xc, 0x7e,0xf7, -0x1c,0x5a,0x4d,0xff,0x78,0x4, 0xd1,0x9c,0xc1,0x99,0x7e,0xd4,0xfe,0x70,0x7e,0xb3, -0x1e,0x84,0xb4,0x1, 0x6, 0x7e,0xe4,0x0, 0xa0,0x80,0x4, 0x7e,0xe4,0x1, 0x40,0x6c, -0xff,0x6c,0x88,0x80,0x34,0x74,0x2, 0xac,0xb8,0x9, 0x75,0x19,0xde,0x9, 0x65,0x19, -0xdf,0x74,0x2, 0xac,0xb6,0x49,0x25,0x4, 0xe4,0xbe,0x24,0x0, 0xa0,0x48,0x18,0xa, -0x57,0x7e,0x53,0x1e,0x8a,0xa, 0x25,0x2d,0x25,0x3e,0x24,0x49,0x22,0x4, 0xe4,0xbe, -0x24,0x0, 0xa0,0x48,0x2, 0xb, 0xf0,0xb, 0x80,0x7e,0x53,0x1c,0x58,0xbc,0x58,0x38, -0xc4,0x7e,0xf7,0x9, 0x66,0xbd,0xfd,0x48,0x8, 0x7e,0xc7,0x9, 0x6e,0xbd,0xcd,0x58, -0x35,0x6d,0xcc,0x9e,0xc7,0x1e,0x76,0xbe,0xc7,0x1c,0x62,0x8, 0x60,0x12,0xab,0x49, -0x60,0x5b,0x7e,0xb3,0x1c,0x7e,0x60,0x2, 0x80,0x51,0x7e,0x83,0x2, 0xa0,0xbe,0x80, -0xff,0x50,0x4a,0x7e,0xb3,0x37,0x3a,0x70,0x44,0x7e,0xb3,0x19,0x67,0x70,0x3e,0xe4, -0x7a,0xb3,0x1c,0x58,0x80,0x37,0x7e,0xc7,0x1e,0x76,0x3e,0xc4,0x6e,0xc4,0xff,0xff, -0xb, 0xc4,0xbe,0xc7,0x1c,0x62,0x8, 0x25,0xbe,0xf4,0xff,0x60,0x58,0x1f,0x6d,0xff, -0x9d,0xfe,0xbe,0xf7,0x9, 0x64,0x8, 0x15,0x4c,0xff,0x78,0x11,0x12,0xab,0x49,0xa, -0xfb,0x4d,0xff,0x68,0x8, 0x7e,0xb3,0x1c,0x7e,0x60,0x2, 0x71,0xf8,0x12,0xa2,0xeb, -0xe4,0x33,0x78,0x5, 0xe4,0x7a,0xb3,0x1c,0x7c,0x12,0x5f,0xf2,0x68,0x6, 0x7e,0xb3, -0x36,0x5, 0x60,0xd, 0x7e,0xb3,0x36,0x7, 0x70,0x7, 0xe4,0x7a,0xb3,0x1c,0x81,0x80, -0x79,0x12,0xd1,0xf5,0x28,0x5, 0xe4,0x7a,0xb3,0x1c,0x81,0x30,0x19,0x5, 0xe4,0x7a, -0xb3,0x1c,0x81,0x12,0xa3,0x20,0x50,0x7, 0xd1,0x9c,0x12,0xa0,0xd4,0x7c,0x9b,0x7e, -0xb3,0x19,0x68,0x70,0x46,0x7e,0xb3,0x19,0x69,0x70,0x40,0x12,0xd1,0xf5,0x28,0x3b, -0x7e,0xb3,0x2, 0xa1,0xbe,0xb0,0x32,0x50,0x5, 0x4, 0x7a,0xb3,0x2, 0xa1,0x7e,0xa3, -0x1c,0x7e,0x4c,0xaa,0x78,0x5, 0xe4,0x7a,0xb3,0x2, 0xa1,0x7e,0xb3,0x2, 0xa1,0xbe, -0xb0,0x5, 0x40,0x1c,0x7e,0x90,0x3, 0xd1,0x9c,0x7e,0xf7,0x9, 0x6e,0xbe,0xf4,0xfc, -0xe0,0x58,0xd, 0x4c,0xaa,0x68,0x9, 0x71,0xf8,0x80,0x5, 0xe4,0x7a,0xb3,0x2, 0xa1, -0xa, 0xf9,0x7a,0xf7,0x1c,0x75,0x7a,0xf7,0x1c,0x77,0x12,0xa3,0x74,0x50,0x2, 0x71, -0xf8,0x12,0x0, 0x6e,0x50,0x11,0xe4,0x7a,0xb3,0x1c,0x81,0x7e,0x73,0x1c,0x58,0xbe, -0x70,0x0, 0x28,0x3, 0x12,0xa1,0x1a,0x7e,0xf7,0x1c,0x5e,0xbe,0xf4,0x0, 0xc8,0x8, -0x14,0x7e,0xf7,0x1c,0x62,0xbe,0xf4,0xff,0x9c,0x8, 0xa, 0x12,0x0, 0x6e,0x50,0x5, -0xe4,0x7a,0xb3,0x1c,0x81,0x12,0x9f,0xe7,0xb4,0x1, 0x5, 0xe4,0x7a,0xb3,0x1c,0x81, -0x12,0xa1,0x28,0x7e,0xb3,0x0, 0x7e,0xbe,0xb0,0x0, 0x28,0x2d,0x14,0x7a,0xb3,0x0, -0x7e,0x70,0x26,0xe4,0x7a,0xb3,0x1c,0x81,0x74,0x1, 0x7a,0xb3,0x1c,0x80,0xe4,0x7a, -0xb3,0x18,0xcf,0x7a,0xb3,0x18,0xce,0x7e,0xb3,0x37,0x3a,0xbe,0xb0,0x1, 0x68,0x9, -0xe4,0x7a,0xb3,0x1c,0x58,0x7a,0xb3,0x19,0x67,0xda,0xf8,0x22,0x74,0x1, 0x7a,0xb3, -0x1c,0x81,0x22,0x12,0x0, 0x6e,0x50,0x2d,0x7e,0xb3,0x1e,0x88,0xbe,0xb0,0x1, 0x68, -0x24,0xe4,0x7a,0xb3,0x1c,0x81,0x7e,0xb3,0x1c,0x58,0x70,0x8, 0x7e,0xb3,0x1c,0x68, -0x70,0x2, 0xd1,0x9c,0x7e,0xb3,0x1c,0x81,0x60,0x6, 0x12,0xce,0xe9,0x12,0xce,0x89, -0x9f,0x0, 0x2, 0x0, 0x68,0x12,0xaa,0xaf,0x91,0x33,0x12,0x0, 0x6a,0x9f,0x0, 0x12, -0x0, 0x68,0x7e,0xb3,0x3d,0x7, 0xb4,0x1, 0xc, 0x7e,0x34,0x0, 0x5, 0x7a,0x37,0x1c, -0x75,0x7a,0x37,0x1c,0x77,0x7e,0xb3,0x37,0xfd,0x60,0x7, 0x14,0x7a,0xb3,0x37,0xfd, -0x80,0x6, 0x7e,0xb3,0x1c,0x80,0x60,0x6, 0x12,0x84,0x3e,0x12,0xbb,0x16,0x7e,0xb3, -0x1c,0x81,0x60,0x6, 0x12,0xce,0xe9,0x2, 0xce,0x89,0x22,0x7e,0xb3,0x3d,0x50,0x14, -0x68,0x13,0x14,0x68,0x2c,0xb, 0xb1,0x68,0x2, 0xe1,0xdb,0xe4,0x7a,0xb3,0x2d,0x4e, -0x7a,0xb3,0x2d,0x5, 0x22,0x7e,0xb3,0x2d,0x4e,0xbe,0xb0,0x1, 0x68,0xc, 0x53,0xeb, -0x5f,0x53,0xac,0x5f,0x74,0x1, 0x7a,0xb3,0x2d,0x4e,0xe5,0x80,0x7a,0xb3,0x2d,0x5, -0x22,0x7e,0xb3,0x2d,0x4e,0xbe,0xb0,0x2, 0x68,0x23,0x53,0xeb,0x5f,0x53,0xac,0x5f, -0x7e,0x8, 0x2d,0x4f,0x7e,0x34,0x0, 0x8, 0xe4,0x12,0x1d,0xd3,0x74,0x2, 0x7a,0xb3, -0x2d,0x4e,0xe4,0x7a,0xb3,0x2d,0x5, 0xe5,0x80,0x7a,0xb3,0x2d,0x57,0x7e,0xa1,0x80, -0x6c,0x77,0xa, 0x27,0x9, 0x62,0x2d,0x4f,0xbe,0x60,0xff,0x50,0x44,0x7e,0x44,0x0, -0x1, 0x7c,0xb7,0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0xb3,0x2d,0x57,0x6c,0xba, -0xa, 0x2b,0x5d,0x24,0x68,0x2b,0xa, 0x27,0x2e,0x24,0x2d,0x4f,0x7e,0x29,0x60,0x7c, -0xb6,0x4, 0x7a,0x29,0xb0,0xbe,0x60,0x5, 0x40,0x17,0x7e,0x44,0x0, 0x1, 0x7c,0xb7, -0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7c,0x69,0x4e,0x63,0x2d,0x5, 0x7a,0x63,0x2d, -0x5, 0xb, 0x70,0xa5,0xbf,0x8, 0xab,0x7a,0xa3,0x2d,0x57,0x22,0x7e,0xa0,0x1, 0x4c, -0xaa,0x78,0x9, 0xe4,0xa, 0x4a,0x19,0xb4,0x2d,0x6, 0x80,0x5f,0xbe,0xa0,0x10,0x38, -0x29,0xa, 0x3a,0x9, 0xb3,0x1e,0xdc,0xa, 0x4a,0x19,0xb4,0x2d,0x6, 0x9, 0xb3,0x2d, -0x6, 0xbe,0xb0,0x23,0x40,0x8, 0x74,0x22,0xa, 0x4a,0x19,0xb4,0x2d,0x6, 0xa, 0x4a, -0x2e,0x44,0x2d,0x6, 0x7e,0x49,0xb0,0x4, 0x80,0x2e,0xa, 0x3a,0x9e,0x34,0x0, 0x10, -0x9, 0xb3,0x1e,0xff,0xa, 0x4a,0x19,0xb4,0x2d,0x6, 0xa, 0x3a,0x9, 0xb3,0x2d,0x6, -0xbe,0xb0,0x24,0x40,0x8, 0x74,0x23,0xa, 0x4a,0x19,0xb4,0x2d,0x6, 0xa, 0x4a,0x2e, -0x44,0x2d,0x6, 0x7e,0x49,0xb0,0x24,0x24,0x7a,0x49,0xb0,0xb, 0xa0,0xbe,0xa0,0x34, -0x40,0x8d,0x22,0xca,0x3b,0x7e,0xb3,0x3d,0x5c,0xb4,0x1, 0x2, 0x80,0x2, 0x21,0x16, -0x7e,0x73,0x3d,0x5d,0xbe,0x70,0x0, 0x38,0x2, 0x21,0x16,0x12,0x22,0x31,0x7e,0x8, -0x2b,0x77,0x7e,0x34,0x0, 0x66,0xe4,0x12,0x1d,0xd3,0x7e,0x64,0x2, 0x30,0x7e,0x8, -0x27,0x15,0x7e,0x34,0x4, 0x60,0x12,0x1d,0xd3,0x75,0x25,0x0, 0x80,0x59,0x31,0x24, -0x12,0x22,0x31,0x6d,0x33,0x80,0x1c,0x7e,0x35,0x26,0x3e,0x34,0x49,0x33,0xf, 0x5c, -0x31,0x19,0x49,0x23,0x27,0x15,0xbd,0x27,0x58,0x4, 0x59,0x73,0x27,0x15,0x7e,0x35, -0x26,0xb, 0x34,0x7a,0x35,0x26,0xbe,0x65,0x26,0x38,0xdc,0x6d,0x33,0x7a,0x35,0x26, -0x7e,0x35,0x26,0x3e,0x34,0x49,0x33,0x4, 0xe4,0x31,0x19,0x49,0x23,0x2b,0x77,0xbd, -0x27,0x58,0x4, 0x59,0x73,0x2b,0x77,0x7e,0x35,0x26,0xb, 0x34,0x7a,0x35,0x26,0xbe, -0x34,0x0, 0x33,0x78,0xdb,0x5, 0x25,0x7e,0x73,0x3d,0x5d,0xbe,0x71,0x25,0x38,0x9e, -0x7d,0x36,0x3e,0x34,0xca,0x39,0x7e,0x18,0x27,0x15,0x7e,0x8, 0xf, 0x5c,0x12,0x1d, -0xae,0x1b,0xfd,0x7e,0x34,0x0, 0x66,0xca,0x39,0x7e,0x18,0x2b,0x77,0x7e,0x8, 0x4, -0xe4,0x12,0x1d,0xae,0x1b,0xfd,0xda,0x3b,0x22,0x12,0x1e,0x5, 0x7d,0x73,0x7e,0x35, -0x26,0x3e,0x34,0x22,0x7e,0x34,0x3, 0xe8,0x2, 0x23,0x51,0x7e,0xb3,0x1f,0x4c,0x70, -0x1f,0x31,0x24,0x12,0x27,0x70,0xe4,0x33,0x68,0xf9,0x12,0x50,0x9b,0x12,0x84,0x3b, -0x20,0x17,0x2, 0x31,0x51,0x74,0x2, 0x7a,0xb3,0x1f,0x4c,0xe4,0x7a,0xb3,0x18,0xcf, -0x22,0xca,0x3b,0x7e,0xb3,0x1f,0x3d,0x7a,0xb3,0x26,0xc9,0x7e,0xf3,0x1f,0x98,0x31, -0xd9,0x7c,0xdb,0xbe,0xd0,0xff,0x68,0x6e,0x6c,0xcc,0x74,0x5, 0xac,0xbc,0x9, 0xb5, -0x19,0x17,0xf5,0x29,0x7e,0x73,0x1f,0x3d,0xbe,0x71,0x29,0x68,0x3b,0x7e,0x70,0x4, -0xac,0x7d,0xa, 0x2c,0x2d,0x32,0x2e,0x34,0x1d,0xf5,0x51,0x70,0x7c,0xeb,0xbe,0xe0, -0x2, 0x38,0x43,0xa, 0xe, 0x7e,0x14,0x2, 0x31,0xad,0x10,0x2e,0x14,0x20,0x36,0x6d, -0x0, 0x7a,0xd, 0x2a,0x7e,0x70,0x25,0xac,0x7e,0x2e,0x34,0x3c,0x72,0x6d,0x22,0x7a, -0x1f,0x3c,0x6e,0x7c,0xbc,0x12,0xa5,0x12,0xb, 0xc0,0xbe,0xc0,0x4, 0x40,0xab,0x7e, -0x73,0x1f,0x98,0xbc,0x7f,0x68,0x6, 0x7a,0xf3,0x1f,0x98,0xd2,0x13,0xd2,0x7, 0x7e, -0xb3,0x26,0xc9,0x12,0x3f,0x6b,0xda,0x3b,0x22,0x7c,0x6b,0x6c,0x77,0x74,0x5, 0xac, -0xb7,0x9, 0x55,0x19,0x17,0xbc,0x56,0x78,0x3, 0x7c,0xb7,0x22,0xb, 0x70,0xbe,0x70, -0x4, 0x40,0xea,0x74,0xff,0x22,0x7c,0x4b,0x7e,0xb3,0x26,0xc9,0xbc,0x4b,0x68,0x59, -0x31,0xd9,0x7c,0x3b,0x7c,0xb4,0x31,0xd9,0x7c,0x5b,0xbe,0x30,0xff,0x68,0x4a,0xbe, -0x50,0xff,0x68,0x45,0x7e,0x70,0x4, 0xac,0x73,0xa, 0x25,0x2d,0x32,0x2e,0x34,0x1d, -0xf5,0x51,0x70,0xbe,0xb0,0x2, 0x38,0x31,0xa, 0x2b,0x7e,0x34,0x2, 0x31,0xad,0x32, -0x2e,0x34,0x20,0x36,0x6d,0x22,0x30,0x1e,0x3, 0x2, 0xa6,0x7c,0x7e,0xb3,0x1f,0x4b, -0xb4,0x1, 0x16,0x7e,0xb3,0x1e,0x8a,0x7e,0x33,0x1e,0x89,0xac,0xb3,0x7a,0x55,0x29, -0x7e,0x8, 0xf, 0x5c,0x74,0x1, 0x2, 0xa6,0x27,0x22,0x7c,0x6b,0x12,0x57,0xb7,0xd2, -0x1e,0x7c,0xb6,0x31,0xf6,0xc2,0x1e,0x22,0x54,0x7, 0xa, 0x3b,0x2e,0x34,0x0, 0x1e, -0x7a,0x71,0x82,0x7a,0x61,0x83,0xe4,0x93,0x22,0x7c,0x5b,0xc4,0x23,0x54,0x1f,0xa, -0x3b,0x9, 0x43,0x1a,0xec,0x7c,0xb5,0x51,0x68,0x5c,0xb4,0x22,0xca,0x79,0x6c,0xff, -0x6c,0xee,0x80,0x4c,0x7c,0xbe,0x51,0x79,0x60,0x44,0x7e,0x34,0x0, 0x2, 0xca,0x39, -0xac,0x7e,0x2e,0x34,0x19,0xde,0x6d,0x22,0x7e,0x30,0x2, 0xac,0x3f,0x2e,0x14,0x19, -0xde,0x6d,0x0, 0x12,0x1d,0xae,0x1b,0xfd,0xf1,0xfb,0xac,0x3f,0x2e,0x14,0x1a,0x1a, -0xac,0x7e,0x2e,0x34,0x1a,0x1a,0x6d,0x22,0xb1,0x9b,0x74,0x2, 0xac,0xbe,0x49,0x45, -0x1c,0x1c,0x74,0x2, 0xac,0xbf,0x59,0x45,0x1c,0x1c,0xd1,0xb6,0xb, 0xf0,0xb, 0xe0, -0xf1,0xe0,0x38,0xb0,0x7a,0xf3,0x1c,0x58,0xda,0x79,0x22,0x12,0x7, 0xfb,0x51,0x8c, -0xf1,0x5d,0x51,0x8c,0x12,0x5b,0xf9,0x12,0x81,0x1, 0x51,0x8c,0x71,0x4f,0x61,0x0, -0x7e,0x33,0x1c,0x58,0xe4,0x7a,0xb3,0x31,0x8a,0x6c,0x22,0x80,0x3d,0x74,0x2, 0xac, -0xb2,0x9, 0x15,0x19,0xdf,0x7e,0x0, 0x1, 0x6c,0x99,0x80,0x28,0xbc,0x92,0x68,0x22, -0x74,0x2, 0xac,0xb9,0x9, 0x85,0x19,0xdf,0xa, 0x28,0x12,0x5e,0x99,0xbe,0x34,0x0, -0x1, 0x18,0x2, 0xb, 0x0, 0xbe,0x0, 0x2, 0x40,0x8, 0x74,0x2, 0x7a,0xb3,0x31,0x8a, -0x80,0x6, 0xb, 0x90,0xbc,0x39,0x38,0xd4,0xb, 0x20,0xbc,0x32,0x38,0xbf,0x22,0xca, -0x3b,0x75,0x27,0x0, 0x6c,0xcc,0xe4,0x7a,0xb3,0x3, 0x20,0x7e,0xe3,0x1c,0x58,0xa, -0xce,0x3e,0xc4,0xca,0xc9,0x7e,0x18,0x19,0xde,0x7e,0x8, 0x2, 0xa8,0x12,0x1d,0xae, -0x1b,0xfd,0x75,0x25,0x0, 0x6c,0xdd,0x81,0x1f,0x7e,0x44,0x3, 0xff,0x7e,0xc0,0xff, -0x6c,0xff,0x80,0x4b,0x74,0x2, 0xac,0xbf,0x9, 0xb5,0x2, 0xa8,0xbe,0xb0,0xff,0x68, -0x3c,0x7c,0xbf,0x51,0x79,0x60,0x36,0x74,0x2, 0xac,0xbf,0x9, 0x75,0x2, 0xa9,0xa, -0x27,0x74,0x2, 0xac,0xbd,0x9, 0x75,0x3d,0x9b,0x12,0x7f,0xbf,0x7d,0xc3,0x74,0x2, -0xac,0xbf,0x9, 0x75,0x2, 0xa8,0xa, 0x27,0x74,0x2, 0xac,0xbd,0x9, 0x75,0x3d,0x9a, -0x12,0x7f,0xbf,0x2d,0xc3,0xbd,0x4c,0x28,0x4, 0x7d,0x4c,0x7c,0xcf,0xb, 0xf0,0xbc, -0xef,0x38,0xb1,0xbe,0xc0,0xff,0x68,0x45,0x7e,0x70,0x2, 0xac,0x7c,0x9, 0xb3,0x2, -0xa8,0x9, 0x73,0x2, 0xa9,0x12,0x2d,0x89,0xbe,0x37,0x1e,0x76,0x48,0x2f,0x7e,0x70, -0x2, 0xac,0x7c,0x9, 0x53,0x2, 0xa8,0x7e,0xb3,0x3, 0x20,0x7e,0x40,0x2, 0xac,0xb4, -0x19,0x55,0x2, 0xe4,0x9, 0x53,0x2, 0xa9,0x19,0x55,0x2, 0xe5,0x74,0xff,0x19,0xb3, -0x2, 0xa8,0x5, 0x25,0x7e,0xb3,0x3, 0x20,0x4, 0x7a,0xb3,0x3, 0x20,0xb, 0xd0,0x7e, -0x73,0x3d,0x99,0xbc,0x7d,0x28,0x2, 0x61,0x79,0x7e,0xd1,0x25,0x81,0xba,0x75,0x26, -0xff,0x12,0x99,0xc9,0x7d,0xd3,0x6c,0xff,0x80,0x48,0x7c,0xbf,0x51,0x79,0x60,0x40, -0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xb3,0x2, 0xa8,0xbe,0xb0,0xff,0x68,0x32,0x9, 0x73, -0x2, 0xa9,0x12,0x2e,0x53,0x7f,0x71,0xb, 0x7a,0xc0,0xbe,0xc4,0x0, 0x0, 0x58,0x5, -0x6d,0xcc,0x1b,0x7a,0xc0,0xb, 0x7a,0x40,0xbd,0x4d,0x8, 0x14,0x7e,0x70,0x2, 0xac, -0x7f,0x9, 0xb3,0x2, 0xa8,0xf5,0x27,0x9, 0xc3,0x2, 0xa9,0x7d,0xd4,0x7a,0xf1,0x26, -0xb, 0xf0,0xbc,0xef,0x38,0xb4,0xe5,0x26,0xbe,0xb0,0xff,0x68,0x2b,0x7e,0x71,0x27, -0x7e,0xb3,0x3, 0x20,0x7e,0x60,0x2, 0xac,0xb6,0x19,0x75,0x2, 0xe4,0x19,0xc5,0x2, -0xe5,0x7e,0x70,0xff,0x7e,0x61,0x26,0x74,0x2, 0xac,0xb6,0x19,0x75,0x2, 0xa8,0x7e, -0xb3,0x3, 0x20,0x4, 0x7a,0xb3,0x3, 0x20,0xb, 0xd0,0xbe,0xd0,0xa, 0x50,0x2, 0x81, -0x2e,0x7e,0xb3,0x38,0xa2,0x7e,0x70,0x2, 0xac,0xb7,0x7a,0x55,0x2f,0x7e,0x8, 0x2, -0xa8,0x12,0xb9,0x9f,0x7e,0xe3,0x3, 0x20,0x7e,0x8, 0x3d,0x9a,0x7e,0x34,0xff,0xff, -0x7e,0x24,0x0, 0x14,0x12,0x59,0xa2,0xbe,0xe0,0x0, 0x38,0x2, 0xa1,0x7d,0x6c,0xdd, -0x80,0x3f,0x6c,0xff,0x80,0x34,0x7e,0x90,0x2, 0xac,0x9d,0x9, 0x64,0x2, 0xa8,0x12, -0x2f,0xf1,0xbc,0x76,0x78,0x22,0x9, 0x64,0x2, 0xa9,0x9, 0x75,0x19,0xdf,0xbc,0x76, -0x78,0x16,0xf1,0xfb,0xac,0x3d,0x2e,0x14,0x3, 0x21,0x6d,0x0, 0xac,0x7f,0x2e,0x34, -0x1a,0x1a,0x6d,0x22,0xb1,0x9b,0x80,0x7, 0xb, 0xf0,0x12,0x5f,0xe5,0x38,0xc7,0xb, -0xd0,0xbc,0xed,0x38,0xbd,0x74,0x5, 0xac,0xbe,0x7a,0x55,0x2f,0x7e,0x8, 0x1a,0x1a, -0x7e,0x18,0x3, 0x21,0xb1,0x9b,0xa, 0x3e,0x3e,0x34,0xca,0x39,0x7e,0x18,0x2, 0xa8, -0x7e,0x8, 0x19,0xde,0x12,0x1d,0xae,0x1b,0xfd,0xa, 0x3e,0x3e,0x34,0xca,0x39,0x7e, -0x18,0x2, 0xa8,0x7e,0x8, 0x3d,0x9a,0x12,0x1d,0xae,0x1b,0xfd,0x6c,0xdd,0x80,0x9, -0x7c,0xbd,0x7e,0x70,0x1, 0xd1,0xbb,0xb, 0xd0,0xbc,0xed,0x38,0xf3,0x7a,0xe3,0x3d, -0x99,0x7a,0xe3,0x1c,0x58,0x7e,0x73,0x1c,0x58,0xbe,0x70,0xa, 0x28,0x6, 0x74,0xa, -0x7a,0xb3,0x1c,0x58,0xda,0x3b,0x22,0x7e,0x18,0x1c,0x82,0xca,0xf8,0x7f,0x21,0x7f, -0x70,0x7f,0x17,0x7f,0x2, 0x7e,0xd5,0x2f,0x1e,0xd4,0x2e,0x55,0x2f,0x1b,0x54,0x7e, -0x2b,0xf0,0x7f,0x27,0x2e,0x55,0x2f,0x1b,0x54,0x7a,0x2b,0xf0,0x6d,0xcc,0x80,0xc, -0xb, 0xa, 0x50,0xb, 0x15,0x1b,0x1a,0x50,0xb, 0x35,0xb, 0xc4,0xbd,0xdc,0x38,0xf0, -0xda,0xf8,0x22,0xca,0x3b,0x6c,0xff,0x7e,0xb7,0x1e,0x76,0x7e,0x73,0x3c,0xe3,0xa, -0xa7,0x3e,0xa4,0x3e,0xa4,0x9e,0xa4,0x0, 0x8c,0xbe,0xa4,0x0, 0x0, 0x58,0x2, 0x6d, -0xaa,0xbe,0xa4,0x0, 0x64,0x8, 0x4, 0x7e,0xa4,0x0, 0x64,0x7e,0x73,0x1d,0xeb,0xbe, -0x70,0x0, 0x28,0x14,0x7e,0xb3,0x1c,0x7c,0x70,0xe, 0x9e,0xb4,0x0, 0x14,0x7e,0x37, -0x1e,0x78,0xbd,0x3b,0x8, 0x2, 0x7d,0xb3,0x2d,0xba,0x6c,0xee,0xc1,0xa5,0x7c,0xbe, -0x12,0xaa,0x9e,0xbd,0x3b,0x48,0x7c,0x12,0xd1,0x7e,0x9, 0xc5,0x19,0xdf,0x7e,0xa5, -0x74,0x49,0xaa,0x0, 0x1, 0xbe,0xa4,0x0, 0x0, 0x28,0x2a,0x7e,0xb3,0x1d,0xeb,0x70, -0x24,0x74,0x2, 0xac,0xbc,0x49,0xa5,0x4, 0xe4,0xbe,0xa4,0x0, 0x50,0x58,0x16,0xa, -0x3d,0x7e,0x53,0x1e,0x8a,0xa, 0xa5,0x2d,0xa3,0x3e,0xa4,0x49,0xaa,0x4, 0xe4,0xbe, -0xa4,0x0, 0x50,0x48,0x3e,0x7c,0xbe,0x51,0x79,0x60,0x38,0x7e,0xa4,0x0, 0xa, 0x7a, -0xa5,0x2f,0x7e,0x30,0xa, 0xac,0x3f,0x2e,0x14,0x1c,0x82,0x6d,0x0, 0x12,0x7f,0x23, -0xb1,0x9b,0x7e,0xa4,0x0, 0x7, 0x7a,0xa5,0x2f,0x7e,0x30,0x7, 0xac,0x3f,0x2e,0x14, -0x32,0xf, 0x6d,0x0, 0x7e,0x70,0x7, 0xac,0x7e,0x2e,0x34,0x32,0xf, 0x6d,0x22,0xb1, -0x9b,0xb, 0xf0,0xb, 0xe0,0xf1,0xe0,0x28,0x2, 0xc1,0x1e,0x7a,0x73,0x1c,0x67,0x7a, -0xf3,0x1d,0xea,0xda,0x3b,0x22,0x7c,0xbf,0x7e,0x70,0x1, 0x7c,0x57,0x7c,0xab,0xc4, -0x23,0x54,0x1f,0x7c,0x4b,0x7c,0xba,0x51,0x68,0x4c,0x55,0x68,0xf, 0xa, 0x34,0x2e, -0x34,0x1a,0xec,0x7e,0x39,0xa0,0x4c,0xba,0x7a,0x39,0xb0,0x22,0x64,0xff,0xa, 0x24, -0x2e,0x24,0x1a,0xec,0x7e,0x29,0x70,0x5c,0x7b,0x7a,0x29,0x70,0x22,0xca,0x79,0x7e, -0x33,0x1e,0x90,0x12,0x0, 0x6e,0x40,0x62,0x6d,0x33,0x9e,0x37,0x1e,0x6b,0x3e,0x34, -0xbe,0x37,0x9, 0x60,0x18,0x54,0x7e,0xb3,0x1c,0x7c,0xb4,0x1, 0x4a,0x7e,0x47,0x1e, -0x6d,0x7e,0x7, 0x1e,0x6f,0x6c,0x22,0x80,0x36,0x7c,0xb2,0x51,0x79,0x60,0x2e,0x74, -0x2, 0xac,0xb2,0x9, 0xf5,0x19,0xde,0x9, 0xe5,0x19,0xdf,0x74,0x2, 0xac,0xbe,0x49, -0x55,0x4, 0xe4,0xbd,0x50,0x48,0x10,0xa, 0x3f,0xa, 0x53,0x2d,0x53,0x3e,0x54,0x49, -0x55,0x4, 0xe4,0xbd,0x54,0x58,0x6, 0x7c,0xb2,0x6c,0x77,0xd1,0xbb,0xb, 0x20,0x7e, -0x73,0x1c,0x58,0xbc,0x72,0x38,0xc2,0x12,0x9a,0x2a,0xda,0x79,0x22,0xca,0x79,0x12, -0x97,0xf6,0x40,0x79,0x6c,0x99,0x80,0x6d,0x74,0x2, 0xac,0xb9,0x9, 0x85,0x19,0xdf, -0x9, 0xf5,0x19,0xde,0x12,0x7f,0x14,0xbe,0x34,0x0, 0xdc,0x18,0x56,0x6c,0xee,0x80, -0x4e,0xbc,0xe9,0x68,0x48,0x7e,0x70,0x2, 0xac,0x7e,0x9, 0xb3,0x19,0xdf,0xf5,0x26, -0x9, 0x73,0x19,0xde,0x7a,0x71,0x25,0xa, 0x27,0xa, 0x3f,0x12,0x7c,0x6e,0xf5,0x27, -0xe5,0x26,0xa, 0x2b,0xa, 0x38,0x12,0x7c,0x6e,0xf5,0x28,0xe5,0x27,0xbe,0xb0,0x5, -0x50,0x1b,0xe5,0x28,0xbe,0xb0,0x5, 0x50,0x14,0x12,0xd1,0xa8,0x7d,0xf3,0x7c,0xbf, -0x12,0x7c,0x66,0x18,0x8, 0x7c,0xb9,0x6c,0x77,0xd1,0xbb,0x80,0x6, 0xb, 0xe0,0xf1, -0xe0,0x38,0xae,0xb, 0x90,0x7e,0x73,0x1c,0x58,0xbc,0x79,0x38,0x8b,0xda,0x79,0x22, -0x7e,0x73,0x1c,0x58,0xbc,0x7e,0x22,0x7e,0x8, 0x3e,0x21,0x12,0xd1,0x2, 0x12,0xd0, -0xfc,0x12,0xd1,0x19,0xe5,0x1f,0x7a,0xb3,0x31,0x4b,0x22,0x7e,0x34,0x0, 0x5, 0x7a, -0x35,0x2f,0x7e,0x30,0x5, 0x22,0xc2,0x6, 0x7e,0xb3,0x18,0xcf,0x60,0x6, 0x7e,0xb3, -0x18,0xce,0x70,0xb, 0x7e,0x73,0x1c,0x58,0xbe,0x70,0x1, 0x28,0x2, 0xd2,0x6, 0xa2, -0x6, 0x22,0x7e,0xb3,0x1e,0x89,0xca,0xf8,0x7c,0xfb,0x7d,0xc0,0x7d,0xd1,0x7d,0xb2, -0x7d,0xa3,0x7a,0xf3,0x2, 0xa8,0x7e,0x73,0x1e,0x8c,0x7a,0x73,0x2, 0xa9,0xe4,0x7a, -0xb3,0x2, 0xab,0x74,0x6, 0x7a,0xb3,0x2, 0xaa,0x7a,0xd7,0x2, 0xac,0x7a,0xd7,0x2, -0xb0,0x7e,0x8, 0x2, 0xa8,0x7e,0x73,0x1f,0x4d,0xa, 0x37,0x12,0x13,0x44,0x7a,0xc7, -0x2, 0xb0,0xe4,0x7a,0xb3,0x2, 0xaa,0x12,0x67,0x1e,0x7a,0xf3,0x2, 0xa8,0x7e,0xb3, -0x1f,0x4b,0x70,0xf, 0xe4,0x7a,0xb3,0x2, 0xab,0x7a,0xd7,0x2, 0xac,0x7e,0x34,0x0, -0x20,0x80,0x10,0x74,0x1, 0x7a,0xb3,0x2, 0xab,0x7a,0xa7,0x2, 0xac,0x7a,0xb7,0x2, -0xae,0x6d,0x33,0xf1,0xc7,0x12,0x12,0x78,0xda,0xf8,0x22,0x7e,0xf, 0x15,0x48,0x7e, -0x18,0x9, 0x74,0xca,0x3b,0x7a,0x1d,0x29,0x7f,0x30,0xf1,0xd0,0x7a,0x55,0x31,0x7e, -0xb3,0x1f,0x4b,0xf5,0x2e,0xe4,0x7a,0xb3,0x1f,0x4b,0x7f,0x3, 0x7e,0x1d,0x29,0x12, -0x68,0xd6,0x74,0x1, 0x12,0x18,0x1b,0xe4,0x12,0x0, 0x6, 0xf1,0x77,0x75,0x2d,0x0, -0xf1,0xdb,0xf1,0x8f,0x12,0x0, 0xe, 0x30,0x12,0xfd,0x74,0x1, 0xf1,0xbf,0x7e,0x14, -0x80,0x0, 0x7d,0x21,0x7d,0x7, 0x11,0x22,0x31,0x29,0x6d,0x33,0x80,0x1e,0x7e,0x35, -0x2f,0x3e,0x34,0x7f,0x3, 0x2d,0x13,0xb, 0xa, 0x20,0x7e,0xd, 0x29,0x2d,0x13,0xb, -0xa, 0x30,0x2d,0x32,0x1b,0xa, 0x30,0x7e,0x35,0x2f,0xb, 0x34,0x7a,0x35,0x2f,0x7e, -0x35,0x31,0xbe,0x35,0x2f,0x38,0xd7,0x5, 0x2d,0xe5,0x2d,0xbe,0xb0,0x1, 0x40,0xb0, -0xe5,0x2e,0x7a,0xb3,0x1f,0x4b,0xda,0x3b,0x22,0xca,0xf8,0x7e,0xf3,0x1e,0x8a,0x7e, -0x8, 0x15,0x4c,0x6d,0x33,0xa, 0x2f,0x31,0x78,0x7e,0x73,0x38,0x9b,0xa, 0x37,0x7e, -0x53,0x1e,0x8d,0x2d,0x23,0xa, 0x3f,0xad,0x32,0x7d,0x43,0x6c,0x77,0x80,0x22,0xa, -0x57,0x2d,0x54,0x3e,0x54,0x7e,0xf, 0x3d,0xf9,0x2d,0x15,0xb, 0xa, 0x10,0x7e,0x50, -0x2, 0xac,0x57,0x2e,0x24,0x15,0x4c,0xb, 0x28,0x50,0x2d,0x51,0x1b,0x28,0x50,0xb, -0x70,0xbc,0xf7,0x38,0xda,0xda,0xf8,0x22,0x7d,0xf2,0x7d,0xe3,0x7f,0x20,0x6d,0x33, -0x80,0x7, 0x1b,0x2a,0xe0,0xb, 0x55,0xb, 0x34,0xbd,0xf3,0x38,0xf5,0x22,0x7e,0x8, -0x31,0xfb,0x6d,0x33,0x7e,0x24,0x0, 0xa, 0x31,0x78,0x7e,0x8, 0x31,0x76,0x6d,0x33, -0x31,0x78,0x74,0x2, 0x6c,0xaa,0xa, 0x4a,0x19,0xb4,0x31,0x6c,0xb, 0xa0,0xbe,0xa0, -0xa, 0x40,0xf3,0x7e,0x8, 0x31,0x4c,0x6d,0x33,0x7e,0x24,0x0, 0xa, 0x21,0x78,0xca, -0x79,0x7e,0x8, 0x2, 0xa8,0x6d,0x33,0x7e,0x24,0x0, 0x24,0x31,0x78,0x6d,0x77,0xf1, -0xb7,0x6c,0x33,0x80,0x19,0x74,0x2, 0xac,0xb3,0x49,0x25,0x5, 0xc8,0x7e,0x7f,0x37, -0xf1,0x2d,0xf5,0xb, 0x7a,0x30,0x9d,0x32,0x59,0x35,0x2, 0xa8,0xb, 0x30,0x7e,0x23, -0x1e,0x8a,0xbc,0x23,0x38,0xdf,0xa9,0xc1,0xcb,0x7e,0x34,0x0, 0xa0,0x7a,0x35,0x2d, -0x7e,0x18,0x2, 0xa8,0x7f,0x1, 0x12,0x6a,0xe9,0x6c,0x33,0x80,0x43,0x7e,0xb3,0x3d, -0x31,0x30,0xe1,0x1c,0x51,0x75,0x28,0x18,0xbe,0x30,0x18,0x68,0x9, 0xbe,0x30,0x19, -0x68,0x4, 0xa5,0xbb,0x1a,0xa, 0x51,0x6c,0xbe,0x34,0x1, 0x2c,0x8, 0x2, 0x51,0x7d, -0x51,0x75,0x28,0xa, 0x51,0x6c,0xbe,0x34,0xff,0x60,0x58,0x2, 0x51,0x7d,0x51,0x6c, -0x12,0x1e,0x5, 0xbd,0x37,0x28,0x7, 0x51,0x6c,0x12,0x1e,0x5, 0x7d,0x73,0xb, 0x30, -0x7e,0x23,0x1e,0x8a,0xbc,0x23,0x38,0xb5,0xa9,0xc1,0xcb,0x7e,0x37,0x1f,0x33,0xbd, -0x37,0x50,0x6, 0x74,0x2, 0x7a,0xb3,0x37,0xf0,0xda,0x79,0x22,0x74,0x2, 0xac,0xb3, -0x49,0x35,0x2, 0xa8,0x22,0x7e,0x23,0x3d,0x32,0xbe,0x20,0x0, 0x22,0xe4,0x7a,0xb3, -0x3e,0x3e,0x7e,0x37,0x3a,0xb4,0x7a,0x37,0x2d,0x58,0x22,0xca,0xf8,0x7c,0x27,0x7c, -0x3b,0xa5,0xbb,0x0, 0x18,0xbe,0x20,0x0, 0x28,0xf, 0x74,0x1, 0x7a,0xb3,0x1d,0xef, -0xe4,0x7a,0xb3,0x1d,0xf1,0x7a,0xb3,0x1d,0xf2,0x31,0x8e,0x80,0x3e,0xa5,0xba,0x0, -0x1a,0x6c,0xff,0x7e,0x20,0xff,0x74,0xa, 0xac,0xbf,0x19,0x25,0x1d,0x4e,0xb, 0xf0, -0xbe,0xf0,0xa, 0x78,0xf1,0x74,0x1, 0x7a,0xb3,0x1d,0xee,0x6c,0xff,0x80,0x18,0x7e, -0x50,0xa, 0xac,0x5f,0x2e,0x24,0x1c,0x82,0x51,0xee,0x7e,0x50,0xa, 0xac,0x5f,0x2e, -0x24,0x1c,0x84,0x51,0xee,0xb, 0xf0,0xbc,0x3f,0x38,0xe4,0xda,0xf8,0x22,0xb, 0x28, -0x30,0x3e,0x34,0x3e,0x34,0x1b,0x28,0x30,0x22,0xca,0xf8,0x7e,0xf3,0x1d,0xea,0x7c, -0xbf,0x7e,0x73,0x32,0xe2,0x51,0x8b,0x7c,0xbf,0x71,0x54,0x7e,0xb3,0x32,0xe2,0x70, -0xb, 0x91,0x8e,0x7e,0x8, 0x1d,0x4a,0x12,0x4d,0x97,0x80,0xb, 0x7e,0xb3,0x1d,0xf1, -0x70,0x5, 0x7c,0xbf,0x12,0x8b,0xaf,0x7c,0xbf,0x12,0x90,0x29,0xbe,0xf0,0x0, 0x28, -0x6, 0x74,0x1, 0x7a,0xb3,0x1d,0xf3,0x7a,0xf3,0x32,0xe2,0xda,0xf8,0x22,0x7e,0xb3, -0x3d,0x32,0x70,0x3, 0x12,0x8c,0x5c,0x91,0x96,0x12,0x99,0x6, 0x12,0xbb,0x3f,0x12, -0x8f,0xf0,0x41,0xf9,0xca,0x79,0x7c,0xfb,0x6c,0x11,0x7e,0x0, 0xff,0x74,0xa, 0xac, -0xb1,0x19,0x5, 0x2, 0xac,0x7e,0x34,0x7f,0xff,0x59,0x35,0x2, 0xa8,0x59,0x35,0x2, -0xaa,0xb, 0x10,0xa5,0xb9,0xa, 0xe3,0xe4,0x6c,0x77,0x7c,0x6f,0x71,0xd6,0x7c,0x7f, -0x7e,0x60,0xa, 0x71,0xd6,0x7c,0x1b,0x6c,0x0, 0x6c,0xee,0x80,0x16,0x74,0xa, 0xac, -0xbe,0x9, 0x65,0x2, 0xac,0x74,0xa, 0xac,0xb0,0x9, 0x75,0x1c,0x86,0xbc,0x76,0x68, -0x6, 0xb, 0xe0,0xbc,0x1e,0x38,0xe6,0xbc,0x1e,0x78,0x14,0x7e,0x70,0xa, 0xac,0x70, -0xf1,0xec,0xac,0x31,0x2e,0x14,0x2, 0xa8,0x74,0xa, 0x12,0x1b,0xc0,0xb, 0x10,0xb, -0x0, 0xbe,0x0, 0xa, 0x40,0xc3,0x91,0x8e,0x7e,0x8, 0x1d,0x4a,0x7e,0x18,0x2, 0xa8, -0x12,0x4d,0x9b,0xda,0x79,0x22,0x7e,0x8, 0x2, 0xa8,0xca,0xd8,0xca,0x79,0x7f,0x70, -0x7c,0xe6,0x7c,0xd7,0x7c,0xfb,0x6c,0x77,0x7a,0xd1,0x25,0x80,0x7b,0x7e,0x50,0xa, -0xac,0x57,0x9, 0x62,0x1d,0x4e,0x7a,0x61,0x26,0x7e,0x31,0x25,0x74,0xa, 0xac,0xb3, -0x9, 0x35,0x1c,0x86,0xbe,0x31,0x26,0x78,0x5d,0xe5,0x26,0xbe,0xb0,0xff,0x68,0x56, -0x91,0x7d,0x39,0x60,0x0, 0x4, 0xe5,0x26,0xa, 0x2b,0x9, 0xb2,0x1d,0xae,0x70,0xc, -0x91,0x86,0x7d,0xd5,0x2e,0xd4,0x1c,0x82,0x6d,0xcc,0x80,0xc, 0x74,0xa, 0xac,0xb7, -0x7d,0xd5,0x2e,0xd4,0x1d,0x4a,0x6d,0xcc,0xb, 0x6a,0x40,0x91,0x7d,0x1b,0xa, 0x40, -0x69,0x46,0x0, 0x2, 0x91,0x7d,0x79,0x40,0x0, 0x2, 0x91,0x86,0x9, 0x65,0x1c,0x87, -0x91,0x7d,0x39,0x60,0x0, 0x5, 0x91,0x86,0x9, 0x65,0x1c,0x88,0x91,0x7d,0x39,0x60, -0x0, 0x6, 0xb, 0xf0,0x80,0x7, 0x5, 0x25,0xbe,0xe1,0x25,0x38,0x80,0xb, 0x70,0xbe, -0x70,0xa, 0x50,0x2, 0x61,0xe8,0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0x74,0xa, 0xac, -0xbf,0x7f,0x7, 0x2d,0x15,0x22,0x7e,0x61,0x25,0x74,0xa, 0xac,0xb6,0x22,0x7e,0x34, -0x0, 0x64,0x7a,0x35,0x2f,0x22,0xca,0x3b,0x6c,0xcc,0x6c,0xff,0x7e,0x8, 0x32,0xf, -0x7e,0x34,0xff,0xff,0x7e,0x24,0x0, 0x46,0x12,0x59,0xa2,0x6c,0x33,0x80,0x43,0x7e, -0x10,0x7, 0xac,0x13,0x19,0x30,0x32,0xf, 0x74,0x2, 0xac,0xb3,0x9, 0x25,0x19,0xde, -0x19,0x20,0x32,0x10,0x9, 0x25,0x19,0xdf,0x19,0x20,0x32,0x11,0x74,0x5, 0xac,0xb3, -0x9, 0x25,0x1a,0x1b,0x19,0x20,0x32,0x14,0x9, 0x25,0x1a,0x1c,0x19,0x20,0x32,0x12, -0x9, 0x25,0x1a,0x1d,0x19,0x20,0x32,0x15,0x9, 0x25,0x1a,0x1e,0x19,0x20,0x32,0x13, -0xb, 0x30,0x7e,0x23,0x1c,0x58,0xbc,0x23,0x38,0xb5,0x6c,0x33,0x74,0xa, 0xac,0xb3, -0x9, 0x25,0x1c,0x86,0xbe,0x20,0xff,0x78,0x2, 0xc1,0xab,0xa, 0x2, 0x9, 0xb0,0x1d, -0xae,0xbe,0xb0,0x1, 0x78,0x2, 0xc1,0xab,0x6c,0xdd,0x74,0xa, 0xac,0xbd,0x9, 0x75, -0x31,0x9b,0xbc,0x72,0x68,0x7, 0xb, 0xd0,0xbe,0xd0,0xa, 0x40,0xed,0xbe,0xd0,0xa, -0x40,0x6, 0x6c,0xcc,0x6c,0xff,0x80,0x5d,0x74,0x5, 0xac,0xb3,0x9, 0xb5,0x1a,0x1a, -0xb4,0x1, 0x52,0x74,0xa, 0xac,0xbd,0x49,0x25,0x31,0x97,0x74,0xa, 0xac,0xb3,0x12, -0x8c,0x53,0x1a,0x6, 0x7c,0xc1,0x7e,0x50,0xa, 0xac,0x5d,0x49,0x42,0x31,0x97,0x7e, -0x70,0xa, 0xac,0x73,0x49,0x3, 0x1c,0x82,0xbd,0x4, 0x50,0x5, 0x6e,0xc0,0xff,0xb, -0xc0,0x49,0x22,0x31,0x99,0x12,0x8c,0x42,0x7d,0x73,0x1a,0x7e,0x74,0xa, 0xac,0xbd, -0x49,0x45,0x31,0x99,0x74,0xa, 0xac,0xb3,0x49,0x5, 0x1c,0x84,0xbd,0x4, 0x50,0x5, -0x6e,0xf0,0xff,0xb, 0xf0,0x4c,0xcc,0x78,0x2, 0xc1,0x20,0xd1,0xc0,0x2e,0x34,0x32, -0x12,0x7e,0x39,0xb0,0x2c,0xbc,0x7a,0x39,0xb0,0x7d,0x30,0x2e,0x34,0x32,0x14,0x7e, -0x39,0xb0,0x2c,0xbc,0x7a,0x39,0xb0,0x9, 0x70,0x32,0x12,0x1a,0x57,0x7e,0x63,0x1e, -0x8b,0xa, 0x46,0x1b,0x44,0xbd,0x54,0x8, 0x8, 0x7c,0x69,0x19,0x60,0x32,0x12,0x80, -0xa, 0xbe,0x70,0x0, 0x58,0x5, 0xe4,0x19,0xb0,0x32,0x12,0x9, 0x70,0x32,0x14,0x1a, -0x57,0xbd,0x54,0x8, 0x8, 0x7c,0x69,0x19,0x60,0x32,0x14,0x80,0xa, 0xbe,0x70,0x0, -0x58,0x5, 0xe4,0x19,0xb0,0x32,0x14,0xd1,0xd3,0xbd,0x34,0x8, 0xa, 0x7e,0x73,0x1e, -0x8b,0xa, 0x37,0x1b,0x34,0x80,0x15,0x1a,0x3c,0x6e,0x34,0xff,0xff,0xb, 0x34,0xbd, -0x23,0x58,0x7, 0xe4,0x19,0xb0,0x32,0x10,0x80,0x6, 0xd1,0xd3,0x19,0x70,0x32,0x10, -0x4c,0xff,0x78,0x2, 0xc1,0xab,0xd1,0xc0,0x2e,0x34,0x32,0x13,0x7e,0x39,0xb0,0x2c, -0xbf,0x7a,0x39,0xb0,0x7d,0x30,0x2e,0x34,0x32,0x15,0x7e,0x39,0xb0,0x2c,0xbf,0x7a, -0x39,0xb0,0x9, 0x70,0x32,0x13,0x1a,0x57,0x7e,0x63,0x1e,0x8c,0xa, 0x46,0x1b,0x44, -0xbd,0x54,0x8, 0x8, 0x7c,0x69,0x19,0x60,0x32,0x13,0x80,0xa, 0xbe,0x70,0x0, 0x58, -0x5, 0xe4,0x19,0xb0,0x32,0x13,0x9, 0x70,0x32,0x15,0x1a,0x57,0xbd,0x54,0x8, 0x8, -0x7c,0x69,0x19,0x60,0x32,0x15,0x80,0xa, 0xbe,0x70,0x0, 0x58,0x5, 0xe4,0x19,0xb0, -0x32,0x15,0xd1,0xc8,0xbd,0x34,0x8, 0xa, 0x7e,0x73,0x1e,0x8c,0xa, 0x37,0x1b,0x34, -0x80,0x15,0x1a,0x3f,0x6e,0x34,0xff,0xff,0xb, 0x34,0xbd,0x23,0x58,0x7, 0xe4,0x19, -0xb0,0x32,0x11,0x80,0x6, 0xd1,0xc8,0x19,0x70,0x32,0x11,0xb, 0x30,0xbe,0x30,0xa, -0x50,0x2, 0x81,0xfc,0x91,0x8e,0x7e,0x8, 0x31,0x97,0x12,0x4d,0x97,0xda,0x3b,0x22, -0x7e,0x10,0x7, 0xac,0x13,0x7d,0x30,0x22,0x9, 0x70,0x32,0x11,0x1a,0x27,0x1a,0x3f, -0x2d,0x32,0x22,0x9, 0x70,0x32,0x10,0x1a,0x27,0x1a,0x3c,0x2d,0x32,0x22,0xca,0x69, -0xca,0xf8,0x7e,0xa3,0x1d,0xea,0x4c,0xaa,0x78,0x11,0x7e,0xb3,0x1d,0xeb,0xbe,0xb0, -0x0, 0x28,0x13,0x74,0x1, 0x7a,0xb3,0x1d,0xef,0x80,0xb, 0xbe,0xa0,0x0, 0x28,0x6, -0x74,0x1, 0x7a,0xb3,0x1d,0xf3,0x91,0x8e,0x7e,0x8, 0x1c,0xe6,0x12,0x4d,0x97,0x6c, -0xff,0x74,0xa, 0xac,0xbf,0x49,0xa5,0x1c,0x82,0x49,0x95,0x1c,0x84,0x7d,0x3a,0xf1, -0x41,0x7d,0x83,0x7d,0x39,0xf1,0x72,0x7d,0x63,0x74,0xa, 0xac,0xbf,0x59,0x85,0x1c, -0xe6,0x59,0x65,0x1c,0xe8,0xb, 0xf0,0xbe,0xf0,0xa, 0x40,0xd5,0xda,0xf8,0xda,0x69, -0x22,0x7e,0x25,0x19,0xe1,0x46,0x7d,0xb2,0x7d,0x23,0x49,0x3b,0x0, 0x2, 0xbd,0x32, -0x38,0x9, 0x9d,0x23,0x7d,0x32,0xf1,0x66,0x2d,0x32,0x22,0x1b,0x34,0x9d,0x32,0xf1, -0x66,0x1b,0x34,0x9d,0x32,0x22,0x7d,0x2b,0x12,0x83,0xb0,0x7d,0x23,0x49,0x3b,0x0, -0x4, 0x22,0x7e,0x25,0x1b,0xe1,0x46,0x7e,0x8, 0x1e,0x89,0x2, 0x11,0xe4,0x74,0x1, -0x12,0x18,0x1b,0xe4,0x12,0x0, 0x6, 0xe4,0x12,0xf, 0xe9,0xf1,0x77,0xe1,0x8f,0x7e, -0x63,0x1f,0x3d,0x7e,0x73,0x3d,0x72,0xac,0x67,0x2e,0x34,0x1, 0xf4,0x7e,0x24,0x1, -0xf4,0x8d,0x32,0xbe,0x70,0x7, 0x28,0x3, 0x7e,0x70,0x7, 0x12,0x2a,0xa9,0x3e,0x34, -0x2d,0x32,0x79,0x30,0x0, 0xa0,0x22,0xa9,0xd1,0xcb,0x74,0x1, 0x2, 0xf, 0xe9,0x12, -0xf, 0xe9,0x7e,0x1f,0x15,0x44,0x22,0x7a,0x37,0x2, 0xb2,0x7e,0x8, 0x2, 0xa8,0x22, -0x7e,0xb3,0x1e,0x8a,0x7e,0x73,0x1e,0x89,0xac,0xb7,0x22,0xe4,0x12,0xf, 0xe9,0x74, -0x1, 0x7e,0x70,0x99,0x2, 0x17,0x57,0x7e,0x70,0xa, 0xac,0x7e,0x2e,0x34,0x1c,0x82, -0x7e,0x30,0xa, 0x22,0x7e,0x37,0x34,0xa9,0xb, 0x34,0x7a,0x37,0x34,0xa9,0x7e,0x37, -0x34,0xab,0xbe,0x37,0x34,0xa9,0x28,0x2, 0x1, 0xb, 0x22,0xe5,0x9a,0x60,0x5, 0xd2, -0x9c,0xa9,0xd6,0xdf,0x22,0x80,0xdd,0xca,0x7b,0xca,0x6b,0xca,0x5b,0xca,0x4b,0xca, -0x2b,0xca,0x1b,0xca,0xb, 0xc0,0xd0,0xc0,0x83,0xc0,0x82,0x11,0x15,0xd0,0x82,0xd0, -0x83,0xd0,0xd0,0xda,0xb, 0xda,0x1b,0xda,0x2b,0xda,0x4b,0xda,0x5b,0xda,0x6b,0xda, -0x7b,0x32,0x74,0xa, 0x7a,0xb3,0x1e,0x69,0x74,0x10,0x7a,0xb3,0x1e,0x6a,0x7e,0x34, -0x0, 0xa0,0x12,0xd1,0x9b,0x7a,0x37,0x1e,0x71,0x74,0x3c,0x7a,0xb3,0x1e,0x75,0x7e, -0x34,0x0, 0xc8,0x7a,0x37,0x1e,0x76,0x7e,0x34,0x0, 0x96,0x7a,0x37,0x1e,0x78,0x7e, -0x34,0xff,0x6a,0x7a,0x37,0x1e,0x7a,0x7e,0x34,0x0, 0x96,0x7a,0x37,0x1e,0x7c,0xe4, -0x7a,0xb3,0x1e,0x80,0x74,0x4, 0x7a,0xb3,0x1e,0x81,0x7e,0x34,0x0, 0x64,0x7a,0x37, -0x1e,0x82,0x7e,0x34,0x8, 0x0, 0x7a,0x37,0x1e,0x7e,0xe4,0x7a,0xb3,0x18,0xd0,0x22, -0x12,0x62,0xcb,0x12,0x64,0x8b,0x12,0x0, 0x2a,0x12,0xd1,0x75,0x7e,0x18,0x4, 0x0, -0x7a,0x1f,0x6, 0xb0,0x7e,0xf, 0x6, 0xb0,0x7e,0x1f,0x6, 0xac,0x12,0x68,0xfc,0x7e, -0x18,0x9, 0x74,0x7a,0x1f,0x15,0x44,0x7e,0x18,0xf, 0x5c,0x7a,0x1f,0x15,0x48,0x7e, -0xf, 0x15,0x48,0x7e,0x1f,0x15,0x44,0x12,0x68,0xd6,0x11,0xf3,0x11,0x42,0x12,0x68, -0x59,0x31,0x49,0x1, 0xe5,0xe4,0x7a,0xb3,0x3d,0xfd,0x7a,0xb3,0x3d,0xfe,0x7a,0xb3, -0x3d,0xff,0x22,0x1, 0xf5,0x7e,0x34,0x0, 0xa0,0x7a,0x37,0x1c,0x69,0x7e,0x34,0x0, -0xc8,0x7a,0x37,0x1c,0x6d,0x7e,0x34,0x0, 0x64,0x7a,0x37,0x1c,0x6b,0x7e,0x34,0x0, -0x96,0x7a,0x37,0x1c,0x6f,0x7e,0x34,0x0, 0x50,0x7a,0x37,0x1c,0x71,0x7e,0x34,0x0, -0x46,0x7a,0x37,0x1c,0x73,0x7e,0x34,0x0, 0x1, 0x7a,0x37,0x1c,0x75,0x7a,0x37,0x1c, -0x77,0x74,0x1, 0x7a,0xb3,0x1c,0x79,0xe4,0x7a,0xb3,0x1c,0x7c,0x7e,0x73,0x38,0xa2, -0x3e,0x34,0x7e,0x8, 0x18,0xdb,0x2, 0x1d,0xd3,0x7e,0x8, 0x1c,0x82,0x7e,0x34,0x1, -0x2c,0x74,0xff,0x12,0x1d,0xd3,0x31,0x6b,0x7e,0x8, 0x1d,0xae,0x12,0x76,0xaa,0x7e, -0x8, 0x1d,0xea,0x7e,0x34,0x0, 0xb, 0xe4,0x2, 0x1d,0xd3,0x7e,0x8, 0x31,0x8a,0x6d, -0x33,0x7e,0x24,0x0, 0xd, 0x21,0xa2,0x7a,0xb3,0x37,0x3a,0x6d,0x33,0x7a,0x37,0x37, -0x41,0x7a,0xb3,0x37,0xc4,0x7a,0xb3,0x37,0x46,0x7e,0x8, 0x37,0x67,0x7e,0x34,0x0, -0x2, 0x74,0xff,0x12,0x1d,0xd3,0x7e,0x8, 0x37,0x3d,0x7e,0x34,0xff,0xff,0x7e,0x24, -0x0, 0x4, 0x7d,0x42,0x7d,0x53,0x7f,0x70,0x7f,0x17,0x7d,0x14,0x1e,0x14,0x7c,0x1b, -0x2d,0xf4,0x1b,0xf4,0x7a,0x7b,0x10,0x6d,0x0, 0x80,0x7, 0x1b,0x1a,0x50,0xb, 0x35, -0xb, 0x4, 0xbd,0x10,0x38,0xf5,0x22,0xca,0xf8,0x7e,0xf3,0x1c,0x58,0x4c,0xff,0x68, -0xb, 0x7e,0xb3,0x37,0x3a,0x70,0xe, 0xbe,0xf0,0x1, 0x28,0x9, 0xe4,0x7a,0xb3,0x37, -0x43,0x31,0x77,0x41,0xa0,0xbe,0xf0,0x1, 0x68,0x2, 0x41,0xa0,0x7e,0xb3,0x37,0x43, -0xbe,0xb0,0x2, 0x40,0x2, 0x41,0xa0,0x70,0x2b,0x7e,0x73,0x19,0xde,0x7a,0x73,0x37, -0x67,0x7e,0x73,0x19,0xdf,0x7a,0x73,0x37,0x68,0x7e,0xb3,0x37,0x46,0x4, 0x7a,0xb3, -0x37,0x46,0x7e,0x37,0x9, 0x62,0x7a,0x37,0x37,0x41,0x74,0x1, 0x7a,0xb3,0x37,0x43, -0x51,0xc6,0x80,0x7c,0x7e,0x73,0x37,0x3d,0xbe,0x73,0x19,0xde,0x38,0x42,0x7e,0x73, -0x37,0x3e,0xbe,0x73,0x19,0xde,0x40,0x38,0x7e,0x73,0x37,0x3f,0xbe,0x73,0x19,0xdf, -0x38,0x2e,0x7e,0x73,0x37,0x40,0xbe,0x73,0x19,0xdf,0x40,0x24,0x7e,0x37,0x37,0x41, -0xbe,0x37,0x9, 0x62,0x58,0x8, 0x7e,0x37,0x9, 0x62,0x7a,0x37,0x37,0x41,0x51,0xc6, -0x7e,0xb3,0x37,0x46,0xbe,0xb0,0x14,0x38,0x12,0x4, 0x7a,0xb3,0x37,0x46,0x80,0xb, -0x74,0x2, 0x7a,0xb3,0x37,0x43,0xe4,0x31,0x77,0x80,0x48,0x7e,0x73,0x37,0x46,0xbe, -0x70,0x14,0x40,0x1c,0x7e,0xb3,0x37,0x3a,0x70,0x16,0x74,0x1, 0x7a,0xb3,0x37,0x3a, -0x7e,0x37,0x37,0x41,0xbe,0x34,0x5, 0xdc,0x58,0x6, 0x74,0x1, 0x7a,0xb3,0x37,0xc4, -0x7e,0xb3,0x37,0x3a,0x60,0x2, 0x80,0xb, 0xe5,0x78,0xb4,0x1, 0xb, 0x74,0x1, 0x7a, -0xb3,0x37,0x3a,0x75,0x78,0x1, 0x80,0x3, 0x75,0x78,0x0, 0x7e,0xb3,0x1c,0x58,0x70, -0x2, 0xf5,0x78,0xda,0xf8,0x22,0x7e,0x73,0x37,0x67,0x7e,0x23,0x37,0x68,0x7e,0x47, -0x9, 0x68,0xe, 0x44,0x7e,0x7, 0x1e,0x6d,0xbd,0x4, 0x8, 0x2, 0x7d,0x40,0x7a,0x73, -0x37,0x3d,0x7c,0x37,0x80,0x20,0xa, 0x3, 0x1b,0x4, 0x7c,0x61,0x7a,0x63,0x37,0x3d, -0x7e,0x63,0x1e,0x8c,0xa, 0x56,0xa, 0x3, 0x2d,0x5, 0x3e,0x4, 0x49,0x0, 0x4, 0xe2, -0xbd,0x4, 0x48,0x7, 0x1b,0x30,0xbe,0x30,0x0, 0x38,0xdb,0x7a,0x73,0x37,0x3e,0x7c, -0x37,0x80,0x1a,0x7a,0x33,0x37,0x3e,0x7e,0x73,0x1e,0x8c,0xa, 0x57,0xa, 0x3, 0x2d, -0x5, 0x3e,0x4, 0x49,0x0, 0x4, 0xe4,0xbd,0x4, 0x48,0xa, 0xb, 0x30,0x7e,0x73,0x1e, -0x8b,0xbc,0x73,0x38,0xde,0x7e,0x47,0x9, 0x6a,0xe, 0x44,0x7e,0x7, 0x1e,0x6f,0xbd, -0x4, 0x8, 0x2, 0x7d,0x40,0x7a,0x23,0x37,0x3f,0x7c,0x32,0x80,0x16,0xa, 0x33,0x1b, -0x34,0x7a,0x73,0x37,0x3f,0x74,0x2, 0xac,0xb3,0x49,0x5, 0x4, 0xe2,0xbd,0x4, 0x48, -0x7, 0x1b,0x30,0xbe,0x30,0x0, 0x38,0xe5,0x7a,0x23,0x37,0x40,0x7c,0x32,0x80,0x12, -0x7a,0x33,0x37,0x40,0x74,0x2, 0xac,0xb3,0x49,0x55,0x4, 0xe4,0xbd,0x54,0x48,0xa, -0xb, 0x30,0x7e,0x23,0x1e,0x8c,0xbc,0x23,0x38,0xe6,0x7e,0xb3,0x37,0xc4,0xb4,0x1, -0x67,0x7e,0xb3,0x37,0x3d,0xbe,0xb0,0x1, 0x40,0x3, 0x14,0x80,0x1, 0xe4,0x7a,0xb3, -0x37,0x3d,0x7e,0xb3,0x37,0x3e,0xa, 0x3b,0xb, 0x34,0x7e,0x23,0x1e,0x8b,0xa, 0x2, -0xbd,0x30,0x48,0xc, 0xa, 0x32,0x1b,0x34,0x7c,0x27,0x7a,0x23,0x37,0x3e,0x80,0x5, -0x4, 0x7a,0xb3,0x37,0x3e,0x7e,0xb3,0x37,0x3f,0xbe,0xb0,0x1, 0x40,0x3, 0x14,0x80, -0x1, 0xe4,0x7a,0xb3,0x37,0x3f,0x7e,0xb3,0x37,0x40,0xa, 0x3b,0xb, 0x34,0x7e,0x23, -0x1e,0x8c,0xa, 0x2, 0xbd,0x30,0x48,0xb, 0xa, 0x32,0x1b,0x34,0x7c,0x27,0x7a,0x23, -0x37,0x40,0x22,0x4, 0x7a,0xb3,0x37,0x40,0x22,0xca,0x3b,0x6c,0xdd,0x6c,0xcc,0xc2, -0x6, 0x7e,0xe0,0x3, 0x12,0x7d,0xc0,0x7e,0xa3,0x19,0x68,0xbe,0xa0,0x1, 0x78,0xc, -0x7e,0xb3,0x19,0x69,0xbe,0xb0,0x1, 0x28,0x3, 0x7e,0xd0,0x1, 0x7e,0xb3,0x19,0x69, -0xb4,0x1, 0x8, 0xbe,0xa0,0x1, 0x28,0x3, 0x7e,0xc0,0x1, 0xbe,0xd0,0x1, 0x68,0x5, -0xbe,0xc0,0x1, 0x78,0x7f,0x6c,0xff,0x7e,0x70,0x7, 0xac,0x7f,0x9, 0xb3,0x32,0xf, -0xbe,0xb0,0xff,0x68,0x68,0xbe,0xd0,0x1, 0x78,0x31,0x9, 0xb3,0x32,0x14,0xbe,0xb0, -0x0, 0x8, 0xa, 0x7d,0x23,0x2e,0x24,0x32,0x14,0x14,0x7a,0x29,0xb0,0x9, 0xb3,0x32, -0x12,0x1a,0x1b,0x7e,0xa3,0x1e,0x8b,0xa, 0x2a,0x1b,0x24,0xbd,0x12,0x58,0x3e,0x7d, -0x23,0x2e,0x24,0x32,0x12,0x4, 0x7a,0x29,0xb0,0x80,0x32,0xbe,0xc0,0x1, 0x78,0x2d, -0x9, 0xb3,0x32,0x15,0xbe,0xb0,0x0, 0x8, 0xa, 0x7d,0x23,0x2e,0x24,0x32,0x15,0x14, -0x7a,0x29,0xb0,0x9, 0xb3,0x32,0x13,0x1a,0x1b,0x7e,0xa3,0x1e,0x8c,0xa, 0x2a,0x1b, -0x24,0xbd,0x12,0x58,0x8, 0x2e,0x34,0x32,0x13,0x4, 0x7a,0x39,0xb0,0xb, 0xf0,0xbe, -0xf0,0xa, 0x78,0x83,0x7e,0x8, 0x37,0x69,0x7e,0x34,0xff,0xff,0x7e,0x24,0x0, 0x1e, -0x31,0xa2,0x6c,0xff,0x80,0xc, 0x7c,0xbf,0xb1,0xae,0xa, 0x3f,0x19,0xb3,0x37,0x69, -0xb, 0xf0,0xf1,0xe5,0x38,0xf0,0x7e,0xd3,0x1d,0xeb,0x7e,0x24,0x2, 0xa8,0x7a,0x27, -0x37,0x65,0xbe,0x70,0x1, 0x38,0x2, 0xa1,0xa6,0x74,0x3, 0x12,0xab,0x4c,0x4c,0xdd, -0x68,0xe, 0x7e,0xa3,0x37,0x38,0x4c,0xaa,0x78,0xa, 0x7e,0xb3,0x37,0x39,0x70,0x4, -0xd2,0x6, 0x80,0x22,0xbe,0xd0,0x1, 0x28,0xb, 0xe5,0x79,0xbe,0xb0,0x8, 0x28,0x4, -0xd2,0x6, 0x80,0x12,0xd2,0x6, 0x7e,0xb3,0x1c,0x58,0xbc,0xbd,0x78,0x8, 0x4c,0xaa, -0x78,0x4, 0x6c,0xee,0xc2,0x6, 0x20,0x6, 0x5, 0x7c,0xbe,0x12,0xab,0x4c,0x7e,0x8, -0x37,0x47,0x12,0xb7,0xe0,0x7a,0xb3,0x37,0x45,0xbe,0xb3,0x1c,0x58,0x50,0x45,0x7e, -0x33,0x37,0x45,0x80,0x31,0x7e,0x70,0x2, 0xac,0x73,0x9, 0x23,0x37,0x88,0x9, 0x13, -0x37,0x89,0x2e,0x37,0x37,0x65,0xb, 0x38,0x40,0x7e,0xb3,0x1e,0x8a,0xac,0xb2,0xa, -0x31,0x2d,0x53,0x3e,0x54,0x7e,0x1f,0x15,0x48,0x2d,0x35,0x1b,0x1a,0x40,0x7c,0xb3, -0x7e,0x70,0x1, 0x12,0x4e,0xbb,0x7c,0x3, 0x1b,0x30,0xa5,0xb8,0x0, 0xc7,0x74,0x1, -0x7a,0xb3,0x37,0x3b,0x7e,0xb3,0x37,0x45,0x7a,0xb3,0x1c,0x58,0x7e,0x70,0x2, 0xac, -0xb7,0x7a,0x55,0x2f,0x7e,0x8, 0x19,0xde,0x7e,0x18,0x37,0x88,0x12,0x4d,0x9b,0x12, -0x7f,0xd8,0xf5,0x79,0x80,0x3, 0x75,0x79,0x64,0x31,0xc7,0xda,0x3b,0x22,0xca,0xf8, -0x7c,0x6b,0x6c,0x22,0x7e,0x30,0xff,0x74,0x2, 0xac,0xb6,0x9, 0x15,0x19,0xde,0x9, -0x5, 0x19,0xdf,0x7e,0xb3,0x1d,0xeb,0x70,0x4, 0x74,0xff,0xc1,0x7b,0x7e,0x73,0x1c, -0x58,0xbc,0x76,0x38,0x4, 0x74,0xff,0xc1,0x7b,0x6c,0x99,0x6c,0x88,0x7e,0x70,0x7, -0xac,0x79,0x9, 0xf3,0x32,0xf, 0xbe,0xf0,0xff,0x78,0x2, 0xc1,0x70,0x9, 0x53,0x32, -0x12,0xbc,0x51,0x40,0x6e,0x9, 0x53,0x32,0x14,0xbc,0x51,0x38,0x66,0x9, 0x53,0x32, -0x13,0xbc,0x50,0x40,0x5e,0x9, 0x53,0x32,0x15,0xbc,0x50,0x38,0x56,0x9, 0xa3,0x32, -0x10,0xbc,0xa1,0x78,0xd, 0x9, 0xb3,0x32,0x11,0xbc,0xb0,0x78,0x5, 0x7e,0x80,0x4, -0x80,0x2f,0xa, 0x2a,0xd1,0x99,0xbe,0x34,0x0, 0x1, 0x18,0xd, 0xd1,0x7e,0xbe,0x34, -0x0, 0x1, 0x18,0x5, 0x7e,0x80,0x3, 0x80,0x18,0xd1,0x8f,0xbe,0x34,0x0, 0x2, 0x18, -0xd, 0xd1,0x7e,0xbe,0x34,0x0, 0x2, 0x18,0x5, 0x7e,0x80,0x2, 0x80,0x3, 0x7e,0x80, -0x1, 0xd1,0x7e,0x7d,0xf3,0xd1,0x8f,0x7d,0x53,0x2d,0x5f,0xbe,0x54,0x0, 0x8, 0x8, -0x2, 0x6c,0x88,0xbc,0x28,0x50,0x4, 0x7c,0x28,0x7c,0x39,0xbe,0x20,0x4, 0x68,0x9, -0xb, 0x90,0xbe,0x90,0xa, 0x50,0x2, 0xa1,0xdb,0x7c,0xb3,0xda,0xf8,0x22,0x74,0x7, -0xac,0xb9,0x9, 0x75,0x32,0x11,0xa, 0x27,0xa, 0x30,0x9d,0x32,0x2, 0x1e,0x5, 0x74, -0x7, 0xac,0xb9,0x9, 0x75,0x32,0x10,0xa, 0x27,0xa, 0x31,0x9d,0x32,0x2, 0x1e,0x5, -0x7e,0x8, 0x3c,0x9, 0x6d,0x33,0x7e,0x24,0x0, 0x60,0x31,0xa2,0x6c,0x77,0x7e,0x44, -0xff,0xff,0x74,0xc, 0xac,0xb7,0x59,0x45,0x3c,0xb, 0x59,0x45,0x3c,0x13,0xb, 0x70, -0xbe,0x70,0x8, 0x40,0xe9,0x7e,0x8, 0x3b,0xf7,0x6d,0x33,0x7e,0x24,0x0, 0xd, 0x21, -0xa2,0xc2,0x7, 0xe4,0x7a,0xb3,0x3e,0x14,0x12,0xc4,0x5a,0x48,0x2a,0x7e,0x37,0x9, -0x66,0xbe,0x34,0xff,0x38,0x48,0x20,0xf1,0xf2,0x68,0x1c,0x7e,0x73,0x3c,0xea,0xbe, -0x70,0x12,0x40,0x13,0x7e,0xb3,0x3d,0x9, 0xbe,0xb0,0x3, 0x68,0xa, 0x7e,0xb3,0x3d, -0x7, 0x70,0x4, 0xf1,0xe2,0x50,0x2, 0xd2,0x7, 0xa2,0x15,0x30,0x7, 0x1, 0xb3,0x50, -0x17,0x30,0x7, 0x3, 0x2, 0x21,0xde,0x11,0xe5,0x7e,0x34,0x0, 0x1, 0x7e,0x24,0x8, -0xa, 0xf1,0x61,0xf1,0x59,0xc2,0x15,0x22,0x20,0x15,0x2d,0x7e,0x37,0x3e,0x0, 0x4d, -0x33,0x78,0x11,0x7e,0x24,0x0, 0x1, 0x7a,0x27,0x3e,0x0, 0x7e,0x24,0x8, 0xa, 0x7a, -0x27,0x3e,0x2, 0x22,0xbe,0x34,0x0, 0x1, 0x78,0xe, 0x6d,0x33,0x7a,0x37,0x3e,0x0, -0x7e,0x34,0x6, 0xb4,0x7a,0x37,0x3e,0x2, 0x22,0x7e,0x34,0x0, 0x3, 0x6d,0x22,0xe1, -0x61,0x7d,0x43,0x7e,0xb3,0x3d,0xfd,0xbe,0xb0,0x5, 0x50,0x18,0x7e,0x70,0x4, 0xac, -0xb7,0x59,0x45,0x3e,0x0, 0x59,0x25,0x3e,0x2, 0x7e,0xb3,0x3d,0xfd,0x4, 0x7a,0xb3, -0x3d,0xfd,0xc3,0x22,0xd3,0x22,0x6d,0x33,0x7e,0x24,0x6, 0xb4,0xf1,0x61,0x7e,0x34, -0x0, 0x1, 0x7e,0x24,0x8, 0xa, 0xe1,0x61,0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x18, -0x39,0x3d,0x7e,0x8, 0x1f,0xbc,0x12,0x1d,0xae,0x1b,0xfd,0x7e,0x34,0x1d,0xf7,0x7a, -0x37,0x1f,0xc2,0xe4,0x7a,0xb3,0x1f,0xc0,0x7a,0xb3,0x1f,0xc1,0x7e,0x34,0x0, 0x4, -0xca,0x39,0x7e,0x18,0x39,0x39,0x7e,0x8, 0x18,0xd2,0x12,0x1d,0xae,0x1b,0xfd,0x7e, -0x34,0x1f,0xc4,0x7a,0x37,0x18,0xd8,0x74,0x1, 0x7a,0xb3,0x18,0xd6,0x7a,0xb3,0x18, -0xd7,0x22,0xa2,0x1, 0x22,0x7e,0x73,0x1c,0x58,0xbc,0x7f,0x22,0x7e,0x24,0x0, 0xa, -0x21,0xa2,0x7e,0xb3,0x1c,0x7c,0xbe,0xb0,0x1, 0x22,0xe4,0x2, 0x72,0x80,0xff,0xff, -0x70,0x8f,0x0, 0xff,0x48,0xb7,0x38,0xc7,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x48,0x38,0x32,0x3, 0x4a,0x31,0x52,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x10,0xef,0x4a,0x31,0x31,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x10,0x23,0xf, 0xe, 0x8, 0x2, 0xa, 0xd, 0xb, 0x7, 0x5, 0x0, 0x1, 0x3, 0x4, 0x6, -0x9, 0xc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x22,0x1e,0x1d,0x1a,0x19,0x14,0x15,0x10,0x11,0xf, 0xd, -0xb, 0x6, 0xe, 0x21,0x1f,0x20,0x1b,0x1c,0x16,0x17,0x12,0x13,0x9, 0x8, 0x7, 0x3, -0xc, 0x18,0x0, 0x4, 0x1, 0x5, 0x2, 0xa, 0x0, 0x5, 0x0, 0x4, 0xff,0x15,0x24,0x2, -0xf4,0xa, 0x1e,0xa, 0x64,0x3c,0x10,0x0, 0x4, 0x0, 0x64,0xd, 0xac,0x0, 0xc8,0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x19,0x3b,0x1, 0xf4, -0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x65,0x66,0x64, -0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64,0x64, -0x64,0x64,0x64,0x52,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a,0x5a, -0x5a,0x5c,0x5f,0x5f,0x5f,0x5f,0x5f,0x64,0x64,0x66,0x67,0x68,0x68,0x6a,0x6b,0x6f, -0x70,0x73,0x74,0x76,0x7a,0x7c,0x66,0x0, 0x5, 0x2f,0x18,0x1, 0x20,0x0, 0x0, 0x0, -0x0, 0x0, 0x1, 0xf4,0x40,0x40,0x10,0x23,0x33,0xf, 0xe, 0x3, 0x78,0xf, 0xe, 0x3, -0x98,0x15,0x1b,0x6, 0x30,0x1, 0x0, 0xba,0x58,0x8, 0x0, 0x2, 0x1c,0x7, 0x60,0x7, -0x10,0x6, 0xa2,0x2, 0x54,0x1, 0xb2,0x1, 0xd, 0xba,0x54,0x11,0x80,0x4, 0xb0,0x10, -0xf2,0x10,0x9a,0x10,0x22,0x2, 0x1e,0x1, 0x8e,0x1, 0x12,0x0, 0xc8,0x0, 0x96,0x0, -0x96,0x0, 0xa0,0x0, 0xa0,0x0, 0xa0,0x0, 0xa0,0x8, 0x0, 0x0, 0xfa,0xa, 0x10,0x64, -0x3e,0x1, 0x2, 0x12,0x1e,0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x52,0xb, 0x0, 0x1, 0x54,0x1, -0x0, 0x10,0x1, 0x48,0x1, 0x1, 0x0, 0x38,0x1, 0x1, 0x1, 0x0, 0x5, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x55,0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x64,0x0, 0xc8,0x0, 0x50, -0x0, 0x46,0x0, 0x1, 0x0, 0x1, 0x1, 0x4, 0x1, 0x90,0x0, 0xc8,0x0, 0x50,0x1, 0x90, -0x0, 0x96,0x1, 0x2c,0x1, 0x2c,0x4, 0x3b,0x0, 0x2f,0x40,0x18,0x45,0x0, 0x1f,0x40, -0x20,0x21,0x2, 0x35,0x40,0x20,0x29,0x1, 0x2a,0x40,0x30,0x3b,0x0, 0x2f,0x40,0x18, -0x3b,0x0, 0x2f,0x40,0x18,0x3b,0x0, 0x2f,0x40,0x18,0x3b,0x0, 0x2f,0x40,0x18,0x4, -0x5, 0xe, 0xf, 0x10,0x11,0x12,0x4, 0x0, 0x78,0x0, 0xa0,0x64,0x0, 0x96,0x1, 0x5e, -0x0, 0x64,0x0, 0x96,0x0, 0x96,0x0, 0x64,0xb, 0xb8,0x8, 0x5, 0x6, 0x80,0x1, 0x90, -0x1, 0x2c,0x1, 0xc2,0x3, 0x20,0xf, 0xa0,0x1, 0x3, 0x20,0x4, 0xb0,0x3, 0x20,0x1, -0x2, 0x2, 0x4, 0x4, 0x6, 0x40,0x0, 0xdc,0x0, 0xbe,0x0, 0xbe,0x0, 0xbe,0x0, 0xbe, -0x0, 0xe6,0x0, 0xbe,0x0, 0xbe,0x0, 0xbe,0x0, 0xbe,0x0, 0x64,0x0, 0x5a,0x0, 0x64, -0x0, 0x6e,0x0, 0x64,0x0, 0xc8,0x0, 0xc8,0x15,0xa, 0x0, 0x9b,0x3, 0x9d,0x0, 0xe9, -0x8, 0x77,0x0, 0x4, 0x1, 0x7c,0x1, 0x7c,0x3, 0x20,0x0, 0x14,0x0, 0x43,0x0, 0x1e, -0x0, 0x80,0x1, 0xe, 0x1, 0x2c,0x0, 0x3c,0x3, 0xe8,0x2, 0x58,0x0, 0x87,0x0, 0x3c, -0x3, 0xe8,0x0, 0x0, 0x4, 0x38,0x0, 0x0, 0x9, 0x60,0x2, 0x1c,0x3, 0x20,0x0, 0x64, -0x0, 0xa0,0x0, 0xa0,0x1, 0xf4,0x1, 0x2c,0x0, 0xa0,0x0, 0xa0,0x10,0x0, 0xc, 0x0, -0x10,0xe, 0x5, 0x7, 0xb, 0xa, 0x6, 0x6, 0xc, 0x64,0xc8,0xe4,0x7a,0xb3,0x3d,0x41, -0x7a,0xb3,0x3d,0x42,0x74,0x10,0x7a,0xb3,0x3d,0x43,0x74,0x23,0x7a,0xb3,0x3d,0x44, -0xe4,0x7a,0xb3,0x3d,0x45,0x74,0xa, 0x7a,0xb3,0x3d,0x46,0xe4,0x7a,0xb3,0x3d,0x47, -0x7a,0xb3,0x3d,0x48,0x74,0x1, 0x7a,0xb3,0x3d,0x4a,0x74,0x32,0x7a,0xb3,0x3d,0x4e, -0x74,0x28,0x7a,0xb3,0x3d,0x4f,0x74,0x3c,0x7a,0xb3,0x3d,0x60,0x74,0x5, 0x7a,0xb3, -0x3d,0x61,0xe4,0x7a,0xb3,0x3d,0x4d,0x74,0x2f,0x7a,0xb3,0x3d,0x63,0x74,0x40,0x7a, -0xb3,0x3d,0x62,0xe4,0x7a,0xb3,0x3d,0x64,0x74,0x40,0x7a,0xb3,0x3d,0x5f,0x74,0x1, -0x7a,0xb3,0x3d,0x5b,0xe4,0x7a,0xb3,0x3d,0x5c,0x7a,0xb3,0x3d,0x5d,0x7e,0x8, 0x3d, -0x65,0x7e,0x34,0x0, 0x2c,0x12,0x1d,0xd3,0x74,0x1, 0x7a,0xb3,0x3d,0x70,0x74,0xf4, -0x7a,0xb3,0x3d,0x71,0x74,0x19,0x7a,0xb3,0x3d,0x72,0x74,0x3b,0x7a,0xb3,0x3d,0x73, -0x7e,0x34,0x0, 0x4, 0xca,0x39,0x7e,0x18,0x39,0x39,0x7e,0x8, 0x3d,0x81,0x12,0x1d, -0xae,0x1b,0xfd,0x74,0x6, 0x7a,0xb3,0x3d,0x8e,0x74,0x1, 0x7a,0xb3,0x3d,0x85,0x7e, -0x34,0x0, 0x28,0xca,0x39,0x7e,0x18,0x39,0xf7,0x7e,0x8, 0x19,0x17,0x12,0x1d,0xae, -0x1b,0xfd,0x22,0xca,0x79,0x7c,0xf7,0x7c,0xab,0x7e,0x33,0x3d,0x72,0xac,0x3a,0x2e, -0x14,0x1, 0xf4,0xbe,0x14,0x0, 0xa, 0x50,0x4, 0x7e,0x14,0x0, 0xa, 0xbe,0x14,0xc, -0x67,0x40,0x4, 0x7e,0x14,0xc, 0x67,0xbe,0x14,0x8, 0x20,0x28,0x4, 0x6c,0x77,0x80, -0x19,0xbe,0x14,0x5, 0xdc,0x40,0x5, 0x7e,0x70,0x3, 0x80,0xe, 0xbe,0x14,0x2, 0xee, -0x40,0x5, 0x7e,0x70,0x1, 0x80,0x3, 0x7e,0x70,0x2, 0x74,0x5, 0xac,0xbf,0x19,0x75, -0x1f,0xac,0x74,0x5, 0xac,0xfb,0x9, 0xb7,0x1f,0xac,0xb4,0x3, 0x4, 0x91,0x9, 0x80, -0x2, 0x74,0x20,0x19,0xb7,0x1f,0xad,0x6d,0x0, 0x71,0xfe,0xda,0x79,0x22,0x7e,0x34, -0xd0,0x0, 0x7e,0x24,0x0, 0x7, 0x2, 0x1b,0x8c,0x6d,0x0, 0x7e,0xf4,0xd0,0x0, 0x7e, -0xe4,0x0, 0x7, 0x7f,0x17,0x12,0x1b,0x8c,0xb, 0x34,0x7e,0x14,0x0, 0x6, 0x8d,0x31, -0xad,0x13,0x6d,0x0, 0x7f,0x17,0x12,0x1b,0x8c,0x7d,0x13,0x74,0x30,0x22,0x9f,0x11, -0x6c,0x33,0x80,0x23,0xa, 0x3, 0x9, 0x20,0x1f,0x0, 0x7e,0xa0,0x3, 0x7c,0xb2,0x84, -0x7c,0x2a,0x74,0x3, 0xac,0xb2,0xa, 0x2, 0xb, 0x4, 0x60,0x5, 0x3e,0x4, 0x14,0x78, -0xfb,0x7d,0x50,0x4d,0x35,0xb, 0x30,0x7e,0x13,0x1e,0x90,0xbc,0x13,0x38,0xd5,0x6c, -0x33,0x80,0x1f,0xa, 0x3, 0x9, 0x20,0x1e,0xdd,0xbe,0x20,0xb, 0x38,0x5, 0x4e,0x60, -0x8, 0x80,0xd, 0xbe,0x20,0x17,0x38,0x5, 0x4e,0x60,0x50,0x80,0x3, 0x4e,0x50,0x6, -0xb, 0x30,0x7e,0x23,0x1e,0x8f,0xbc,0x23,0x38,0xd9,0x22,0xca,0xf8,0x7e,0x73,0x1e, -0x90,0xbe,0x70,0x23,0x28,0x4, 0x7c,0xf7,0x80,0x3, 0x7e,0xf0,0x23,0x74,0x10,0x7a, -0xb3,0x1e,0x89,0x74,0x23,0x7a,0xb3,0x1e,0x8a,0x74,0x10,0x7a,0xb3,0x1e,0x8d,0x74, -0x23,0x7a,0xb3,0x1e,0x8e,0x74,0x10,0x7a,0xb3,0x1e,0x8f,0x74,0x23,0x7a,0xb3,0x1e, -0x90,0xe4,0x7a,0xb3,0x1e,0x93,0x74,0x10,0x7a,0xb3,0x1e,0x8b,0x74,0x23,0x7a,0xb3, -0x1e,0x8c,0x7e,0x73,0x38,0x99,0x7a,0x73,0x1e,0x94,0x7e,0x73,0x38,0x9c,0x7a,0x73, -0x1e,0x95,0x7e,0x34,0x0, 0x10,0xca,0x39,0x7e,0x18,0x38,0x52,0x7e,0x8, 0x1e,0x96, -0x12,0x1d,0xae,0x1b,0xfd,0xa, 0x3f,0xca,0x39,0x7e,0x18,0x38,0x75,0x7e,0x8, 0x1e, -0xb9,0x12,0x1d,0xae,0x1b,0xfd,0x7e,0x34,0x0, 0x23,0xca,0x39,0x7e,0x18,0x38,0xe0, -0x7e,0x8, 0x1f,0x4f,0x12,0x1d,0xae,0x1b,0xfd,0xd1,0x25,0x12,0x68,0x8d,0x12,0x5f, -0x98,0x74,0x1, 0x12,0x31,0xaa,0xe4,0x7a,0xb3,0x1f,0x2d,0x7a,0xb3,0x1f,0x2e,0x91, -0x2e,0x7a,0x1f,0x1f,0x39,0x74,0x3, 0x7a,0xb3,0x1f,0x2f,0xe4,0x7a,0xb3,0x1f,0x30, -0x74,0x2, 0x7a,0xb3,0x1f,0x31,0x7e,0x34,0x0, 0xa0,0x7a,0x37,0x1f,0x33,0x74,0x4, -0x7a,0xb3,0x1f,0x32,0x7e,0x34,0x0, 0xf, 0x7a,0x37,0x1f,0x35,0x7e,0x34,0x20,0x5f, -0x7a,0x37,0x1f,0x37,0x74,0x18,0x7a,0xb3,0x1f,0x98,0x74,0x1, 0x7a,0xb3,0x1f,0x3e, -0x74,0x20,0x7a,0xb3,0x1f,0x3f,0x74,0x4, 0x7a,0xb3,0x1f,0x41,0x74,0x3b,0x7a,0xb3, -0x1f,0x3d,0x12,0x3e,0xc9,0xe4,0x7a,0xb3,0x1f,0x4b,0x7a,0xb3,0x1f,0x4c,0x7e,0x34, -0x1, 0xf4,0x7a,0x37,0x1f,0x47,0x74,0x1, 0x7a,0xb3,0x1f,0x40,0x74,0x40,0x7a,0xb3, -0x1f,0x4e,0x74,0x2f,0x7a,0xb3,0x1f,0x4d,0x6d,0x33,0x7a,0x37,0x1f,0x43,0x7a,0x37, -0x1f,0x45,0xe4,0x7a,0xb3,0x1f,0x42,0x7e,0x24,0x0, 0x30,0x7a,0x27,0x1f,0xa0,0x74, -0x4, 0x7a,0xb3,0x1f,0x9d,0x7a,0x37,0x1f,0x9e,0xe4,0x7a,0xb3,0x1f,0x9c,0x7e,0x34, -0x4, 0x2d,0x7a,0x37,0x1f,0xa2,0x7a,0xb3,0x1f,0x99,0x7a,0xb3,0x1f,0x9a,0x7a,0xb3, -0x1f,0x9b,0x74,0x1, 0x7a,0xb3,0x1f,0x96,0xe4,0x7a,0xb3,0x1f,0x97,0x7e,0x34,0x1d, -0x5a,0x7a,0x37,0x1f,0xa4,0x74,0x18,0x7a,0xb3,0x1f,0xa6,0x7e,0x34,0x1d,0x72,0x7a, -0x37,0x1f,0xb8,0x74,0x6, 0x7a,0xb3,0x1f,0xba,0x74,0x1, 0x7a,0xb3,0x1f,0xbb,0x7e, -0x34,0x0, 0x23,0xca,0x39,0x7e,0x18,0x39,0x3, 0x7e,0x8, 0x1f,0x72,0x12,0x1d,0xae, -0x1b,0xfd,0xda,0xf8,0x22,0x7e,0x8, 0x0, 0x26,0x7e,0x18,0x0, 0x25,0xf1,0x65,0x7e, -0x8, 0x1e,0xa6,0x7e,0xb3,0x1e,0xa5,0x7e,0x34,0x0, 0x2, 0x12,0x1d,0xd3,0x7e,0x8, -0x1f,0x5f,0x7e,0xb3,0x1f,0x5e,0x7e,0x34,0x0, 0x2, 0xd1,0x61,0x1b,0x35,0x7e,0x8, -0x1e,0xa8,0xe5,0x26,0xd1,0x61,0x1b,0x35,0x7e,0x8, 0x1f,0x61,0xe5,0x25,0x2, 0x1d, -0xd3,0x12,0x1d,0xd3,0x7e,0x73,0x38,0x99,0xa, 0x37,0x22,0xca,0x79,0x7e,0xe3,0x1e, -0x8a,0x7e,0x73,0x3c,0x2, 0x4c,0x77,0x78,0x2, 0xe1,0x17,0x7e,0xa4,0x2, 0xb6,0x1e, -0xa4,0x3e,0xa4,0xf1,0x1a,0x7d,0xba,0x7a,0xb7,0x2, 0xb0,0xe4,0x7a,0xb3,0x2, 0xaa, -0x7a,0xb3,0x2, 0xab,0xd1,0x64,0x7e,0x53,0x1e,0x89,0xa, 0x25,0x2d,0x23,0xa, 0x3e, -0xad,0x32,0x7d,0xb3,0x3e,0xb4,0x7e,0x1f,0x3d,0xf9,0x2d,0x3b,0x7d,0xb3,0x7a,0xb7, -0x2, 0xac,0x7e,0xb4,0x0, 0x20,0x7a,0xb7,0x2, 0xb2,0x7e,0x8, 0x2, 0xa8,0x12,0x12, -0x78,0x6c,0xff,0x80,0x19,0x7c,0x3f,0xac,0x3e,0x3e,0x14,0x2d,0x1a,0x6d,0x0, 0x7c, -0xbe,0x12,0xa3,0xe4,0x74,0x2, 0xac,0xbf,0x59,0x35,0x3, 0x8e,0xb, 0xf0,0x7e,0x73, -0x3c,0x2, 0xbc,0x7f,0x38,0xdf,0x6c,0xff,0x80,0x25,0xbe,0xf0,0x4, 0x50,0x28,0xa, -0x3f,0x9, 0x63,0x3c,0x5, 0xbe,0x60,0x4, 0x50,0x13,0x74,0x2, 0xac,0xbf,0x49,0x45, -0x3, 0x8e,0x7e,0x70,0xc, 0x7c,0xb6,0xac,0xb7,0x59,0x45,0x3c,0x11,0xb, 0xf0,0x7e, -0x73,0x3c,0x2, 0xbc,0x7f,0x38,0xd3,0xda,0x79,0x22,0x7a,0x73,0x2, 0xa8,0x7e,0x73, -0x1e,0x8a,0x7a,0x73,0x2, 0xa9,0x22,0x7e,0xb3,0x1f,0x4b,0xb4,0x1, 0x2f,0xf1,0x5e, -0x7e,0x1f,0x3d,0xf9,0x7a,0x37,0x2, 0xb0,0x7e,0x34,0xf, 0x5c,0x7a,0x37,0x2, 0xac, -0x7e,0x73,0x1e,0x89,0xf1,0x1a,0x7a,0xb3,0x2, 0xab,0x7e,0x34,0x0, 0x20,0x7a,0x37, -0x2, 0xb2,0x7a,0xb3,0x2, 0xaa,0x7e,0x8, 0x2, 0xa8,0x2, 0x12,0x78,0x22,0xa9,0xd1, -0xcb,0xe4,0x2, 0xf, 0xe9,0x7f,0x71,0x6c,0xaa,0xe4,0xa, 0x4b,0x9, 0x74,0x1e,0x96, -0xbc,0x7a,0x68,0x6, 0x4, 0xbe,0xb0,0x10,0x40,0xf0,0xbe,0xb0,0x10,0x68,0x7, 0xb, -0xa0,0xbe,0xa0,0x23,0x40,0xe3,0x7a,0xb, 0xa0,0x74,0x6e,0x7a,0x7b,0xb0,0x22,0x7c, -0x5b,0x7d,0x13,0x7a,0x53,0x2, 0xa8,0xf1,0x1e,0x7a,0x17,0x2, 0xb0,0xe4,0x7a,0xb3, -0x2, 0xaa,0x7a,0xb3,0x2, 0xab,0x7e,0x34,0x80,0x0, 0x7a,0x37,0x2, 0xac,0x7e,0x34, -0x0, 0x20,0x12,0x57,0xc7,0x2, 0x12,0x78,0x12,0x57,0xb7,0x7e,0x34,0xf, 0x5c,0x7e, -0xb3,0x1e,0x89,0xf1,0x8f,0xf1,0xd2,0x7a,0x37,0x3d,0xf5,0x74,0x1, 0x7a,0xb3,0x18, -0xcf,0x22,0x12,0xcd,0xf0,0x6d,0x22,0x7e,0x33,0x1f,0x4d,0xa, 0x13,0x6d,0x0, 0x12, -0x1b,0x1f,0x74,0x6, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4, -0x22,0x7e,0x54,0x0, 0x4e,0x7e,0x44,0x0, 0xff,0x69,0x32,0x0, 0x4, 0x69,0x22,0x0, -0x2, 0xb, 0x2a,0x10,0x7a,0x1d,0x27,0x7a,0x15,0x25,0x7e,0x34,0x0, 0x20,0x7e,0x8, -0x0, 0x25,0x7e,0x24,0x0, 0x6, 0x12,0x0, 0x46,0x74,0x32,0x7a,0xb3,0x3c,0xe2,0x74, -0x25,0x7a,0xb3,0x3c,0xe3,0x74,0xa, 0x7a,0xb3,0x3c,0xe4,0x7a,0xb3,0x3c,0xe5,0x7a, -0xb3,0x3c,0xe6,0x74,0x80,0x7a,0xb3,0x3c,0xe7,0x7e,0x34,0x0, 0x59,0xca,0x39,0x7e, -0x18,0x39,0x81,0x7e,0x8, 0x3c,0xe8,0x12,0x1d,0xae,0x1b,0xfd,0xe5,0x26,0x7a,0xb3, -0x3d,0x13,0xe5,0x29,0x7a,0xb3,0x3d,0x2, 0x22,0x7e,0x8, 0x19,0x3f,0x7e,0x34,0x3, -0x2a,0xe4,0x12,0x1d,0xd3,0x7e,0x8, 0x19,0x70,0x7e,0x34,0x0, 0xc8,0x74,0xff,0x12, -0x1d,0xd3,0x7e,0x8, 0x19,0x98,0x7e,0x34,0x0, 0xc8,0x12,0x1d,0xd3,0x7e,0x63,0x38, -0xa2,0x7e,0x70,0xa, 0xac,0x67,0x7e,0x8, 0x1a,0xf0,0x2, 0x1d,0xd3,0xca,0xf8,0x7e, -0x73,0x1e,0x94,0xa, 0x47,0x7e,0x73,0x1e,0x8d,0xa, 0x57,0x2d,0x54,0x7e,0xa3,0x1e, -0x8f,0xbc,0xab,0x28,0x2, 0x7c,0xba,0x7e,0xf3,0x1e,0x8e,0x7e,0xa3,0x1e,0x90,0xbc, -0xaf,0x28,0x2, 0x7c,0xfa,0x75,0x25,0xb, 0x7e,0x8, 0x1e,0xdd,0x7e,0x18,0x1e,0x96, -0x12,0x15,0xfd,0x75,0x25,0xb, 0x7e,0x8, 0x1f,0x0, 0x7e,0x18,0x1e,0xb9,0x7c,0xbf, -0x12,0x16,0x47,0xda,0xf8,0x22,0x7f,0x71,0x7f,0x60,0x7e,0xb3,0x1e,0x89,0x7e,0x73, -0x1e,0x8a,0xac,0xb7,0x7d,0xb5,0x3e,0xb4,0x7f,0x7, 0x7d,0x3b,0xe4,0x12,0x1d,0xd3, -0x7f,0x6, 0x7d,0x3b,0x12,0x1d,0xd3,0x7a,0xb3,0x18,0xcf,0x22,0x7f,0x71,0x7f,0x60, -0x7e,0x73,0x1e,0x90,0xa, 0x47,0x7e,0x73,0x1e,0x8f,0xa, 0x57,0x2d,0x54,0x3e,0x54, -0x7c,0xab,0xe4,0x7a,0xb3,0x18,0xce,0x7f,0x7, 0xa, 0x3a,0x12,0x1d,0xd3,0x7f,0x6, -0xa, 0x3a,0x2, 0x1d,0xd3,0x7f,0x71,0x7f,0x20,0x6d,0x33,0x80,0xc, 0xb, 0x7a,0x20, -0xb, 0xf5,0x1b,0x2a,0x20,0xb, 0x55,0xb, 0x34,0x7e,0x25,0x34,0xbd,0x23,0x38,0xed, -0x22,0xca,0x79,0x7f,0x51,0x7f,0x60,0x7e,0x73,0x1e,0x90,0xa, 0x37,0x7e,0x53,0x1e, -0x8f,0xa, 0x75,0x2d,0x73,0xa, 0x3f,0x7a,0x35,0x34,0x7f,0x6, 0x7e,0x1d,0x29,0x31, -0x25,0x7e,0xb3,0x1f,0x2d,0xb4,0x1, 0x22,0x6c,0x77,0x80,0x1a,0x7e,0x90,0x2, 0xac, -0x97,0x7f,0x5, 0x2d,0x14,0xb, 0xa, 0x50,0x7f,0x6, 0x2d,0x14,0xb, 0xa, 0x20,0x9d, -0x25,0x1b,0xa, 0x20,0xb, 0x70,0xbc,0xf7,0x38,0xe2,0xda,0x79,0x22,0xca,0x3b,0x7f, -0x61,0x7f,0x50,0x7e,0x14,0x0, 0x26,0x7e,0x4, 0x0, 0xff,0x69,0x30,0x0, 0x2, 0xb, -0xa, 0x20,0x7a,0x1d,0x30,0x7e,0x73,0x1e,0x89,0xa, 0x37,0x7a,0x35,0x34,0x7f,0x5, -0x7f,0x16,0x31,0x25,0x6c,0xdd,0x7e,0xf4,0x7f,0xff,0x75,0x2f,0x0, 0x9f,0x44,0xe4, -0x7a,0xb3,0x2, 0xa8,0x6c,0xcc,0x80,0x57,0x51,0xdb,0xbc,0xab,0x40,0x4f,0x51,0xca, -0xbc,0xab,0x50,0x49,0x51,0xd2,0xb, 0x1a,0x10,0x7d,0x3f,0x12,0x1e,0x5, 0x7d,0x3, -0x7d,0x31,0x12,0x1e,0x5, 0xbd,0x30,0x58,0x2, 0x7d,0xf1,0xbe,0x15,0x2d,0x8, 0x5, -0x7e,0x15,0x2d,0x80,0xb, 0x6d,0x0, 0x9e,0x5, 0x2d,0xbd,0x1, 0x8, 0x2, 0x7d,0x10, -0x7d,0x31,0x1a,0x26,0x1a,0x24,0x2f,0x41,0x7e,0xb3,0x2, 0xa8,0x4, 0x7a,0xb3,0x2, -0xa8,0xbe,0x14,0x0, 0x0, 0x48,0x4, 0x5, 0x2f,0x80,0x2, 0x15,0x2f,0xb, 0xc0,0x7e, -0x73,0x1e,0x8b,0xbc,0x7c,0x38,0xa1,0x7e,0x73,0x2, 0xa8,0x4c,0x77,0x78,0x2, 0x41, -0xbe,0xa, 0x17,0xf1,0x6e,0x7d,0x73,0x12,0x1e,0x5, 0x7d,0xe3,0x7d,0x3f,0x12,0x1e, -0x5, 0xbd,0x3e,0x8, 0x13,0xe5,0x2f,0x1a,0x3b,0x12,0x1e,0x5, 0x7e,0x53,0x2, 0xa8, -0xa, 0x25,0xbd,0x32,0x78,0x2, 0x7d,0x7f,0xbe,0x75,0x2d,0x8, 0x5, 0x7e,0x75,0x2d, -0x80,0xb, 0x6d,0xee,0x9e,0xe5,0x2d,0xbd,0xe7,0x8, 0x2, 0x7d,0x7e,0x6c,0xcc,0x80, -0x45,0x51,0xdb,0xbc,0xab,0x40,0x3d,0x51,0xca,0xbc,0xab,0x50,0x37,0x51,0xd2,0xb, -0x1a,0x40,0xbe,0x44,0x0, 0x0, 0x48,0x13,0xbd,0x47,0x58,0xf, 0x6d,0xee,0x74,0x2, -0xac,0xbc,0x7f,0x15,0x2d,0x35,0x1b,0x1a,0xe0,0x80,0x19,0xbe,0x44,0x0, 0x0, 0x58, -0x6, 0xbe,0x74,0x0, 0x0, 0x18,0xd, 0x9d,0x47,0x74,0x2, 0xac,0xbc,0x7f,0x15,0x2d, -0x35,0x1b,0x1a,0x40,0xb, 0xc0,0x7e,0x73,0x1e,0x8b,0xbc,0x7c,0x38,0xb3,0xb, 0xd0, -0xbe,0xd0,0x3, 0x50,0x2, 0x21,0xb6,0xda,0x3b,0x22,0x7c,0x1d,0x2e,0x10,0x31,0xa5, -0xe7,0x22,0x74,0x2, 0xac,0xbc,0x7f,0x16,0x2d,0x35,0x22,0xa, 0xec,0x9, 0xae,0x1e, -0xdd,0x7c,0x1d,0x2e,0x10,0x30,0xa5,0xe7,0x22,0xca,0x3b,0x7f,0x71,0x7f,0x60,0x6d, -0xbb,0x6c,0xff,0x7e,0x54,0x7f,0xff,0x7a,0x55,0x2f,0x6c,0xee,0x9f,0x44,0x6c,0xdd, -0x6c,0xcc,0x80,0x4e,0x71,0xe8,0x78,0x48,0x71,0xdc,0x7d,0x5a,0xf1,0xc0,0x2d,0xb5, -0x7e,0x35,0x2f,0x12,0x1e,0x5, 0x7d,0x53,0x7d,0x3a,0x12,0x1e,0x5, 0xbd,0x35,0x58, -0x3, 0x7a,0xa5,0x2f,0x7e,0x55,0x2d,0xbd,0x5a,0x58,0x4, 0x7d,0xa5,0x80,0xb, 0x6d, -0x55,0x9e,0x55,0x2d,0xbd,0x5a,0x8, 0x2, 0x7d,0xa5,0x7d,0x3a,0x1a,0x26,0x1a,0x24, -0x2f,0x41,0xb, 0xd0,0xbe,0xa4,0x0, 0x0, 0x48,0x4, 0xb, 0xe0,0x80,0x2, 0x1b,0xe0, -0xb, 0xc0,0x7e,0x73,0x1e,0x8c,0xbc,0x7c,0x38,0xaa,0x4c,0xdd,0x68,0x70,0xa, 0x1d, -0xf1,0x6e,0x7d,0x43,0x12,0x1e,0x5, 0x7d,0x53,0x7e,0x35,0x2f,0x12,0x1e,0x5, 0xbd, -0x35,0x8, 0xe, 0x1a,0x3e,0x12,0x1e,0x5, 0xa, 0x2d,0xbd,0x32,0x78,0x3, 0x7e,0x45, -0x2f,0x6c,0xcc,0x80,0x41,0x7e,0x70,0x2, 0xac,0x7c,0x7f,0x7, 0x2d,0x13,0xb, 0xa, -0x50,0x2d,0x3d,0x7d,0x2c,0x1b,0x1a,0x50,0x71,0xe8,0x78,0x28,0x71,0xdc,0xbe,0xa4, -0x0, 0x0, 0x48,0xd, 0xbd,0xa4,0x58,0x9, 0x6d,0x11,0x51,0xd2,0x1b,0x1a,0x10,0x80, -0x13,0xbe,0xa4,0x0, 0x0, 0x58,0x6, 0xbe,0x44,0x0, 0x0, 0x18,0x7, 0x9d,0xa4,0x51, -0xd2,0x1b,0x1a,0xa0,0xb, 0xc0,0x7e,0x73,0x1e,0x8c,0xbc,0x7c,0x38,0xb7,0xb, 0xf0, -0xbe,0xf0,0x3, 0x50,0x2, 0x41,0xf3,0x7d,0x3b,0xda,0x3b,0x22,0x74,0x2, 0xac,0xbc, -0x7f,0x17,0x2d,0x35,0xb, 0x1a,0xa0,0x22,0xa, 0x5c,0x9, 0x75,0x1f,0x0, 0xa, 0x57, -0x9, 0x75,0x34,0xc0,0xbc,0x7f,0x22,0xca,0x3b,0x7f,0x31,0x7a,0xd, 0x25,0x7e,0x35, -0x29,0x7a,0x35,0x2d,0x7e,0xd, 0x25,0x7f,0x13,0x51,0xe9,0x7a,0x35,0x2b,0x30,0x7, -0x10,0x7e,0x35,0x29,0x7a,0x35,0x2d,0xf1,0xb8,0x91,0x29,0x7f,0x13,0x2d,0x35,0x31, -0x8d,0x7e,0x35,0x2b,0xda,0x3b,0x22,0x74,0x2, 0xac,0xb7,0x7e,0xd, 0x25,0x2d,0x15, -0x22,0xca,0xe8,0x7e,0x18,0x1d,0xae,0x7a,0x1d,0x25,0x6c,0x77,0x7e,0x60,0xff,0x74, -0xa, 0xac,0xb7,0x19,0x65,0x1c,0x86,0xe4,0xa, 0x27,0x19,0xb2,0x2, 0xa8,0x74,0xff, -0x19,0xb2,0x2, 0xba,0x19,0xb2,0x2, 0xc4,0xb, 0x70,0xa5,0xbf,0xa, 0xde,0x7e,0x63, -0x1d,0xea,0xa5,0xbe,0x0, 0x2e,0x7e,0xb3,0x37,0xc7,0x70,0x2, 0xc1,0xeb,0x6c,0x77, -0x7e,0x24,0x7f,0xff,0x91,0x27,0x79,0x20,0x0, 0x14,0x91,0x27,0x79,0x20,0x0, 0x28, -0x74,0x2, 0xac,0xb7,0x59,0x25,0x37,0xc8,0x59,0x25,0x37,0xdc,0xb, 0x70,0xa5,0xbf, -0xa, 0xde,0xc1,0xeb,0x7e,0xb3,0x37,0xc7,0x70,0x45,0xbe,0x60,0x0, 0x28,0x40,0x6c, -0x77,0x80,0x32,0x74,0xa, 0xac,0xb7,0x49,0x45,0x1c,0x82,0x91,0x27,0x79,0x40,0x0, -0x14,0x74,0xa, 0xac,0xb7,0x49,0x45,0x1c,0x84,0x91,0x27,0x79,0x40,0x0, 0x28,0x91, -0x27,0xf1,0xa3,0x74,0x1, 0xa, 0x27,0x19,0xb2,0x2, 0xa8,0x74,0xa, 0xac,0xb7,0x19, -0x75,0x1c,0x86,0xb, 0x70,0x7e,0x63,0x1d,0xea,0xbc,0x67,0x38,0xc6,0xc1,0xeb,0x6c, -0x77,0x7e,0x44,0x7f,0xff,0xf1,0x7d,0x59,0x45,0x17,0x8e,0x59,0x45,0x17,0xb4,0x59, -0x45,0x17,0xb6,0xb, 0x70,0xa5,0xbf,0xa, 0xe8,0x7e,0x63,0x37,0xc7,0xbe,0x63,0x1d, -0xea,0x28,0xd, 0xbe,0x60,0x2, 0x40,0x8, 0x74,0x1, 0x7a,0xb3,0x37,0xc6,0x80,0x5, -0xe4,0x7a,0xb3,0x37,0xc6,0x6c,0x77,0xa1,0xc3,0x6c,0xee,0x7e,0x50,0x2, 0xac,0x5e, -0x7e,0x7d,0x25,0x2d,0xf2,0x69,0x7, 0x0, 0x14,0xbe,0x4, 0x7f,0xff,0x78,0x2, 0xa1, -0xb8,0xa, 0x1e,0x9, 0xb1,0x2, 0xc4,0xb4,0xff,0x7e,0x49,0x52,0x37,0xc8,0xbe,0x54, -0x7f,0xff,0x68,0x54,0x49,0x22,0x37,0xc8,0x69,0x57,0x0, 0x14,0x7d,0x45,0x9d,0x42, -0x2d,0x45,0x74,0x2, 0xac,0xbe,0x49,0xd5,0x37,0xdc,0x69,0x57,0x0, 0x28,0x7d,0x25, -0x9d,0x2d,0x2d,0x25,0xbe,0x44,0x0, 0x80,0x58,0x4, 0x7e,0x44,0x0, 0x80,0xbe,0x24, -0x0, 0x80,0x58,0x4, 0x7e,0x24,0x0, 0x80,0x7e,0x63,0x1e,0x8b,0xf1,0x94,0xbd,0x54, -0x58,0x2, 0x7d,0x45,0x7e,0x63,0x1e,0x8c,0xf1,0x94,0xbd,0x52,0x58,0x2, 0x7d,0x25, -0xf1,0x7d,0x59,0x25,0x17,0x8e,0x80,0x12,0x74,0x2, 0xac,0xb7,0x3e,0x54,0x59,0x5, -0x17,0x8c,0x69,0x7, 0x0, 0x28,0x59,0x5, 0x17,0x8e,0xa, 0x7, 0x19,0xe0,0x2, 0xba, -0x74,0x1, 0x19,0xb1,0x2, 0xc4,0x80,0x9, 0xb, 0xe0,0xbe,0xe0,0xa, 0x50,0x2, 0xa1, -0x1b,0xb, 0x70,0x7e,0x63,0x37,0xc7,0xbc,0x67,0x28,0x2, 0xa1,0x19,0x6c,0x77,0x91, -0x27,0xf1,0xa3,0xb, 0x70,0xa5,0xbf,0xa, 0xf6,0x6c,0x77,0xa, 0x27,0x9, 0xb2,0x2, -0xba,0xb4,0xff,0x20,0x6c,0xee,0xa, 0x2e,0x9, 0xb2,0x2, 0xc4,0xb4,0xff,0xe, 0xa, -0x17,0x19,0xe1,0x2, 0xba,0x74,0x1, 0x19,0xb2,0x2, 0xc4,0x80,0x7, 0xb, 0xe0,0xbe, -0xe0,0xa, 0x40,0xe2,0xb, 0x70,0xa5,0xbf,0xa, 0xd1,0x6c,0x77,0x80,0x1e,0x7e,0x10, -0xa, 0xac,0x17,0x49,0x40,0x1c,0x82,0x7e,0x30,0x2, 0xac,0x37,0x3e,0x14,0x59,0x41, -0x17,0xb4,0x49,0x20,0x1c,0x84,0x59,0x21,0x17,0xb6,0xb, 0x70,0x7e,0x63,0x1d,0xea, -0xbc,0x67,0x38,0xda,0x7e,0x34,0x17,0x8c,0x7a,0x37,0x2, 0xb4,0x7e,0x34,0x17,0xb4, -0x7a,0x37,0x2, 0xb6,0x7e,0x34,0x17,0xdc,0x7a,0x37,0x2, 0xb8,0x7e,0x73,0x37,0xc7, -0x7a,0x73,0x2, 0xb2,0x7e,0x73,0x1d,0xea,0x7a,0x73,0x2, 0xb3,0x7e,0x8, 0x2, 0xb2, -0x12,0x6, 0x62,0x6c,0x77,0x80,0x59,0x7e,0x60,0xff,0x6c,0xee,0x74,0x2, 0xac,0xbe, -0x49,0x15,0x17,0xdc,0xa, 0x27,0xbd,0x21,0x78,0x8, 0xa, 0x2e,0x9, 0x62,0x2, 0xba, -0x80,0x7, 0xb, 0xe0,0xbe,0xe0,0xa, 0x40,0xe3,0xbe,0x60,0xff,0x68,0x30,0x74,0xa, -0xac,0xb7,0x19,0x65,0x1c,0x86,0x74,0x1, 0xa, 0x26,0x19,0xb2,0x2, 0xa8,0x74,0xa, -0xac,0xb7,0x49,0x25,0x1c,0x82,0xf1,0x75,0x2d,0x15,0x79,0x20,0x0, 0x14,0x74,0xa, -0xac,0xb7,0x49,0x25,0x1c,0x84,0xf1,0x75,0x2d,0x15,0x79,0x20,0x0, 0x28,0xb, 0x70, -0x7e,0x53,0x1d,0xea,0xbc,0x57,0x38,0x9f,0x6c,0x77,0xa, 0x27,0x9, 0xb2,0x2, 0xa8, -0xbe,0xb0,0x1, 0x68,0x10,0x7e,0x44,0x7f,0xff,0x91,0x27,0x79,0x40,0x0, 0x14,0x91, -0x27,0x79,0x40,0x0, 0x28,0xb, 0x70,0xa5,0xbf,0xa, 0xdf,0x7e,0xe3,0x1d,0xea,0x7a, -0xe3,0x37,0xc7,0x6c,0x77,0xa, 0x27,0x9, 0xb2,0x2, 0xa8,0xb4,0x1, 0x36,0xf1,0x88, -0xb4,0x1, 0x6, 0x74,0x3, 0x39,0xb0,0x0, 0xa, 0xa, 0x27,0x7e,0xd, 0x25,0x2d,0x12, -0x29,0x60,0x0, 0xa, 0xa5,0xbe,0x3, 0x6, 0xe4,0x7a,0xb, 0xb0,0x80,0x38,0xa5,0xbe, -0x0, 0x7, 0x74,0x2, 0x7a,0xb, 0xb0,0x80,0x2d,0xa5,0xbe,0x2, 0x29,0x74,0x2, 0x7a, -0xb, 0xb0,0x80,0x22,0xf1,0x88,0xbe,0xb0,0x2, 0x68,0x2, 0x70,0x14,0x74,0x1, 0x7a, -0xb, 0xb0,0x7c,0xae,0xb, 0xe0,0x7e,0x60,0xa, 0xac,0xa6,0x19,0x75,0x1c,0x86,0x80, -0x5, 0x74,0x3, 0x7a,0xb, 0xb0,0xa, 0x27,0x7e,0xd, 0x25,0x2d,0x12,0x7e,0xb, 0x60, -0x39,0x60,0x0, 0xa, 0xb, 0x70,0xbe,0x70,0xa, 0x40,0x8a,0xda,0xe8,0x22,0x6d,0x0, -0x7f,0x14,0x2, 0x1b,0x8c,0x74,0x2, 0xac,0xb6,0x7e,0xd, 0x25,0x22,0x74,0x2, 0xac, -0xb7,0x3e,0x54,0x59,0x45,0x17,0x8c,0x22,0xa, 0x27,0x7e,0xd, 0x25,0x2d,0x12,0x29, -0xb0,0x0, 0xa, 0x22,0xa, 0xc6,0x7e,0xd4,0x1, 0x0, 0xad,0xdc,0x7d,0x5d,0x9e,0x54, -0x0, 0x80,0x22,0x69,0x20,0x0, 0x14,0x59,0x25,0x37,0xc8,0x69,0x40,0x0, 0x28,0x74, -0x2, 0xac,0xb7,0x59,0x45,0x37,0xdc,0x22,0x7e,0xb3,0x1e,0x90,0x7e,0x70,0x2, 0x22, -0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0xe, 0x54,0x22,0xca,0x7b,0xca,0x2b,0xca, -0x1b,0xca,0xb, 0xc0,0x83,0xc0,0x82,0x12,0x71,0x2b,0xd0,0x82,0xd0,0x83,0xda,0xb, -0xda,0x1b,0xda,0x2b,0xda,0x7b,0x32,0xa9,0xc0,0x93,0x75,0x76,0x0, 0x32,0x7c,0x7b, -0x7a,0x73,0x3d,0x41,0x7c,0xb7,0xc4,0x54,0x7, 0xbe,0xb0,0x4, 0x68,0x3, 0xb4,0x2, -0x4, 0x74,0x3, 0x80,0x7, 0x60,0x3, 0xb4,0x1, 0x7, 0x74,0x1, 0x7a,0xb3,0x3d,0x9, -0x22,0x74,0x1, 0x7a,0xb3,0x3d,0x9, 0xe4,0x7a,0xb3,0x3d,0x41,0x22,0x7e,0xb3,0x3d, -0x92,0xbe,0xb0,0x9, 0x50,0x10,0x4, 0x7a,0xb3,0x3d,0x92,0x7e,0x73,0x3d,0x92,0xa, -0x37,0x9, 0xb3,0x34,0x22,0x22,0x74,0xff,0x22,0x7c,0xab,0xbe,0xa0,0x9a,0x78,0x5, -0x7e,0xb3,0x3e,0x23,0x22,0xbe,0xa0,0x9b,0x78,0x5, 0x7e,0xb3,0x3e,0x24,0x22,0x4c, -0xaa,0x78,0x5, 0x7e,0xb3,0x3d,0x41,0x22,0xbe,0xa0,0x3, 0x38,0x15,0x75,0x7a,0x0, -0x20,0x14,0x20,0x51,0xcd,0x6d,0x22,0xbe,0x18,0x0, 0x0, 0x68,0x16,0x7a,0x1d,0x15, -0x80,0x11,0xbe,0xa0,0x5e,0x38,0x19,0x75,0x7a,0x0, 0xbe,0xa0,0x3e,0x78,0x4, 0x31, -0x78,0xc2,0x14,0xa, 0x1a,0x7e,0x1d,0x15,0x2d,0x31,0x1b,0x34,0x7e,0x1b,0xb0,0x22, -0xbe,0xa0,0xa0,0x78,0x3, 0x74,0xb, 0x22,0xbe,0xa0,0x80,0x40,0xc, 0xbe,0xa0,0xdf, -0x38,0x7, 0xa, 0x3a,0x9, 0xb3,0x3c,0x62,0x22,0xbe,0xa0,0xe1,0x68,0x5, 0xbe,0xa0, -0xe2,0x78,0x10,0xbe,0xa0,0xe1,0x78,0x7, 0xe4,0x7a,0xb3,0x3d,0x92,0x80,0x2, 0x15, -0x77,0x1, 0x1d,0xbe,0xa0,0xeb,0x68,0x5, 0xbe,0xa0,0xec,0x78,0x4, 0x7c,0xba,0x21, -0xaa,0xbe,0xa0,0xee,0x78,0x5, 0x7e,0xb3,0x1d,0xf6,0x22,0xbe,0xa0,0xfc,0x78,0x5, -0x7e,0xb3,0x3d,0x9, 0x22,0xbe,0xa0,0xfd,0x78,0x17,0x6c,0xaa,0x7e,0xb3,0x1c,0x7c, -0x60,0x3, 0x7e,0xa0,0x1, 0x7e,0xb3,0x3c,0x0, 0x60,0x3, 0x4e,0xa0,0x2, 0x7c,0xba, -0x22,0xbe,0xa0,0xfe,0x78,0x5, 0x7e,0xb3,0x1f,0x3d,0x22,0x74,0xff,0x22,0x7c,0xab, -0x6c,0x77,0x31,0x70,0x78,0x8, 0x7c,0xba,0x11,0x39,0x7c,0x7b,0x80,0xa, 0xb4,0x4, -0x7, 0x7c,0xba,0x12,0x27,0xfa,0x7c,0x7b,0x7c,0xb7,0x22,0x30,0x90,0x1b,0xc2,0x90, -0xe5,0x76,0x70,0x9, 0x75,0x76,0x1, 0xe5,0x91,0xf5,0x77,0x80,0x13,0x7e,0x71,0x91, -0xe5,0x77,0x31,0x57,0x5, 0x77,0x75,0x76,0x2, 0x30,0x91,0xa, 0xc2,0x91,0x5, 0x77, -0xe5,0x77,0x31,0xe, 0xf5,0x91,0x22,0x7c,0xa7,0x7c,0x7b,0x31,0x70,0x78,0x6, 0x7c, -0xb7,0x7c,0x7a,0x21,0xde,0xb4,0x4, 0x7, 0x7c,0xb7,0x7c,0x7a,0x2, 0x2f,0xfa,0x22, -0x7e,0xb3,0x3d,0x41,0xc4,0x54,0x7, 0x22,0xc2,0xaf,0x7e,0x73,0x34,0x38,0xbe,0x70, -0x0, 0x28,0x22,0x7e,0xb3,0x34,0x2c,0x4, 0x7a,0xb3,0x34,0x2c,0x7e,0x73,0x34,0x2c, -0xbe,0x70,0x4, 0x40,0x5, 0xe4,0x7a,0xb3,0x34,0x2c,0x7e,0xb3,0x34,0x38,0x14,0x7a, -0xb3,0x34,0x38,0x80,0x2, 0x51,0x84,0xd2,0xaf,0x22,0x7c,0x7b,0xa5,0xbf,0xeb,0x5, -0xe4,0x7a,0xb3,0x3d,0x97,0x7e,0x73,0x3d,0x97,0xa, 0x27,0x2e,0x24,0x0, 0x15,0x51, -0x77,0x7c,0xab,0x7c,0xb7,0x4, 0x7a,0xb3,0x3d,0x97,0xb4,0x3, 0xb, 0xe4,0x7a,0xb3, -0x3d,0x97,0x6d,0x33,0x7a,0x37,0x3d,0x95,0x75,0x77,0xeb,0x7c,0xba,0x22,0x7c,0x47, -0x7c,0x5b,0xa5,0xbd,0x0, 0x7, 0x7c,0xb4,0x12,0x6f,0xee,0x80,0x7a,0xbe,0x50,0xeb, -0x68,0x4, 0xa5,0xbd,0xec,0x8, 0x7c,0xb5,0x7c,0x74,0x51,0x8d,0x80,0x69,0xa5,0xbd, -0xee,0x6, 0x7a,0x43,0x1d,0xf6,0x80,0x5f,0xbe,0x50,0x80,0x40,0x5a,0xbe,0x50,0xdf, -0x38,0x55,0x7c,0xb5,0x24,0x80,0x7c,0x74,0x51,0xf0,0xa5,0xbd,0xd1,0x1a,0x7e,0xb3, -0x3d,0x31,0x54,0xfe,0x7a,0xb3,0x3d,0x31,0x7c,0xb4,0xc4,0x7c,0x7b,0x5e,0x70,0x1, -0x4e,0x73,0x3d,0x31,0x7a,0x73,0x3d,0x31,0xa5,0xbd,0x81,0x16,0xbe,0x40,0x23,0x50, -0x4, 0x74,0x23,0x80,0x7, 0xbe,0x40,0x28,0x28,0x17,0x74,0x28,0x7a,0xb3,0x3c,0xe3, -0x80,0xf, 0xa5,0xbd,0x85,0xb, 0xbe,0x40,0x40,0x50,0x6, 0x74,0x40,0x7a,0xb3,0x3c, -0xe7,0xa5,0xbd,0xd0,0x2, 0xc2,0x18,0xa5,0xbd,0xfc,0x5, 0x7c,0xb4,0x2, 0x36,0x60, -0x74,0x1, 0x7a,0xb3,0x3, 0xff,0x22,0x7a,0x51,0x82,0x7a,0x41,0x83,0xe4,0x93,0x22, -0x7a,0xb3,0x34,0x38,0x7e,0x73,0x34,0x2d,0x7a,0x73,0x34,0x2c,0x22,0x7c,0xa7,0xbe, -0xb0,0xeb,0x68,0x3, 0xb4,0xec,0x35,0x7e,0x37,0x3d,0x95,0x4d,0x33,0x78,0xf, 0xbe, -0xa0,0xaa,0x78,0xa, 0x7e,0x34,0x0, 0x1, 0x7a,0x37,0x3d,0x95,0x15,0x77,0x7e,0x37, -0x3d,0x95,0xbe,0x34,0x0, 0x1, 0x78,0x11,0xbe,0xa0,0x9, 0x78,0x6, 0x7e,0x34,0x0, -0x2, 0x80,0x2, 0x6d,0x33,0x7a,0x37,0x3d,0x95,0x75,0x77,0xea,0x22,0xc2,0xaf,0x7e, -0xb3,0x34,0x38,0x70,0xb, 0x74,0x64,0x7a,0xb3,0x34,0x39,0xd2,0xaf,0x6d,0x33,0x22, -0x7e,0x63,0x34,0x2c,0x7e,0x70,0x3e,0xac,0x67,0x2e,0x34,0x33,0x2b,0xd2,0xaf,0x22, -0x7c,0xa7,0x7c,0x7b,0x2e,0x70,0xdd,0x68,0x26,0x2e,0x70,0xfd,0x68,0x21,0x1b,0x71, -0x68,0x1d,0x1b,0x72,0x68,0x19,0x1b,0x71,0x68,0x15,0x1b,0x70,0x68,0x11,0x2e,0x70, -0xa, 0x78,0x4, 0x7a,0xa3,0x3c,0xe1,0xa, 0x3b,0x19,0xa3,0x3c,0xe2,0xd2,0x16,0x22, -0xc2,0xaf,0x7e,0xb3,0x34,0x38,0x70,0x6, 0x74,0x64,0x7a,0xb3,0x34,0x39,0x7e,0x73, -0x34,0x38,0xbe,0x70,0x4, 0x50,0xb, 0x7e,0xb3,0x34,0x38,0x4, 0x7a,0xb3,0x34,0x38, -0x80,0x4, 0x74,0x1, 0x51,0x80,0x7e,0xb3,0x34,0x2d,0x4, 0x7a,0xb3,0x34,0x2d,0x7e, -0x73,0x34,0x2d,0xbe,0x70,0x4, 0x40,0x5, 0xe4,0x7a,0xb3,0x34,0x2d,0xd2,0xaf,0x22, -0xca,0xd8,0xca,0x79,0x75,0x25,0x0, 0x6c,0xff,0x75,0x26,0x0, 0x75,0x27,0x0, 0x75, -0x29,0x3, 0x6c,0xee,0x7e,0x58,0x1d,0xae,0x7e,0xb3,0x3d,0x32,0x70,0x3, 0x12,0x35, -0xdd,0x7e,0xb3,0x1d,0xf3,0x70,0xe, 0x7e,0xb3,0x1d,0xef,0x70,0x8, 0x7e,0xb3,0x1d, -0xf0,0x70,0x2, 0xa1,0xf6,0xd1,0x87,0x7d,0x93,0x6d,0x88,0x7f,0x4, 0x7e,0x34,0xff, -0xff,0x7e,0x24,0x0, 0x3e,0x12,0x59,0xa2,0x7e,0x73,0x1d,0xec,0x7a,0x4b,0x70,0x6c, -0x88,0xa1,0x8b,0x74,0xa, 0xac,0xb8,0x9, 0xd5,0x1c,0xea,0x7c,0xbd,0x54,0xf, 0xa, -0x3b,0xd1,0x3b,0xf5,0x29,0x7c,0xbd,0x54,0xf0,0xbe,0xb0,0x0, 0x28,0x2, 0xa1,0x89, -0xe5,0x29,0xbe,0xb0,0x3, 0x78,0x2, 0xa1,0x89,0x7e,0x8, 0x0, 0x29,0x7c,0xbd,0xf1, -0x2e,0x50,0x2, 0xa1,0x89,0x74,0xa, 0xac,0xb8,0x9, 0xb5,0x1c,0xeb,0xf5,0x26,0x74, -0xa, 0xac,0xb8,0x9, 0xb5,0x1c,0xec,0xf5,0x27,0xbe,0xb0,0xf, 0x28,0x3, 0x75,0x27, -0xf, 0xe5,0x27,0xc4,0x54,0xf0,0xf5,0x27,0x7e,0x93,0x1e,0x69,0xbc,0x9d,0x28,0x54, -0x7e,0xb3,0x1d,0xf1,0x70,0x28,0x75,0x2e,0xf, 0x7e,0x8, 0x0, 0x26,0xa, 0x3d,0x2e, -0x34,0x34,0x2e,0x6d,0x22,0x74,0x1, 0xd1,0x43,0x75,0x2e,0x20,0x7e,0x8, 0x0, 0x27, -0xa, 0x3d,0x2e,0x34,0x34,0x3a,0x6d,0x22,0x74,0x10,0xd1,0x43,0x80,0xe, 0xa, 0x3d, -0x9, 0xb3,0x34,0x2e,0xf5,0x26,0x9, 0xb3,0x34,0x3a,0xf5,0x27,0xa, 0x3d,0xd1,0x3b, -0xb4,0x1, 0x11,0xe4,0xa, 0x3d,0x19,0xb3,0x34,0x2e,0x19,0xb3,0x34,0x3a,0x75,0x26, -0x0, 0x75,0x27,0x0, 0x7e,0xb3,0x1e,0x80,0xb4,0xff,0x13,0x75,0x26,0x0, 0x74,0xa, -0xac,0xb8,0x9, 0xb5,0x1c,0xea,0xbe,0xb0,0xff,0x68,0x3, 0x75,0x26,0x1, 0x7e,0x70, -0xa, 0xac,0x78,0x49,0x13,0x1c,0xe6,0x7a,0x15,0x2a,0x49,0x23,0x1c,0xe8,0x7a,0x25, -0x2c,0xe5,0x29,0xb4,0x1, 0x2d,0x75,0x28,0x0, 0x7e,0x11,0x28,0x74,0xa, 0xac,0x1b, -0x9, 0xb0,0x34,0x48,0x54,0xf, 0xbc,0xbd,0x78,0x10,0x49,0x50,0x34,0x44,0x7a,0x55, -0x2a,0x49,0x0, 0x34,0x46,0x7a,0x5, 0x2c,0x80,0x9, 0x5, 0x28,0xe5,0x28,0xbe,0xb0, -0xa, 0x40,0xd6,0x7e,0x5, 0x2a,0x5e,0x0, 0xf, 0x7a,0x5, 0x2a,0x7e,0x5, 0x2c,0x5e, -0x0, 0xf, 0x7a,0x5, 0x2c,0x9, 0x93,0x1c,0xea,0xa, 0x59,0xc4,0x54,0xf0,0x7c,0xab, -0xe4,0x7d,0x5, 0x2e,0x5, 0x2c,0x7a,0x5, 0x2c,0xbe,0x90,0xff,0x68,0x53,0xe5,0x29, -0xbe,0xb0,0x1, 0x68,0x2, 0x5, 0x25,0xb, 0xf0,0xe5,0x29,0xa, 0x5b,0x3, 0x3, 0x54, -0xc0,0x7c,0xab,0xe4,0x7d,0x5, 0x2e,0x5, 0x2a,0x7a,0x5, 0x2a,0x7e,0xb3,0x3, 0xf5, -0xbe,0xb0,0xff,0x68,0x36,0xbe,0x93,0x3, 0xf5,0x78,0x30,0xa, 0x2, 0x7c,0x91,0x7a, -0x93,0x3, 0xf1,0x7c,0x93,0x7a,0x93,0x3, 0xf2,0xa, 0x14,0x7c,0x93,0x7a,0x93,0x3, -0xf3,0x7c,0x95,0x7a,0x93,0x3, 0xf4,0x9, 0x93,0x1c,0xec,0x7a,0x93,0x3, 0xf8,0x80, -0xa, 0x7e,0x35,0x2a,0x2e,0x34,0xc0,0x0, 0x7a,0x35,0x2a,0x7e,0x35,0x2a,0x74,0x6, -0xac,0xbe,0x7f,0x4, 0x2d,0x15,0x79,0x30,0x0, 0x2, 0x7e,0x35,0x2c,0x74,0x6, 0xac, -0xbe,0x7f,0x4, 0x2d,0x15,0x79,0x30,0x0, 0x4, 0x7e,0x91,0x26,0x74,0x6, 0xac,0xbe, -0x7f,0x14,0x2d,0x35,0x39,0x91,0x0, 0x6, 0x7e,0x91,0x27,0x74,0x6, 0xac,0xbe,0x7f, -0x14,0x2d,0x35,0x39,0x91,0x0, 0x7, 0xb, 0xe0,0xb, 0x80,0x7e,0x93,0x1e,0x69,0xbc, -0x98,0x28,0x2, 0x61,0xb3,0xe5,0x25,0x39,0xb4,0x0, 0x1, 0x7e,0xb3,0x3d,0x32,0xb4, -0x1, 0x1a,0x7e,0xb3,0x1d,0xf0,0xb4,0x1, 0x2, 0x80,0x24,0xa2,0xc, 0xe4,0x33,0x78, -0x22,0xc2,0xaf,0x12,0x5f,0xfa,0xd2,0xaf,0xd2,0xc, 0x80,0x17,0xc2,0xc, 0xbe,0xf0, -0x0, 0x38,0xc, 0x7e,0xb3,0x1d,0xf0,0x70,0x6, 0x7e,0xb3,0x1d,0xf5,0x60,0x4, 0xd1, -0xe5,0x71,0x20,0x7e,0xb3,0x1d,0xef,0x60,0xa, 0x7e,0xb3,0x3b,0xf2,0x70,0x4, 0x7f, -0x5, 0xd1,0xaa,0xe4,0x7a,0xb3,0x1d,0xf3,0x7a,0xb3,0x1d,0xef,0x7a,0xb3,0x1d,0xf0, -0x7a,0xb3,0x1d,0xf5,0x80,0x1a,0x7e,0xb3,0x3e,0x28,0xb4,0x1, 0x13,0x7e,0x73,0x3d, -0x7, 0xbe,0x70,0x2, 0x50,0xa, 0x74,0x1, 0x12,0x27,0x7b,0xe4,0x7a,0xb3,0x3e,0x28, -0xd2,0x6, 0x12,0x27,0x87,0x12,0x54,0x8e,0x7e,0x8, 0x34,0x44,0x7e,0x18,0x1c,0xe6, -0x12,0x4d,0x9b,0x4c,0xff,0x78,0xf, 0x7e,0x8, 0x34,0x44,0x7e,0x34,0xff,0xff,0x7e, -0x24,0x0, 0x64,0x12,0x59,0xa2,0xda,0x79,0xda,0xd8,0x22,0x2d,0x3b,0x7d,0x2a,0x7e, -0x1b,0xb0,0x22,0x7c,0xab,0x7f,0x71,0x7f,0x60,0x7e,0x7b,0xb0,0x70,0x7, 0x7e,0x6b, -0xa0,0x7a,0x7b,0xa0,0x22,0xa, 0x2b,0x7e,0x6b,0xb0,0xa, 0x3b,0x9d,0x32,0x12,0x1e, -0x5, 0xe5,0x2e,0xa, 0x2b,0xbd,0x32,0x8, 0x17,0x7e,0x7b,0x70,0x7e,0x6b,0x60,0xbc, -0x67,0x28,0x6, 0x7c,0xb7,0x2c,0xba,0x80,0x4, 0x7c,0xb7,0x9c,0xba,0x7a,0x7b,0xb0, -0x7e,0x7b,0x70,0x7a,0x6b,0x70,0x22,0x7e,0x83,0x34,0x2d,0x7e,0x90,0x3e,0xac,0x89, -0x2e,0x44,0x33,0x2b,0x80,0x3, 0x12,0x23,0x44,0x7e,0xb3,0x34,0x38,0xb4,0x4, 0x7, -0xe5,0x1f,0xbe,0xb0,0xfa,0x28,0xef,0x7d,0x34,0x22,0x7f,0x70,0x6c,0x77,0x74,0x3, -0xa, 0x27,0x7f,0x7, 0x2d,0x12,0x7a,0xb, 0xb0,0x7f,0x7, 0x2d,0x12,0x39,0xb0,0x0, -0xa, 0x7e,0x44,0x7f,0xff,0x74,0x2, 0xac,0xb7,0x7f,0x7, 0x2d,0x15,0x79,0x40,0x0, -0x14,0x74,0x2, 0xac,0xb7,0x7f,0x7, 0x2d,0x15,0x79,0x40,0x0, 0x28,0xb, 0x70,0xbe, -0x70,0xa, 0x40,0xca,0x22,0x7e,0x73,0x3, 0xf5,0x7a,0x73,0x34,0x23,0x7e,0x73,0x3, -0xf0,0x7a,0x73,0x34,0x24,0x7e,0x73,0x3, 0xf9,0x7a,0x73,0x34,0x25,0x7e,0x73,0x3, -0xf8,0x7a,0x73,0x34,0x26,0x7e,0x73,0x3, 0xf1,0x7a,0x73,0x34,0x27,0x7e,0x73,0x3, -0xf2,0x7a,0x73,0x34,0x28,0x7e,0x73,0x3, 0xf3,0x7a,0x73,0x34,0x29,0x7e,0x73,0x3, -0xf4,0x7a,0x73,0x34,0x2a,0x7e,0x73,0x3, 0xfa,0x7a,0x73,0x34,0x2b,0x22,0x7c,0x9b, -0x7e,0xb, 0xb0,0x60,0x3, 0xb4,0x2, 0x2f,0xa, 0x39,0x9, 0xa3,0x31,0x8b,0xbe,0xa3, -0x31,0x95,0x50,0xe, 0x7d,0x23,0x2e,0x24,0x31,0x8b,0x7c,0xba,0x4, 0x7a,0x29,0xb0, -0xd3,0x22,0xbe,0xa3,0x31,0x95,0x40,0x9, 0xbe,0xa0,0xff,0x68,0x4, 0xe4,0x7a,0xb, -0xb0,0x74,0xff,0xa, 0x39,0x80,0x13,0xa, 0x39,0x9, 0xb3,0x31,0x8b,0xbe,0xb0,0xff, -0x68,0x7, 0xe4,0x19,0xb3,0x31,0x8b,0xd3,0x22,0xe4,0x19,0xb3,0x31,0x8b,0xc3,0x22, -0xe4,0x7a,0xb3,0x3d,0x41,0xf1,0xb4,0xf1,0x98,0xe1,0x8b,0x75,0x76,0x0, 0x75,0x77, -0x0, 0x7e,0xb3,0x3d,0x41,0xf5,0x91,0x22,0xe1,0x9a,0x7e,0xb3,0x38,0x0, 0x54,0xfe, -0x75,0x91,0x0, 0xc2,0x90,0xc2,0x91,0xc2,0xc9,0x54,0xfe,0xf5,0x92,0xd2,0xe8,0xc2, -0xc0,0xd2,0xad,0x22,0x7e,0x8, 0x33,0x2b,0x7e,0x34,0xff,0xff,0x7e,0x24,0x0, 0xf8, -0x2, 0x59,0xa2,0xa2,0x15,0x22,0x74,0x1, 0xf1,0xe5,0x20,0x1f,0x5, 0x12,0x88,0x2e, -0xf1,0xf5,0x7e,0xb3,0x3d,0xff,0xb4,0x1, 0x9, 0xf1,0xc3,0x50,0x5, 0x12,0x87,0xc9, -0xf1,0xf5,0xe4,0xe1,0xe5,0x7c,0x7b,0xbe,0x70,0x8, 0x50,0x8, 0xa, 0x57,0x2e,0x54, -0x0, 0x8, 0xf5,0xcc,0x22,0xd2,0x7, 0x2, 0x26,0xad,0x30,0x21,0x5, 0x74,0x6, 0x12, -0x57,0xe1,0x7e,0xb3,0x3d,0xff,0xb4,0x1, 0x61,0x11,0x6b,0xac,0xb7,0x49,0x45,0x3e, -0x0, 0x49,0x15,0x3e,0x2, 0x6d,0x0, 0xbe,0x8, 0x0, 0x0, 0x68,0x11,0xbe,0x90,0x0, -0x40,0xc, 0xbe,0x90,0x2, 0x38,0x7, 0x74,0x1, 0x12,0xf, 0xe9,0x11,0x73,0x7e,0x34, -0x0, 0x1, 0x7c,0xb9,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x4e,0x73,0x3e,0x14,0x7a, -0x73,0x3e,0x14,0x7e,0xb3,0x3d,0xfe,0x4, 0x7a,0xb3,0x3d,0xfe,0x7e,0x73,0x3d,0xfd, -0xbe,0x73,0x3d,0xfe,0x28,0xe, 0x12,0x37,0xcd,0xb4,0x1, 0x4, 0x74,0x1, 0x80,0x6, -0x74,0x3, 0x80,0x2, 0x74,0x2, 0x7a,0xb3,0x3d,0xff,0x22,0x7e,0xb3,0x3d,0xfe,0x7e, -0x70,0x4, 0x22,0x7e,0xb3,0x1e,0x8f,0x7e,0x73,0x1e,0x90,0x2, 0x8, 0x0, 0x1, 0x80, -0xca,0x79,0x6c,0xff,0x7e,0xb3,0x18,0xcf,0xbe,0xb0,0x1, 0x68,0x9, 0x70,0x20,0x7e, -0xb3,0x1c,0x58,0xb4,0x1, 0x19,0x6c,0xee,0x80,0xc, 0x7c,0xbe,0x7c,0x7f,0x6c,0x66, -0x11,0xb2,0xb, 0xf0,0xb, 0xe0,0x12,0x4f,0xe0,0x38,0xef,0x7a,0xf3,0x1c,0x58,0xda, -0x79,0x22,0xca,0x3b,0x7c,0xd6,0x7c,0xe7,0x7c,0xfb,0x7e,0x90,0x5, 0xac,0x9f,0x9, -0x64,0x1a,0x1b,0x7a,0x61,0x37,0x9, 0xb4,0x1a,0x1c,0xf5,0x38,0x9, 0xa4,0x1a,0x1d, -0x7a,0xa1,0x39,0x9, 0x74,0x1a,0x1e,0x7a,0x71,0x3a,0xa, 0x2b,0xb, 0x24,0xa, 0x16, -0x9d,0x21,0x7c,0xb5,0xf5,0x3b,0xa, 0x37,0xb, 0x34,0xa, 0x2a,0x9d,0x32,0x7c,0xc7, -0x75,0x3c,0x0, 0xf1,0x23,0x7a,0x1d,0x4b,0x7e,0x70,0x2, 0xac,0x7f,0x9, 0xb3,0x19, -0xde,0xf5,0x35,0x9, 0x73,0x19,0xdf,0x7a,0x71,0x36,0x12,0x2d,0x89,0xb, 0x34,0x7a, -0x35,0x3d,0xe, 0x34,0x7a,0x35,0x3f,0xe5,0x37,0x7e,0x71,0x38,0x12,0x9e,0xca,0xe5, -0x37,0x7e,0x71,0x39,0x12,0x2e,0x53,0x7a,0x35,0x47,0x7e,0x34,0x17,0xdc,0x7a,0x35, -0x49,0x85,0x37,0x41,0x85,0x39,0x42,0x85,0x3b,0x43,0x7a,0xc1,0x44,0x7e,0xb3,0x1e, -0x75,0xf5,0x45,0x75,0x46,0x0, 0xbe,0xd0,0x1, 0x78,0x8, 0xe5,0x45,0x1e,0xb0,0x1e, -0xb0,0xf5,0x45,0x7e,0x37,0x1c,0x5e,0xbe,0x34,0x4, 0x4c,0x8, 0x10,0x7e,0x37,0x1c, -0x5a,0xbe,0x34,0x0, 0x32,0x28,0x6, 0xe5,0x45,0x3e,0xb0,0xf5,0x45,0x7e,0x8, 0x0, -0x41,0x12,0xf, 0x75,0x7e,0x37,0x17,0xdc,0x7d,0x3, 0x6d,0x11,0x7e,0x37,0x17,0xde, -0x6d,0x22,0x2f,0x10,0x7a,0x1d,0x25,0x7e,0x17,0x17,0xe0,0x7d,0x41,0x6d,0x55,0x7e, -0x17,0x17,0xe2,0x6d,0x0, 0x2f,0x2, 0x7a,0xd, 0x29,0x7e,0x17,0x17,0xe4,0x6d,0x0, -0x7d,0x41,0x7e,0x17,0x17,0xe6,0x2f,0x2, 0x7a,0xd, 0x31,0x7a,0x1d,0x2d,0x7e,0xd1, -0x37,0x61,0x37,0x7e,0xc1,0x39,0x61,0x2d,0x71,0xb1,0x7e,0x53,0x1e,0x75,0xa, 0x25, -0x7d,0xf3,0x9d,0xf2,0xbe,0xf4,0x0, 0x0, 0x18,0x2, 0x61,0x2b,0x7c,0xbf,0x7c,0x7d, -0x7c,0x6c,0xf1,0x2f,0xf5,0x4f,0xe5,0x36,0xa, 0x2b,0x1a,0x3c,0x9d,0x32,0x12,0x1e, -0x5, 0x7d,0xe3,0xe5,0x35,0xa, 0x2b,0x1a,0x3d,0x9d,0x32,0x12,0x1e,0x5, 0xbd,0x3e, -0x8, 0x8, 0xe5,0x35,0xa, 0x2b,0x1a,0x3d,0x80,0x6, 0xe5,0x36,0xa, 0x2b,0x1a,0x3c, -0x91,0x6e,0xf5,0x50,0x75,0x51,0x0, 0x71,0xb1,0xbe,0x35,0x3d,0x48,0x2, 0x80,0x31, -0xe5,0x50,0xbe,0xb1,0x4f,0x28,0x37,0xe5,0x4f,0xbe,0xb0,0x1, 0x38,0x2, 0x80,0x21, -0xe5,0x37,0xbc,0xbd,0x68,0x6, 0xe5,0x38,0xbc,0xbd,0x78,0xe, 0xe5,0x39,0xbc,0xbc, -0x68,0xf, 0xe5,0x3a,0xbc,0xbc,0x78,0x2, 0x80,0x7, 0xe5,0x50,0xbe,0xb0,0x2, 0x28, -0x5, 0x75,0x51,0x2, 0x80,0x8, 0xe5,0x4f,0xb4,0x2, 0x3, 0x75,0x51,0x1, 0xe5,0x51, -0x60,0x2, 0x41,0xd9,0xe5,0x37,0xa, 0x3b,0xe5,0x38,0xa, 0xeb,0x9d,0xe3,0xbe,0xe4, -0x0, 0x2, 0x48,0x75,0xe5,0x39,0xa, 0x3b,0xe5,0x3a,0xa, 0xeb,0x9d,0xe3,0xbe,0xe4, -0x0, 0x2, 0x48,0x65,0xe5,0x35,0xbc,0xbd,0x68,0x5f,0xe5,0x36,0xbc,0xbc,0x68,0x59, -0xe5,0x37,0xbc,0xbd,0x78,0x10,0xe5,0x39,0xbc,0xbc,0x78,0xa, 0x1a,0x5d,0xb, 0x54, -0x71,0xc0,0x58,0x45,0x80,0x40,0xe5,0x38,0xbc,0xbd,0x78,0x10,0xe5,0x3a,0xbc,0xbc, -0x78,0xa, 0x1a,0x5d,0x1b,0x54,0x71,0xca,0x58,0x2f,0x80,0x2a,0xe5,0x37,0xbc,0xbd, -0x78,0x10,0xe5,0x3a,0xbc,0xbc,0x78,0xa, 0x1a,0x5d,0xb, 0x54,0x71,0xca,0x58,0x19, -0x80,0x14,0xe5,0x38,0xbc,0xbd,0x78,0x11,0xe5,0x39,0xbc,0xbc,0x78,0xb, 0x1a,0x5d, -0x1b,0x54,0x71,0xc0,0x58,0x3, 0x75,0x51,0x2, 0xe5,0x51,0xb4,0x1, 0x2, 0xe, 0xf4, -0xe5,0x51,0xbe,0xb0,0x0, 0x28,0x3b,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x1a,0x1d,0x71, -0xb8,0x7e,0x1d,0x29,0x9f,0x10,0x7a,0x1d,0x29,0x7d,0x3f,0x1a,0x26,0x1a,0x24,0x1a, -0x1c,0x71,0xb8,0x7e,0x1d,0x31,0x9f,0x10,0x7a,0x1d,0x31,0x7d,0x1f,0xf1,0x1b,0x9f, -0x10,0x7a,0x1d,0x25,0x1a,0x2, 0x1a,0x0, 0x7e,0x1d,0x2d,0x9f,0x10,0x7a,0x1d,0x2d, -0x80,0x9, 0x71,0xb1,0xbe,0x35,0x3f,0x48,0x2, 0x5, 0x3c,0xb, 0xc0,0xe5,0x3a,0xbc, -0xbc,0x40,0x2, 0x21,0xb8,0xb, 0xd0,0xe5,0x38,0xbc,0xbd,0x40,0x2, 0x21,0xb3,0x7e, -0x71,0x3c,0x74,0xa, 0xac,0xbf,0x19,0x75,0x1a,0xf6,0x7e,0x35,0x3d,0xe, 0x34,0xe, -0x34,0xe, 0x34,0xe, 0x34,0x74,0xa, 0xac,0xbf,0x19,0x75,0x1a,0xf5,0x7e,0x1d,0x25, -0xbe,0x18,0x0, 0x0, 0x78,0x5, 0xb, 0x1c,0x7a,0x1d,0x25,0x7e,0x1d,0x2d,0xbe,0x18, -0x0, 0x0, 0x78,0x5, 0xb, 0x1c,0x7a,0x1d,0x2d,0x7e,0x1d,0x29,0x7e,0xd, 0x25,0x71, -0xd4,0x7d,0x13,0x7e,0x1d,0x4b,0x1b,0x1a,0x10,0x7e,0x1d,0x31,0x7e,0xd, 0x2d,0x71, -0xd4,0x7e,0xd, 0x4b,0x79,0x30,0x0, 0x2, 0x7e,0x71,0x35,0x74,0xa, 0xac,0xbe,0x19, -0x75,0x1a,0xf7,0x7e,0x71,0x36,0x74,0xa, 0xac,0xbe,0x19,0x75,0x1a,0xf8,0xda,0x3b, -0x22,0x7c,0xbd,0x7c,0x7c,0x2, 0x2d,0x89,0x1a,0x2, 0x12,0x1b,0x1f,0x7f,0x1, 0x22, -0x1a,0x3c,0xb, 0x34,0x12,0x2d,0x89,0xbd,0x3f,0x22,0x1a,0x3c,0x1b,0x34,0x12,0x2d, -0x89,0xbd,0x3f,0x22,0x7f,0x70,0x7f,0x1, 0x7c,0x41,0x7c,0x52,0x7c,0x63,0x6c,0x77, -0x7f,0x7, 0x12,0x1b,0x3b,0x2e,0x18,0x0, 0x80,0x22,0x7c,0xbe,0x7c,0x7f,0xca,0xf8, -0x7c,0x7b,0x6c,0x99,0x74,0xa, 0xac,0xb7,0x9, 0xf5,0x1c,0x89,0x9, 0x85,0x1c,0x8a, -0xf1,0x14,0x91,0x7c,0x7d,0xf3,0xbe,0xf4,0x0, 0x5a,0x58,0x6, 0x7e,0xf4,0x0, 0x5a, -0x80,0xa, 0xbe,0xf4,0x0, 0x78,0x8, 0x4, 0x7e,0xf4,0x0, 0x78,0xbe,0xf0,0x0, 0x28, -0xb, 0xa, 0x5f,0x1b,0x54,0x91,0x66,0x58,0x3, 0x7e,0x90,0x1, 0xbe,0xf0,0xf, 0x50, -0xa, 0xa, 0x5f,0xb, 0x54,0x91,0x66,0x58,0x2, 0xb, 0x90,0xbe,0x80,0x22,0x50,0xa, -0x7c,0xbf,0xa, 0x38,0x71,0xc2,0x58,0x2, 0xb, 0x90,0xbe,0x80,0x0, 0x28,0xa, 0x7c, -0xbf,0xa, 0x38,0x71,0xcc,0x58,0x2, 0xb, 0x90,0xbe,0x90,0x2, 0x40,0x4, 0x74,0x1, -0x80,0x1, 0xe4,0xda,0xf8,0x22,0x7c,0x78,0x12,0x2d,0x89,0xbd,0x3f,0x22,0x9d,0x32, -0x12,0x1e,0x5, 0x7c,0xb7,0x22,0x7e,0x34,0x0, 0x3, 0xad,0x30,0x7e,0x24,0x0, 0x4, -0x2, 0x1a,0xed,0xca,0x79,0x7c,0xe5,0x7d,0xd3,0x7c,0xfb,0x7f,0x70,0x6c,0x33,0x6d, -0xcc,0x6c,0x22,0xa1,0xac,0x74,0x2, 0xac,0xb2,0x7f,0x57,0x2d,0xb5,0xb, 0x5a,0x0, -0x4c,0xee,0x68,0x6, 0x6e,0x4, 0xff,0xff,0xb, 0x4, 0xbd,0xd0,0x48,0x2, 0xa1,0xaa, -0xa5,0xba,0x0, 0x8, 0x6d,0x44,0x69,0xc7,0x0, 0x2, 0x80,0x16,0xa, 0x3f,0x1b,0x34, -0xa, 0x52,0xbd,0x53,0x78,0x6, 0xd1,0xbe,0x6d,0xcc,0x80,0x6, 0xd1,0xbe,0x69,0xc5, -0x0, 0x2, 0x4c,0xee,0x68,0xc, 0x6e,0x44,0xff,0xff,0xb, 0x44,0x6e,0xc4,0xff,0xff, -0xb, 0xc4,0xbd,0x40,0x48,0x2, 0xa1,0xaa,0xbd,0xc0,0x8, 0x2, 0xa1,0xaa,0x75,0x2b, -0x1, 0x4c,0xee,0x68,0x2, 0xa1,0x91,0x91,0x76,0xbd,0x3c,0x58,0x2b,0xa, 0x3f,0x1b, -0x34,0xa, 0x52,0xb, 0x55,0xbd,0x53,0x18,0x1f,0x69,0x35,0x0, 0x4, 0xbd,0x3c,0x8, -0x17,0xbd,0x3d,0x8, 0x13,0xf1,0x9, 0x79,0x35,0x0, 0x2, 0xb1,0xb7,0x69,0xc1,0x0, -0x2, 0xbd,0xc0,0x8, 0x3, 0x75,0x2b,0x0, 0x91,0x76,0xbd,0x34,0x58,0x2d,0xbe,0x20, -0x2, 0x40,0x28,0xb1,0xb7,0x1b,0x36,0xb, 0x1a,0x30,0xbd,0x34,0x8, 0x1d,0xbd,0x3d, -0x8, 0x19,0xf1,0x9, 0x7d,0x43,0xb1,0xb7,0x1b,0x35,0x1b,0x1a,0x40,0xb1,0xb7,0x1b, -0x35,0xb, 0x1a,0x40,0xbd,0x40,0x8, 0x3, 0x75,0x2b,0x0, 0x75,0x2a,0x0, 0x80,0x26, -0x7e,0x73,0x1e,0x89,0xbc,0x7f,0x78,0xa, 0xd1,0xa6,0x9, 0x75,0x19,0xde,0xd1,0xe8, -0x48,0x18,0x7e,0x73,0x1e,0x8a,0xbc,0x7f,0x78,0xa, 0xd1,0xa6,0x9, 0x75,0x19,0xdf, -0xd1,0xe8,0x48,0x6, 0x5, 0x2a,0xd1,0xb6,0x38,0xd6,0xd1,0xb6,0x38,0x3, 0x75,0x2b, -0x0, 0xe5,0x2b,0xb4,0x1, 0xc, 0xa, 0x53,0x7e,0x1d,0x25,0x2d,0x35,0x7a,0x1b,0x20, -0xb, 0x30,0x7e,0x73,0x38,0xa3,0xbc,0x73,0x28,0x8, 0xb, 0x20,0xbc,0xf2,0x28,0x2, -0x81,0x95,0x7c,0xb3,0xda,0x79,0x22,0x74,0x2, 0xac,0xb2,0x7f,0x17,0x2d,0x35,0x22, -0x7e,0x8, 0x19,0x6a,0x7e,0x34,0x0, 0x3, 0xe4,0x12,0x1d,0xd3,0x7e,0x8, 0x19,0x6d, -0x7e,0x34,0x0, 0x3, 0x12,0x1d,0xd3,0x7a,0xb3,0x19,0x67,0x7a,0xb3,0x19,0x68,0x7a, -0xb3,0x19,0x69,0x7a,0xb3,0x19,0xd4,0x7a,0xb3,0x19,0xd5,0x7a,0xb3,0x19,0xd6,0x7e, -0x18,0x19,0x53,0xd1,0xdc,0x7e,0x37,0x1e,0x6f,0x6c,0x55,0x91,0x83,0x7a,0xb3,0x19, -0x69,0x7e,0x18,0x19,0x3f,0xd1,0xf6,0x7e,0xb3,0x1e,0x89,0x7e,0x37,0x1e,0x6d,0x6c, -0x55,0x91,0x83,0x7a,0xb3,0x19,0x68,0x6c,0x77,0x80,0x17,0x7c,0xb7,0x54,0x7, 0x7e, -0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0xd1,0xc6,0x2e,0x24,0x19,0x6a, -0xd1,0xd1,0x7e,0x63,0x19,0x68,0xbc,0x67,0x38,0xe1,0x6c,0x77,0x80,0x17,0x7c,0xb7, -0x54,0x7, 0x7e,0x24,0x0, 0x1, 0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0xd1,0xc6,0x2e, -0x24,0x19,0x6d,0xd1,0xd1,0x7e,0xa3,0x19,0x69,0xbc,0xa7,0x38,0xe1,0x7e,0xb3,0x19, -0x68,0xa4,0x7a,0xb3,0x19,0x67,0xd1,0xae,0x68,0x13,0x7e,0x18,0x19,0xca,0xd1,0xdc, -0x7e,0x37,0x1e,0x6f,0x7e,0x50,0x1, 0x91,0x83,0x7a,0xb3,0x19,0xd6,0xd1,0xae,0x68, -0x17,0x7e,0x18,0x19,0xc0,0xd1,0xf6,0x7e,0xb3,0x1e,0x89,0x7e,0x37,0x1e,0x6d,0x7e, -0x50,0x1, 0x91,0x83,0x7a,0xb3,0x19,0xd5,0x7e,0xb3,0x19,0xd5,0x7e,0xa3,0x19,0xd6, -0xa4,0x7a,0xb3,0x19,0xd4,0x22,0x7e,0x71,0x2a,0x74,0x2, 0xac,0xb7,0x22,0x7e,0xb3, -0x3c,0xea,0xbe,0xb0,0x12,0x22,0x7e,0x73,0x1c,0x58,0xbe,0x71,0x2a,0x22,0x7f,0x15, -0x1b,0x35,0xb, 0x1a,0x40,0x22,0x7c,0xa5,0x7c,0xb7,0xc4,0x23,0x54,0x1f,0xa, 0x2b, -0x22,0x7e,0x29,0x60,0x4c,0x6a,0x7a,0x29,0x60,0xb, 0x70,0x22,0x7a,0x1d,0x25,0x7e, -0xf, 0x6, 0xb0,0x7e,0xb3,0x1e,0x8a,0x22,0xa, 0x37,0xa, 0x22,0x9d,0x32,0x12,0x1e, -0x5, 0xbe,0x34,0x0, 0x3, 0x22,0x7a,0x1d,0x25,0x7e,0xb3,0x1e,0x8a,0x7e,0x70,0x2, -0xac,0xb7,0x7e,0xf, 0x6, 0xb0,0x2d,0x15,0x22,0x2d,0x30,0xb, 0x34,0x7e,0x24,0x0, -0x2, 0x2, 0x1a,0xed,0x7c,0xbf,0x7c,0x78,0x2, 0x2d,0x89,0x1a,0x2, 0x1a,0x0, 0x7e, -0x1d,0x25,0x22,0x7e,0x70,0xa, 0xac,0x7e,0x2e,0x34,0x1a,0xf0,0x6d,0x22,0x22,0xca, -0x79,0x7c,0x36,0x7c,0x27,0x7c,0x1b,0x7e,0x0, 0xff,0x6c,0x99,0x80,0x24,0xbc,0x91, -0x68,0x1e,0xf1,0xaa,0xa, 0x32,0xf1,0xc6,0xf1,0x6f,0x7c,0xf7,0xbc,0xf8,0x50,0x4, -0x7c,0xe8,0x80,0x2, 0x7c,0xef,0xbc,0xe, 0x28,0x2, 0x7c,0xe, 0x4c,0xee,0x68,0xa, -0xb, 0x90,0x7e,0x73,0x1c,0x58,0xbc,0x79,0x38,0xd4,0x7c,0xb0,0xda,0x79,0x22,0xa, -0x33,0x9d,0x32,0x2, 0x1e,0x5, 0x7e,0xb3,0x1d,0xea,0xbe,0xb0,0x2, 0x68,0x2, 0xe4, -0x22,0x7e,0x73,0x1c,0xed,0x7e,0x33,0x1c,0xee,0x7e,0x63,0x1c,0xf7,0x7e,0x23,0x1c, -0xf8,0xa, 0x26,0xf1,0xbf,0xbe,0x34,0x0, 0x5, 0x58,0xd, 0xa, 0x22,0xf1,0x6f,0xbe, -0x34,0x0, 0x5, 0x58,0x3, 0x74,0x1, 0x22,0xe4,0x22,0x74,0x2, 0xac,0xb9,0x9, 0x85, -0x19,0xde,0xa, 0x28,0x22,0x7e,0x73,0x2, 0xeb,0xa, 0x27,0x7e,0x73,0x2, 0xe4,0xa, -0x37,0x9d,0x32,0x2, 0x1e,0x5, 0x9d,0x32,0x12,0x1e,0x5, 0x7c,0x87,0x74,0x2, 0xac, -0xb9,0x9, 0x75,0x19,0xdf,0xa, 0x27,0x22,0xca,0xf8,0x7e,0x20,0x64,0x7e,0x10,0x64, -0x6c,0x0, 0x80,0x39,0xa, 0x40,0xb, 0x44,0x80,0x29,0xf1,0xaa,0x74,0x2, 0xac,0xb0, -0x9, 0x85,0x19,0xde,0xa, 0x38,0xf1,0xc6,0x74,0x2, 0xac,0xb0,0x9, 0x75,0x19,0xdf, -0x12,0x7f,0xbf,0x7c,0xf7,0xbc,0x28,0x28,0x2, 0x7c,0x28,0xbc,0x1f,0x28,0x2, 0x7c, -0x1f,0xb, 0x90,0x7e,0x73,0x1c,0x58,0xbc,0x79,0x38,0xcf,0xb, 0x0, 0x7e,0x83,0x1c, -0x58,0xbc,0x80,0x38,0xbf,0xa5,0xba,0x64,0x2, 0x6c,0x22,0xa5,0xb9,0x64,0x2, 0x6c, -0x11,0xbc,0x12,0x28,0x4, 0x7c,0x31,0x80,0x2, 0x7c,0x32,0x7c,0xb3,0xda,0xf8,0x22, -0x7e,0x34,0x3c,0xe2,0x30,0x16,0x26,0xc2,0x16,0x9, 0x73,0x0, 0x5, 0x12,0x2a,0xb4, -0x7a,0x37,0x1e,0x7e,0x7e,0x73,0x3e,0x23,0xbe,0x73,0x3c,0xfc,0x68,0xf, 0xe4,0x7a, -0xb3,0x3e,0x24,0x11,0x6e,0x7e,0x73,0x3c,0xfc,0x7a,0x73,0x3e,0x23,0x22,0x74,0xa, -0x7a,0xb3,0x3e,0x26,0xe4,0x7a,0xb3,0x3e,0x27,0x22,0xca,0xf8,0x7c,0xfb,0x7e,0x60, -0x2c,0x7e,0x70,0x1e,0x7e,0x53,0x3e,0x20,0xbe,0x50,0x0, 0x28,0x11,0x7e,0x60,0x1d, -0x7e,0x70,0x12,0x7e,0xb3,0x3e,0x29,0x70,0x5, 0xe4,0x7a,0xb3,0x3e,0x20,0x7e,0xa3, -0x3e,0x23,0x4c,0xaa,0x68,0x3, 0x7e,0x60,0x28,0xbc,0x6f,0x40,0x1d,0x7e,0xb3,0x3e, -0x29,0x60,0x6, 0xbc,0x7f,0x50,0x2, 0x80,0x11,0xbe,0xf0,0x0, 0x38,0x4, 0x4c,0xaa, -0x68,0xc, 0x71,0x25,0xa, 0x3b,0x4d,0x33,0x68,0x4, 0x74,0x14,0x80,0x5, 0x4c,0xff, -0x78,0x5, 0xe4,0x7a,0xb3,0x3e,0x29,0x7e,0xb3,0x3e,0x29,0xbe,0xb0,0x0, 0x28,0x18, -0x7e,0x37,0x1c,0x5c,0xbe,0x34,0x0, 0x14,0x50,0x5, 0x14,0x7a,0xb3,0x3e,0x29,0xe4, -0x7a,0xb3,0x1c,0x58,0xd2,0x19,0x80,0x6, 0xc2,0x19,0x51,0xc4,0x11,0x6e,0xda,0xf8, -0x22,0xca,0x3b,0x6c,0xff,0x7e,0xd0,0xff,0x7e,0xe0,0xff,0xe4,0x7a,0xb3,0x3e,0x28, -0x6c,0xcc,0x80,0x22,0x7c,0xbc,0x12,0x4a,0x79,0x60,0x19,0x7c,0xbc,0x31,0x91,0xf5, -0x25,0xbc,0xbf,0x28,0xf, 0x7e,0xf1,0x25,0x74,0x2, 0xac,0xbc,0x9, 0xd5,0x19,0xde, -0x9, 0xe5,0x19,0xdf,0xb, 0xc0,0x7e,0x73,0x1c,0x58,0xbc,0x7c,0x38,0xd6,0x7a,0xf3, -0x3e,0x25,0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0x33,0x7e,0xb3,0x3d,0x31,0x54,0x2, 0xb4, -0x2, 0x2a,0xbe,0xd0,0x0, 0x28,0x2a,0x51,0xa0,0x58,0x26,0xbe,0xe0,0x0, 0x28,0x21, -0x7e,0x73,0x1e,0x8c,0xa, 0x27,0x1b,0x24,0xa, 0x3e,0xbd,0x32,0x58,0x13,0xbe,0xe0, -0x17,0x40,0x5, 0xbe,0xe0,0x1b,0x28,0x9, 0x74,0x1, 0x80,0x1, 0xe4,0x7a,0xb3,0x3e, -0x20,0x7c,0xbf,0x11,0x7a,0x51,0xfc,0x30,0x19,0x2, 0x51,0xdd,0x51,0xad,0xda,0x3b, -0x22,0xca,0x3b,0x7c,0x3b,0x7e,0xe0,0x23,0x7e,0xc7,0x1c,0x5e,0x7e,0xd4,0x0, 0x5, -0xad,0xdc,0xe, 0xd4,0xe, 0xd4,0xe, 0xd4,0x74,0x2, 0xac,0xb3,0x9, 0x65,0x19,0xde, -0x9, 0xd5,0x19,0xdf,0x7a,0xd1,0x26,0x7e,0x8, 0x0, 0x27,0x7a,0xd, 0x2b,0x7c,0xbd, -0x7c,0x76,0x7d,0x2d,0x7e,0x8, 0x0, 0x28,0x31,0xf5,0x7c,0xfb,0x85,0x28,0x29,0x85, -0x27,0x2a,0x1b,0xd0,0xbe,0xd0,0x0, 0x48,0x4, 0x51,0x81,0x50,0xf5,0x7e,0xd1,0x26, -0x85,0x29,0x28,0x85,0x2a,0x27,0xb, 0xd0,0xbc,0xed,0x8, 0x4, 0x51,0x81,0x50,0xf6, -0x7c,0xbf,0xda,0x3b,0x22,0xca,0x3b,0x7f,0x70,0x7d,0x42,0x7c,0xd6,0x7c,0xf7,0x7c, -0xeb,0x75,0x2f,0x10,0x7c,0xcf,0x80,0xc, 0x51,0x7a,0xbd,0x34,0x48,0x4, 0x7c,0xfc, -0x80,0x6, 0xb, 0xc0,0xbc,0xdc,0x58,0xf0,0xa, 0x6f,0x1b,0x64,0x7c,0xcd,0x80,0x8, -0x51,0x7a,0xbd,0x34,0x48,0x7, 0x1b,0xc0,0xbe,0xc0,0x0, 0x58,0xf3,0xb, 0xc0,0xbe, -0xc0,0x0, 0x58,0x2, 0x6c,0xcc,0x7a,0x7b,0xc0,0xa, 0x6f,0xb, 0x64,0x7c,0xcd,0x80, -0x8, 0x51,0x7a,0xbd,0x34,0x48,0x8, 0xb, 0xc0,0xe5,0x2f,0xbc,0xbc,0x18,0xf2,0x1b, -0xc0,0xe5,0x2f,0xbc,0xbc,0x18,0x3, 0x7e,0xc0,0xf, 0x7e,0x1d,0x2b,0x7a,0x1b,0xc0, -0x7e,0x7b,0x70,0xa, 0x47,0x7e,0x1d,0x2b,0x7e,0x1b,0x70,0xa, 0x57,0x9d,0x54,0xb, -0x54,0xbe,0xb0,0x0, 0x58,0x1, 0xe4,0xda,0x3b,0x22,0x7c,0xbc,0x7c,0x7e,0x2, 0x2d, -0x89,0x7e,0x18,0x0, 0x27,0x7a,0x1d,0x2b,0x7c,0xbd,0x7e,0x71,0x28,0x7e,0x61,0x27, -0x7d,0x2d,0x7e,0x8, 0x0, 0x28,0x31,0xf5,0x7c,0xcb,0x2c,0xfc,0xbe,0xc0,0x3, 0x22, -0x7e,0x73,0x1e,0x8b,0xa, 0x27,0x1b,0x24,0xa, 0x3d,0xbd,0x32,0x22,0x30,0x19,0x13, -0x12,0x5f,0xf2,0x68,0x6, 0x7e,0xb3,0x36,0x5, 0x60,0x8, 0x7e,0x34,0xb, 0xb8,0x7a, -0x37,0x3e,0x21,0x22,0x7e,0xb3,0x3e,0x23,0x60,0x12,0x7e,0xb3,0x3e,0x24,0xb4,0x1, -0xb, 0xe4,0x7a,0xb3,0x3e,0x24,0x74,0x1, 0x7a,0xb3,0x3e,0x28,0x22,0x7e,0xb3,0x3e, -0x23,0x60,0x18,0x7e,0xb3,0x3e,0x24,0x70,0x12,0x7e,0xb3,0x3e,0x27,0x70,0xc, 0x74, -0x1, 0x7a,0xb3,0x3e,0x27,0x74,0xa, 0x7a,0xb3,0x3e,0x26,0x22,0x7e,0xb3,0x3e,0x23, -0x60,0x22,0x7e,0xb3,0x3e,0x24,0x70,0x1c,0x7e,0xb3,0x3e,0x27,0xb4,0x1, 0x15,0x7e, -0xb3,0x3e,0x26,0x14,0x7a,0xb3,0x3e,0x26,0x70,0xa, 0x74,0x1, 0x7a,0xb3,0x3e,0x24, -0x7a,0xb3,0x3e,0x28,0x22,0x6c,0x77,0x7e,0x63,0x1e,0x8a,0x7e,0x33,0x1e,0x89,0xac, -0x36,0x7d,0x21,0x1e,0x24,0x1e,0x14,0x1e,0x14,0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0x24, -0x7e,0xb3,0x3d,0x31,0x54,0x2, 0xb4,0x2, 0x1b,0x7e,0x7, 0x1c,0x5e,0xbe,0x4, 0x1, -0xf4,0x58,0x11,0x7e,0x14,0x0, 0x5a,0x7e,0x63,0x19,0xdb,0xbe,0x60,0x1b,0x28,0x4, -0x7e,0x14,0x0, 0x50,0x7e,0x7, 0x1c,0x5e,0xbe,0x4, 0x2, 0xbc,0x58,0x10,0x7d,0x52, -0x3e,0x54,0x7e,0x44,0x0, 0x3, 0x8d,0x54,0x7d,0x25,0x9e,0x24,0x0, 0xa, 0x7e,0x7, -0x1c,0x5c,0x2e,0x7, 0x1c,0x5a,0xbd,0x2, 0x38,0x8, 0x7e,0x27,0x1c,0x5a,0xbd,0x21, -0x28,0x1b,0x7e,0xb3,0x3e,0x23,0x70,0x12,0x7e,0x63,0x19,0xdb,0xbe,0x60,0x11,0x28, -0xc, 0x7e,0x63,0x19,0xda,0xbe,0x60,0x8, 0x28,0x3, 0x7e,0x70,0x1, 0x7c,0xb7,0x22, -0x7d,0x42,0x7d,0xf3,0x49,0xd4,0x0, 0x4, 0x1b,0xd4,0x6d,0xcc,0x74,0xa, 0x2f,0x66, -0x14,0x78,0xfb,0x6d,0xee,0x7d,0x5e,0x3e,0x54,0x2d,0x54,0x49,0x55,0x0, 0x6, 0xbd, -0x5f,0x28,0x8, 0xb, 0xe4,0xbe,0xe4,0x0, 0x3, 0x48,0xea,0xbe,0xe4,0x0, 0x3, 0x58, -0x10,0xb, 0x48,0x10,0x7d,0x3e,0x1a,0x26,0x1a,0x24,0x12,0x1b,0x30,0x9f,0x61,0x80, -0x4, 0x9f,0x66,0x6d,0x55,0x4d,0xee,0x78,0x15,0x7f,0x16,0x2e,0x18,0x0, 0x7f,0x74, -0xa, 0x1e,0x34,0x1e,0x24,0x50,0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x1b,0xe4, -0x3e,0xe4,0x2d,0x4e,0x49,0x14,0x0, 0xc, 0x6d,0x0, 0x7d,0x3f,0x9d,0x35,0x6d,0x22, -0x12,0x1b,0x1f,0x2f,0x16,0x2e,0x18,0x0, 0x7f,0x74,0xa, 0x1e,0x34,0x1e,0x24,0x50, -0x3, 0x4e,0x60,0x80,0x14,0x78,0xf4,0x22,0x2, 0x4d,0xd3,0xc2,0x17,0x22,0x12,0xa2, -0xad,0x12,0xa2,0x74,0x81,0x3b,0xca,0xf8,0x7e,0xf0,0xff,0x7e,0xb3,0x3b,0xfa,0xb4, -0x1, 0x7, 0x91,0x3e,0xe4,0x7a,0xb3,0x3b,0xfa,0x7e,0xb3,0x3b,0xf8,0xb4,0x2, 0x2, -0x80,0x2, 0xa1,0x2f,0xf1,0x32,0x38,0x10,0xf1,0x2a,0x38,0xc, 0xf1,0x22,0x38,0x8, -0x7e,0xb3,0x18,0xcf,0x60,0x2, 0xa1,0x2f,0x74,0x3, 0xb1,0x46,0x7c,0x5b,0x7e,0xb3, -0x3b,0xf7,0x4, 0x7a,0xb3,0x3b,0xf7,0x74,0x3, 0xb1,0x46,0x7c,0x4b,0xbe,0x40,0xff, -0x68,0x28,0xbe,0x50,0xff,0x68,0x21,0x7e,0x30,0xc, 0xac,0x35,0x49,0x41,0x3c,0xd, -0xbe,0x44,0x1, 0x90,0x28,0x14,0x74,0xc, 0xac,0xb4,0x49,0x35,0x3c,0xd, 0x3e,0x34, -0xbd,0x43,0x28,0x6, 0x7c,0x54,0x80,0x2, 0x7c,0x54,0xa5,0xbd,0xff,0x11,0xe4,0x7a, -0xb3,0x3b,0xf7,0x7a,0xb3,0x3b,0xf8,0x7a,0xb3,0x3c,0x4, 0x74,0xff,0x80,0x74,0x7e, -0x43,0x3b,0xf7,0xbe,0x40,0x4, 0x38,0xb, 0xbe,0x40,0x2, 0x28,0x52,0x7e,0xb3,0x18, -0xcf,0x70,0x4c,0x74,0xc, 0xac,0xb5,0x49,0x35,0x3c,0xd, 0xbe,0x34,0x1, 0x90,0x40, -0x6, 0x7e,0xb3,0x18,0xcf,0x70,0x31,0x7e,0x37,0x3b,0xfe,0xbe,0x34,0x1, 0x2c,0x28, -0x27,0x74,0x5, 0xac,0xb5,0x9, 0x45,0x19,0x17,0xbe,0x43,0x1f,0x3d,0x68,0x19,0x7c, -0xf5,0xbe,0xf0,0x4, 0x50,0xc, 0x7e,0xb3,0x1f,0x3d,0x12,0x49,0xd9,0xbe,0xb0,0x4, -0x40,0x6, 0x74,0x1, 0x7a,0xb3,0x3b,0xfa,0xe4,0x7a,0xb3,0x3c,0x4, 0xb1,0xad,0xbe, -0xf0,0xff,0x68,0xd, 0xe4,0x7a,0xb3,0x3b,0xf7,0xb1,0xad,0x6d,0x33,0x7a,0x37,0x3b, -0xfe,0x7c,0xbf,0xda,0xf8,0x22,0xca,0x79,0x7c,0x3b,0x7e,0x44,0xff,0xff,0x6c,0x22, -0x80,0x1a,0xb1,0xb4,0x68,0x14,0x74,0xc, 0xac,0xb2,0x49,0x5, 0x3c,0x11,0x49,0x35, -0x3c,0xd, 0xbd,0x30,0x50,0x4, 0x59,0x5, 0x3c,0xd, 0xb, 0x20,0xbc,0x32,0x50,0xe2, -0x6c,0xff,0x6c,0x22,0x80,0x28,0xb1,0xb4,0x78,0x12,0xa, 0x2, 0xb, 0x4, 0x7c,0xe1, -0xbc,0x3e,0x50,0x18,0xa, 0x33,0xb, 0x34,0x9c,0xe7,0x80,0x10,0x74,0xc, 0xac,0xb2, -0x49,0x5, 0x3c,0xd, 0xbd,0x4, 0x50,0x4, 0x7d,0x40,0x7c,0xf2,0xb, 0x20,0xbc,0x32, -0x50,0xd4,0x4d,0x44,0x78,0x2, 0x7c,0xfe,0x7c,0xbf,0xda,0x79,0x22,0x74,0x1, 0x7a, -0xb3,0x3b,0xf8,0x22,0x74,0x5, 0xac,0xb2,0x9, 0x75,0x19,0x17,0xbe,0x73,0x1f,0x3d, -0x22,0x7e,0xb3,0x3b,0xf5,0x60,0x6, 0x14,0x7a,0xb3,0x3b,0xf5,0x22,0x7e,0xb3,0x3c, -0xed,0x70,0x14,0x7e,0xb3,0x37,0xff,0xb4,0x1, 0xd, 0xe4,0x12,0x3f,0x89,0xe4,0x7a, -0xb3,0x3b,0xf8,0x7a,0xb3,0x3c,0x0, 0xb1,0xfc,0x91,0x46,0x7e,0xa3,0x3c,0xed,0x7a, -0xa3,0x37,0xff,0xbe,0xb0,0xff,0x68,0x3, 0x2, 0x3f,0x89,0x22,0xd1,0x2e,0xc1,0x0, -0x7e,0x73,0x3c,0xe7,0x12,0x2a,0xb4,0x7e,0xb3,0x3b,0xf8,0x60,0x6, 0x74,0x1, 0x7a, -0xb3,0x3c,0x0, 0x7e,0xb3,0x3c,0x0, 0xb4,0x1, 0xa, 0x74,0x3, 0x7a,0xb3,0x31,0x96, -0x3e,0x34,0x80,0x5, 0xe4,0x7a,0xb3,0x31,0x96,0x7a,0x37,0x1e,0x7e,0x22,0x7e,0x27, -0x3d,0xf5,0xbe,0x24,0x0, 0x64,0x28,0x7, 0xe4,0x7a,0xb3,0x3b,0xf6,0xb1,0xad,0xbe, -0x24,0x0, 0xc8,0x28,0xb, 0xe4,0x7a,0xb3,0x3b,0xf6,0x74,0x2, 0x7a,0xb3,0x3b,0xf8, -0x7e,0x37,0x3b,0xfe,0xbd,0x32,0x50,0x4, 0x7a,0x27,0x3b,0xfe,0xf1,0x32,0x38,0x8, -0xf1,0x2a,0x38,0x4, 0xf1,0x22,0x28,0x38,0xd1,0xaa,0xbe,0x24,0x0, 0x32,0x50,0x27, -0x7e,0xb3,0x3b,0xf6,0x4, 0x7a,0xb3,0x3b,0xf6,0x7e,0x73,0x3b,0xf6,0xbe,0x70,0x32, -0x28,0x1a,0x74,0x32,0x7a,0xb3,0x3b,0xf6,0xe4,0x7a,0xb3,0x3b,0xf8,0x7a,0xb3,0x3c, -0x0, 0x7a,0xb3,0x3c,0x6b,0x80,0x5, 0xe4,0x7a,0xb3,0x3b,0xf6,0x7d,0x32,0xe1,0x3a, -0xc1,0xa2,0xf1,0x18,0xe4,0x7a,0xb3,0x3c,0x4, 0x22,0x7e,0xb3,0x3c,0x4, 0xb4,0x1, -0x7, 0x74,0x2, 0x7a,0xb3,0x3b,0xf8,0x22,0x7e,0xb3,0x3c,0x6a,0x4, 0x7a,0xb3,0x3c, -0x6a,0x7e,0xb3,0x3b,0xf8,0xb4,0x2, 0x2b,0x7e,0xb3,0x3c,0x69,0x4, 0x7a,0xb3,0x3c, -0x69,0x7e,0x37,0x3d,0xf5,0xbe,0x34,0x1, 0x2c,0x28,0x9, 0x7e,0xb3,0x3c,0x69,0x4, -0x7a,0xb3,0x3c,0x69,0x7e,0xb3,0x3c,0x69,0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x3c, -0x6a,0xb1,0xad,0x7e,0x73,0x3c,0x69,0xbe,0x70,0x3, 0x40,0x10,0x74,0x1, 0x7a,0xb3, -0x3c,0x4, 0x74,0x2, 0x7a,0xb3,0x3b,0xf8,0xf1,0xab,0xf1,0x18,0x7e,0x73,0x3c,0x6a, -0xbe,0x70,0xa, 0x28,0x2, 0xe1,0x18,0x22,0xe4,0x7a,0xb3,0x3c,0x6a,0x7a,0xb3,0x3c, -0x69,0x22,0x7e,0x73,0x19,0xd9,0xbe,0x70,0x0, 0x22,0x7e,0x73,0x19,0xd8,0xbe,0x70, -0x0, 0x22,0x7e,0x73,0x1c,0x66,0xbe,0x70,0x0, 0x22,0x7d,0x23,0xbe,0x24,0x1, 0xf4, -0x28,0xd, 0x7e,0x73,0x3c,0x6b,0xbe,0x70,0x8, 0x50,0x3a,0x74,0x8, 0x80,0x32,0xbe, -0x24,0x1, 0x90,0x28,0xd, 0x7e,0x73,0x3c,0x6b,0xbe,0x70,0x6, 0x50,0x27,0x74,0x6, -0x80,0x1f,0xbe,0x24,0x1, 0x2c,0x28,0x8, 0xf1,0xa3,0x50,0x19,0x74,0x4, 0x80,0x11, -0xbe,0x24,0x0, 0xc8,0x28,0xf, 0x7e,0x73,0x3c,0x6b,0xbe,0x70,0x2, 0x50,0x6, 0x74, -0x2, 0x7a,0xb3,0x3c,0x6b,0x7e,0xb3,0x3c,0x6b,0xbe,0xb0,0x0, 0x28,0x14,0x14,0x7a, -0xb3,0x3c,0x6b,0x74,0x1, 0x7a,0xb3,0x18,0xd0,0xf1,0xa3,0x28,0x5, 0xe4,0x7a,0xb3, -0x18,0xcf,0x22,0x7e,0x73,0x3c,0x6b,0xbe,0x70,0x4, 0x22,0xe4,0x7a,0xb3,0x3b,0xf6, -0x6d,0x44,0x6c,0x77,0x74,0xc, 0xac,0xb7,0x59,0x45,0x3c,0xd, 0xb, 0x70,0xbe,0x70, -0x4, 0x40,0xf1,0xe4,0x7a,0xb3,0x3b,0xf7,0x22,0x74,0xc8,0x7a,0xb3,0x3e,0x30,0xc2, -0x1f,0x80,0x9, 0xf1,0xf3,0x30,0x1f,0x4, 0x75,0xe9,0xff,0x22,0x7e,0xb3,0x3d,0xff, -0xbe,0xb0,0x1, 0x68,0xee,0x22,0x7e,0xb3,0x3d,0xff,0xbe,0xb0,0x1, 0x68,0xf7,0x20, -0x93,0xfd,0x22,0x80,0x24,0x74,0x81,0x7a,0xb3,0x3e,0x2a,0x7e,0xb3,0x3d,0xff,0xbe, -0xb0,0x1, 0x68,0x5, 0xc2,0x7, 0x12,0x26,0xad,0x7e,0xb3,0x3d,0xff,0xbe,0xb0,0x2, -0x68,0x1b,0x20,0x1f,0x18,0xe4,0x12,0x27,0x29,0x20,0x93,0xd9,0x74,0x81,0x7a,0xb3, -0x3e,0x2a,0xa9,0xd1,0xcd,0xa9,0xc5,0xea,0x74,0x2, 0x2, 0x27,0x29,0x22,0xd2,0x6, -0x80,0x16,0x30,0x6, 0x10,0x7e,0xb3,0x3d,0xff,0xbe,0xb0,0x1, 0x68,0x7, 0xc2,0x6, -0xc2,0x7, 0x12,0x26,0xad,0x12,0x87,0xf3,0x30,0x1f,0xe7,0x22,0x7e,0x34,0x0, 0xb4, -0x22,0x7e,0xb3,0x3d,0x7, 0x70,0x27,0x7e,0xb3,0x3c,0xea,0xb4,0x12,0x5, 0x7e,0xa0, -0x4, 0x80,0x3, 0x7e,0xa0,0x6, 0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0x3, 0x7e,0xa0,0xc, -0xe5,0x1f,0xa, 0x3b,0x2e,0x37,0x3e,0x3c,0x7a,0x37,0x3e,0x3c,0x80,0xc, 0x7e,0xa3, -0x3c,0xeb,0xbe,0xa0,0x7f,0x28,0x3, 0x7e,0xa0,0x7f,0x7c,0xba,0x1, 0x8e,0x7c,0x7b, -0x75,0x1f,0x0, 0x7a,0x73,0x3e,0x30,0xc2,0x1f,0x22,0x1, 0x9c,0xca,0xd8,0xca,0x79, -0x7c,0xf4,0x7c,0xe5,0x7c,0xdb,0x7d,0xd3,0x7c,0xbf,0x71,0x46,0x7d,0xc3,0x7e,0x70, -0xa, 0xac,0x7e,0x9, 0x53,0x1a,0xf6,0xbe,0x50,0x7, 0x28,0x1c,0xa, 0xbf,0x9, 0xbb, -0x31,0x62,0x70,0x14,0x74,0x2, 0xac,0xbf,0x49,0x45,0x31,0x76,0xbe,0x44,0x0, 0xfa, -0x50,0x6, 0x6d,0xbb,0x59,0xb5,0x31,0x76,0x7e,0xb3,0x1d,0xeb,0xb4,0x1, 0x1e,0x71, -0x24,0x28,0x1a,0x7e,0xb3,0x3c,0xee,0x70,0x14,0x74,0x1, 0x71,0x1b,0xa, 0xbf,0x9, -0xbb,0x1d,0xae,0x70,0x13,0x74,0x2, 0x19,0xbb,0x31,0x6c,0x80,0xb, 0x7e,0xb3,0x1d, -0xea,0xb4,0x1, 0x4, 0x74,0x2, 0x71,0x1b,0x7e,0xb3,0x37,0x44,0xb4,0x1, 0x4, 0x74, -0x2, 0x71,0x1b,0xbe,0xd4,0x4, 0xb0,0x50,0x2c,0xa, 0xbf,0x9, 0xbb,0x31,0x6c,0xb4, -0x1, 0x23,0xbe,0xc4,0x0, 0x0, 0x28,0x1d,0x71,0x24,0x28,0x19,0xbe,0x50,0x9, 0x28, -0x6, 0x1e,0xc4,0x1e,0xc4,0x80,0x2, 0x1e,0xc4,0xbe,0xc4,0x0, 0x8, 0x50,0xe, 0x7e, -0xc4,0x0, 0x8, 0x80,0x8, 0x74,0x2, 0xa, 0x2f,0x19,0xb2,0x31,0x6c,0x7e,0x23,0x3c, -0xee,0xbe,0x20,0x0, 0x28,0x5, 0x7e,0x30,0x12,0x80,0x3, 0x7e,0x30,0x17,0x74,0x2, -0xac,0xbf,0x49,0x25,0x31,0x76,0xa, 0x3, 0xbd,0x20,0x50,0x14,0xbe,0x20,0x0, 0x28, -0x6, 0x7e,0x4, 0x3, 0x0, 0x80,0x4, 0x7e,0x4, 0x3, 0x60,0x7a,0x5, 0x70,0x80,0xe, -0xbe,0x20,0x0, 0x28,0x2, 0x80,0x0, 0x7e,0x44,0x0, 0xf0,0x7a,0x45,0x70,0x7e,0x45, -0x70,0xbd,0x4d,0x28,0x2e,0xbe,0x24,0x0, 0xfa,0x50,0x28,0xbe,0xc4,0x0, 0x6, 0x28, -0x22,0xa, 0x43,0xbd,0x24,0x50,0xb, 0x7d,0x45,0x2e,0x44,0x31,0x76,0xb, 0x24,0x1b, -0x48,0x20,0xa, 0x2f,0x9, 0x52,0x31,0x62,0xbe,0x50,0x3, 0x38,0xe, 0x7e,0xc4,0x0, -0x1, 0x80,0x8, 0x7e,0x24,0x0, 0xfa,0x59,0x25,0x31,0x76,0xbe,0xc4,0x0, 0x1, 0x28, -0x34,0xbe,0xc4,0x0, 0x40,0x50,0x2e,0x9, 0x53,0x1c,0x89,0xbe,0x50,0x0, 0x28,0x25, -0xbe,0x50,0xf, 0x50,0x20,0x7d,0x1c,0xad,0x1c,0x7d,0xc1,0x2e,0xc4,0x0, 0x20,0x1e, -0xc4,0x1e,0xc4,0x1e,0xc4,0x1e,0xc4,0x1e,0xc4,0x1e,0xc4,0xbe,0xc4,0x0, 0x4, 0x50, -0x4, 0x7e,0xc4,0x0, 0x4, 0x74,0xa, 0xac,0xbd,0x91,0x3e,0x7d,0xd3,0x74,0xa, 0xac, -0xbd,0x91,0x4b,0x7d,0xb3,0x7d,0x4d,0x2d,0x4b,0x74,0x2, 0xac,0xbf,0x49,0x35,0x32, -0xcd,0x12,0x1e,0x5, 0x7d,0x13,0x74,0x2, 0xac,0xbf,0x49,0x35,0x32,0xb9,0x12,0x1e, -0x5, 0x2d,0x31,0xbe,0x34,0x2, 0x0, 0x50,0x58,0x7e,0xb3,0x3d,0x32,0x70,0x52,0x7d, -0x13,0xad,0x13,0x2e,0x8, 0x1, 0x0, 0x7c,0x32,0x7c,0x21,0xa, 0x0, 0x7d,0x21,0xa, -0x5f,0x9, 0x35,0x31,0x62,0xbe,0x30,0x0, 0x28,0xa, 0x71,0x2c,0xbe,0x24,0x0, 0x4, -0x50,0x10,0x80,0xa, 0x71,0x2c,0x1e,0xa4,0xbe,0x24,0x0, 0x4, 0x50,0x4, 0x7e,0x24, -0x0, 0x4, 0xbe,0xa4,0x0, 0x80,0x28,0x4, 0x7e,0xa4,0x0, 0x80,0x2d,0x2a,0x2d,0x32, -0x71,0xa6,0x7d,0x14,0x12,0x1b,0x39,0xbd,0x3c,0x50,0x1f,0x7d,0xc3,0xb, 0xc4,0x80, -0x19,0xa, 0x3f,0x9, 0xb3,0x31,0x62,0xb4,0x3, 0x10,0x74,0x2, 0x19,0xb3,0x31,0x62, -0xbe,0xc4,0x0, 0xa0,0x28,0x4, 0x7e,0xc4,0x0, 0xa0,0x7d,0x4b,0x71,0x39,0x5e,0x90, -0xfc,0x7e,0x50,0xa, 0xac,0x5d,0x49,0x32,0x1d,0x4a,0x74,0xa, 0xac,0xbe,0x49,0x55, -0x1c,0x82,0xbd,0x53,0x28,0xf, 0x7d,0x52,0x2e,0x54,0x1d,0x4a,0x7d,0xb3,0x2d,0xb4, -0x1b,0x58,0xb0,0x80,0xd, 0x7d,0xb2,0x2e,0xb4,0x1d,0x4a,0x7d,0x53,0x9d,0x54,0x1b, -0xb8,0x50,0x7d,0x4d,0x71,0x39,0x5e,0x90,0xfc,0x7e,0x70,0xa, 0xac,0x7d,0x49,0xb3, -0x1d,0x4c,0x74,0xa, 0xac,0xbe,0x49,0x25,0x1c,0x84,0xbd,0x2b,0x28,0xf, 0x7d,0x53, -0x2e,0x54,0x1d,0x4c,0x7d,0x2b,0x2d,0x24,0x1b,0x58,0x20,0x80,0x9, 0x2e,0x34,0x1d, -0x4c,0x9d,0xb4,0x1b,0x38,0xb0,0xda,0x79,0xda,0xd8,0x22,0x7a,0xb3,0x31,0x6c,0x7a, -0xb3,0x31,0x6d,0x22,0x7e,0x43,0x1d,0xea,0xbe,0x40,0x1, 0x22,0x7d,0xa4,0x1e,0xa4, -0x1e,0xa4,0x1e,0xa4,0x1e,0xa4,0x1e,0xa4,0x22,0x7d,0x3c,0xad,0x34,0x7c,0x76,0x7c, -0x65,0xa, 0x24,0x7d,0x43,0x22,0xca,0xf8,0x7c,0xfb,0x7d,0x3, 0x7d,0xf0,0x7e,0xe7, -0x1e,0x7e,0x12,0x7f,0x76,0xbe,0xb0,0x0, 0x28,0x2, 0x3e,0xe4,0xbd,0xe0,0x38,0x6, -0x7e,0x34,0x1, 0x0, 0x80,0x13,0x7d,0x30,0x71,0xa6,0x7d,0x1e,0x12,0x1b,0x39,0xbe, -0x34,0x0, 0x10,0x50,0x4, 0x7e,0x34,0x0, 0x10,0x74,0x2, 0xac,0xbf,0x49,0x25,0x31, -0xfb,0xbd,0x2f,0x28,0xc, 0xbe,0x24,0x0, 0x40,0x28,0x6, 0x49,0x35,0x31,0x4c,0x80, -0x4, 0x59,0x35,0x31,0x4c,0x59,0xf5,0x31,0xfb,0xbe,0x34,0x1, 0x0, 0x28,0x4, 0x7e, -0x34,0x1, 0x0, 0xda,0xf8,0x22,0x6d,0x22,0x7c,0x56,0x7c,0x67,0x6c,0x77,0x22,0xca, -0x3b,0x7c,0xfb,0x6c,0xee,0x80,0x44,0x6c,0xcc,0x74,0xa, 0xac,0xbc,0x9, 0x45,0x1d, -0x4e,0x7e,0x70,0xa, 0xac,0x7e,0x9, 0x53,0x1c,0x86,0xbc,0x45,0x68,0x7, 0xb, 0xc0, -0xbe,0xc0,0xa, 0x40,0xe4,0xbe,0xc0,0xa, 0x50,0x5c,0x74,0xa, 0xac,0xbc,0x9, 0xd5, -0x1d,0x4e,0x91,0x3e,0x7d,0x43,0x74,0xa, 0xac,0xbc,0x91,0x4b,0x2d,0x34,0x7a,0x35, -0x25,0x7c,0xbc,0x7c,0x5e,0x7c,0x4d,0x11,0x9a,0xb, 0xe0,0xbc,0xfe,0x38,0xb8,0x80, -0x35,0x74,0xa, 0xac,0xbe,0x9, 0xd5,0x1c,0x86,0xbe,0xd0,0xa, 0x50,0x26,0xa, 0x4d, -0x9, 0xb4,0x1d,0xae,0xb4,0x1, 0x1d,0xe4,0x19,0xb4,0x31,0x62,0x6d,0x33,0x74,0x2, -0xac,0xbd,0x59,0x35,0x31,0x4c,0x59,0x35,0x31,0xfb,0x59,0x35,0x31,0x76,0x74,0x2, -0x19,0xb4,0x31,0x6c,0xb, 0xe0,0xbe,0xe0,0xa, 0x40,0xc6,0xda,0x3b,0x22,0x49,0x25, -0x1d,0x4c,0x49,0x33,0x1c,0x84,0x9d,0x32,0x2, 0x1e,0x5, 0x49,0x25,0x1d,0x4a,0x74, -0xa, 0xac,0xbe,0x49,0x35,0x1c,0x82,0x9d,0x32,0x2, 0x1e,0x5, 0xca,0x3b,0x7e,0x34, -0x0, 0xc8,0x7a,0x37,0x2, 0xaa,0x7e,0xb3,0x3d,0x25,0x54,0x1, 0xf5,0x28,0x7e,0xe3, -0x1d,0xea,0x4c,0xee,0x78,0x20,0x6c,0xff,0x6d,0x33,0x7e,0x50,0x2, 0xac,0x5f,0xd1, -0xd0,0x74,0xa, 0xac,0xbf,0xd1,0xee,0x74,0x2, 0xa, 0x3f,0x19,0xb3,0x33,0x1f,0xb, -0xf0,0xbe,0xf0,0xa, 0x78,0xe2,0xf1,0x71,0x7e,0x24,0x0, 0x50,0xad,0x32,0x2e,0x34, -0xc, 0x80,0x7a,0x37,0x2, 0xa8,0x6c,0xff,0xc1,0xbe,0x74,0xa, 0xac,0xbf,0x9, 0xb5, -0x1c,0x86,0x54,0xf, 0xf5,0x26,0xbe,0xb0,0xa, 0x40,0x2, 0xc1,0xbc,0xe5,0x26,0xa, -0x3b,0x9, 0xb3,0x1d,0xae,0xbe,0xb0,0x1, 0x78,0x2, 0xc1,0x9d,0x70,0xb, 0x7c,0xbf, -0x7e,0x71,0x26,0x6d,0x11,0x7d,0x21,0xd1,0xfd,0x75,0x25,0x0, 0x7e,0x71,0x25,0x74, -0xa, 0xac,0x7b,0x9, 0x53,0x31,0x9b,0x7a,0x51,0x27,0xbe,0x51,0x26,0x68,0x2, 0xc1, -0x90,0x49,0x23,0x31,0x99,0x74,0xa, 0xac,0xbf,0x49,0x35,0x1c,0x84,0x9d,0x32,0x12, -0x1e,0x5, 0x7d,0x63,0x7e,0x71,0x25,0x74,0xa, 0xac,0xb7,0x49,0x25,0x31,0x97,0x74, -0xa, 0xac,0xbf,0x91,0x53,0x2d,0x63,0xe5,0x26,0x7e,0x91,0x25,0x7e,0xa0,0xa, 0xac, -0x9a,0x49,0x14,0x31,0x97,0x7e,0x50,0xa, 0xac,0x5f,0x49,0x32,0x1c,0x82,0x9d,0x31, -0x49,0x14,0x31,0x99,0x49,0x22,0x1c,0x84,0x9d,0x21,0xf1,0xb0,0xbe,0x64,0xe, 0x10, -0x28,0x2, 0xa1,0xfc,0x7c,0xbf,0x7e,0x71,0x26,0x7e,0x31,0x25,0x7e,0x60,0xa, 0xac, -0x36,0x49,0x21,0x31,0x97,0x49,0x11,0x31,0x99,0xd1,0xfd,0xa, 0x3b,0x4d,0x33,0x68, -0x8, 0xbe,0x64,0x1, 0x2c,0x28,0x2, 0xa1,0xfc,0xe5,0x27,0xa, 0x3b,0x9, 0x53,0x33, -0x1f,0xbe,0x50,0x0, 0x28,0x1b,0x7e,0x41,0x27,0x74,0x2, 0xac,0xb4,0x59,0x65,0x33, -0xb, 0x2e,0x34,0x33,0x1f,0x7c,0xb5,0x14,0x7a,0x39,0xb0,0xe5,0x28,0x70,0x2, 0xc1, -0xbc,0x7e,0x71,0x27,0x74,0x2, 0xac,0x7b,0x49,0x23,0x33,0xb, 0xbe,0x24,0x0, 0xc8, -0x28,0xa, 0x7d,0x12,0x2e,0x17,0x2, 0xa8,0xbd,0x16,0x40,0x45,0xe5,0x28,0xbe,0xb0, -0x1, 0x68,0x3e,0x7e,0x17,0x31,0x60,0xbe,0x14,0x0, 0x14,0x40,0x6, 0x7e,0x14,0x0, -0x96,0x80,0x4, 0x7e,0x14,0x0, 0xf0,0x7a,0x17,0x2, 0xaa,0xbe,0x27,0x2, 0xaa,0x28, -0xa, 0x7e,0x17,0x2, 0xaa,0xbd,0x16,0x50,0x2, 0x80,0x10,0x7d,0x12,0x2e,0x14,0x0, -0xc8,0xbd,0x16,0x50,0xc, 0xbe,0x27,0x2, 0xaa,0x28,0x6, 0x59,0x63,0x33,0xb, 0xc1, -0xbc,0x7e,0x73,0x18,0xd0,0xbe,0x70,0x0, 0x28,0x2, 0xc1,0xbc,0x7e,0x73,0x31,0x4b, -0xbe,0x70,0x6, 0x50,0x6, 0x7e,0x34,0x2, 0x58,0x80,0x4, 0x7e,0x34,0x3, 0x20,0x7a, -0x35,0x72,0x7e,0xb3,0x37,0x3a,0xb4,0x1, 0x14,0xd1,0xd8,0x49,0x35,0x33,0xb, 0xbe, -0x34,0x0, 0xc8,0x28,0x8, 0x7e,0x35,0x72,0x3e,0x34,0x7a,0x35,0x72,0x7e,0x35,0x72, -0xbd,0x36,0x40,0xb, 0xe5,0x28,0xb4,0x1, 0x4f,0xbe,0x64,0x1, 0x90,0x28,0x49,0xe5, -0x26,0xa, 0x3b,0x9, 0xb3,0x1d,0xae,0x70,0x4, 0x74,0x3, 0x80,0x2, 0x74,0x1, 0x19, -0xb3,0x1d,0xae,0x7e,0xa0,0x3, 0xe5,0x27,0xa, 0x3b,0x19,0xa3,0x1d,0xb8,0xbe,0xe0, -0x0, 0x28,0x59,0x1b,0xe0,0x7e,0x70,0xa, 0xac,0x7f,0x2e,0x34,0x1c,0x82,0x7e,0x14, -0x2, 0xac,0x74,0xa, 0x12,0x1b,0xc0,0x12,0x57,0xe7,0xac,0x3f,0xd1,0xe5,0x7e,0x34, -0x2, 0xac,0xd1,0xe0,0x1b,0xf0,0x80,0x0, 0xd1,0xd8,0x59,0x65,0x33,0xb, 0x80,0x2c, -0x5, 0x25,0xe5,0x25,0xbe,0xb0,0xa, 0x50,0x2, 0x81,0xdc,0x80,0x1f,0x6d,0x33,0x7e, -0x51,0x26,0x74,0x2, 0xac,0x5b,0xd1,0xd0,0x7e,0x61,0x26,0x74,0xa, 0xac,0xb6,0xd1, -0xee,0x7e,0xa0,0x2, 0xe5,0x26,0xa, 0x3b,0x19,0xa3,0x33,0x1f,0xb, 0xf0,0xbc,0xef, -0x28,0x2, 0x81,0xaa,0xe4,0x7a,0xb3,0x18,0xd0,0x7a,0xe3,0x1d,0xea,0xda,0x3b,0x22, -0x59,0x32,0x33,0xb, 0x7e,0x70,0xff,0x22,0x7e,0x71,0x27,0x74,0x2, 0xac,0xb7,0x22, -0x7e,0x30,0xa, 0xac,0x3e,0x2e,0x14,0x1c,0x82,0x74,0xa, 0x2, 0x1b,0xc0,0x19,0x75, -0x31,0x9b,0x6d,0x33,0x59,0x32,0x32,0xcd,0x59,0x32,0x32,0xb9,0x22,0xca,0x69,0xca, -0xf8,0x7d,0x61,0x7a,0x25,0x29,0x7c,0xf7,0x7c,0x5b,0x74,0xa, 0xac,0xb5,0x49,0x35, -0x1c,0x82,0x49,0x45,0x1c,0x84,0xa, 0x2f,0x9, 0xb2,0x1d,0xae,0x7e,0xa0,0x1, 0x70, -0xe, 0x74,0x2, 0xac,0xbf,0x59,0x35,0x32,0xe3,0x59,0x45,0x32,0xf7,0x80,0x3c,0xb4, -0x2, 0x39,0x7e,0xb3,0x1c,0x7c,0x70,0x1c,0x7a,0x35,0x2b,0x7a,0x45,0x2d,0x74,0x2, -0xac,0xbf,0x49,0x35,0x32,0xe3,0x49,0x25,0x32,0xf7,0x7e,0x15,0x29,0x7d,0x6, 0x12, -0x97,0xfe,0x7c,0xab,0x4c,0xaa,0x78,0x4, 0x74,0x1, 0x80,0x10,0x7e,0x45,0x29,0x74, -0x2, 0xac,0xbf,0x59,0x45,0x32,0xe3,0x59,0x65,0x32,0xf7,0xe4,0xda,0xf8,0xda,0x69, -0x22,0x7e,0x73,0x1d,0xeb,0xbe,0x73,0x1d,0xea,0x78,0x12,0xf1,0xa8,0x40,0xe, 0x7e, -0x37,0x31,0x60,0xbe,0x34,0x0, 0x14,0x38,0xe, 0xb, 0x34,0x80,0x6, 0x7e,0x37,0x31, -0x60,0x1e,0x34,0x7a,0x37,0x31,0x60,0x7e,0xb3,0x1d,0xea,0x70,0x6, 0x6d,0x33,0x7a, -0x37,0x31,0x60,0x7e,0x37,0x31,0x60,0x22,0x7e,0x73,0x1d,0xea,0xbe,0x70,0x1, 0x22, -0x7d,0x12,0x7d,0x3, 0x7c,0x5b,0x3e,0x4, 0x3e,0x4, 0x3e,0x14,0x3e,0x14,0x74,0x2, -0xac,0xb5,0x49,0x45,0x32,0xb9,0x4d,0x44,0x78,0x11,0x49,0x35,0x32,0xcd,0x4d,0x33, -0x78,0x9, 0x59,0x5, 0x32,0xb9,0x59,0x15,0x32,0xcd,0x22,0x2d,0x4, 0xe, 0x4, 0x59, -0x5, 0x32,0xb9,0x49,0x35,0x32,0xcd,0x2d,0x31,0xe, 0x34,0x59,0x35,0x32,0xcd,0x22, -0x7e,0xa3,0x1d,0xeb,0xbe,0xa0,0x0, 0x38,0x2f,0xbe,0xa3,0x1d,0xea,0x50,0x19,0x7e, -0xb3,0x1d,0xf4,0xbe,0xb3,0x33,0x2a,0x28,0x14,0x7e,0xb3,0x33,0x2a,0x4, 0x7a,0xb3, -0x33,0x2a,0x7a,0xa3,0x1d,0xea,0x80,0x5, 0xe4,0x7a,0xb3,0x33,0x2a,0x7e,0xb3,0x1d, -0xea,0x70,0x5, 0xe4,0x7a,0xb3,0x1d,0xf3,0x22,0x6c,0x77,0x74,0xa, 0xac,0xb7,0x49, -0x25,0x1d,0x4a,0x1e,0x24,0x1e,0x24,0x59,0x25,0x1c,0x82,0x74,0xa, 0xac,0xb7,0x49, -0x25,0x1d,0x4c,0x1e,0x24,0x1e,0x24,0x59,0x25,0x1c,0x84,0x74,0xa, 0xac,0xb7,0x9, -0x65,0x1d,0x4e,0x19,0x65,0x1c,0x86,0x74,0xa, 0xac,0xb7,0x9, 0x65,0x1d,0x4f,0x19, -0x65,0x1c,0x87,0x74,0xa, 0xac,0xb7,0x9, 0x65,0x1d,0x50,0x19,0x65,0x1c,0x88,0xb, -0x70,0xbe,0x70,0xa, 0x40,0xb5,0x22,0x7d,0x43,0x7e,0x34,0x17,0x8c,0x7a,0x37,0x2, -0xaa,0x7e,0x34,0x17,0xb4,0x7a,0x37,0x2, 0xac,0x7e,0x34,0x17,0xdc,0x7a,0x37,0x2, -0xae,0x74,0x1, 0x7a,0xb3,0x2, 0xa8,0x7a,0xb3,0x2, 0xa9,0x7a,0x47,0x17,0x8c,0x7a, -0x27,0x17,0x8e,0x7a,0x17,0x17,0xb4,0x7a,0x7, 0x17,0xb6,0x7e,0x8, 0x2, 0xa8,0x12, -0x14,0xb3,0x7e,0x37,0x17,0xdc,0x22,0xca,0x3b,0x7c,0xf7,0x7c,0xeb,0x75,0x26,0x0, -0x7e,0xd3,0x3c,0xee,0xa, 0x3f,0x9, 0xb3,0x3b,0x6d,0xbe,0xb0,0x2, 0x78,0x2, 0x21, -0x7b,0x74,0xa, 0xac,0xbe,0x49,0x35,0x1c,0x82,0x49,0x25,0x1c,0x84,0x74,0xa, 0xac, -0xbf,0xf1,0xa9,0xbe,0x34,0x0, 0xc8,0x28,0x6, 0x74,0x20,0x7a,0xb3,0x3a,0xd6,0x7e, -0x35,0x28,0xbe,0x34,0x0, 0xa0,0x28,0x13,0xf1,0xa0,0x7e,0x24,0x1, 0x0, 0xb1,0xed, -0x40,0x9, 0x74,0x20,0x7a,0xb3,0x3a,0xe4,0xe4,0x80,0x26,0x12,0xd1,0xdd,0x28,0x9, -0xf1,0xcf,0x50,0x5, 0x14,0x7a,0xb3,0x3a,0xd6,0x12,0xd1,0xd5,0x28,0x9, 0xf1,0xcf, -0x50,0x5, 0x14,0x7a,0xb3,0x3a,0xe4,0x7e,0xb3,0x3a,0xd7,0xbe,0xb0,0x46,0x50,0x5, -0x4, 0x7a,0xb3,0x3a,0xd7,0x12,0x57,0xe7,0xf1,0xe0,0xa, 0x3f,0x9, 0xb3,0x3b,0x6d, -0x70,0x36,0x74,0x14,0x7a,0xb3,0x3b,0xe6,0xbe,0xd0,0x1, 0x78,0x4, 0xf1,0x8c,0x40, -0x9, 0xbe,0xd0,0x2, 0x78,0xa, 0xf1,0x8c,0x28,0x6, 0x74,0x14,0x7a,0xb3,0x3a,0xf3, -0xbe,0xd0,0x1, 0x78,0x4, 0xf1,0x8c,0x38,0x9, 0xbe,0xd0,0x2, 0x78,0xa, 0xf1,0x8c, -0x50,0x6, 0x74,0x14,0x7a,0xb3,0x3a,0xef,0xe4,0xa1,0xde,0xf1,0xd7,0x49,0x25,0x3b, -0xb, 0xf1,0xa9,0x12,0x57,0xe7,0xf1,0xe0,0xa, 0x3f,0x9, 0xb3,0x3a,0xda,0xbe,0xb0, -0xff,0x50,0x8, 0x2e,0x34,0x3a,0xda,0x4, 0x7a,0x39,0xb0,0x7e,0x34,0x0, 0x1, 0x7c, -0xbf,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x5e,0x37,0x3a,0xf1,0x68,0x20,0x12,0x7b, -0xea,0x70,0x2, 0xf1,0xb7,0xf1,0x99,0x70,0x4, 0xf5,0x25,0x81,0xf5,0x7e,0xb3,0x3d, -0x32,0xb4,0x1, 0x5, 0x75,0x25,0x0, 0x81,0xf5,0x75,0x25,0x1, 0x81,0xf5,0x7c,0xbe, -0x7c,0x7f,0x6c,0x66,0x12,0xbe,0x2, 0x7c,0xcb,0xbe,0xc0,0x0, 0x28,0x24,0xbe,0xc0, -0x3, 0x50,0x1f,0xf1,0xa0,0x7e,0xb3,0x3a,0xe4,0x60,0x6, 0x7e,0x24,0x0, 0x8, 0x80, -0x2, 0x6d,0x22,0x3e,0x24,0x3e,0x24,0x2e,0x24,0x0, 0xb4,0xb1,0xed,0x50,0x3, 0x7e, -0xc0,0x3, 0xa, 0x3f,0x9, 0x73,0x3a,0xda,0xbe,0x70,0x3c,0x50,0x32,0x4c,0xdd,0x78, -0x2e,0xbe,0xc0,0x0, 0x28,0x29,0xbe,0xc0,0x3, 0x50,0x24,0xf1,0xa0,0x7e,0x24,0x2, -0x80,0xb1,0xed,0x50,0x1a,0x74,0xa, 0xac,0xbf,0x49,0x35,0x3b,0x83,0xbe,0x34,0x20, -0x80,0x28,0xc, 0x7e,0x35,0x28,0xbe,0x34,0x0, 0x60,0x28,0x3, 0x7e,0xc0,0x3, 0x4c, -0xdd,0x78,0x52,0x4c,0xcc,0x68,0x24,0x74,0xa, 0xac,0xbf,0x49,0x45,0x3b,0x9, 0xbe, -0x44,0x2, 0x0, 0x50,0x16,0x49,0x25,0x3b,0x81,0x74,0xa, 0xac,0xbe,0x49,0x35,0x1c, -0x82,0x9d,0x32,0xbe,0x34,0x1, 0x0, 0x8, 0x2, 0x6c,0xcc,0x4c,0xcc,0x68,0x47,0x74, -0xa, 0xac,0xbf,0x49,0x45,0x3b,0x9, 0xbe,0x44,0xe, 0x0, 0x28,0x39,0x49,0x35,0x3b, -0x81,0x74,0xa, 0xac,0xbe,0x49,0x25,0x1c,0x82,0x9d,0x32,0xbe,0x34,0x1, 0x0, 0x8, -0x25,0x6c,0xcc,0x80,0x21,0x4c,0xcc,0x68,0x1d,0x74,0xa, 0xac,0xbf,0x49,0x35,0x3b, -0x83,0x74,0xa, 0xac,0xbe,0x49,0x25,0x1c,0x84,0x9d,0x32,0x12,0x1e,0x5, 0xbe,0x34, -0x1, 0x0, 0x8, 0x2, 0x6c,0xcc,0xd1,0x3, 0xf5,0x27,0xbe,0xc0,0x3, 0x50,0xa, 0xe5, -0x27,0x30,0xe1,0x5, 0x7e,0xc0,0x3, 0x80,0x21,0xbe,0xc0,0x2, 0x38,0xf, 0xe5,0x27, -0x30,0xe2,0xa, 0xe5,0x27,0x20,0xe1,0x5, 0x7e,0xc0,0x2, 0x80,0xa, 0xe5,0x27,0x20, -0xe1,0x8, 0xbe,0xc0,0x2, 0x38,0x3, 0x75,0x26,0x1, 0xe5,0x27,0x30,0xe3,0x15,0x30, -0x10,0x21,0x74,0xff,0xf1,0xb8,0x75,0x26,0x0, 0x7e,0xc0,0x8, 0x74,0x8, 0x19,0xb3, -0x3b,0x77,0x80,0xf, 0xe5,0x27,0x70,0xb, 0xf1,0x99,0xb4,0xff,0x6, 0x74,0x24,0x19, -0xb3,0x3a,0xcc,0x7e,0x50,0xa, 0xac,0x5f,0x9, 0x72,0x3b,0x10,0xbe,0x70,0x1, 0x28, -0xa, 0xbe,0x70,0xe, 0x50,0x5, 0xbe,0xd0,0x0, 0x28,0x7b,0x7e,0xb3,0x3a,0xe4,0x70, -0x75,0x6d,0x44,0x4c,0xdd,0x78,0x2f,0x9, 0xa2,0x3b,0x11,0xbe,0xa0,0x0, 0x28,0xb, -0x7c,0xb7,0xa, 0x3a,0x1b,0x34,0x12,0x2d,0x89,0x7d,0x43,0x7e,0x70,0xa, 0xac,0x7f, -0x9, 0xa3,0x3b,0x11,0xbe,0xa0,0x22,0x50,0xd, 0x9, 0xb3,0x3b,0x10,0xa, 0x3a,0xb, -0x34,0x12,0x2d,0x89,0x2d,0x43,0x7e,0x70,0xb, 0xac,0x7c,0x2d,0x34,0xbe,0x34,0x0, -0xdc,0x58,0x16,0x7e,0x70,0xa, 0xac,0x7f,0x9, 0xb3,0x3b,0x10,0x9, 0x73,0x3b,0x11, -0x12,0x2d,0x89,0xbe,0x34,0x0, 0x21,0x48,0x1b,0x7e,0x35,0x28,0xbe,0x34,0x0, 0xe4, -0x28,0x14,0xbe,0xc0,0x2, 0x38,0xf, 0xa, 0x3f,0x12,0xc1,0x31,0x50,0x8, 0x7e,0xb3, -0x3a,0xd8,0x70,0x2, 0x6c,0xcc,0xa, 0xff,0x9, 0x7f,0x3a,0xcc,0xbe,0x70,0x24,0x28, -0x2, 0x81,0x64,0xbe,0xc0,0x2, 0x28,0x2, 0x81,0x64,0x4c,0xdd,0x78,0x18,0x74,0xa, -0xac,0xbf,0x49,0x45,0x3b,0x81,0x7a,0x45,0x2a,0x49,0xe5,0x3b,0x9, 0x7a,0xe5,0x2c, -0x7e,0xe4,0x10,0x0, 0x80,0x16,0x74,0xa, 0xac,0xbf,0x49,0x45,0x3b,0x83,0x7a,0x45, -0x2a,0x49,0xe5,0x3b,0xb, 0x7a,0xe5,0x2c,0x7e,0xe4,0x23,0x0, 0x7a,0xe5,0x2e,0xe5, -0x27,0x20,0xe2,0x2f,0x9, 0x7f,0x3b,0x77,0xbe,0x70,0x5, 0x50,0x26,0x9, 0x7f,0x3a, -0xda,0xbe,0x70,0x24,0x50,0x1d,0x7e,0x35,0x2a,0x7e,0x24,0x1, 0x40,0x7e,0x15,0x2e, -0xb1,0xf1,0x40,0xf, 0x4c,0xdd,0x68,0x2, 0x81,0x9d,0xe4,0xa, 0xef,0x19,0xbe,0x3a, -0xcc,0x80,0x7a,0xa, 0xef,0x9, 0x7e,0x3b,0x77,0xbe,0x70,0x4, 0x50,0x6f,0x7e,0xb3, -0x3a,0xe4,0x70,0x69,0x7e,0x35,0x2c,0x7e,0x24,0x0, 0xb4,0x7e,0x15,0x2e,0xb1,0xf1, -0x40,0x2, 0x80,0x1b,0x7e,0xe4,0x1, 0x0, 0x7c,0xbf,0x12,0xc1,0xaf,0x50,0x4, 0x7e, -0xe4,0x2, 0x0, 0x7e,0x35,0x2a,0x7d,0x2e,0x7e,0x15,0x2e,0xb1,0xf1,0x40,0x3e,0x75, -0x26,0x1, 0x80,0x39,0xbe,0xc0,0x0, 0x28,0x34,0x4c,0xdd,0x78,0x30,0x30,0xf, 0x1e, -0xbe,0xc0,0x5, 0x50,0x19,0x74,0xa, 0xac,0xbf,0x49,0xe5,0x3b,0x83,0xbe,0xe4,0xd, -0x0, 0x50,0xb, 0x75,0x26,0x1, 0x74,0x2, 0x19,0xbf,0x3b,0x77,0x80,0xf, 0x9, 0x7f, -0x3a,0xcc,0xbe,0x70,0xff,0x50,0x6, 0x74,0x24,0x19,0xbf,0x3a,0xcc,0x4c,0xcc,0x78, -0x10,0xa, 0x3f,0x9, 0x53,0x3a,0xcc,0xbe,0x50,0xff,0x50,0x5, 0xe4,0x19,0xb3,0x3a, -0xcc,0xf1,0x99,0x60,0x32,0x70,0x4, 0xf5,0x25,0x80,0x2f,0x75,0x25,0x1, 0x9, 0x73, -0x3b,0x77,0xbe,0x70,0x3, 0x50,0x23,0xf1,0xf6,0x50,0x1f,0xe5,0x27,0x20,0xe1,0x1a, -0x4c,0xdd,0x68,0x4, 0xb1,0xe1,0x40,0x12,0xf1,0xd7,0x7e,0x24,0x0, 0xb4,0xb1,0xed, -0x40,0x8, 0x75,0x26,0x1, 0x80,0x3, 0x75,0x25,0x0, 0x4c,0xdd,0x78,0x7, 0xb1,0xe1, -0x50,0x3, 0x75,0x26,0x0, 0xa, 0x4f,0x9, 0xb4,0x3a,0xcc,0xbe,0xb0,0x0, 0x28,0x11, -0xbe,0xb0,0xff,0x50,0xc, 0x7d,0x34,0x2e,0x34,0x3a,0xcc,0x9e,0xb1,0x26,0x7a,0x39, -0xb0,0xe5,0x25,0x60,0x17,0x74,0xa, 0xac,0xbf,0x49,0x55,0x3b,0x83,0xbe,0x54,0x11, -0x80,0x28,0x2, 0xd2,0xf, 0x12,0xc1,0x6b,0x74,0x1, 0xa1,0xde,0x7e,0xb3,0x3a,0xd6, -0x70,0x8, 0x7e,0x73,0x31,0x95,0x19,0x74,0x31,0x8b,0x74,0x3, 0x19,0xb4,0x3b,0x6d, -0x7e,0x70,0xa, 0xac,0x7e,0x49,0x3, 0x1c,0x82,0x7e,0x50,0xa, 0xac,0x5f,0x49,0x52, -0x3b,0x9, 0x7d,0x15,0x2e,0x14,0x0, 0x50,0xbd,0x10,0x50,0xc, 0xbe,0x54,0x0, 0xa0, -0x50,0x6, 0x7e,0x54,0x0, 0xa0,0x80,0x14,0x7d,0x15,0x9e,0x14,0x0, 0x50,0xbd,0x10, -0x28,0xe, 0xbe,0x54,0xf, 0x60,0x28,0x8, 0x7e,0x54,0xf, 0x60,0x59,0x52,0x3b,0x9, -0x74,0x3, 0x19,0xb4,0x31,0x62,0x49,0x22,0x3b,0xb, 0x12,0x8c,0x42,0x7d,0x43,0x74, -0xa, 0xac,0xbf,0x49,0x25,0x3b,0x9, 0x12,0x8c,0x4f,0xbe,0xd0,0x0, 0x28,0x6, 0x7d, -0x24,0x7d,0x43,0x7d,0x32,0xbe,0x44,0x0, 0xe4,0x40,0x1c,0xbe,0x34,0x0, 0x20,0x50, -0x16,0x7e,0x70,0xa, 0xac,0x7f,0x2e,0x34,0x3b,0x81,0x12,0x8e,0xe0,0x74,0x4, 0xa, -0x3f,0x19,0xb3,0x31,0x62,0x80,0xc, 0x7e,0x70,0xa, 0xac,0x7f,0x2e,0x34,0x3b,0x9, -0x12,0x8e,0xe0,0xe4,0xa, 0x3f,0x19,0xb3,0x1d,0xae,0x19,0xb3,0x1d,0xb8,0xda,0x3b, -0x22,0x74,0xa, 0xac,0xbf,0x49,0x35,0x3b,0x81,0x7e,0x24,0x0, 0xc0,0x7e,0x14,0x10, -0x0, 0x7d,0x1, 0x7d,0x13,0xbd,0x21,0x38,0x6, 0x9d,0x2, 0xbd,0x1, 0x50,0x2, 0xd3, -0x22,0xc3,0x22,0x7c,0xbf,0x6c,0x77,0xca,0x79,0x7c,0x87,0x7c,0x9b,0x6c,0xff,0x74, -0xa, 0xac,0xb9,0x49,0xe5,0x3b,0x81,0x49,0xf5,0x3b,0x83,0x7e,0xe3,0x3c,0xee,0x4c, -0xee,0x78,0x4a,0x7d,0x3e,0x7e,0x24,0x0, 0xa0,0xb1,0xed,0x50,0x24,0x7e,0xf0,0x6, -0xbe,0xf4,0x21,0x0, 0x40,0xd, 0xf1,0xc7,0x38,0x6, 0x7e,0xb3,0x3b,0xe6,0x60,0x3, -0x7e,0xf0,0x7, 0xa, 0x39,0x9, 0x93,0x3a,0xda,0xbe,0x90,0x1e,0x28,0x3, 0x4e,0xf0, -0x1, 0x7d,0x3e,0x7e,0x24,0x1, 0x7c,0xb1,0xed,0x40,0x2, 0xe1,0x87,0xbe,0xf4,0x20, -0x18,0x50,0x2, 0xe1,0x87,0x4e,0xf0,0x4, 0x4e,0xf0,0x8, 0xe1,0x87,0x7e,0xb3,0x3c, -0xef,0x7e,0x90,0x4, 0xac,0xb9,0x7d,0xd5,0x2e,0xd4,0x3a,0xf5,0x6d,0xcc,0xbe,0xe0, -0x1, 0x78,0xc, 0xf1,0xeb,0xb1,0xf1,0x50,0x6, 0xbe,0xe4,0x2, 0x12,0x28,0x11,0xbe, -0xe0,0x2, 0x78,0x5a,0xf1,0xeb,0xb1,0xf1,0x50,0x54,0xbe,0xe4,0xd, 0xee,0x40,0x4e, -0x7e,0xf0,0x4, 0x4c,0x88,0x68,0x2, 0x80,0x42,0xf1,0xc7,0x38,0x6, 0x7e,0xb3,0x3b, -0xe6,0x60,0x3b,0xbe,0xf4,0x2, 0x2e,0x38,0x16,0x7e,0xb3,0x3a,0xf3,0x60,0x5, 0xbe, -0xe0,0x1, 0x68,0x27,0x7e,0xb3,0x3a,0xef,0x60,0x5, 0xbe,0xe0,0x2, 0x68,0x1c,0xbe, -0xf4,0x20,0xd2,0x40,0x19,0x7e,0xb3,0x3a,0xf3,0x60,0x5, 0xbe,0xe0,0x2, 0x68,0xb, -0x7e,0xb3,0x3a,0xef,0x60,0x8, 0xbe,0xe0,0x1, 0x78,0x3, 0x7e,0xf0,0x7, 0x7d,0x3f, -0x29,0x46,0x0, 0x1, 0x7e,0x50,0x8, 0xac,0x45,0x7e,0x14,0x23,0x0, 0xb1,0xf1,0x50, -0x26,0xbe,0xe0,0x1, 0x78,0x8, 0xf1,0xbf,0xac,0xb7,0xbd,0x5e,0x38,0x13,0xbe,0xe0, -0x2, 0x78,0x14,0xf1,0xbf,0xac,0xb7,0x7e,0x34,0x10,0x0, 0x9d,0x35,0xbd,0x3e,0x38, -0x6, 0x4e,0xf0,0x4, 0x4e,0xf0,0x8, 0x7e,0x6b,0xb0,0x7e,0x70,0x8, 0xac,0xb7,0xbd, -0x5f,0x28,0x2, 0x80,0x3e,0x29,0xb6,0x0, 0x3, 0x7e,0x70,0x2, 0xac,0xb7,0x7e,0x34, -0x8, 0xc0,0x9d,0x35,0x3e,0x34,0x3e,0x34,0xbd,0x3f,0x38,0x5, 0x4e,0xf0,0x4, 0x80, -0x25,0xbe,0xf4,0x2, 0x0, 0x40,0x6, 0xbe,0xf4,0x21,0x0, 0x40,0x19,0xbe,0xe0,0x1, -0x78,0x6, 0xbe,0xe4,0xf, 0x0, 0x38,0xb, 0xbe,0xe0,0x2, 0x78,0x9, 0xbe,0xe4,0x1, -0x0, 0x50,0x3, 0x4e,0xf0,0x6, 0x7d,0x3f,0x7e,0x24,0x0, 0xb4,0x7e,0x14,0x23,0x0, -0xb1,0xf1,0x50,0x3, 0x4e,0xf0,0x2, 0x7c,0xbf,0xda,0x79,0x22,0x74,0xa, 0xac,0xbf, -0x49,0x35,0x3b,0x83,0xbe,0x34,0x11,0x0, 0x22,0xa, 0x3f,0x9, 0xb3,0x3a,0xcc,0x22, -0x74,0xa, 0xac,0xbf,0x49,0x35,0x3b,0x81,0x22,0x49,0x15,0x3b,0x81,0x49,0x5, 0x3b, -0x83,0x11,0x77,0x7a,0x35,0x28,0x22,0xe4,0xa, 0x3f,0x19,0xb3,0x3a,0xcc,0x22,0x29, -0xb6,0x0, 0x2, 0x7e,0x70,0x8, 0x22,0x7e,0x73,0x3a,0xd9,0xbe,0x70,0x0, 0x22,0x7e, -0x35,0x28,0xbe,0x34,0x0, 0x50,0x22,0x74,0xa, 0xac,0xbf,0x49,0x35,0x3b,0x9, 0x22, -0xac,0x3f,0x2e,0x14,0x3b,0x81,0x74,0xa, 0x2, 0x1b,0xc0,0x7d,0x3f,0x7e,0x24,0x2, -0x2e,0x7e,0x14,0x23,0x0, 0x22,0x7e,0x73,0x1c,0x58,0xbe,0x70,0x2, 0x22,0xca,0x3b, -0x7d,0xd0,0x7d,0xc1,0x7d,0xb2,0x7d,0xa3,0x7e,0x75,0x2b,0x7e,0x65,0x2d,0x75,0x3b, -0x1, 0x75,0x3c,0x57,0xbd,0xd6,0x8, 0x7, 0xbd,0xc7,0x58,0x3, 0x75,0x3c,0x4b,0x7d, -0x1b,0x1a,0x2, 0x1a,0x0, 0x7d,0x3d,0x11,0xf0,0x7f,0x71,0x7d,0x1a,0x1a,0x2, 0x1a, -0x0, 0x7d,0x3c,0x11,0xf0,0x2f,0x17,0x7a,0x1d,0x2f,0x11,0xd3,0x2f,0x17,0x7a,0x1d, -0x33,0x9d,0x7c,0x9d,0x6d,0x9d,0xca,0x9d,0xdb,0x11,0xd3,0x7f,0x21,0x2f,0x27,0x7e, -0xd, 0x33,0x7e,0x1d,0x2f,0x2f,0x1, 0x9f,0x2, 0x7a,0xd, 0x37,0x11,0xfb,0x7a,0x1d, -0x2f,0x7e,0x1d,0x33,0x11,0xfb,0x7a,0x1d,0x33,0x7e,0x7d,0x33,0xbe,0x78,0x0, 0xc8, -0x58,0x4, 0x74,0x1, 0x80,0x5a,0x7e,0x1d,0x2f,0x7f,0x7, 0x12,0x1b,0x1f,0x7f,0x21, -0x2f,0x22,0x7e,0x14,0x0, 0x64,0x7e,0x1d,0x37,0x12,0x1b,0x30,0x7f,0x2, 0x12,0x1b, -0x8c,0x7a,0x1d,0x37,0xbe,0x18,0x0, 0x64,0x8, 0x9, 0x7e,0x8, 0x0, 0x64,0x7a,0xd, -0x37,0x80,0xd, 0xbe,0x1c,0xff,0x9c,0x58,0x7, 0x7e,0x1c,0xff,0x9c,0x7a,0x1d,0x37, -0xe5,0x3c,0xa, 0x1b,0x6d,0x0, 0x7e,0x1d,0x37,0xbf,0x10,0x58,0x11,0x2e,0x18,0x0, -0xa0,0x2f,0x11,0x2f,0x11,0x2f,0x11,0xbf,0x71,0x8, 0x3, 0x75,0x3b,0x0, 0xe5,0x3b, -0xda,0x3b,0x22,0x7d,0x1d,0x1a,0x2, 0x1a,0x0, 0x7d,0x36,0x1a,0x26,0x1a,0x24,0x9f, -0x10,0x7f,0x1, 0x12,0x1b,0x1f,0x7f,0x71,0x7d,0x1c,0x1a,0x2, 0x1a,0x0, 0x7d,0x37, -0x1a,0x26,0x1a,0x24,0x9f,0x10,0x7f,0x1, 0x2, 0x1b,0x1f,0x7c,0xb4,0x12,0x18,0x53, -0x12,0x18,0xcd,0x2, 0x18,0x90,0x6c,0x33,0x6c,0x22,0x74,0xa, 0xac,0xb2,0x9, 0x15, -0x1c,0x86,0xbe,0x10,0xa, 0x50,0x4f,0xa, 0x31,0x9, 0xb3,0x1d,0xae,0x70,0x16,0x74, -0xa, 0xac,0xb1,0x49,0x45,0x1c,0x82,0x59,0x45,0x32,0x55,0x49,0x35,0x1c,0x84,0x59, -0x35,0x32,0x57,0x80,0x31,0x74,0xa, 0xac,0xb1,0x49,0x45,0x32,0x55,0x49,0x35,0x1c, -0x82,0x9d,0x43,0x49,0xf5,0x32,0x57,0x49,0x55,0x1c,0x84,0x9d,0xf5,0x7d,0x3f,0x12, -0x1e,0x5, 0x7d,0x53,0x7d,0x34,0x12,0x1e,0x5, 0x2d,0x53,0xbe,0x54,0x2, 0x0, 0x8, -0x5, 0x7e,0x30,0x1, 0x80,0x7, 0xb, 0x20,0xbe,0x20,0xa, 0x40,0x9d,0x7e,0xa3,0x1d, -0xea,0xbe,0xa0,0x0, 0x28,0x14,0x7e,0xb3,0x32,0xe1,0xbe,0xb0,0xf, 0x50,0x5, 0x4, -0x7a,0xb3,0x32,0xe1,0x4c,0x33,0x68,0x7, 0x80,0x0, 0xe4,0x7a,0xb3,0x32,0xe1,0x7e, -0xb3,0x31,0x8a,0xb4,0x2, 0x18,0xbe,0xa0,0x1, 0x28,0x13,0x7e,0x73,0x32,0xe1,0xbe, -0x70,0xf, 0x50,0xa, 0x7e,0xb3,0x3d,0x32,0x70,0x4, 0x74,0x1, 0x80,0x1, 0xe4,0x7a, -0xb3,0x31,0x95,0x7e,0xb3,0x31,0x8a,0xb4,0x2, 0xe, 0x7e,0x73,0x31,0x96,0xbe,0x73, -0x31,0x95,0x28,0x4, 0x7a,0x73,0x31,0x95,0x22,0x7e,0x73,0x3c,0xe3,0xa, 0x17,0x3e, -0x14,0x3e,0x14,0x9e,0x14,0x0, 0x8c,0x12,0x97,0xf6,0x50,0x3, 0x6d,0x33,0x22,0x7e, -0x37,0x1c,0x5e,0x12,0x7f,0xd, 0x7e,0x57,0x1e,0x76,0x7e,0x44,0x0, 0x3, 0x8d,0x54, -0x7d,0x25,0x3e,0x24,0x2e,0x27,0x1e,0x76,0xbd,0x23,0x50,0x2, 0x7d,0x32,0xbe,0x14, -0x0, 0x0, 0x58,0x2, 0x6d,0x11,0xbe,0x14,0x0, 0x64,0x8, 0x4, 0x7e,0x14,0x0, 0x64, -0x7e,0x27,0x1e,0x76,0x2d,0x21,0x7e,0x33,0x1d,0xeb,0xbe,0x30,0x0, 0x28,0x4, 0x2e, -0x24,0x0, 0x32,0xbd,0x23,0x28,0x2, 0x7d,0x32,0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x1e, -0x6b,0x7e,0xb3,0x1c,0x58,0xbe,0xb0,0x0, 0x28,0x35,0x6d,0x22,0x9d,0x23,0xbe,0x27, -0x9, 0x60,0x58,0x2b,0x12,0x7f,0xd, 0xbe,0x37,0x9, 0x62,0x8, 0x22,0xe4,0x7a,0xb3, -0x1c,0x58,0x7e,0xb3,0x1d,0xeb,0x70,0x17,0x7e,0xb3,0x3d,0x9, 0xb4,0x1, 0x10,0x6c, -0xaa,0x5, 0x7b,0xe5,0x7b,0xbe,0xb0,0x10,0x28,0x5, 0xd2,0x1a,0x75,0x7b,0x0, 0x4c, -0xaa,0x68,0x3, 0x75,0x7b,0x0, 0x22,0x7e,0x73,0x18,0xd1,0xa, 0x37,0x5e,0x34,0x0, -0x1, 0x68,0x22,0x7e,0x37,0x1c,0x6d,0x7a,0x35,0x29,0xd2,0x7, 0x7e,0x8, 0x5, 0x56, -0x7e,0x18,0x4, 0x72,0x12,0x6b,0xf7,0x2e,0x37,0x35,0x50,0x7a,0x37,0x35,0x50,0xe, -0x34,0x7a,0x37,0x35,0x50,0x7e,0x73,0x18,0xd1,0x12,0x26,0xe2,0x68,0x24,0x7e,0x37, -0x1e,0x6b,0x7a,0x35,0x29,0xd2,0x7, 0x7e,0x8, 0x4, 0xe4,0x7e,0x18,0x4, 0x0, 0x12, -0x6b,0xf7,0x2e,0x37,0x35,0x2c,0x7a,0x37,0x35,0x2c,0xe, 0x34,0x7a,0x37,0x35,0x2c, -0x80,0x13,0x7e,0x34,0x0, 0x46,0xca,0x39,0x7e,0x18,0x5, 0x56,0x7e,0x8, 0x4, 0xe4, -0x12,0x1d,0xae,0x1b,0xfd,0x7e,0x73,0x1c,0x68,0xbe,0x70,0x5, 0x50,0x18,0x7e,0x37, -0x35,0x2c,0xbe,0x34,0x0, 0x3c,0x58,0xe, 0x7e,0x37,0x35,0x50,0xbe,0x34,0x1, 0x90, -0x8, 0x4, 0xd2,0x1b,0x80,0x19,0x30,0x1b,0x16,0x7e,0x37,0x35,0x2c,0xbe,0x34,0x0, -0x32,0x58,0xc, 0x7e,0x37,0x35,0x50,0xbe,0x34,0x0, 0x32,0x58,0x2, 0xc2,0x1b,0x71, -0x27,0xe4,0x7a,0xb3,0x3, 0xfe,0x22,0xca,0xd8,0xca,0x79,0x7e,0xf3,0x1e,0x8b,0x7e, -0xe3,0x1e,0x8c,0xd1,0x5f,0x6c,0xdd,0x80,0x19,0xc2,0x7, 0x71,0x5b,0x4d,0x33,0x68, -0xf, 0x7e,0x18,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0xd1,0xbd, -0xb, 0xd0,0xbc,0xfd,0x38,0xe3,0xda,0x79,0xda,0xd8,0x22,0x7c,0xbd,0x7c,0x7e,0xca, -0x69,0xca,0xf8,0x7c,0xf7,0x7c,0x3b,0xc2,0x8, 0x74,0x46,0xac,0xb3,0x7e,0x5f,0x15, -0x48,0x2d,0xb5,0x74,0x2, 0xac,0xb3,0x49,0x95,0x35,0x76,0x49,0x65,0x35,0xbc,0x20, -0x7, 0xa, 0xbe,0x94,0x0, 0x14,0x58,0x4, 0x6d,0x33,0x81,0x9c,0xbe,0x94,0x4, 0xb0, -0x8, 0x2, 0xd2,0x8, 0x6c,0x77,0x74,0x4, 0xac,0xb7,0x49,0x45,0x34,0xe4,0xbd,0x49, -0x58,0x6, 0x49,0x95,0x34,0xe6,0x80,0x7, 0xb, 0x70,0xbe,0x70,0x3, 0x40,0xe7,0xa5, -0xbf,0x3, 0x4, 0x6d,0x33,0x81,0x9c,0x7e,0xb3,0x1c,0x68,0xb4,0x1, 0xa, 0xbe,0x94, -0x0, 0x46,0x58,0x4, 0x7e,0x94,0x0, 0x46,0xbd,0x69,0x8, 0xe, 0xbe,0x64,0x0, 0x78, -0x58,0x4, 0x7d,0x96,0x80,0x4, 0x7e,0x94,0x0, 0x78,0x7a,0xf1,0x52,0x6d,0x88,0x7a, -0x85,0x53,0x7a,0x85,0x55,0x7a,0x85,0x57,0x7e,0x34,0x0, 0x1, 0x7a,0x35,0x59,0x7a, -0x85,0x5b,0xb1,0x75,0x91,0xa1,0x7a,0xf1,0x52,0x7e,0x87,0x36,0x2, 0x7a,0x85,0x53, -0x6d,0x88,0x9e,0x87,0x36,0x2, 0x7a,0x85,0x55,0x6d,0x88,0x7a,0x85,0x57,0x7a,0x85, -0x59,0x7a,0x85,0x5b,0x7e,0x84,0x0, 0x2, 0xb1,0x75,0x91,0xa1,0x7e,0x87,0x36,0x2, -0xbe,0x84,0xff,0xce,0x58,0x10,0x69,0x35,0x0, 0x44,0x6d,0x22,0x9d,0x29,0xbd,0x32, -0x58,0x4, 0x6d,0x99,0x9d,0x93,0x7e,0x37,0x36,0x2, 0xbe,0x34,0x7f,0xff,0x78,0x1f, -0xb, 0x5a,0x30,0xbe,0x34,0x0, 0x0, 0x58,0xa, 0x6d,0x22,0x9d,0x26,0x7a,0x27,0x36, -0x2, 0x80,0x24,0xbe,0x34,0x0, 0x0, 0x8, 0x1e,0x7a,0x67,0x36,0x2, 0x80,0x18,0xbd, -0x89,0x8, 0x6, 0x7a,0x97,0x36,0x2, 0x80,0xe, 0x6d,0x33,0x9d,0x39,0xbe,0x37,0x36, -0x2, 0x8, 0x4, 0x7a,0x37,0x36,0x2, 0x7a,0x5d,0x52,0x7a,0xf1,0x57,0x6d,0x33,0x7a, -0x35,0x58,0x7a,0x35,0x5a,0xb1,0x78,0xb1,0x81,0x7e,0x37,0x36,0x2, 0xbe,0x34,0xff, -0xce,0x18,0x9, 0x7e,0xb3,0x35,0x74,0x4, 0x7a,0xb3,0x35,0x74,0xda,0xf8,0xda,0x69, -0x22,0x7f,0x71,0x7f,0x60,0x7e,0x45,0x5d,0xa9,0xd6,0xcb,0xd1,0xa9,0x7d,0x3d,0xd1, -0x9a,0x79,0x30,0x0, 0x8, 0x7e,0x35,0x53,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xe, -0x7e,0x35,0x55,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x10,0x7c,0x6b,0xe5,0x52,0x7c, -0xa6,0x7e,0x1f,0x3e,0x43,0x79,0x51,0x0, 0xc, 0x5e,0x44,0x0, 0x3, 0x7d,0x14,0x7c, -0x23,0x6c,0x33,0x3e,0x14,0x3e,0x14,0x3e,0x14,0x7e,0x1f,0x3e,0x43,0x2e,0x34,0x0, -0x38,0xb1,0x6c,0x7e,0x15,0x5b,0x7c,0x23,0x6c,0x33,0xb1,0x68,0x7e,0x55,0x59,0x7d, -0x15,0x7c,0x23,0x6c,0x33,0xb1,0x66,0x7e,0x55,0x57,0x7d,0x15,0x7c,0x23,0x6c,0x33, -0x3e,0x14,0xb1,0x66,0x7e,0x1f,0x3e,0x43,0x7e,0x1f,0x3e,0x43,0xb, 0x1a,0x50,0x4e, -0xa0,0x80,0x1b,0x1a,0x50,0xa1,0x27,0xa9,0xd7,0xcb,0xd1,0x39,0x4e,0x70,0x1, 0x80, -0x11,0xd1,0x39,0x7d,0x23,0x5e,0x24,0x0, 0x8, 0xbe,0x24,0x0, 0x8, 0x78,0x6, 0x4e, -0x70,0x4, 0x1b,0xa, 0x30,0x7e,0xf, 0x3e,0x43,0x69,0x30,0x0, 0x38,0x5e,0x34,0x80, -0x0, 0xbe,0x34,0x80,0x0, 0x78,0xda,0xb, 0xa, 0x30,0x4e,0x60,0x40,0x1b,0xa, 0x30, -0xd1,0xa9,0xa9,0xc6,0xcb,0x22,0x3e,0x14,0x7e,0x1f,0x3e,0x43,0xb, 0x1a,0x50,0x4d, -0x51,0x1b,0x1a,0x50,0x22,0x7a,0x85,0x5d,0x7f,0x5, 0x7e,0x18,0x36,0x2, 0x74,0x1, -0x22,0x7f,0x71,0xa9,0xd6,0xcb,0x7d,0x31,0xd1,0x9a,0x79,0x30,0x0, 0x6, 0x7e,0x1d, -0x52,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x8, 0x7c,0x4b,0x6c,0x55,0xe5,0x57,0xa, -0x3b,0x4d,0x32,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0xc, 0x7e,0x25,0x5a,0x7c,0x45, -0x6c,0x55,0xd1,0x39,0x4d,0x32,0x1b,0xa, 0x30,0x7e,0x35,0x58,0xd1,0x23,0x4e,0x70, -0x30,0xd1,0x36,0x4e,0x60,0x80,0x1b,0xa, 0x30,0xa1,0x27,0x7f,0x71,0xa9,0xd6,0xcb, -0x7d,0x31,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x4, 0x7d,0x3f,0x7e,0xf, 0x3e,0x43, -0x79,0x30,0x0, 0x8, 0x7c,0x4b,0x6c,0x55,0xe5,0x25,0xa, 0x3b,0x4d,0x32,0x7e,0xf, -0x3e,0x43,0x79,0x30,0x0, 0xc, 0x7e,0x25,0x2a,0x7c,0x45,0x6c,0x55,0x7e,0xf, 0x3e, -0x43,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x7e,0x35,0x28,0x7d,0x23,0x7c,0x45, -0x6c,0x55,0x3e,0x24,0x7e,0xf, 0x3e,0x43,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30, -0x7e,0x35,0x26,0x7d,0x23,0x7c,0x45,0x6c,0x55,0x3e,0x24,0x3e,0x24,0x7e,0xf, 0x3e, -0x43,0xb, 0xa, 0x30,0x4d,0x32,0x1b,0xa, 0x30,0x7e,0xf, 0x3e,0x43,0xb, 0xa, 0x30, -0x22,0xb1,0xcb,0x4e,0x70,0x10,0xd1,0x36,0x4e,0x60,0x80,0x1b,0xa, 0x30,0xa1,0x27, -0xb1,0xcb,0x4e,0x70,0x20,0xd1,0x36,0x4e,0x60,0x80,0x1b,0xa, 0x30,0xa1,0x27,0xd1, -0x87,0x7e,0xf, 0x15,0x48,0x7e,0x18,0x35,0x76,0x74,0x10,0xd1,0x50,0xd1,0x87,0x7e, -0xf, 0x15,0x48,0x7e,0x18,0x35,0xbc,0x74,0x10,0xd1,0x41,0x9f,0x11,0x7a,0x1f,0x35, -0x8, 0xe4,0x7a,0xb3,0x35,0x74,0x22,0x75,0x25,0x23,0x6d,0x33,0x7a,0x35,0x26,0x7e, -0x24,0x0, 0x1, 0x7a,0x25,0x28,0x7a,0x35,0x2a,0x22,0x7e,0xf, 0x3e,0x43,0x79,0x30, -0x0, 0x4, 0x7d,0x3f,0x7e,0xf, 0x3e,0x43,0x22,0x6d,0x11,0x7e,0x1f,0x3e,0x43,0x1b, -0x1a,0x10,0x6d,0x33,0x7e,0xf, 0x3e,0x43,0x79,0x30,0x0, 0x38,0x22,0x4e,0x37,0x35, -0xa, 0x4e,0x27,0x35,0x8, 0x7a,0x1f,0x35,0x8, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xf7, -0x7c,0xab,0x7e,0xe3,0x1e,0x8c,0x7c,0xda,0x80,0x2e,0x7e,0x18,0x0, 0x1, 0x7c,0xbd, -0x60,0x5, 0x2f,0x11,0x14,0x78,0xfb,0x5e,0x37,0x35,0xa, 0x5e,0x27,0x35,0x8, 0x4d, -0x23,0x78,0x13,0xd2,0x7, 0x71,0x5b,0x7e,0x18,0x0, 0x1, 0x7c,0xbd,0x60,0x5, 0x2f, -0x11,0x14,0x78,0xfb,0xd1,0xbd,0xb, 0xd0,0xbc,0xfd,0x50,0xce,0xda,0x79,0xda,0xd8, -0x22,0x7e,0xb3,0x35,0x74,0x22,0xf1,0x6f,0x7d,0x13,0x7e,0x37,0x3e,0x3a,0x7a,0x37, -0x3e,0x36,0x7a,0x17,0x3e,0x38,0xbd,0x31,0x50,0x1a,0x7d,0x1, 0x9e,0x7, 0x3e,0x3a, -0xe, 0x4, 0xe, 0x4, 0xe, 0x4, 0xe, 0x4, 0xe, 0x4, 0x7d,0x21,0x9d,0x20,0x7a,0x27, -0x3e,0x3a,0x80,0xe, 0x7d,0x23,0x9d,0x21,0xe, 0x24,0xf1,0x66,0x9d,0x32,0x7a,0x37, -0x3e,0x3a,0x7e,0x37,0x3e,0x3a,0x7a,0x37,0x3e,0x34,0xbe,0x34,0x1, 0x40,0x28,0x3, -0xd2,0x1c,0x22,0xc2,0x1c,0x22,0xe, 0x24,0xe, 0x24,0xe, 0x24,0xe, 0x24,0x22,0xca, -0xf8,0x6d,0x44,0x12,0x41,0x81,0x7c,0x67,0x74,0x1, 0x12,0xf, 0xe9,0x7e,0x30,0x2, -0xac,0x36,0x2e,0x14,0x8, 0xa, 0x7e,0x10,0x4, 0xac,0x16,0x2e,0x4, 0x8, 0xa, 0x6c, -0xff,0x80,0x3f,0x7e,0x70,0x2, 0xac,0x7f,0x7d,0x23,0x2d,0x20,0xb, 0x28,0x20,0x2d, -0x31,0xb, 0x38,0x30,0xf1,0xdf,0xbd,0x4f,0x50,0x2, 0x7d,0x4f,0x74,0x2, 0xac,0xbf, -0x7d,0xe5,0x2d,0xe1,0xb, 0xe8,0xe0,0xbe,0xe4,0x7f,0xff,0x78,0x4, 0x7e,0x44,0x7f, -0xff,0x2d,0x50,0xb, 0x58,0x50,0xbe,0x54,0x7f,0xff,0x78,0x4, 0x7e,0x44,0x7f,0xff, -0xb, 0xf0,0x7e,0x73,0x1e,0x90,0xbc,0x7f,0x38,0xb9,0x7d,0x34,0xda,0xf8,0x22,0x9d, -0x32,0x12,0x1e,0x5, 0x7d,0xf3,0x22,0xca,0x3b,0x7e,0xa3,0x1c,0x58,0xbe,0xa0,0x0, -0x38,0x3, 0x2, 0xa0,0xbc,0x7e,0xb3,0x0, 0x81,0x70,0x3f,0x7a,0xa3,0x0, 0x81,0xe4, -0x7a,0xb3,0x0, 0x83,0x6c,0xff,0x80,0x2b,0x7e,0x90,0x9, 0xac,0x9f,0x2e,0x44,0x0, -0x84,0x74,0x2, 0xac,0xbf,0x9, 0xc5,0x19,0xde,0x9, 0xd5,0x19,0xdf,0x7a,0x49,0xc0, -0x19,0xd4,0x0, 0x1, 0x74,0x1, 0x19,0xb4,0x0, 0x8, 0x12,0x2d,0x85,0x59,0x34,0x0, -0x2, 0xb, 0xf0,0x12,0x5f,0xe5,0x38,0xd0,0x1, 0xc1,0x7e,0xe3,0x0, 0x81,0x6c,0xff, -0x80,0x37,0x7e,0x90,0x9, 0xac,0x9f,0x2e,0x44,0x0, 0x84,0x7e,0x49,0xc0,0x9, 0xd4, -0x0, 0x1, 0x9, 0xb4,0x0, 0x8, 0x70,0x4, 0x1b,0xe0,0x80,0x1b,0x12,0x2d,0x85,0x7d, -0x23,0x49,0x34,0x0, 0x2, 0x12,0x9f,0xdf,0xbe,0xf4,0x0, 0x23,0x8, 0x9, 0x74,0x5, -0x19,0xb4,0x0, 0x8, 0x75,0x7c,0x1, 0xb, 0xf0,0xbc,0xef,0x38,0xc5,0x4c,0xee,0x78, -0x2, 0x80,0x2c,0x7e,0x73,0x0, 0x83,0xbe,0x70,0x4, 0x40,0x27,0x6c,0xff,0x80,0x14, -0x7e,0x90,0x9, 0xac,0x9f,0x2e,0x44,0x0, 0x84,0x9, 0xb4,0x0, 0x8, 0xbe,0xb0,0x5, -0x68,0x6, 0xb, 0xf0,0xbc,0xef,0x38,0xe8,0xbc,0xef,0x78,0x3, 0x75,0x7c,0x0, 0x11, -0xc6,0x80,0xe, 0x7c,0xb7,0x4, 0x7a,0xb3,0x0, 0x83,0x80,0x5, 0x11,0xc6,0x75,0x7c, -0x0, 0xe5,0x7c,0xda,0x3b,0x22,0xe4,0x7a,0xb3,0x0, 0x82,0x7a,0xb3,0x0, 0x81,0x7a, -0xb3,0x0, 0x83,0x22,0x7e,0xa0,0x1, 0x7e,0x37,0x9, 0x60,0xbe,0x34,0xfe,0x20,0x58, -0x12,0x7e,0xb3,0x1c,0x80,0x60,0x7, 0xe4,0x7a,0xb3,0x1c,0x81,0x80,0x29,0x7e,0xa0, -0x5, 0x80,0x24,0xbe,0x34,0xfe,0x70,0x58,0x5, 0x7e,0xa0,0x4, 0x80,0x19,0xbe,0x34, -0xfe,0xc0,0x58,0x5, 0x7e,0xa0,0x3, 0x80,0xe, 0xbe,0x34,0xff,0x10,0x58,0x5, 0x7e, -0xa0,0x2, 0x80,0x3, 0x7e,0xa0,0x1, 0x7c,0xba,0x22,0xe4,0x7a,0xb3,0x0, 0x7e,0x7a, -0xb3,0x1c,0x80,0x74,0x2, 0x2, 0x41,0x78,0x7e,0x60,0x4, 0x7e,0x27,0x3e,0x2c,0xbe, -0x24,0x3, 0xe8,0x28,0x3, 0x7e,0x60,0x8, 0x7e,0x73,0x1d,0xeb,0xbe,0x70,0x0, 0x38, -0x7, 0x7e,0xb3,0x3d,0x7, 0xb4,0x1, 0x6, 0x74,0x1, 0x7a,0xb3,0x2, 0xa2,0x7e,0x73, -0x2, 0xa2,0xbe,0x70,0x0, 0x28,0x23,0x7e,0x27,0x1c,0x5e,0xbe,0x24,0x0, 0x96,0x58, -0x19,0x7e,0x27,0x1c,0x62,0xbe,0x24,0xff,0x6a,0x8, 0xf, 0x7e,0x27,0x9, 0x60,0xbe, -0x24,0xff,0x60,0x8, 0x5, 0xe4,0x7a,0xb3,0x2, 0xa2,0x7e,0xb3,0x1c,0x80,0xb4,0x1, -0x19,0x7e,0x73,0x0, 0x7f,0xbc,0x76,0x50,0xe, 0xe4,0x7a,0xb3,0x1c,0x81,0x31,0x1a, -0x7e,0xb3,0x0, 0x7f,0x4, 0x80,0x4, 0xe4,0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x7f,0x7e, -0xb3,0x1c,0x81,0xb4,0x1, 0x21,0x7e,0xa3,0x0, 0x80,0xbe,0xa0,0x5, 0x50,0xa, 0xe4, -0x7a,0xb3,0x1c,0x81,0x7c,0xba,0x4, 0x80,0xf, 0x7e,0xb3,0x2, 0xa2,0x70,0x4, 0x74, -0x4, 0x80,0x5, 0x74,0x5, 0x80,0x1, 0xe4,0x7a,0xb3,0x0, 0x80,0x7e,0xb3,0x1d,0xeb, -0x70,0x6b,0x7e,0x37,0x1e,0x76,0xbe,0x37,0x1c,0x5e,0x28,0x61,0x7e,0x37,0x1c,0x5e, -0xbe,0x34,0x0, 0x32,0x58,0x8, 0x7e,0x34,0x0, 0x2, 0x7a,0x37,0x2, 0xa3,0x7e,0x37, -0x2, 0xa3,0xbe,0x34,0x0, 0x2, 0x8, 0x1d,0x7e,0xb3,0x1c,0x81,0x70,0x17,0x7e,0x34, -0x0, 0x4, 0x7a,0x37,0x2, 0xa3,0x7e,0x37,0x2, 0xa5,0x7e,0x24,0x15,0x18,0x51,0x42, -0x50,0x3, 0x12,0x46,0x9c,0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0x9, 0x7e,0x34,0x0, 0x1, -0x7a,0x37,0x2, 0xa3,0x22,0x7e,0x37,0x2, 0xa3,0xbe,0x34,0x0, 0x1, 0x78,0xe, 0x7e, -0x34,0x0, 0x3, 0x7a,0x37,0x2, 0xa3,0x51,0x3e,0x7a,0x37,0x2, 0xa5,0x22,0x7e,0x35, -0x1d,0x22,0x7d,0x2, 0x7d,0x13,0x7e,0x34,0xff,0xff,0x9d,0x31,0xbd,0x30,0x40,0x12, -0xbe,0x15,0x1d,0x38,0xb, 0x7d,0x20,0x2d,0x21,0xbe,0x25,0x1d,0x28,0x2, 0xc3,0x22, -0xd3,0x22,0xb, 0x34,0x9d,0x3, 0xbe,0x5, 0x1d,0x38,0x7, 0xbe,0x15,0x1d,0x28,0x2, -0xd3,0x22,0xc3,0x22,0x7e,0x8, 0x2, 0xa8,0x7e,0x34,0x0, 0xc, 0xe4,0x12,0x1d,0xd3, -0x12,0x67,0x1e,0x7e,0x73,0x1e,0x89,0x7a,0x73,0x2, 0xa8,0xa9,0xd1,0xcb,0x12,0x57, -0xbf,0x7a,0x37,0x2, 0xac,0x7e,0x1f,0x3d,0xf9,0x7a,0x37,0x2, 0xae,0x7e,0x1f,0x15, -0x44,0x7a,0x37,0x2, 0xb0,0x6d,0x33,0x12,0x57,0xc7,0x2, 0x12,0x78,0x6c,0x77,0x80, -0x25,0x74,0x2, 0xac,0xb7,0x49,0x25,0x5, 0xc8,0x49,0x45,0x4, 0x0, 0x2d,0x42,0x59, -0x45,0x5, 0xc8,0x30,0x4, 0xe, 0x49,0x45,0x4, 0x72,0x49,0x25,0x6, 0x3a,0x2d,0x24, -0x59,0x25,0x6, 0x3a,0xb, 0x70,0x7e,0x63,0x1e,0x90,0xa, 0x6, 0x7e,0x63,0x1e,0x8f, -0xa, 0x16,0x2d,0x10,0xa, 0x27,0xbd,0x21,0x48,0xc7,0x22,0xd2,0x7, 0x6c,0x77,0x6c, -0x55,0x80,0x14,0x7c,0x45,0x74,0x2, 0xac,0xb4,0x49,0x15,0x5, 0x56,0xbe,0x14,0xfe, -0x70,0x58,0x2, 0xb, 0x70,0xb, 0x50,0x7e,0x63,0x1e,0x8a,0xbc,0x65,0x38,0xe4,0xa, -0x26,0x1e,0x24,0x1e,0x24,0xa, 0x37,0xbd,0x32,0x8, 0x2, 0xc2,0x7, 0xa2,0x7, 0x22, -0x7e,0x53,0x1e,0x8b,0x7e,0x73,0x1e,0x8c,0x7e,0x60,0x1, 0x80,0x1a,0xa, 0x6, 0x7e, -0x43,0x1e,0x8a,0xa, 0x14,0x2d,0x10,0x3e,0x14,0x49,0x11,0x4, 0xe4,0xbe,0x14,0xff, -0x60,0x58,0x2, 0xd3,0x22,0xb, 0x60,0xa, 0x5, 0x1b,0x4, 0xa, 0x16,0xbd,0x10,0x48, -0xdc,0x7e,0x60,0x2, 0x80,0x12,0x74,0x2, 0xac,0xb6,0x49,0x25,0x4, 0xe4,0xbe,0x24, -0xff,0x60,0x58,0x2, 0xd3,0x22,0xb, 0x60,0xa, 0x17,0x1b,0x15,0xa, 0x26,0xbd,0x21, -0x48,0xe4,0xc3,0x22,0x6d,0x44,0x7e,0xb3,0x1c,0x7e,0x60,0x13,0x7e,0x57,0x9, 0x6e, -0xbe,0x54,0xfe,0x70,0x58,0x9, 0x7e,0x73,0x19,0xdb,0xbe,0x70,0x8, 0x28,0x3, 0xe4, -0x80,0x32,0x6c,0x77,0x74,0x2, 0xac,0xb7,0x49,0x25,0x5, 0x56,0xbe,0x24,0xfe,0xd4, -0x58,0x7, 0x7d,0x52,0x12,0x6f,0xc0,0x2d,0x45,0xb, 0x70,0xa5,0xbf,0x23,0xe5,0xbe, -0x44,0xff,0xb5,0x58,0xe, 0x7e,0xb3,0x2, 0xa7,0xbe,0xb0,0xa, 0x28,0x2, 0xd3,0x22, -0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x2, 0xa7,0xc3,0x22,0x7c,0x6b,0x7e,0x73,0x1f,0x98, -0xbc,0x76,0x68,0x6, 0x7a,0x63,0x1f,0x98,0xd2,0x13,0x30,0x13,0x6, 0x12,0x3f,0xcd, -0x2, 0x0, 0xa, 0x22,0xca,0xd8,0xca,0x79,0x7c,0xfb,0x7f,0x70,0x6c,0xdd,0x6d,0xcc, -0x7d,0x4c,0x7d,0xdc,0x9f,0x44,0x7f,0x14,0x6c,0xee,0x80,0x13,0x74,0x2, 0xac,0xbe, -0x7f,0x7, 0x2d,0x15,0xb, 0xa, 0x10,0x1a,0x2, 0x1a,0x0, 0x2f,0x10,0xb, 0xe0,0xbc, -0xfe,0x38,0xe9,0xa, 0x1f,0x91,0x7c,0x7f,0x14,0x6c,0xee,0x80,0x1b,0x74,0x2, 0xac, -0xbe,0x7f,0x7, 0x2d,0x15,0xb, 0xa, 0xb0,0xbd,0x4b,0x8, 0xa, 0x7d,0x1b,0x1a,0x2, -0x1a,0x0, 0x2f,0x10,0xb, 0xd0,0xb, 0xe0,0xbc,0xfe,0x38,0xe1,0x7d,0x4c,0xbe,0xd0, -0x0, 0x28,0x4, 0xa, 0x1d,0x91,0x7c,0x6c,0xee,0x80,0x12,0x74,0x2, 0xac,0xbe,0x7f, -0x17,0x2d,0x35,0xb, 0x1a,0x50,0x9d,0x54,0x1b,0x1a,0x50,0xb, 0xe0,0xbc,0xfe,0x38, -0xea,0x6c,0xee,0x80,0xc, 0x91,0x84,0xbd,0x3d,0x8, 0x4, 0x91,0x84,0x7d,0xd3,0xb, -0xe0,0xbc,0xfe,0x38,0xf0,0x7d,0x3d,0xda,0x79,0xda,0xd8,0x22,0x6d,0x0, 0x12,0x1b, -0x8c,0x7d,0x43,0x22,0x74,0x2, 0xac,0xbe,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0x30,0x2, -0x1e,0x5, 0x7f,0x71,0x7f,0x60,0x6d,0x0, 0x6c,0xaa,0x6d,0x11,0x80,0x1c,0x7d,0x31, -0x3e,0x34,0x2d,0x3f,0x7d,0x2e,0x91,0x8c,0xbd,0x30,0x48,0xc, 0x7d,0x1, 0x3e,0x4, -0x7f,0x17,0x2d,0x30,0x91,0x8c,0x7d,0x3, 0xb, 0x14,0x7e,0x35,0x33,0xbd,0x31,0x38, -0xdd,0x80,0x7, 0xb, 0xa0,0xbe,0xa0,0x8, 0x50,0x11,0x7c,0xba,0x7d,0x40,0x60,0x5, -0xe, 0x44,0x14,0x78,0xfb,0xbe,0x44,0x0, 0x7f,0x18,0xe8,0x7f,0x16,0x2e,0x35,0x33, -0x7a,0x1b,0xa0,0x6d,0x11,0x80,0x23,0x7d,0x1, 0x3e,0x4, 0x7f,0x17,0x2d,0x30,0xb, -0x1a,0x0, 0x7f,0x16,0x2e,0x35,0x33,0x7e,0x1b,0xb0,0x60,0x5, 0xe, 0x4, 0x14,0x78, -0xfb,0x7f,0x16,0x2d,0x31,0x7a,0x1b,0x10,0xb, 0x14,0x7e,0x5, 0x33,0xbd,0x1, 0x38, -0xd6,0x22,0xca,0x3b,0x7f,0x30,0x7c,0x6b,0x7e,0xb3,0x1f,0x4b,0xf5,0x2e,0x7e,0xb3, -0x1f,0x3d,0xf5,0x2f,0x7e,0xb3,0x1f,0x42,0xf5,0x30,0x7e,0xb3,0x1f,0x4d,0xf5,0x31, -0x7e,0xb3,0x1f,0x4e,0xf5,0x32,0x74,0x1, 0x7a,0xb3,0x1f,0x4b,0x74,0x5, 0xac,0xb6, -0x9, 0x75,0x19,0x18,0x7a,0x73,0x1f,0x42,0x74,0x5, 0xac,0xb6,0x9, 0x75,0x19,0x19, -0x7a,0x73,0x1f,0x4d,0x74,0x5, 0xac,0xb6,0x9, 0x75,0x19,0x1a,0x7a,0x73,0x1f,0x4e, -0x74,0x5, 0xac,0xb6,0x9, 0x75,0x19,0x1b,0xbe,0x73,0x1f,0x98,0x68,0x6, 0x7a,0x73, -0x1f,0x98,0xd2,0x13,0xc2,0x7, 0x74,0x5, 0xac,0xb6,0x9, 0xb5,0x19,0x17,0x12,0x3f, -0x6b,0x12,0x57,0x77,0x12,0x57,0xdb,0x12,0x0, 0xe, 0x30,0x12,0xfd,0x74,0x1, 0x12, -0xf, 0xe9,0x7e,0x14,0x80,0x0, 0x7d,0x31,0x7e,0x2f,0x15,0x44,0x7d,0x25,0x7e,0x4, -0xf, 0x5c,0x12,0x50,0x22,0x12,0x57,0xd0,0x7a,0x55,0x33,0x7f,0x3, 0x7e,0x18,0xf, -0x5c,0x91,0x92,0xb1,0xd6,0xe5,0x2e,0x7a,0xb3,0x1f,0x4b,0xe5,0x2f,0x7a,0xb3,0x1f, -0x3d,0xe5,0x30,0x7a,0xb3,0x1f,0x42,0xe5,0x31,0x7a,0xb3,0x1f,0x4d,0xe5,0x32,0x7a, -0xb3,0x1f,0x4e,0xda,0x3b,0x22,0x7e,0x73,0x38,0x9b,0xa, 0x17,0x7e,0x73,0x1e,0x8d, -0xa, 0x7, 0x2d,0x1, 0x7e,0x73,0x1e,0x8a,0xa, 0x47,0x7d,0x10,0xad,0x14,0x7d,0x21, -0x6c,0x66,0x80,0x22,0xa, 0x56,0x2d,0x52,0x3e,0x54,0x7e,0xf, 0x3d,0xf9,0x2d,0x15, -0xb, 0xa, 0xf0,0x7e,0x30,0x2, 0xac,0x36,0x49,0x1, 0x15,0x4c,0x7d,0x5f,0x9d,0x50, -0x59,0x51,0x2, 0xa8,0xb, 0x60,0xbc,0x76,0x38,0xda,0x7a,0x45,0x33,0x7e,0xf, 0x3c, -0x6e,0x7e,0x18,0x2, 0xa8,0x81,0x92,0x7c,0xab,0x7f,0x71,0x7f,0x60,0x6d,0x44,0x80, -0x25,0x4c,0xaa,0x68,0xf, 0xd1,0x6a,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0xd1,0x5e, -0x2d,0x32,0x80,0xd, 0xd1,0x6a,0x60,0x5, 0x3e,0x24,0x14,0x78,0xfb,0xd1,0x5e,0x9d, -0x32,0x1b,0xa, 0x30,0xb, 0x44,0x7e,0x35,0x29,0xbd,0x34,0x38,0xd4,0x22,0x7d,0x34, -0x3e,0x34,0x7f,0x6, 0x2d,0x13,0xb, 0xa, 0x30,0x22,0x7f,0x17,0x2d,0x34,0x7e,0x1b, -0xb0,0x1a,0x2b,0x7f,0x7, 0x2e,0x15,0x29,0x7e,0xb, 0xb0,0x22,0x7c,0xab,0x7e,0xb3, -0x38,0x9b,0xa, 0x3b,0x7e,0xb3,0x1e,0x8d,0xa, 0x2b,0x2d,0x23,0x7e,0xb3,0x1e,0x8a, -0xa, 0x3b,0xad,0x32,0x7d,0x43,0x3e,0x44,0x7e,0xf, 0x3d,0xf9,0x2d,0x14,0xa, 0x3b, -0x7a,0x35,0x29,0x7e,0x70,0x25,0xac,0x7a,0x2e,0x34,0x3c,0x72,0x6d,0x22,0xe4,0xc1, -0x27,0xe4,0x7a,0xb3,0x1c,0x7c,0x7a,0xb3,0x36,0x5, 0x22,0xca,0x69,0xd2,0x7, 0x6c, -0x99,0x6c,0x88,0x30,0x7, 0x29,0xa, 0x58,0x9, 0xb5,0x37,0x26,0xa, 0x38,0x9, 0x73, -0x37,0x20,0x12,0x2d,0x89,0x74,0x2, 0xac,0xb8,0x49,0x25,0x37,0x2c,0x7d,0xf3,0x9d, -0xf2,0xbe,0xf4,0x0, 0x32,0x18,0x6, 0xbe,0xf4,0xff,0xce,0x58,0x2, 0xc2,0x7, 0x7e, -0x73,0x1c,0x58,0xbc,0x78,0x28,0xe, 0x74,0x2, 0xac,0xb8,0x9, 0xc5,0x19,0xde,0x9, -0xd5,0x19,0xdf,0x80,0x3e,0xa, 0xe9,0xa, 0x58,0x2d,0x5e,0xbe,0x54,0x0, 0x5, 0x58, -0x2a,0x9, 0x65,0x37,0x26,0xa, 0x66,0x2e,0x64,0x0, 0x8, 0x7c,0xcd,0x9, 0x65,0x37, -0x20,0xa, 0x56,0x2e,0x54,0x0, 0x11,0x7c,0xdb,0xbe,0xc0,0x10,0x40,0x3, 0x9e,0xc0, -0x10,0xbe,0xd0,0x23,0x40,0xd, 0x9e,0xd0,0x23,0x80,0x8, 0x7e,0xc3,0x1c,0x64,0x7e, -0xd3,0x1c,0x65,0xa, 0xe7,0xa, 0x59,0x2d,0x5e,0xbe,0x54,0x0, 0x5, 0x58,0x2f,0xa, -0x27,0xa, 0x39,0x2d,0x32,0x7c,0x67,0x7a,0x61,0x25,0xa, 0x58,0x9, 0x75,0x37,0x26, -0xa, 0x26,0x19,0x72,0x37,0x26,0x9, 0x75,0x37,0x20,0x19,0x72,0x37,0x20,0x74,0x2, -0xac,0xb8,0x49,0xe5,0x37,0x2c,0xf1,0xa1,0x59,0xe5,0x37,0x2c,0xb, 0x90,0xa, 0x58, -0x19,0xc5,0x37,0x26,0x19,0xd5,0x37,0x20,0x12,0x2d,0x85,0x74,0x2, 0xac,0xb8,0x59, -0x35,0x37,0x2c,0xb, 0x80,0xbe,0x80,0x6, 0x50,0x2, 0xc1,0xc3,0xa2,0x7, 0xda,0x69, -0x22,0x7e,0x70,0x2, 0x7c,0xb6,0xac,0xb7,0x22,0xca,0x3b,0x7e,0xb3,0x18,0xd1,0x54, -0x3, 0xf5,0x25,0xc2,0x7, 0x6c,0x99,0x7e,0x27,0x1c,0x6d,0x7d,0xd2,0x7e,0x37,0x1c, -0x6b,0x7d,0xe3,0x7e,0x37,0x3e,0x21,0x4d,0x33,0x68,0x6, 0x7d,0x32,0xe, 0x34,0x7d, -0xd3,0x6c,0xee,0x7e,0xa3,0x1e,0x8a,0x7c,0xda,0x7e,0xb3,0x1c,0x79,0x14,0x68,0x25, -0x14,0x68,0x16,0x24,0xc2,0x68,0x8, 0x24,0xfb,0x68,0x1a,0x24,0x45,0x78,0x14,0x7c, -0xea,0x7e,0xb3,0x1e,0x89,0x7c,0xdb,0x80,0xc, 0x7e,0xb3,0x1e,0x89,0x2c,0xbd,0x7c, -0xdb,0x80,0x2, 0x6c,0xdd,0x6c,0xff,0x80,0xe, 0x7c,0xbf,0x51,0x9e,0xbe,0x34,0x2, -0x58,0x8, 0x2, 0xb, 0x90,0xb, 0xf0,0x7e,0x33,0x1c,0x58,0xbc,0x3f,0x38,0xea,0xbe, -0x90,0x3, 0x40,0x2, 0x41,0x5b,0xe5,0x25,0xbe,0xb0,0x3, 0x40,0x2, 0x1, 0xea,0x75, -0x26,0x0, 0xe5,0x25,0xb4,0x2, 0x33,0x6c,0xff,0x74,0x2, 0xac,0xbf,0x49,0x35,0x4, -0xe4,0x7d,0xf3,0x49,0x35,0x36,0x8, 0xbd,0x3f,0x8, 0x6, 0x49,0x45,0x36,0x8, 0x80, -0x2, 0x7d,0x4f,0x49,0x25,0x36,0x94,0x51,0x7e,0x59,0x45,0x36,0x94,0x59,0xf5,0x36, -0x8, 0xb, 0xf0,0xbe,0xf0,0x23,0x78,0xd1,0x80,0x36,0xe5,0x25,0xb4,0x1, 0x31,0x6c, -0xff,0x74,0x2, 0xac,0xbf,0x49,0x35,0x5, 0x56,0x7d,0xf3,0x49,0x35,0x36,0x4e,0xbd, -0x3f,0x58,0x6, 0x49,0x45,0x36,0x4e,0x80,0x2, 0x7d,0x4f,0x49,0x25,0x36,0xda,0x51, -0x7e,0x59,0x45,0x36,0xda,0x59,0xf5,0x36,0x4e,0xb, 0xf0,0xbe,0xf0,0x23,0x78,0xd1, -0x51,0x66,0x18,0x5, 0xbe,0x30,0x0, 0x28,0x79,0x6c,0xff,0x74,0x2, 0xac,0xbf,0x49, -0x25,0x36,0x94,0xbd,0x2e,0x8, 0x2, 0x5, 0x26,0x20,0x7, 0x1a,0x49,0x35,0x36,0xda, -0xbd,0x3d,0x8, 0x12,0xbd,0x2e,0x58,0x10,0x6d,0x33,0x9d,0x3e,0xe, 0x34,0xbd,0x23, -0x8, 0x6, 0xd2,0x7, 0x80,0x2, 0xd2,0x0, 0xb, 0xf0,0xbe,0xf0,0x23,0x78,0xcc,0xe5, -0x26,0xbe,0xb0,0x6, 0x28,0x3c,0xc2,0x7, 0x80,0x38,0x51,0x5e,0x38,0xf, 0xbe,0x30, -0x0, 0x38,0x4, 0x51,0x66,0x8, 0x2b,0x7e,0xb3,0x19,0x67,0x70,0x25,0x6c,0xff,0x80, -0x1d,0x51,0x8b,0x8, 0x17,0x49,0x10,0x4, 0xe4,0xbd,0x1e,0x58,0xf, 0x6d,0x33,0x9d, -0x3e,0x12,0x7f,0xd, 0xbd,0x13,0x8, 0x4, 0xd2,0x7, 0x80,0x6, 0xb, 0xf0,0xbc,0xdf, -0x38,0xdf,0x12,0x0, 0x6e,0x50,0x2, 0xc2,0x7, 0x30,0x7, 0x20,0x7e,0xb3,0x36,0x5, -0x4, 0x7a,0xb3,0x36,0x5, 0x7e,0x73,0x36,0x5, 0xbe,0x70,0xa, 0x28,0x1d,0x74,0xa, -0x7a,0xb3,0x36,0x5, 0x74,0x1, 0x7a,0xb3,0x1c,0x7c,0x80,0xf, 0x7e,0x73,0x36,0x5, -0xbe,0x70,0x0, 0x28,0x6, 0x1e,0x70,0x7a,0x73,0x36,0x5, 0x6c,0xcc,0x7e,0x43,0x1c, -0x58,0xbe,0x40,0x0, 0x38,0x4, 0x51,0x5e,0x28,0x56,0x7e,0xb3,0x1c,0x7b,0xb4,0x1, -0x9, 0x7e,0xb3,0x1c,0x7e,0xbe,0xb0,0x1, 0x68,0x46,0x7e,0xb3,0x1c,0x7c,0xb4,0x1, -0x3f,0xe5,0x25,0xb4,0x3, 0x3a,0x6c,0xff,0x80,0x13,0x74,0x2, 0xac,0xbf,0x9, 0xb5, -0x19,0xdf,0x51,0x71,0x8, 0x5, 0x7e,0xc0,0x1, 0x80,0x6, 0xb, 0xf0,0xbc,0x4f,0x38, -0xe9,0x6c,0xff,0x80,0x13,0x74,0x2, 0xac,0xbf,0x9, 0xb5,0x1a,0xb1,0x51,0x71,0x8, -0x5, 0x7e,0xc0,0x1, 0x80,0xa, 0xb, 0xf0,0x7e,0x73,0x1c,0x59,0xbc,0x7f,0x38,0xe5, -0xe5,0x25,0xb4,0x3, 0x5e,0x6c,0xff,0x80,0x1e,0x51,0x8b,0x8, 0x18,0x49,0x10,0x4, -0xe4,0xbd,0x1e,0x58,0x10,0x6d,0x33,0x9d,0x3e,0x12,0x7f,0xd, 0xbd,0x13,0x8, 0x5, -0x7e,0xc0,0x1, 0x80,0x6, 0xb, 0xf0,0xbc,0xdf,0x38,0xde,0x4c,0xcc,0x78,0x25,0x7e, -0xb3,0x36,0x6, 0x4, 0x7a,0xb3,0x36,0x6, 0x7e,0x73,0x36,0x6, 0xbe,0x70,0x32,0x28, -0x22,0x74,0x32,0x7a,0xb3,0x36,0x6, 0x7e,0xb3,0x1c,0x7c,0x60,0x2, 0xd2,0x2, 0x12, -0xa6,0xb1,0x80,0xf, 0x7e,0x73,0x36,0x6, 0xbe,0x70,0x0, 0x28,0x6, 0x1e,0x70,0x7a, -0x73,0x36,0x6, 0x7e,0x37,0x9, 0x6e,0xbe,0x34,0x0, 0x0, 0x18,0x1a,0x12,0x9f,0x11, -0xbe,0xb0,0x5, 0x28,0xa, 0x7e,0x37,0x1c,0x5e,0xbe,0x34,0x0, 0x1e,0x48,0x8, 0x12, -0x9f,0x11,0xbe,0xb0,0x9, 0x28,0x2, 0xd2,0x1, 0x30,0x1, 0xf, 0x12,0xa6,0xb1,0x7e, -0x37,0x1e,0x6f,0xbe,0x37,0x9, 0x70,0x28,0x2, 0xc2,0x1, 0xda,0x3b,0x22,0x7e,0x73, -0x1c,0x59,0xbe,0x70,0x0, 0x22,0x7e,0x37,0x1e,0x7a,0xe, 0x34,0xbe,0x37,0x1c,0x62, -0x22,0x7c,0x5b,0x74,0x2, 0xac,0xb5,0x49,0x35,0x5, 0x56,0xbd,0x3d,0x22,0x7e,0x34, -0x0, 0x3, 0xad,0x32,0x2d,0x43,0xe, 0x44,0xe, 0x44,0x22,0xa, 0x1f,0xa, 0xce,0x7d, -0x2c,0x2d,0x21,0x7d,0x2, 0x3e,0x4, 0x49,0x30,0x5, 0x56,0xbd,0x3d,0x22,0x7c,0x7b, -0x74,0x2, 0xac,0x7b,0x9, 0xb3,0x19,0xde,0x9, 0x73,0x19,0xdf,0x2, 0x2d,0x89,0x7e, -0x73,0x1e,0x8a,0x7e,0x47,0x1c,0x6d,0xe4,0x7a,0xb3,0x36,0x7, 0x12,0x77,0xc3,0x50, -0x62,0xe4,0x7a,0xb3,0x1c,0x7b,0x7e,0xb3,0x19,0x67,0x70,0x57,0x7e,0x63,0x1c,0x58, -0xbe,0x60,0x0, 0x28,0x4e,0x6c,0x55,0x80,0x46,0x74,0x2, 0xac,0xb5,0x9, 0x45,0x19, -0xde,0x9, 0x35,0x19,0xdf,0x74,0x2, 0xac,0xb3,0x49,0x55,0x5, 0x56,0x6d,0x0, 0x9d, -0x4, 0xbd,0x50,0x48,0x10,0xa, 0xf4,0xa, 0x57,0x2d,0x5f,0x3e,0x54,0x49,0x55,0x5, -0x56,0xbd,0x50,0x58,0x18,0x74,0x1, 0x7a,0xb3,0x1c,0x7b,0x7e,0x57,0x3e,0x2c,0xbe, -0x54,0xb, 0xb8,0x50,0xe, 0x74,0x16,0x7a,0xb3,0x36,0x7, 0x80,0x6, 0xb, 0x50,0xbc, -0x65,0x38,0xb6,0x12,0xa7,0xa9,0xe4,0x7a,0xb3,0x1c,0x7d,0x7e,0x37,0x1c,0x5c,0x2e, -0x37,0x1c,0x5a,0xbe,0x37,0x1c,0x73,0x28,0x6, 0x74,0x1, 0x7a,0xb3,0x1c,0x7d,0x12, -0xa6,0xbb,0xe4,0x33,0x7a,0xb3,0x1c,0x7e,0x22,0x74,0x1, 0x22,0xca,0x3b,0x7c,0xfb, -0x75,0x3c,0x0, 0x75,0x3d,0x0, 0x75,0x3e,0x0, 0x75,0x3f,0x0, 0x7e,0xb3,0x1e,0x8b, -0xf5,0x44,0x7e,0xb3,0x1e,0x8c,0xf5,0x45,0x75,0x46,0x28,0x75,0x47,0x6, 0x12,0xba, -0x73,0x7e,0xb3,0x1c,0x58,0xf5,0x29,0xe4,0x7a,0xb3,0x37,0x45,0x7a,0xb3,0x37,0x38, -0x7a,0xb3,0x37,0x39,0x7e,0x8, 0x37,0x47,0x6d,0x33,0x7e,0x53,0x38,0xa2,0xa, 0x25, -0x12,0x59,0xa2,0x7e,0x8, 0x37,0x88,0x6d,0x33,0x7e,0x53,0x38,0xa2,0xa, 0x25,0x3e, -0x24,0x12,0x59,0xa2,0x6c,0x11,0x12,0xba,0x3f,0x12,0xba,0xba,0x12,0xb9,0xfb,0x7e, -0xb3,0x37,0x44,0x70,0xc, 0x7e,0x3, 0x1d,0xeb,0xbe,0x0, 0x3, 0x28,0x3, 0x75,0x47, -0x4, 0x7e,0x84,0x1, 0x5e,0x7d,0x38,0x7e,0x27,0x9, 0x6a,0xbd,0x28,0x48,0x8, 0x7e, -0x87,0x9, 0x68,0xbd,0x83,0x58,0x0, 0xe5,0x29,0xbe,0xb0,0x2, 0x50,0x3, 0x2, 0xb5, -0xe3,0x6c,0xee,0x2, 0xb5,0xda,0x12,0xd1,0x7e,0x9, 0x25,0x19,0xdf,0x7a,0x23,0x2, -0xe4,0x7e,0x33,0x1e,0x8a,0x7e,0x90,0x2, 0xac,0x93,0x74,0x2, 0xac,0xbd,0x7d,0x85, -0x2d,0x84,0x7e,0x1f,0x6, 0xb0,0x7f,0x21,0x2d,0x58,0xb, 0x2a,0x80,0x7a,0x87,0x2, -0xe5,0x7e,0x30,0x2, 0x7c,0xb2,0xac,0xb3,0x2d,0x35,0xb, 0x1a,0x80,0x7a,0x87,0x2, -0xe7,0x4c,0xee,0x68,0x8, 0xa, 0x8e,0x9, 0xb8,0x37,0x47,0x70,0xa, 0xa, 0x3e,0xb, -0x34,0xa, 0x8e,0x19,0x78,0x37,0x47,0xe5,0x29,0xa, 0x3b,0x1b,0x34,0xa, 0x8e,0xbd, -0x83,0x78,0x3, 0x2, 0xb5,0xe3,0xa, 0x5e,0xb, 0x54,0xf5,0x2a,0x2, 0xb5,0xce,0x75, -0x54,0x0, 0x74,0xff,0x7a,0xb3,0x2, 0xe9,0x7a,0xb3,0x2, 0xea,0x12,0x7e,0xa6,0x9, -0xc5,0x19,0xde,0x9, 0x75,0x19,0xdf,0x7a,0x73,0x2, 0xeb,0x12,0xb6,0x11,0x7a,0x73, -0x2, 0xec,0x12,0x7f,0xb5,0x7a,0x73,0x2, 0xed,0x75,0x57,0x0, 0x7e,0x73,0x2, 0xec, -0xbe,0x71,0x47,0x40,0x3, 0x2, 0xb5,0xcc,0x12,0xd1,0xe5,0x40,0x3, 0x2, 0xb5,0xcc, -0x7e,0xb3,0x2, 0xe4,0xf5,0x5f,0x7a,0xc1,0x60,0x7e,0xb3,0x2, 0xeb,0xf5,0x61,0x7e, -0x8, 0x0, 0x30,0x7e,0x18,0x0, 0x32,0x7c,0xbd,0x12,0xb9,0xa6,0x75,0x3c,0x0, 0x75, -0x3d,0x0, 0x75,0x2f,0x0, 0x75,0x3e,0x0, 0x75,0x3f,0x0, 0x7c,0xbd,0x7e,0x73,0x2, -0xe4,0x12,0x2d,0x89,0x7a,0x35,0x34,0x7c,0xbc,0x7e,0x73,0x2, 0xeb,0x12,0x2d,0x89, -0x7a,0x35,0x36,0x7d,0x83,0x2e,0x85,0x34,0xe, 0x84,0x7a,0x85,0x55,0x7e,0x85,0x34, -0xbe,0x85,0x36,0x8, 0x5, 0x7e,0x85,0x36,0x80,0x3, 0x7e,0x85,0x34,0x7a,0x85,0x3a, -0xe, 0x84,0x7a,0x85,0x38,0x7e,0xa3,0x2, 0xec,0xbe,0xa0,0x1, 0x38,0x10,0x12,0xd1, -0xed,0x38,0xb, 0x7c,0xbf,0x30,0xe1,0x6, 0x75,0x2f,0x1, 0x2, 0xb1,0x3b,0xbe,0xa0, -0x1, 0x38,0x8, 0x12,0xd1,0xed,0x38,0x3, 0x2, 0xb1,0x3b,0xbe,0xa1,0x47,0x40,0x3, -0x2, 0xb1,0x3b,0x12,0xd1,0xe5,0x40,0x3, 0x2, 0xb1,0x3b,0x7c,0xbf,0x20,0xe0,0x3, -0x2, 0xb1,0x3b,0x6d,0x88,0x7d,0x98,0x7a,0x85,0x58,0x75,0x5a,0x0, 0xc2,0x7, 0xc2, -0x8, 0xbc,0xcd,0x28,0x4, 0x7c,0xbd,0x80,0x2, 0x7c,0xbc,0xf5,0x25,0xbc,0xcd,0x50, -0x4, 0x7c,0xbd,0x80,0x2, 0x7c,0xbc,0xf5,0x27,0x7e,0xa3,0x2, 0xeb,0xbe,0xa3,0x2, -0xe4,0x28,0x6, 0x7e,0xb3,0x2, 0xe4,0x80,0x4, 0x7e,0xb3,0x2, 0xeb,0xf5,0x26,0xbe, -0xa3,0x2, 0xe4,0x50,0x6, 0x7e,0xb3,0x2, 0xe4,0x80,0x4, 0x7e,0xb3,0x2, 0xeb,0xf5, -0x28,0x12,0xd1,0x87,0xe5,0x27,0xa, 0x8b,0xbd,0x83,0x58,0x8, 0xe5,0x27,0xa, 0x5b, -0xb, 0x54,0x80,0x2, 0xe5,0x27,0xf5,0x50,0xe5,0x25,0xbe,0xb0,0x0, 0x28,0x8, 0xe5, -0x25,0xa, 0x5b,0x1b,0x54,0x80,0x2, 0xe5,0x25,0xf5,0x51,0x12,0xd1,0x8e,0x58,0x8, -0xe5,0x28,0xa, 0x5b,0xb, 0x54,0x80,0x2, 0xe5,0x28,0xf5,0x52,0xe5,0x26,0xbe,0xb0, -0x0, 0x28,0x8, 0xe5,0x26,0xa, 0x5b,0x1b,0x54,0x80,0x2, 0xe5,0x26,0xf5,0x53,0x75, -0x2b,0x0, 0x80,0x79,0xbe,0xe1,0x2b,0x68,0x72,0xe5,0x2a,0xbe,0xb1,0x2b,0x68,0x6b, -0x7e,0x91,0x2b,0x74,0x2, 0xac,0x9b,0x9, 0xa4,0x19,0xde,0xbe,0xa1,0x50,0x78,0x13, -0xe5,0x27,0xa, 0x3b,0xb, 0x34,0xe5,0x50,0xa, 0x8b,0xbd,0x83,0x78,0x5, 0x85,0x27, -0x50,0x80,0x16,0xbe,0xa1,0x51,0x78,0x11,0xe5,0x51,0xa, 0x8b,0xb, 0x84,0xe5,0x25, -0xa, 0x5b,0xbd,0x85,0x78,0x3, 0x85,0x25,0x51,0x9, 0xa4,0x19,0xdf,0xbe,0xa1,0x52, -0x78,0x13,0xe5,0x28,0xa, 0x3b,0xb, 0x34,0xe5,0x52,0xa, 0x8b,0xbd,0x83,0x78,0x5, -0x85,0x28,0x52,0x80,0x16,0xbe,0xa1,0x53,0x78,0x11,0xe5,0x53,0xa, 0x3b,0xb, 0x34, -0xe5,0x26,0xa, 0x8b,0xbd,0x38,0x78,0x3, 0x85,0x26,0x53,0x5, 0x2b,0xe5,0x29,0xbe, -0xb1,0x2b,0x38,0x80,0xe5,0x27,0xbe,0xb1,0x25,0x78,0x29,0xd2,0x7, 0xe5,0x25,0x60, -0xb, 0x12,0xd1,0x87,0xe5,0x25,0xa, 0x8b,0xbd,0x83,0x78,0x2, 0xd2,0x8, 0xe5,0x25, -0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x25,0x12,0xd1,0x87,0xe5,0x27,0xa, 0x8b,0xbd,0x83, -0x58,0x2, 0x5, 0x27,0xe5,0x28,0xbe,0xb1,0x26,0x78,0x26,0xd2,0x7, 0xe5,0x26,0x60, -0xe, 0xe5,0x45,0xa, 0x3b,0x1b,0x34,0xe5,0x26,0xa, 0x8b,0xbd,0x83,0x78,0x2, 0xd2, -0x8, 0xe5,0x26,0xbe,0xb0,0x0, 0x28,0x2, 0x15,0x26,0x12,0xd1,0x8e,0x58,0x2, 0x5, -0x28,0x75,0x2d,0x0, 0x75,0x2e,0x0, 0x75,0x2c,0x0, 0x80,0x16,0xe5,0x2c,0xa, 0x8b, -0x9, 0x78,0x19,0x3f,0xbe,0x71,0x50,0x38,0x7, 0xbe,0x71,0x51,0x40,0x2, 0x5, 0x2d, -0x5, 0x2c,0x7e,0x73,0x19,0x68,0xbe,0x71,0x2c,0x38,0xe1,0x75,0x2c,0x0, 0x80,0x16, -0xe5,0x2c,0xa, 0x8b,0x9, 0x78,0x19,0x53,0xbe,0x71,0x52,0x38,0x7, 0xbe,0x71,0x53, -0x40,0x2, 0x5, 0x2e,0x5, 0x2c,0x7e,0x73,0x19,0x69,0xbe,0x71,0x2c,0x38,0xe1,0x85, -0x25,0x40,0x80,0x61,0x85,0x26,0x41,0x80,0x53,0xe5,0x40,0x7e,0x71,0x41,0x12,0x2d, -0x89,0x7a,0x35,0x42,0xe5,0x25,0xbe,0xb1,0x40,0x68,0x15,0xe5,0x27,0xbe,0xb1,0x40, -0x68,0xe, 0xe5,0x26,0xbe,0xb1,0x41,0x68,0x7, 0xe5,0x28,0xbe,0xb1,0x41,0x78,0x13, -0x7e,0x85,0x42,0x2d,0x98,0x7e,0x85,0x32,0xbe,0x85,0x42,0x58,0x2, 0x5, 0x3e,0x5, -0x3f,0x80,0x17,0x5, 0x5a,0x7e,0x85,0x42,0x2e,0x85,0x58,0x7a,0x85,0x58,0x7e,0x85, -0x32,0xbe,0x85,0x42,0x58,0x2, 0x5, 0x3c,0x5, 0x3d,0x5, 0x41,0xe5,0x28,0xbe,0xb1, -0x41,0x50,0xa6,0x5, 0x40,0xe5,0x27,0xbe,0xb1,0x40,0x50,0x98,0xe5,0x27,0x12,0xd1, -0xaa,0x9d,0x93,0xe5,0x25,0x7e,0x71,0x28,0x12,0x2d,0x89,0x9d,0x93,0x12,0xd1,0xa8, -0x9d,0x93,0xe5,0x27,0x7e,0x71,0x28,0x12,0x2d,0x89,0x9d,0x93,0x7e,0x85,0x36,0x2e, -0x85,0x34,0x7a,0x85,0x38,0x30,0x7, 0x15,0x20,0x8, 0x12,0x9e,0x95,0x38,0x15,0x3f, -0x15,0x3f,0xe5,0x3e,0xbe,0xb0,0x2, 0x40,0x4, 0x15,0x3e,0x15,0x3e,0xe5,0x3f,0xbe, -0xb0,0x4, 0x28,0x13,0xe5,0x3f,0x24,0xfc,0xf5,0x3f,0xe5,0x3e,0xbe,0xb0,0x4, 0x40, -0x6, 0xe5,0x3e,0x24,0xfc,0xf5,0x3e,0xbe,0x94,0x0, 0x0, 0x58,0x2, 0x6d,0x99,0x75, -0x46,0x22,0x12,0xd1,0x87,0xa, 0x2d,0xbd,0x32,0x68,0x5f,0xa, 0x8c,0xbd,0x38,0x68, -0x59,0x4c,0xdd,0x68,0x55,0x4c,0xcc,0x68,0x51,0xe5,0x2e,0x7e,0x71,0x2d,0xac,0xb7, -0xbe,0x54,0x0, 0x1, 0x78,0x34,0x7e,0x73,0x19,0x68,0xbe,0x70,0x1, 0x28,0x10,0x7e, -0xb3,0x19,0x69,0xb4,0x1, 0x9, 0x12,0x7f,0xb5,0xd1,0xf, 0xbd,0x38,0x48,0x22,0x7e, -0xb3,0x19,0x68,0xb4,0x1, 0x14,0x7e,0x73,0x19,0x69,0xbe,0x70,0x1, 0x28,0xb, 0x12, -0x7f,0xb5,0xd1,0xf, 0xbd,0x38,0x8, 0x2, 0x80,0x7, 0x7e,0xb3,0x3d,0x32,0xb4,0x1, -0x9, 0xe5,0x46,0xa, 0x3b,0x12,0x7f,0xd, 0xd1,0x25,0x7e,0x73,0x1e,0x8a,0xa, 0x37, -0x1b,0x34,0x7e,0x53,0x2, 0xe4,0xa, 0x25,0xbd,0x23,0x78,0x12,0x7e,0x53,0x2, 0xeb, -0xa, 0x85,0xbd,0x83,0x78,0x8, 0xd1,0x11,0xbe,0x34,0x0, 0x3, 0x8, 0x3c,0x4c,0xdd, -0x78,0xd, 0x4c,0xcc,0x78,0x9, 0x12,0x7f,0xb5,0xbe,0x34,0x0, 0x3, 0x8, 0x2b,0x7e, -0x73,0x1e,0x89,0xa, 0x37,0x1b,0x34,0xa, 0x2d,0xbd,0x23,0x78,0x11,0xa, 0x8c,0xbd, -0x83,0x78,0xb, 0x12,0x7f,0xb5,0xbe,0x34,0x0, 0x3, 0x18,0x2, 0x80,0xc, 0x7e,0xb3, -0x19,0x67,0x70,0xa, 0x7e,0xb3,0x1d,0xeb,0x70,0x4, 0xd1,0x1a,0x80,0xf, 0x7e,0xb3, -0x37,0x87,0xb4,0x1, 0x8, 0xe5,0x46,0xb4,0x22,0x3, 0x75,0x46,0x28,0x7e,0x73,0x1d, -0xeb,0xbe,0x70,0x0, 0x28,0x10,0x7e,0x85,0x30,0xbe,0x84,0x0, 0x8, 0x78,0x7, 0x7e, -0x84,0x0, 0x9, 0x7a,0x85,0x30,0x7e,0xb3,0x19,0x67,0xb4,0x1, 0x25,0x7e,0xb3,0x1d, -0xeb,0x70,0x1f,0x7e,0x87,0x1c,0x5a,0xbe,0x84,0x0, 0x12,0x40,0x2, 0xd1,0x1a,0xd1, -0x2c,0x8, 0x7, 0xe5,0x3c,0xbe,0xb1,0x3d,0x78,0x8, 0xe5,0x5a,0xa, 0x5b,0x1e,0x54, -0xf5,0x5a,0x7e,0x15,0x58,0x1a,0x2, 0x1a,0x0, 0x7d,0x39,0x1a,0x26,0x1a,0x24,0x2f, -0x10,0xe5,0x46,0xa, 0x1b,0x6d,0x0, 0x12,0x1b,0x1f,0x7f,0x71,0x7a,0x7d,0x48,0x7e, -0x15,0x38,0x1a,0x2, 0x1a,0x0, 0x7e,0x35,0x30,0x1a,0x26,0x1a,0x24,0x12,0x1b,0x1f, -0xe5,0x5a,0xa, 0xdb,0x6d,0xcc,0xe5,0x3f,0xa, 0x1b,0x6d,0x0, 0x2f,0x6, 0x12,0x1b, -0x1f,0x7a,0x1d,0x4c,0xbf,0x71,0x8, 0x3, 0x75,0x2f,0x2, 0x12,0x0, 0x6e,0x50,0x2, -0x61,0x30,0x7e,0xb3,0x19,0x68,0xb4,0x2, 0x2, 0x80,0x2, 0x41,0x46,0x7e,0xb3,0x19, -0x69,0xb4,0x1, 0x2, 0x80,0x2, 0x41,0x46,0x7e,0x73,0x19,0x3f,0xa, 0x57,0xb, 0x54, -0xf5,0x2b,0x80,0x1f,0xb1,0xe6,0x7d,0x85,0x2d,0x84,0x7e,0xf, 0x6, 0xb0,0x2d,0x18, -0x69,0x30,0x0, 0x2, 0xbe,0x34,0x0, 0x50,0x48,0x12,0xb, 0xa, 0x80,0xbd,0x38,0x18, -0xb, 0x5, 0x2b,0x7e,0x73,0x19,0x40,0xbe,0x71,0x2b,0x38,0xd8,0xe5,0x2b,0x7a,0xb3, -0x2, 0xe9,0x7e,0x73,0x19,0x40,0xa, 0x57,0x1b,0x54,0xf5,0x2b,0x80,0x2f,0xb1,0xe6, -0x7d,0x85,0x2d,0x84,0x7e,0x1f,0x6, 0xb0,0x2d,0x38,0x1b,0x35,0xb, 0x1a,0x40,0xbe, -0x44,0x0, 0x50,0x48,0x21,0x7e,0x63,0x1e,0x8a,0x7e,0x70,0x2, 0xac,0x67,0x7e,0x51, -0x2b,0x74,0x2, 0xac,0xb5,0x2d,0x53,0xd1,0x55,0x18,0xb, 0x15,0x2b,0x7e,0x73,0x19, -0x3f,0xbe,0x71,0x2b,0x40,0xc8,0xd1,0x4a,0xbc,0x7d,0x40,0xc, 0x7e,0x63,0x2, 0xea, -0xbc,0x6c,0x38,0x4, 0xbc,0xdc,0x40,0x16,0xbc,0x7c,0x50,0x2, 0x61,0x30,0x7e,0x73, -0x2, 0xea,0xbc,0x7d,0x28,0x2, 0x61,0x30,0xbc,0xcd,0x40,0x2, 0x61,0x30,0xe5,0x2f, -0xb4,0x2, 0x2, 0x80,0x2, 0x61,0x30,0x74,0x1, 0xd1,0x61,0xbe,0xb0,0x0, 0x38,0x2, -0x61,0x30,0xd1,0x3f,0x12,0x7f,0xbf,0xbe,0x34,0x0, 0x6, 0x48,0x2, 0x61,0x30,0xd1, -0x2c,0x58,0x2, 0x61,0x30,0x7e,0xb3,0x37,0x44,0xb4,0x1, 0x18,0xe5,0x3c,0x60,0x2, -0x61,0x2d,0xe5,0x3f,0xbe,0xb1,0x3e,0x68,0x2, 0x61,0x2d,0xe5,0x3e,0xbe,0xb0,0x0, -0x28,0x2, 0x61,0x30,0x61,0x2d,0x7e,0xb3,0x19,0x69,0xb4,0x2, 0x2, 0x80,0x2, 0x61, -0x30,0x7e,0xb3,0x19,0x68,0xb4,0x1, 0x2, 0x80,0x2, 0x61,0x30,0x7e,0x73,0x19,0x53, -0xa, 0x57,0xb, 0x54,0xf5,0x2b,0x80,0x1b,0x7e,0x71,0x2b,0x74,0x2, 0x12,0x7f,0x0, -0x69,0x30,0x0, 0x2, 0xbe,0x34,0x0, 0x50,0x48,0x12,0xb, 0xa, 0x80,0xbd,0x38,0x18, -0xb, 0x5, 0x2b,0x7e,0x73,0x19,0x54,0xbe,0x71,0x2b,0x38,0xdc,0xe5,0x2b,0x7a,0xb3, -0x2, 0xe9,0x7e,0x73,0x19,0x54,0xa, 0x57,0x1b,0x54,0xf5,0x2b,0x80,0x1b,0xb1,0xef, -0x7e,0x1f,0x6, 0xb0,0x2d,0x35,0x1b,0x35,0xb, 0x1a,0x40,0xbe,0x44,0x0, 0x50,0x48, -0x11,0xb1,0xef,0xd1,0x55,0x18,0xb, 0x15,0x2b,0x7e,0x73,0x19,0x53,0xbe,0x71,0x2b, -0x40,0xdc,0xd1,0x4a,0xbe,0x73,0x2, 0xe4,0x40,0x14,0x7e,0x63,0x2, 0xea,0xbe,0x63, -0x2, 0xeb,0x38,0xa, 0x7e,0x63,0x2, 0xe4,0xbe,0x63,0x2, 0xeb,0x40,0x1a,0xbe,0x73, -0x2, 0xeb,0x40,0x4c,0x7e,0x73,0x2, 0xea,0xbe,0x73,0x2, 0xe4,0x38,0x42,0x7e,0x73, -0x2, 0xeb,0xbe,0x73,0x2, 0xe4,0x50,0x38,0xe5,0x2f,0xb4,0x2, 0x33,0xe4,0xd1,0x61, -0xbe,0xb0,0x0, 0x28,0x2b,0xd1,0x3f,0x12,0x7f,0xbf,0xbe,0x34,0x0, 0x6, 0x58,0x20, -0xd1,0x2c,0x48,0x1c,0x7e,0xb3,0x37,0x44,0xb4,0x1, 0x12,0xe5,0x3c,0x70,0xe, 0xe5, -0x3f,0xbe,0xb1,0x3e,0x78,0x7, 0xe5,0x3e,0xbe,0xb0,0x0, 0x38,0x3, 0x75,0x2f,0x0, -0x7e,0xb3,0x1d,0xeb,0x70,0x2, 0x81,0x3b,0xa, 0x8e,0x9, 0x68,0x37,0x69,0xbe,0x60, -0xff,0x78,0x2, 0x81,0x3b,0xe5,0x2a,0xa, 0x2b,0x9, 0x72,0x37,0x69,0xbe,0x70,0xff, -0x78,0x2, 0x81,0x3b,0xbc,0x67,0x68,0x2, 0x81,0x33,0xd1,0x6f,0x18,0x16,0x7e,0x87, -0x1c,0x5e,0xbe,0x84,0x2, 0xbc,0x48,0xc, 0x7e,0x87,0x1c,0x62,0xbe,0x84,0xff,0x6, -0x48,0x2, 0x81,0x3b,0xa, 0x4c,0xa, 0x5d,0x2d,0x54,0x7d,0x25,0xe, 0x24,0x5e,0x54, -0x0, 0x1, 0x2d,0x52,0xf5,0x5c,0x7e,0x73,0x2, 0xeb,0xa, 0x37,0x7e,0x33,0x2, 0xe4, -0xa, 0x53,0x2d,0x53,0x7d,0x35,0xe, 0x34,0x5e,0x54,0x0, 0x1, 0x2d,0x53,0xf5,0x5d, -0x75,0x5e,0x0, 0x7e,0x33,0x2, 0xec,0xbe,0x30,0x2, 0x40,0x18,0xbe,0x30,0x5, 0x38, -0x13,0x7e,0x23,0x2, 0xed,0xbe,0x20,0x2, 0x40,0xa, 0xbe,0x20,0x5, 0x38,0x5, 0x75, -0x5e,0x3, 0x80,0x1f,0xbe,0x30,0x2, 0x50,0x9, 0x7e,0x23,0x2, 0xed,0xbe,0x20,0x3, -0x50,0xe, 0xbe,0x30,0x3, 0x40,0xc, 0x7e,0x33,0x2, 0xed,0xbe,0x30,0x2, 0x50,0x3, -0x75,0x5e,0x2, 0x7e,0xb3,0x37,0x44,0xb4,0x1, 0x3b,0xe5,0x5e,0xbe,0xb0,0x0, 0x8, -0x34,0x7c,0xb5,0xb1,0xfa,0x48,0x28,0xa, 0x4c,0xa, 0x5d,0x2d,0x54,0xe, 0x54,0xb1, -0xf7,0x48,0x1c,0xe5,0x5c,0x7e,0xa3,0x2, 0xeb,0xa, 0x2a,0x7e,0xa3,0x2, 0xe4,0xa, -0x3a,0x2d,0x32,0xe, 0x34,0xb1,0xfa,0x48,0x6, 0xe5,0x5c,0xb1,0xf7,0x58,0x6, 0x7e, -0xb3,0x37,0x87,0x60,0x16,0x7e,0x73,0x37,0x3c,0xbe,0x70,0x64,0x38,0xd, 0x75,0x2f, -0x2, 0x80,0x8, 0xe5,0x2f,0xb4,0x2, 0x3, 0x75,0x2f,0x0, 0x12,0x0, 0x6e,0x40,0x14, -0x7e,0xb3,0x19,0x67,0xb4,0x1, 0xd, 0xd1,0x6f,0x8, 0x9, 0x7e,0xb3,0x1d,0xeb,0x70, -0x3, 0x75,0x2f,0x2, 0x7e,0x87,0x1c,0x5e,0xbe,0x84,0x3, 0x20,0x48,0x2, 0xa1,0x44, -0x7e,0x73,0x18,0xd1,0xa, 0x87,0x5e,0x84,0x0, 0x2, 0x78,0x2, 0xa1,0x44,0x12,0x0, -0x6e,0x50,0x2, 0xa1,0x44,0xe5,0x2f,0xbe,0xb0,0x1, 0x38,0x2, 0x81,0xfe,0x7e,0xb3, -0x37,0x3a,0xb4,0x1, 0x2, 0x80,0x2, 0xa1,0x44,0x7e,0x43,0x37,0x3d,0xbc,0x4d,0x50, -0x34,0x7e,0x63,0x37,0x3e,0xbc,0x6d,0x28,0x2c,0x7e,0x73,0x37,0x3f,0xbe,0x73,0x2, -0xe4,0x50,0x22,0x7e,0x53,0x37,0x40,0xbe,0x53,0x2, 0xe4,0x28,0x18,0xbc,0x4c,0x38, -0x48,0xbc,0x6c,0x40,0x44,0xbe,0x73,0x2, 0xeb,0x38,0x3e,0xbe,0x53,0x2, 0xeb,0x40, -0x2, 0xa1,0x44,0x80,0x34,0xbc,0x4c,0x50,0x7b,0x7e,0x53,0x37,0x3e,0xbc,0x5c,0x28, -0x73,0x7e,0x63,0x37,0x3f,0xbe,0x63,0x2, 0xeb,0x50,0x69,0x7e,0x73,0x37,0x40,0xbe, -0x73,0x2, 0xeb,0x28,0x5f,0xbc,0x4d,0x38,0x10,0xbc,0x5d,0x40,0xc, 0xbe,0x63,0x2, -0xe4,0x38,0x6, 0xbe,0x73,0x2, 0xe4,0x50,0x4b,0x75,0x2f,0x0, 0x80,0x46,0xe5,0x2f, -0x70,0x42,0x7e,0xb3,0x37,0x3a,0xb4,0x1, 0x3b,0x7e,0x43,0x37,0x3d,0xbc,0x4d,0x50, -0x33,0x7e,0x53,0x37,0x3e,0xbc,0x5d,0x28,0x2b,0x7e,0x63,0x37,0x3f,0xbe,0x63,0x2, -0xe4,0x50,0x21,0x7e,0x73,0x37,0x40,0xbe,0x73,0x2, 0xe4,0x28,0x17,0xbc,0x4c,0x50, -0x13,0xbc,0x5c,0x28,0xf, 0xbe,0x63,0x2, 0xeb,0x50,0x9, 0xbe,0x73,0x2, 0xeb,0x28, -0x3, 0x75,0x2f,0x2, 0xe5,0x2f,0x70,0x19,0x7e,0xb3,0x1c,0x7c,0x60,0x13,0x7c,0xbd, -0x7e,0x73,0x2, 0xe4,0x7c,0x6c,0x7e,0x53,0x2, 0xeb,0xd1,0x83,0x60,0x3, 0x75,0x2f, -0x2, 0xe5,0x2f,0xbe,0xb0,0x0, 0x28,0x64,0xe5,0x2f,0xa, 0x8b,0x2e,0x84,0x37,0x37, -0x7e,0x89,0xb0,0x4, 0x7a,0x89,0xb0,0xe5,0x2a,0xa, 0x8b,0x9, 0xa8,0x37,0x47,0x4c, -0xaa,0x78,0xc, 0xa, 0x3e,0x9, 0xb3,0x37,0x47,0x19,0xb8,0x37,0x47,0x80,0x3d,0xa, -0x3e,0x9, 0xb3,0x37,0x47,0xf5,0x5b,0xbc,0xba,0x28,0x3, 0x7a,0xa1,0x5b,0x75,0x2b, -0x0, 0x80,0x22,0x9, 0x58,0x37,0x47,0xe5,0x2b,0xa, 0x3b,0x9, 0x43,0x37,0x47,0xbc, -0x45,0x68,0xa, 0xa, 0x1e,0x9, 0x51,0x37,0x47,0xbc,0x45,0x78,0x6, 0xe5,0x5b,0x19, -0xb3,0x37,0x47,0x5, 0x2b,0xe5,0x29,0xbe,0xb1,0x2b,0x38,0xd7,0x5, 0x2a,0xe5,0x29, -0xbe,0xb1,0x2a,0x28,0x3, 0x2, 0xac,0x4f,0xb, 0xe0,0xe5,0x29,0xbc,0xbe,0x28,0x3, -0x2, 0xab,0xe6,0xda,0x3b,0x22,0x7e,0x83,0x1e,0x8a,0x7e,0x90,0x2, 0xac,0x89,0x7e, -0x71,0x2b,0x74,0x2, 0xac,0xb7,0x22,0x7e,0x71,0x5d,0x12,0x2d,0x89,0xe5,0x5e,0x1a, -0x1b,0x7e,0x5, 0x55,0xad,0x10,0x7d,0x21,0xe, 0x24,0xe, 0x24,0xbd,0x32,0x22,0x7d, -0x83,0xa, 0x2c,0xa, 0x3d,0x9d,0x32,0x2, 0x1e,0x5, 0xe5,0x46,0xa, 0x3b,0x7e,0x24, -0x0, 0x3, 0x12,0x1a,0xed,0x7c,0xb7,0x25,0x46,0xf5,0x46,0x22,0xe5,0x3c,0xa, 0x2b, -0xe5,0x3d,0xa, 0x3b,0x7d,0x83,0x9d,0x82,0x3e,0x84,0x3e,0x84,0xbd,0x83,0x22,0x7e, -0x73,0x2, 0xea,0xa, 0x27,0x7e,0x73,0x2, 0xe9,0x22,0xe5,0x2b,0x7a,0xb3,0x2, 0xea, -0x7e,0x73,0x2, 0xe9,0x22,0x7e,0x1f,0x6, 0xb0,0x2d,0x35,0xb, 0x1a,0x80,0xbd,0x48, -0x22,0x7e,0x73,0x1d,0xeb,0xbe,0x70,0x0, 0x28,0x3, 0x74,0x1, 0x22,0xe4,0x22,0x7e, -0x1d,0x4c,0x2f,0x11,0x7e,0x8, 0x0, 0x3, 0x12,0x1b,0x8c,0x7f,0x1, 0x7e,0x1d,0x48, -0xbf,0x10,0x22,0xc1,0x85,0xca,0xd8,0xca,0x79,0x7c,0xa5,0x7c,0x96,0x7c,0x87,0x7c, -0xfb,0x7e,0xf, 0x15,0x48,0x7e,0xe0,0xff,0x7e,0xd0,0xff,0x7e,0x70,0x23,0xac,0x79, -0xa, 0x8a,0x7d,0xc3,0x2d,0xc8,0x3e,0xc4,0x7f,0x10,0x2d,0x3c,0xb, 0x1a,0xc0,0x7e, -0x70,0x23,0xac,0x7f,0xa, 0x28,0x2d,0x32,0x3e,0x34,0x7f,0x70,0x2d,0xf3,0xb, 0x7a, -0xb0,0xbd,0xbc,0x58,0x6, 0x7d,0xdb,0xe, 0xd4,0x80,0x4, 0x7d,0xdc,0xe, 0xd4,0xbe, -0xd4,0x1, 0xf4,0x8, 0x4, 0x7e,0xd4,0x1, 0xf4,0x7e,0xb3,0x1d,0xeb,0xbe,0xb0,0x1, -0x38,0x2e,0xbe,0xd4,0x1, 0x2c,0x8, 0x4, 0x7e,0xd4,0x1, 0x2c,0x7d,0x38,0x9d,0x32, -0x12,0x1e,0x5, 0xbe,0x34,0x0, 0x8, 0x8, 0x4, 0x7e,0xd4,0x0, 0x64,0xa, 0x28,0xa, -0x3a,0x9d,0x32,0x12,0x1e,0x5, 0xbe,0x34,0x0, 0x6, 0x8, 0x4, 0x7e,0xd4,0x0, 0x78, -0xbc,0x8a,0x28,0x3, 0x7e,0xd0,0x1, 0xbc,0xf9,0x28,0x3, 0x7e,0xe0,0x1, 0x6d,0xcc, -0xf1,0x93,0xbd,0x3f,0x78,0x41,0xbc,0xf9,0x68,0x62,0x1a,0x3e,0xa, 0x29,0x2d,0x23, -0x7e,0x34,0x0, 0x23,0xad,0x32,0xa, 0x2a,0x2d,0x32,0x3e,0x34,0x7f,0x70,0x2d,0xf3, -0xb, 0x7a,0xc0,0x7e,0x70,0x23,0xac,0x79,0x1a,0xbd,0x2d,0xb2,0x2d,0xb3,0x3e,0xb4, -0x7f,0x10,0x2d,0x3b,0xb, 0x1a,0xb0,0xbd,0xcb,0x58,0x6, 0x7d,0xab,0x2c,0xad,0x80, -0x24,0x7d,0xac,0x2c,0x9e,0x80,0x1e,0xf1,0x93,0xbd,0x3f,0x8, 0x4, 0x2c,0x9e,0x80, -0x2, 0x2c,0xad,0x7e,0x70,0x23,0xac,0x79,0xa, 0xaa,0x2d,0xa3,0x3e,0xa4,0x7f,0x10, -0x2d,0x3a,0xb, 0x1a,0xa0,0xbd,0xda,0x8, 0x95,0xe4,0x80,0x2, 0x74,0x1, 0xda,0x79, -0xda,0xd8,0x22,0xa, 0x28,0xa, 0x3a,0x9d,0x32,0x12,0x1e,0x5, 0x7d,0xf3,0xa, 0x2f, -0xa, 0x39,0x9d,0x32,0x2, 0x1e,0x5, 0xca,0xd8,0xca,0x79,0x7c,0xf7,0x7c,0xeb,0x6c, -0xdd,0xa, 0x3d,0x9, 0xb3,0x3b,0x6d,0xb4,0x2, 0x19,0x7c,0xbe,0x7c,0x7f,0x7e,0x50, -0xa, 0xac,0x5d,0x9, 0x62,0x3b,0x88,0x9, 0x52,0x3b,0x89,0xd1,0x83,0x60,0x4, 0x74, -0x1, 0x80,0x8, 0xb, 0xd0,0xbe,0xd0,0xa, 0x40,0xd7,0xe4,0xda,0x79,0xda,0xd8,0x22, -0xca,0x3b,0x7f,0x50,0x7e,0xb3,0x1c,0x58,0xf5,0x29,0x6c,0xee,0x7e,0xd0,0x1, 0x80, -0x1a,0xa, 0x3e,0x2d,0x3b,0x7d,0x2a,0x7e,0x1b,0x60,0xa, 0x2d,0x7f,0x5, 0x2d,0x12, -0x7e,0xb, 0x70,0xbc,0x76,0x40,0x2, 0x7c,0xed,0xb, 0xd0,0xe5,0x29,0xbc,0xbd,0x38, -0xe0,0xa, 0x3e,0x2d,0x3b,0x7d,0x2a,0x7e,0x1b,0xe0,0x6c,0xff,0x7e,0xd0,0x1, 0x21, -0x8d,0x75,0x2a,0x0, 0x6d,0x33,0x7a,0x35,0x2b,0x7a,0x35,0x2d,0x9f,0x44,0x7a,0x4d, -0x25,0xe4,0x7a,0xb3,0x2, 0xe4,0x74,0xff,0x7a,0xb3,0x2, 0xe5,0xe4,0x7a,0xb3,0x2, -0xe6,0x74,0xff,0x7a,0xb3,0x2, 0xe7,0xe4,0x7a,0xb3,0x2, 0xe8,0x6c,0xcc,0x1, 0xf7, -0x74,0x2, 0xac,0xbc,0x9, 0x95,0x19,0xde,0x9, 0x85,0x19,0xdf,0xa, 0x5c,0x7f,0x15, -0x2d,0x35,0x7e,0x1b,0x70,0xbc,0x7d,0x68,0x2, 0x1, 0xf5,0x5, 0x2a,0x31,0x98,0x7d, -0x53,0x2e,0x55,0x2b,0x7a,0x55,0x2b,0x31,0x98,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0xa, -0x39,0x6d,0x22,0x12,0x1b,0x1f,0x7f,0x1, 0x7e,0x1d,0x25,0x2f,0x10,0x7a,0x1d,0x25, -0x31,0x98,0x7d,0x13,0x1a,0x2, 0x1a,0x0, 0xa, 0x38,0x6d,0x22,0x12,0x1b,0x1f,0x2f, -0x41,0x31,0x98,0xbe,0x35,0x2d,0x8, 0x5, 0x31,0x98,0x7a,0x35,0x2d,0x74,0x5, 0xac, -0xbc,0x9, 0x75,0x1a,0x1a,0x2e,0x73,0x2, 0xe4,0x7a,0x73,0x2, 0xe4,0x9, 0x75,0x1a, -0x1b,0xbe,0x73,0x2, 0xe5,0x50,0x4, 0x7a,0x73,0x2, 0xe5,0x9, 0x75,0x1a,0x1c,0xbe, -0x73,0x2, 0xe6,0x28,0x4, 0x7a,0x73,0x2, 0xe6,0x9, 0x75,0x1a,0x1d,0xbe,0x73,0x2, -0xe7,0x50,0x4, 0x7a,0x73,0x2, 0xe7,0x9, 0x75,0x1a,0x1e,0xbe,0x73,0x2, 0xe8,0x28, -0x4, 0x7a,0x73,0x2, 0xe8,0xb, 0xc0,0xe5,0x29,0xbc,0xbc,0x28,0x2, 0x1, 0x50,0xe5, -0x2a,0xbe,0xb0,0x0, 0x38,0x2, 0x21,0x8b,0x7e,0x35,0x2b,0x1a,0x26,0x1a,0x24,0x7e, -0x8, 0x0, 0x2, 0x12,0x1b,0x8c,0x7e,0xd, 0x25,0x2f,0x1, 0x7a,0xd, 0x25,0x2f,0x41, -0x7e,0x15,0x2b,0x12,0x7f,0x1b,0x12,0x1b,0x8c,0x7a,0x1d,0x25,0x7e,0x15,0x2b,0x1a, -0x2, 0x1a,0x0, 0x7f,0x14,0x12,0x1b,0x8c,0x7f,0x41,0x7e,0x1d,0x25,0x74,0x2, 0xac, -0xbf,0x19,0x75,0x37,0x88,0x7d,0x39,0x74,0x2, 0xac,0xbf,0x19,0x75,0x37,0x89,0x12, -0x4f,0xfb,0xac,0x3f,0x2e,0x14,0x1a,0x1a,0x6d,0x0, 0x31,0x9f,0x7e,0x37,0x1c,0x5e, -0xbe,0x35,0x2d,0x78,0xd, 0x7e,0x1d,0x25,0x7a,0x73,0x1c,0x60,0x7d,0x39,0x7a,0x73, -0x1c,0x61,0x7e,0x37,0x37,0x65,0x4d,0x33,0x68,0xf, 0x7e,0x25,0x2d,0x7e,0x70,0x2, -0xac,0x7f,0x2e,0x37,0x37,0x65,0x1b,0x38,0x20,0xb, 0xf0,0xb, 0xd0,0xbc,0xed,0x40, -0x2, 0x1, 0x21,0x7c,0xbf,0xda,0x3b,0x22,0x7c,0xb9,0x7c,0x78,0x2, 0x2d,0x89,0x7e, -0x18,0x2, 0xe4,0x2, 0x4d,0x9b,0x7c,0x9b,0x7f,0x71,0x7f,0x60,0x7e,0x34,0x20,0xdf, -0x7e,0x24,0x0, 0xff,0x7e,0x14,0x2, 0xee,0x74,0x2a,0x12,0x1b,0xe1,0x7e,0x58,0x2, -0xee,0x7c,0xb9,0x7e,0x71,0x5f,0x12,0x2d,0x89,0x7d,0x43,0xe5,0x60,0x7e,0x71,0x61, -0x12,0x2d,0x89,0x2d,0x34,0xe, 0x34,0x7f,0x5, 0x7e,0x50,0x7, 0xb, 0xa, 0x50,0xbd, -0x53,0x58,0xf, 0x69,0x30,0x0, 0x2, 0x1b,0x6a,0x30,0x69,0x30,0x0, 0x4, 0x1b,0x7a, -0x30,0x22,0x2e,0x14,0x0, 0x6, 0x1b,0x50,0x78,0xe2,0x22,0x7e,0xb3,0x37,0x44,0xb4, -0x1, 0x5, 0xe4,0x7a,0xb3,0x37,0x3c,0x7e,0xa3,0x1d,0xeb,0xbe,0xa0,0x1, 0x78,0xa, -0x7e,0xb3,0x37,0x3c,0x70,0x4, 0x74,0x1, 0x80,0x20,0x7e,0xb3,0x19,0x67,0xbe,0xb0, -0x1, 0x28,0x16,0xbe,0xa0,0x1, 0x78,0x11,0x7e,0xb3,0x37,0x3c,0xbe,0xb0,0xfa,0x50, -0xd, 0xbe,0xb0,0x0, 0x28,0x8, 0x4, 0x80,0x1, 0xe4,0x7a,0xb3,0x37,0x3c,0x22,0x7e, -0x73,0x18,0xd1,0x12,0x26,0xe2,0x68,0x2a,0x7e,0x37,0x9, 0x68,0xbe,0x34,0x6, 0xa4, -0x48,0xa, 0x7e,0x37,0x9, 0x6a,0xbe,0x34,0x7, 0xd0,0x58,0x3, 0xe4,0x80,0xf, 0x7e, -0x37,0x1c,0x5e,0xbe,0x34,0x2, 0xbc,0x58,0x3, 0xe4,0x80,0x2, 0x74,0x1, 0x7a,0xb3, -0x37,0x44,0x22,0x7e,0x37,0x9, 0x62,0xbe,0x34,0x0, 0x32,0x58,0xc, 0x7e,0xb3,0x37, -0xc5,0xbe,0xb0,0x0, 0x28,0x21,0x14,0x80,0x1a,0xbe,0x34,0x0, 0x96,0x8, 0x18,0x7e, -0x37,0x1c,0x5e,0xbe,0x34,0x0, 0x32,0x58,0xe, 0x7e,0xb3,0x37,0xc5,0xbe,0xb0,0x14, -0x50,0x5, 0x4, 0x7a,0xb3,0x37,0xc5,0x7e,0x73,0x37,0xc5,0xa5,0xbf,0x0, 0x3, 0xc2, -0xe, 0x22,0xbe,0x70,0xa, 0x28,0x2, 0xd2,0xe, 0x22,0x6c,0x66,0x7e,0x50,0xfe,0x7e, -0x43,0x1c,0x58,0xbe,0x40,0x2, 0x50,0x5, 0xe4,0x7a,0xb3,0x37,0x87,0x6c,0x33,0x80, -0x16,0x74,0x2, 0xac,0xb3,0x9, 0x25,0x19,0xdf,0xbc,0x26,0x28,0x2, 0x7c,0x62,0xbc, -0x25,0x50,0x2, 0x7c,0x52,0xb, 0x30,0xbc,0x43,0x38,0xe6,0xa, 0x25,0xa, 0x36,0x9d, -0x32,0x12,0x1e,0x5, 0xbe,0x70,0x9, 0x28,0x4, 0x74,0x1, 0x80,0x14,0x7e,0xb3,0x37, -0x87,0xb4,0x1, 0xc, 0xbe,0x70,0x7, 0x28,0x4, 0x74,0x1, 0x80,0x4, 0xe4,0x80,0x1, -0xe4,0x7a,0xb3,0x37,0x87,0x22,0x6c,0x77,0x80,0x1c,0x7e,0x30,0x2, 0xac,0x37,0x49, -0x1, 0x15,0x94,0x49,0x21,0x15,0x4c,0xbd,0x20,0x28,0x9, 0x2e,0x14,0x15,0x4c,0x9d, -0x20,0x1b,0x18,0x20,0xb, 0x70,0x7e,0x63,0x1e,0x8a,0xbc,0x67,0x38,0xdc,0x22,0xca, -0x3b,0x6c,0xcc,0x7e,0xf0,0x9, 0x7e,0xa3,0x1d,0xea,0x7c,0xda,0xe4,0x7a,0xb3,0x3b, -0xf2,0x4c,0xaa,0x78,0xf, 0x12,0xd1,0xdd,0x28,0x5, 0x14,0x7a,0xb3,0x3a,0xd6,0xe4, -0x7a,0xb3,0x3a,0xd7,0x7e,0xb3,0x3d,0x32,0xb4,0x1, 0xb, 0x7e,0x8, 0x3b,0x6d,0x6d, -0x33,0x12,0x5f,0xec,0x81,0x36,0x6c,0xee,0x80,0xf, 0x7c,0xbe,0x91,0x39,0x70,0x2, -0xb, 0xe0,0xbe,0xc0,0xa, 0x38,0xa, 0xb, 0xc0,0x7e,0x73,0x1d,0xea,0xbc,0x7e,0x38, -0xe9,0x7e,0x73,0x3b,0xf2,0xa, 0x27,0xa, 0x3d,0x9d,0x32,0x7a,0x73,0x3a,0xd9,0x6c, -0xee,0x80,0x2, 0x1b,0xf0,0xa, 0x3f,0x9, 0xb3,0x1d,0xae,0xbe,0xb0,0x3, 0x68,0x5, -0xbe,0xf0,0x0, 0x38,0xee,0x7c,0xbe,0x7c,0x7f,0x91,0x63,0x60,0x6, 0x4c,0xff,0x68, -0x9, 0x1b,0xf0,0xb, 0xe0,0xbe,0xe0,0xa, 0x40,0xdb,0x7e,0xa3,0x3b,0xf2,0x4c,0xaa, -0x78,0x9, 0xc2,0xf, 0xe4,0x7a,0xb3,0x3a,0xcb,0x80,0xe, 0x7e,0xb3,0x3a,0xcb,0xbe, -0xb3,0x3b,0xf2,0x50,0x4, 0x7a,0xa3,0x3a,0xcb,0x7e,0x73,0x3a,0xd8,0xbe,0x73,0x1d, -0xea,0x50,0x3, 0xd3,0x80,0x1, 0xc3,0x92,0x10,0x7e,0xa3,0x1d,0xea,0x7a,0xa3,0x3a, -0xd8,0x7e,0xb3,0x3a,0xf3,0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x3a,0xf3,0x7e, -0xb3,0x3a,0xef,0xbe,0xb0,0x0, 0x28,0x5, 0x14,0x7a,0xb3,0x3a,0xef,0x7e,0xb3,0x3b, -0xe6,0x60,0x5, 0x14,0x7a,0xb3,0x3b,0xe6,0x4c,0xaa,0x78,0xa, 0x12,0xd1,0xd5,0x28, -0x5, 0x14,0x7a,0xb3,0x3a,0xe4,0xda,0x3b,0x22,0x7c,0x5b,0x74,0xa, 0xac,0xb5,0x9, -0x75,0x1c,0x86,0x5e,0x70,0xf, 0xa, 0x17,0x9, 0xb1,0x1d,0xae,0xbe,0x70,0xa, 0x40, -0x2, 0xe4,0x22,0x70,0x4, 0x7c,0xb5,0x81,0xff,0xb4,0x2, 0x5, 0x7c,0xb5,0x2, 0x90, -0xb7,0xe4,0x22,0xca,0x79,0x7c,0xe7,0x7c,0xfb,0xa, 0x3f,0x9, 0xb3,0x1d,0xae,0xb4, -0x1, 0x2, 0x80,0x2, 0x81,0xfb,0x9, 0xb3,0x3b,0x6d,0xb4,0x2, 0x7e,0x74,0x1, 0x19, -0xb3,0x3b,0x6d,0x7c,0xbf,0x12,0xc2,0x21,0x60,0x71,0x7e,0x23,0x1d,0xea,0xbe,0x20, -0xa, 0x50,0x68,0xe4,0xa, 0x3e,0x19,0xb3,0x1d,0xae,0x19,0xb3,0x1d,0xb8,0x7e,0x70, -0xa, 0xac,0x7f,0x2e,0x34,0x3b,0x9, 0x7e,0x30,0xa, 0xac,0x23,0x12,0x8e,0xe5,0x7e, -0x73,0x1d,0xea,0x74,0xa, 0xac,0xb7,0x19,0xe5,0x1c,0x86,0x7c,0xb7,0x4, 0x7a,0xb3, -0x1d,0xea,0x7e,0x73,0x1d,0xea,0x80,0x19,0x7e,0x50,0xa, 0xac,0x57,0x9, 0x62,0x1c, -0x86,0xbc,0x6f,0x68,0x4, 0xbc,0x6e,0x78,0x6, 0x74,0xff,0x19,0xb2,0x1c,0x86,0xb, -0x70,0xbe,0x70,0xa, 0x40,0xe2,0x7e,0x73,0x31,0x95,0xa, 0x2e,0x19,0x72,0x31,0x8b, -0xe4,0xa, 0x3f,0x19,0xb3,0x3a,0xda,0x74,0x1, 0x80,0x1, 0xe4,0xda,0x79,0x22,0xca, -0x79,0x7c,0xf7,0x7c,0xeb,0x12,0x57,0xe7,0xac,0x3f,0x2e,0x14,0x3b,0x9, 0x74,0xa, -0x12,0x1b,0xc0,0x7e,0x30,0xa, 0xac,0x3f,0x7d,0x31,0x2e,0x34,0x3b,0x9, 0x12,0x97, -0xe2,0x12,0x97,0xb7,0x19,0xb3,0x3b,0xe8,0x19,0xb3,0x3a,0xe5,0x7c,0xbe,0xb1,0xfd, -0x60,0x5, 0x7e,0x70,0x2, 0x80,0x2, 0x6c,0x77,0xa, 0x2f,0x19,0x72,0x3b,0x6d,0x7c, -0xbf,0x7e,0x70,0x1, 0x12,0x96,0x7, 0x60,0x8, 0x74,0x2, 0xa, 0x3f,0x19,0xb3,0x3b, -0x6d,0xa, 0x2f,0x9, 0xb2,0x3b,0x6d,0x70,0x15,0x12,0x97,0xa0,0xbe,0x34,0x0, 0xb4, -0x40,0x6, 0xbe,0x34,0xf, 0x4c,0x28,0x6, 0x74,0x2, 0x19,0xb2,0x3b,0x6d,0xe4,0x19, -0xb2,0x3a,0xda,0x19,0xb2,0x3b,0x77,0x9, 0xa2,0x3b,0x6d,0xbe,0xa0,0x2, 0x78,0x6, -0x74,0x24,0x19,0xb2,0x3a,0xcc,0x7e,0x44,0x0, 0x1, 0x7c,0xbf,0x60,0x5, 0x3e,0x44, -0x14,0x78,0xfb,0x7d,0x34,0x6e,0x34,0xff,0xff,0x5e,0x37,0x3a,0xf1,0x7a,0x37,0x3a, -0xf1,0xbe,0xa0,0x2, 0x68,0x47,0x12,0x7b,0xea,0x60,0x42,0x7e,0x73,0x3a,0xd6,0xbe, -0x70,0x0, 0x38,0x16,0x74,0xa, 0xac,0xbe,0x9, 0x75,0x1c,0x8a,0xa, 0x27,0x7e,0x73, -0x1e,0x8c,0xa, 0x37,0x1b,0x34,0xbd,0x23,0x78,0x23,0x74,0x2, 0xa, 0x3f,0x19,0xb3, -0x3b,0x6d,0x74,0x8, 0x19,0xb3,0x3a,0xcc,0x7e,0x34,0x0, 0x1, 0x7c,0xbf,0x60,0x5, -0x3e,0x34,0x14,0x78,0xfb,0x4e,0x37,0x3a,0xf1,0x7a,0x37,0x3a,0xf1,0x12,0x97,0x99, -0x60,0x7, 0x12,0xc1,0x6b,0x74,0x1, 0x80,0x1, 0xe4,0xda,0x79,0x22,0x7e,0x60,0x1, -0xc1,0x2, 0xca,0x3b,0x7a,0x61,0x32,0x7a,0x71,0x31,0xf5,0x30,0x75,0x33,0x1, 0x6d, -0x33,0x7a,0x35,0x36,0x7a,0x35,0x38,0x75,0x3a,0x0, 0x75,0x3b,0x0, 0x75,0x3c,0x0, -0x7e,0x73,0x3c,0xee,0x7a,0x71,0x3d,0x7e,0x51,0x30,0x74,0xa, 0xac,0x5b,0x9, 0xb2, -0x1c,0x89,0xf5,0x34,0x9, 0xb2,0x1c,0x8a,0xf5,0x35,0xbe,0x70,0x0, 0x28,0x2b,0x75, -0x33,0x1, 0xe5,0x3d,0xb4,0x1, 0x8, 0xe5,0x35,0x70,0x4, 0xe5,0x34,0x60,0xf, 0xe5, -0x3d,0xb4,0x2, 0x16,0xe5,0x35,0xb4,0x22,0x11,0xe5,0x34,0xb4,0xf, 0xc, 0x7e,0x73, -0x3a,0xd8,0xbe,0x70,0x0, 0x28,0x3, 0x75,0x33,0x4, 0xe5,0x3d,0x70,0x5a,0xe5,0x34, -0xbe,0xb0,0x2, 0x28,0x7, 0xe5,0x34,0xbe,0xb0,0xd, 0x40,0x4c,0x12,0x2e,0x6d,0xe5, -0x3e,0x70,0x2, 0xe1,0x1c,0x7e,0x38,0x0, 0x48,0xe5,0x34,0x7e,0x71,0x35,0x7e,0x60, -0x1, 0x7e,0x51,0x32,0x12,0x2e,0x7c,0xe5,0x3f,0xbe,0xb0,0x3, 0x50,0xa, 0xe5,0x49, -0xbe,0xb0,0x4, 0x28,0x3, 0x75,0x49,0x4, 0xe5,0x49,0x25,0x3f,0xf5,0x3f,0xe5,0x4a, -0x25,0x40,0xf5,0x40,0x7e,0x35,0x4c,0x2e,0x35,0x42,0x7a,0x35,0x42,0x7e,0x35,0x4e, -0x2e,0x35,0x44,0x7a,0x35,0x44,0x80,0x54,0xe5,0x3d,0xbe,0xb0,0x0, 0x28,0x49,0x6c, -0xaa,0xe5,0x34,0x60,0x5, 0xe5,0x34,0xb4,0xf, 0x14,0x7e,0x38,0x0, 0x52,0xe5,0x34, -0x7e,0x71,0x35,0x6c,0x66,0x7e,0x51,0x32,0x12,0x2e,0x7c,0x7e,0xa0,0x1, 0xe5,0x35, -0xbe,0xb0,0x2, 0x28,0x7, 0xe5,0x35,0xbe,0xb0,0x20,0x40,0x5, 0x12,0x2e,0x6d,0x80, -0x1b,0x4c,0xaa,0x68,0xf, 0x7e,0x34,0x0, 0x52,0x7e,0x14,0x0, 0x3e,0x74,0xa, 0x12, -0x1b,0xc0,0x80,0x8, 0xe4,0x2, 0xc1,0x2e,0xe4,0x2, 0xc1,0x2e,0x85,0x3e,0x3a,0x85, -0x3f,0x3b,0x85,0x40,0x3c,0x7e,0x35,0x42,0x7a,0x35,0x36,0x7e,0x35,0x44,0x7a,0x35, -0x38,0xe5,0x3a,0x60,0x49,0xe5,0x3d,0x70,0x31,0x12,0xd1,0xcd,0x49,0x45,0x1c,0x84, -0xbe,0x44,0x21,0xc0,0x28,0x12,0x49,0x45,0x1c,0x82,0xbe,0x44,0x0, 0xc0,0x40,0x26, -0xbe,0x44,0xf, 0x40,0x28,0x28,0x80,0x1e,0x49,0x35,0x1c,0x82,0xbe,0x34,0x0, 0xdc, -0x40,0x14,0xbe,0x34,0xf, 0x40,0x28,0x16,0x80,0xc, 0x12,0xd1,0xcd,0x49,0x35,0x1c, -0x82,0x12,0x95,0xe9,0x50,0x5, 0x75,0x33,0x2, 0x80,0x3, 0x75,0x33,0x0, 0xe5,0x3a, -0x70,0x11,0xe5,0x32,0x60,0xd, 0xe5,0x34,0x7e,0x71,0x35,0x12,0xb7,0xa7,0x60,0x3, -0x75,0x33,0x3, 0xe5,0x3e,0x70,0x1d,0xe5,0x3d,0xbe,0xb0,0x0, 0x28,0x16,0xe5,0x3b, -0x12,0xd1,0xbb,0xe5,0x3b,0x9c,0xba,0xf5,0x3b,0xe5,0x3c,0x12,0xd1,0xbb,0xe5,0x3c, -0x9c,0xba,0xf5,0x3c,0x7e,0x25,0x46,0xe5,0x31,0xa, 0x3b,0x9, 0x33,0x3a,0xe5,0xa, -0x13,0x3e,0x14,0x3e,0x14,0xbd,0x12,0x58,0x24,0xbe,0x24,0x4, 0x0, 0x48,0x8, 0x74, -0xff,0x19,0xb3,0x3a,0xe5,0x80,0x8, 0xe, 0x24,0xe, 0x24,0x19,0x53,0x3a,0xe5,0xe5, -0x3b,0xa, 0x1b,0xe5,0x3c,0xa, 0x2b,0x2d,0x21,0x19,0x53,0x3b,0xe8,0xe5,0x3a,0x60, -0x9, 0xe5,0x3b,0xbe,0xb0,0x4, 0x28,0x2, 0x5, 0x33,0xe5,0x3b,0xbe,0xb0,0x5, 0x28, -0x2, 0x5, 0x33,0xe5,0x3b,0xbe,0xb0,0x6, 0x28,0x2, 0x5, 0x33,0xe5,0x3b,0xbe,0xb0, -0x7, 0x28,0x2, 0x5, 0x33,0x7e,0x25,0x38,0xbe,0x24,0x0, 0x0, 0x18,0x5, 0x6d,0x22, -0x7a,0x25,0x38,0x7e,0x25,0x36,0x7d,0x12,0xe, 0x14,0xe, 0x14,0xbe,0x15,0x38,0x8, -0x12,0xe5,0x32,0x70,0xe, 0x7e,0x15,0x38,0x2e,0x15,0x36,0xbe,0x14,0x5, 0x28,0x8, -0x2, 0x5, 0x33,0x7d,0x12,0xe, 0x14,0xbe,0x15,0x38,0x8, 0xe, 0x7e,0x15,0x38,0x2e, -0x15,0x36,0xbe,0x14,0xc, 0xe4,0x8, 0x2, 0x5, 0x33,0xbe,0x25,0x38,0x58,0x26,0xe5, -0x3b,0xbe,0xb0,0x6, 0x50,0x1f,0xbe,0x24,0xd, 0xaa,0x58,0x19,0xe5,0x33,0xbe,0xb0, -0x0, 0x28,0x2, 0x15,0x33,0xe5,0x3d,0xbe,0xb0,0x0, 0x28,0x9, 0xe5,0x33,0xbe,0xb0, -0x0, 0x28,0x2, 0x15,0x33,0xe5,0x32,0xa, 0xb, 0x2e,0x4, 0x0, 0x3, 0xe5,0x3b,0xa, -0x1b,0xbd,0x10,0x8, 0x2, 0x5, 0x33,0xe5,0x3d,0xbe,0xb0,0x0, 0x28,0x1b,0x7e,0x15, -0x38,0x7d,0x1, 0x3e,0x4, 0xbe,0x5, 0x36,0x8, 0xf, 0xbe,0x14,0xb, 0xb8,0x58,0x9, -0xbe,0x24,0xd, 0xac,0x58,0x3, 0x75,0x33,0x2, 0xe5,0x3d,0xb4,0x1, 0x16,0xe5,0x35, -0xb4,0x22,0x11,0xe5,0x3b,0xbe,0xb0,0x5, 0x50,0xa, 0xe5,0x33,0xbe,0xb0,0x2, 0x28, -0x3, 0x75,0x33,0x2, 0xe5,0x3b,0x70,0x2, 0xf5,0x33,0xe5,0x3d,0xbe,0xb0,0x0, 0x28, -0x18,0xe5,0x41,0xbe,0xb0,0x1, 0x28,0x11,0xe5,0x3b,0xbe,0xb0,0x7, 0x50,0xa, 0xe5, -0x33,0xbe,0xb0,0x2, 0x28,0x3, 0x75,0x33,0x2, 0xe5,0x32,0x60,0x2, 0x80,0x9, 0x9, -0x53,0x3b,0x77,0xbe,0x51,0x33,0x50,0x6, 0xe5,0x33,0x19,0xb3,0x3b,0x77,0xe5,0x33, -0x70,0xc, 0x9, 0x53,0x3b,0x77,0xbe,0x50,0x3, 0x28,0x3, 0x75,0x33,0x1, 0xe5,0x33, -0xbe,0xb0,0x2, 0x50,0x7, 0x31,0x31,0x28,0x3, 0x75,0x33,0x2, 0xe5,0x33,0xda,0x3b, -0x22,0x9, 0x73,0x3b,0x77,0xbe,0x70,0x4, 0x22,0x7c,0x36,0x7c,0x27,0x7c,0xab,0xbe, -0xa0,0x4, 0x50,0x4, 0xa, 0x3a,0x80,0x1a,0xa, 0x22,0x7d,0x42,0x1b,0x46,0xa, 0x3a, -0xbd,0x34,0x58,0x8, 0x1a,0x3, 0x3e,0x4, 0x3e,0x4, 0x80,0xc, 0x9e,0x24,0x0, 0x8, -0x9d,0x32,0x1a,0x23,0xad,0x32,0x7d,0x3, 0x7d,0x30,0x22,0x7c,0xbe,0x7c,0x7f,0x7c, -0x17,0x7c,0xb, 0x7e,0xb3,0x1d,0xea,0x14,0x7a,0xb3,0x1d,0xea,0x7e,0x63,0x1d,0xea, -0x7e,0x70,0xa, 0xac,0x67,0x12,0x57,0xec,0xac,0x30,0x12,0x8e,0xe5,0x7e,0x0, 0xff, -0x7e,0xb3,0x1d,0xea,0x7e,0x70,0xa, 0xac,0xb7,0x19,0x5, 0x1c,0x86,0x74,0x3, 0xa, -0x31,0x19,0xb3,0x1d,0xae,0x7e,0xb3,0x3b,0xf2,0x4, 0x7a,0xb3,0x3b,0xf2,0x22,0xca, -0xf8,0x7c,0x3b,0x7e,0x23,0x1d,0xea,0xbe,0x20,0x2, 0x50,0x3, 0xc3,0x80,0x5f,0x74, -0xa, 0xac,0xb3,0x49,0x45,0x3b,0x81,0x49,0x5, 0x3b,0x83,0x6c,0x22,0x80,0x46,0x7e, -0x70,0xa, 0xac,0x72,0x9, 0xf3,0x1c,0x86,0x5e,0xf0,0xf, 0xbc,0x3f,0x68,0x34,0xa, -0x2f,0x9, 0xb2,0x3b,0x6d,0xbe,0xb0,0x2, 0x68,0x29,0x49,0x23,0x1c,0x82,0x7d,0x34, -0x9d,0x32,0x12,0x1e,0x5, 0xbe,0x34,0x3, 0x0, 0x58,0x18,0x74,0xa, 0xac,0xb2,0x49, -0x25,0x1c,0x84,0x7d,0x30,0x9d,0x32,0x12,0x1e,0x5, 0xbe,0x34,0x3, 0x0, 0x58,0x3, -0xd3,0x80,0xb, 0xb, 0x20,0x7e,0x73,0x1d,0xea,0xbc,0x72,0x38,0xb2,0xc3,0xda,0xf8, -0x22,0xca,0x79,0x7c,0xfb,0x7e,0x70,0xa, 0xac,0x7f,0x9, 0xb3,0x3b,0x88,0x9, 0x73, -0x3b,0x89,0x12,0x2d,0x89,0x7d,0xa3,0x7e,0xe3,0x3c,0xee,0x7e,0x73,0x3c,0xe3,0xa, -0xb7,0x3e,0xb4,0x3e,0xb4,0x2e,0xb7,0x1e,0x76,0x9e,0xb4,0x0, 0x8c,0x7e,0x34,0x0, -0x1, 0x7c,0xbf,0x60,0x5, 0x3e,0x34,0x14,0x78,0xfb,0x5e,0x37,0x3a,0xf1,0x68,0x3, -0xe4,0x61,0x17,0x7e,0x73,0x1d,0xf4,0xbe,0x70,0x0, 0x28,0x3, 0xe4,0x61,0x17,0x12, -0x96,0x3, 0x30,0xe0,0x3, 0xe4,0x61,0x17,0x7e,0xa3,0x3a,0xe4,0x4c,0xaa,0x68,0x9, -0xbe,0xa4,0x0, 0x21,0x8, 0x3, 0xe4,0x61,0x17,0xa, 0x4f,0x9, 0xb4,0x3a,0xe5,0xbe, -0xb0,0x58,0x50,0x1f,0x9, 0xb4,0x3b,0xe8,0xbe,0xb0,0x5, 0x28,0x16,0x9, 0xb4,0x3a, -0xda,0xbe,0xb0,0xa, 0x38,0xa, 0xbe,0xa4,0x0, 0x2c,0x18,0x4, 0x4c,0xaa,0x68,0x3, -0xe4,0x80,0x64,0x9, 0x74,0x3a,0xda,0xbe,0x70,0x50,0x50,0x5a,0xbe,0x70,0x1, 0x40, -0x55,0xbd,0xba,0x8, 0x51,0x71,0x1a,0x38,0x6, 0x7e,0xb3,0x3b,0xe6,0x60,0x29,0x4c, -0xee,0x78,0x25,0x7e,0x73,0x3a,0xd7,0xbe,0x70,0x46,0x50,0x1c,0x12,0x97,0xd7,0xbe, -0x34,0x1, 0x0, 0x40,0x6, 0xbe,0x34,0xf, 0x0, 0x28,0xd, 0x49,0x55,0x3b,0xb, 0xbe, -0x54,0x20,0x0, 0x28,0x3, 0xe4,0x80,0x1f,0x9, 0xa4,0x3b,0x77,0xbe,0xa0,0x4, 0x28, -0x4, 0x4c,0xee,0x68,0xa, 0xbe,0xe0,0x0, 0x28,0x8, 0xbe,0xa0,0x4, 0x28,0x3, 0xe4, -0x80,0x5, 0x74,0x1, 0x80,0x1, 0xe4,0xda,0x79,0x22,0x7e,0x73,0x1d,0xea,0xbe,0x70, -0x0, 0x22,0x7e,0xb3,0x3d,0x32,0x70,0x4, 0xd1,0x6, 0xc1,0xc, 0x71,0x85,0x91,0x63, -0x7c,0xab,0xbe,0xa0,0x24,0x78,0x13,0x7e,0x73,0x3d,0x31,0x7c,0xb7,0x20,0xe0,0xa, -0x6c,0xaa,0x7c,0xb7,0x30,0xe1,0x3, 0x7e,0xa0,0x25,0xbe,0xa0,0x25,0x78,0xc, 0x6c, -0xaa,0x7e,0xb3,0x3d,0x31,0x30,0xe1,0x3, 0x7e,0xa0,0x25,0x71,0x1a,0x28,0xc, 0x7e, -0xb3,0x3, 0xf6,0xb4,0x1, 0x5, 0x7e,0xa0,0x26,0x80,0x7, 0xa5,0xbf,0x0, 0x3, 0x75, -0x7d,0x0, 0x4c,0xaa,0x68,0xe, 0x7a,0xa3,0x3d,0x35,0x74,0x1, 0x7a,0xb3,0x1d,0xf0, -0x7a,0xa3,0x3, 0xf0,0x22,0x7e,0xa3,0x1d,0xea,0x7e,0x73,0x1d,0xeb,0xbe,0xa0,0x1, -0x38,0xf, 0xbe,0x70,0x1, 0x38,0xa, 0x7e,0x27,0x1c,0x5a,0xbe,0x24,0x0, 0x1e,0x28, -0x35,0x7e,0xb3,0x3d,0x31,0x30,0xe1,0xb, 0x7e,0xb3,0x3, 0xf6,0xbe,0xb0,0x1, 0x78, -0x2, 0x81,0x59,0x91,0x5a,0x18,0x2, 0x81,0x41,0x6d,0x33,0x7a,0x37,0x3e,0x3c,0x12, -0x27,0xd1,0x68,0x7d,0xbe,0xb0,0x4, 0x68,0x78,0xbe,0xb0,0x5, 0x68,0x73,0x74,0x1, -0x7a,0xb3,0x3d,0x7, 0x80,0x6b,0x4c,0xaa,0x78,0x5, 0xe4,0x7a,0xb3,0x2d,0x5a,0x7e, -0x63,0x31,0x22,0x4c,0x66,0x68,0x4a,0x7e,0xb3,0x3, 0xf6,0xb4,0x1, 0xb, 0x74,0x1, -0x7a,0xb3,0x2d,0x5a,0xe4,0x7a,0xb3,0x3e,0x15,0x7e,0xb3,0x2d,0x5a,0xbe,0xb0,0x1, -0x68,0x57,0x7e,0x27,0x2d,0x58,0x4d,0x22,0x78,0x27,0x7e,0x27,0x9, 0x6e,0xbe,0x24, -0xff,0x38,0x8, 0x2d,0x6d,0x22,0x7a,0x27,0x3e,0x3c,0x12,0x27,0xd1,0x68,0x22,0xbe, -0xb0,0x4, 0x68,0x1d,0xbe,0xb0,0x5, 0x68,0x18,0x74,0x1, 0x7a,0xb3,0x3d,0x7, 0x80, -0x10,0x4c,0xaa,0x78,0xe, 0xa5,0xbf,0x1, 0xa, 0x7e,0x27,0x2d,0x58,0x7a,0x27,0x31, -0x24,0xc1,0x12,0xa5,0xbe,0x0, 0x12,0xa5,0xbf,0x0, 0xe, 0xbe,0xa0,0x1, 0x78,0x9, -0x74,0x1, 0x7a,0xb3,0x31,0x22,0x12,0x52,0x82,0x22,0x7e,0x37,0x9, 0x6e,0xbe,0x34, -0xff,0x38,0x22,0xca,0x79,0x6c,0xaa,0x6d,0x0, 0x7d,0x40,0x7e,0xe3,0x1d,0xea,0x7e, -0xf3,0x1d,0xeb,0x7e,0xb3,0x3e,0x15,0x60,0x11,0x7e,0x17,0x3e,0x1e,0x4d,0x11,0x78, -0x2, 0xa1,0x9a,0xbe,0xe0,0x1, 0x28,0x2, 0xa1,0x9a,0xbe,0xe0,0x1, 0x78,0x29,0xbe, -0xb0,0x4, 0x78,0x2, 0xa1,0x9a,0x7e,0x47,0x1c,0xe6,0x7e,0x7, 0x1c,0xe8,0x7d,0x34, -0x7d,0x20,0xd1,0x44,0xbe,0xb0,0x1, 0x78,0x2, 0xa1,0x9a,0x7d,0x34,0x7d,0x20,0xd1, -0x1e,0xbe,0xb0,0x1, 0x78,0x2, 0xa1,0x9a,0x7e,0x73,0x3e,0x15,0x7c,0xb7,0x14,0x68, -0x5f,0x14,0x78,0x2, 0xa1,0x58,0x14,0x68,0x57,0x14,0x78,0x2, 0xa1,0x97,0xb, 0xb2, -0x68,0x2, 0xa1,0x9a,0xbe,0xe0,0x1, 0x68,0x2, 0xa1,0xbd,0x4c,0xff,0x68,0x2, 0xa1, -0xbd,0x74,0x1, 0x7a,0xb3,0x3e,0x15,0x7a,0x47,0x3e,0x16,0x7a,0x7, 0x3e,0x18,0x75, -0x7d,0x1, 0xa, 0x28,0x7c,0x65,0x7a,0x63,0x3, 0xf1,0x7d,0xe4,0x5e,0xe4,0x0, 0xff, -0x7d,0x2e,0x7c,0x65,0x7a,0x63,0x3, 0xf2,0xa, 0x20,0x7c,0x65,0x7a,0x63,0x3, 0xf3, -0x7d,0xe0,0x5e,0xe4,0x0, 0xff,0x7d,0x2e,0x7c,0x65,0x7a,0x63,0x3, 0xf4,0x80,0x6d, -0x4c,0xee,0x78,0x20,0xa5,0xbf,0x1, 0x12,0x74,0x2, 0x7a,0xb3,0x3e,0x15,0x75,0x7d, -0x2, 0x7e,0xb3,0x3d,0x31,0x30,0xe0,0x62,0x80,0x53,0x74,0x4, 0xb1,0xcc,0x7e,0xe7, -0x3a,0x8a,0x80,0x4d,0x7a,0x47,0x3e,0x1a,0x7a,0x7, 0x3e,0x1c,0x7e,0xb3,0x3a,0x79, -0xb1,0xd4,0x4d,0xff,0x68,0x44,0x80,0x65,0xbe,0xe0,0x1, 0x78,0x60,0x4c,0xff,0x78, -0x5c,0x7a,0x47,0x3e,0x1a,0x7a,0x7, 0x3e,0x1c,0x7e,0x17,0x3a,0x86,0x9e,0x17,0x3a, -0x82,0xbe,0x17,0x3e,0x1e,0x40,0x23,0x7e,0xb3,0x3a,0x78,0xb1,0xd4,0x4d,0xff,0x68, -0x19,0x7a,0x47,0x3e,0x16,0x7a,0x7, 0x3e,0x18,0x74,0x3, 0xb1,0xcc,0x7e,0xe7,0x3a, -0x86,0x7a,0xe7,0x3e,0x1e,0x80,0x26,0x7e,0xa0,0x24,0x7e,0xb3,0x3e,0x15,0xb4,0x2, -0x3, 0x7e,0xa0,0x25,0x7e,0xb3,0x3, 0xf6,0xb4,0x1, 0x3, 0x7e,0xa0,0x26,0xe4,0x7a, -0xb3,0x3e,0x15,0x6d,0xee,0x7a,0xe7,0x3e,0x1e,0x7c,0xba,0x80,0xc, 0x7e,0xb3,0x3, -0xf6,0xb4,0x1, 0x3, 0x7e,0xa0,0x26,0x7c,0xba,0xda,0x79,0x22,0x7a,0xb3,0x3e,0x15, -0x75,0x7d,0x4, 0x22,0xa, 0x3b,0xb1,0xdb,0xa, 0xfb,0x22,0x7d,0x13,0x3e,0x14,0x3e, -0x14,0x3e,0x14,0x7e,0x37,0x3e,0x1a,0x9e,0x37,0x3e,0x16,0x12,0x1e,0x5, 0xbd,0x31, -0x38,0x12,0x7e,0x37,0x3e,0x1c,0x9e,0x37,0x3e,0x18,0x12,0x1e,0x5, 0xbd,0x31,0x38, -0x3, 0x74,0x1, 0x22,0xe4,0x22,0xe4,0x7a,0xb3,0x31,0x22,0x22,0xe4,0x7a,0xb3,0x3e, -0x15,0x22,0x74,0xfe,0x7a,0xb3,0x3d,0x35,0xe4,0x7a,0xb3,0x31,0x22,0x22,0x7e,0xb3, -0x3d,0x31,0x20,0xe1,0x2, 0xe4,0x22,0xbe,0x34,0x1, 0xbd,0x28,0x15,0xbe,0x34,0x2, -0x7b,0x50,0xf, 0xbe,0x24,0x6, 0x7d,0x28,0x9, 0xbe,0x24,0x7, 0x3b,0x50,0x3, 0x74, -0x1, 0x22,0xe4,0x22,0x7d,0x13,0x7e,0x37,0x3a,0x7a,0xbd,0x31,0x50,0x1a,0x7e,0x37, -0x3a,0x7c,0xbd,0x31,0x28,0x12,0x7e,0x37,0x3a,0x7e,0xbd,0x32,0x50,0xa, 0x7e,0x37, -0x3a,0x80,0xbd,0x32,0x28,0x2, 0xe4,0x22,0x74,0x1, 0x22,0xca,0x3b,0xe4,0x7a,0xb3, -0x3, 0xf6,0x7a,0xb3,0x3, 0xf7,0x74,0xff,0x7a,0xb3,0x3, 0xfa,0x7e,0xb3,0x3d,0x32, -0x70,0x5, 0xe4,0x7a,0xb3,0x3, 0xf0,0x7e,0xb3,0x3d,0x31,0x20,0xe1,0x9, 0x74,0xff, -0x7a,0xb3,0x3, 0xfb,0x2, 0xc8,0x3, 0x75,0x25,0x0, 0x6d,0xdd,0x6c,0xdd,0x6c,0xee, -0x75,0x27,0x0, 0x7e,0xb3,0x3, 0xf5,0xb4,0xff,0x71,0x6c,0xff,0x80,0x63,0xe4,0x7c, -0x7f,0x12,0xc8,0x6, 0x60,0x59,0x12,0xd1,0x1f,0x50,0x5, 0x7e,0xd0,0x1, 0x80,0x9, -0xbe,0xb4,0x0, 0x64,0x50,0x3, 0x7e,0xd0,0x2, 0xbe,0xc4,0x0, 0x23,0x50,0x5, 0x7e, -0xe0,0x1, 0x80,0x9, 0xbe,0xc4,0x0, 0x64,0x50,0x3, 0x7e,0xe0,0x2, 0x75,0x27,0x0, -0x75,0x25,0x1, 0x12,0xd1,0xc6,0x7d,0xd3,0x7e,0xa7,0x9, 0x6a,0xbe,0xa4,0x5, 0x14, -0x58,0x4, 0xe, 0xd4,0x80,0xd, 0x7d,0x3d,0x3e,0x34,0x7e,0x24,0x0, 0x7, 0x12,0x1a, -0xed,0x7d,0xd3,0xbe,0xd4,0x0, 0x50,0x58,0x7c,0x7e,0xd4,0x0, 0x50,0x80,0x76,0xb, -0xf0,0x7e,0x73,0x1d,0xea,0xbc,0x7f,0x38,0x95,0x80,0x6a,0x6c,0xff,0x80,0x5e,0x74, -0xa, 0xac,0xbf,0x9, 0x75,0x1c,0x86,0xbe,0x73,0x3, 0xf5,0x78,0x4e,0x74,0x1, 0x7c, -0x7f,0x12,0xc8,0x6, 0x60,0x4f,0x12,0xd1,0x1f,0x50,0x5, 0x7e,0xd0,0x1, 0x80,0x9, -0xbe,0xb4,0x0, 0x64,0x50,0x3, 0x7e,0xd0,0x2, 0xbe,0xc4,0x0, 0x23,0x50,0x5, 0x7e, -0xe0,0x1, 0x80,0x9, 0xbe,0xc4,0x0, 0x64,0x50,0x3, 0x7e,0xe0,0x2, 0x12,0xd1,0xc6, -0x7e,0x24,0x0, 0x6, 0x12,0x1a,0xed,0x7d,0xd3,0xbe,0xd4,0x0, 0x46,0x58,0x4, 0x7e, -0xd4,0x0, 0x46,0x75,0x27,0x1, 0x75,0x25,0x1, 0x80,0xa, 0xb, 0xf0,0x7e,0x73,0x1d, -0xea,0xbc,0x7f,0x38,0x9a,0xe5,0x25,0x70,0x2, 0x80,0x15,0x7d,0x3d,0x7c,0xbd,0x7c, -0x5e,0x12,0xc8,0x67,0xbe,0xb0,0x8, 0x38,0xd, 0xe5,0x27,0xbe,0xb0,0x1, 0x68,0x6, -0x74,0xff,0x7a,0xb3,0x3, 0xf5,0xe4,0x7a,0xb3,0x3, 0xf6,0x7e,0x73,0x3, 0xf7,0x7a, -0x73,0x3, 0xf9,0x7e,0xa3,0x3, 0xf5,0xbe,0xa0,0xff,0x68,0x11,0x74,0x1, 0x7a,0xb3, -0x3, 0xf6,0xe4,0x7a,0xb3,0x3, 0xfa,0x7a,0xa3,0x3, 0xfc,0x80,0x20,0x74,0x1, 0x7a, -0xb3,0x3, 0xfa,0xbe,0xa3,0x3, 0xfc,0x68,0x6, 0x74,0x1, 0x7a,0xb3,0x3, 0xf6,0x7e, -0x73,0x3, 0xfc,0x7a,0x73,0x3, 0xf5,0x74,0xff,0x7a,0xb3,0x3, 0xfc,0x7e,0xb3,0x3d, -0x32,0x70,0x10,0x7e,0xb3,0x3, 0xf6,0xb4,0x1, 0x4, 0x74,0x26,0x80,0x1, 0xe4,0x7a, -0xb3,0x3, 0xf0,0xda,0x3b,0x22,0x7c,0x57,0x7e,0x70,0xa, 0xac,0x75,0x9, 0xb3,0x1c, -0x86,0xbe,0xb0,0xff,0x68,0x4f,0x49,0x13,0x1c,0xe6,0x7d,0x51,0x49,0x23,0x1c,0xe8, -0x7d,0x2, 0xbe,0x54,0x1, 0x9a,0x40,0x3d,0xbe,0x54,0x2, 0x9e,0x38,0x37,0xbe,0x4, -0x6, 0x5a,0x40,0x31,0xbe,0x4, 0x7, 0x5e,0x38,0x2b,0x74,0x1, 0x7a,0xb3,0x3, 0xf6, -0x9, 0x13,0x1c,0xea,0x7a,0x13,0x3, 0xf5,0xa, 0x2, 0x7a,0x13,0x3, 0xf1,0x7a,0x33, -0x3, 0xf2,0xa, 0x14,0x7a,0x33,0x3, 0xf3,0x7a,0x53,0x3, 0xf4,0x9, 0x73,0x1c,0xec, -0x7a,0x73,0x3, 0xf8,0x22,0xe4,0x22,0xca,0xd8,0xca,0x79,0x7c,0x95,0x7c,0x8b,0x7d, -0x23,0x7d,0xe2,0xc2,0x6, 0x7e,0x57,0x9, 0x66,0xbe,0x54,0x4, 0xb0,0x58,0x11,0x7e, -0x57,0x1c,0x62,0xbe,0x54,0xff,0x6a,0x58,0x7, 0x12,0x8f,0xa8,0x28,0x2, 0xd2,0x6, -0xbe,0x80,0x1, 0x78,0xc, 0xbe,0x90,0x1, 0x78,0x7, 0x7d,0x5e,0x12,0x6f,0xc0,0x9d, -0xe5,0xbe,0xe4,0x0, 0x46,0x58,0x4, 0x7e,0xe4,0x0, 0x46,0x6c,0xff,0x7e,0xe0,0x18, -0x7e,0xd0,0x6, 0x6d,0x11,0x7d,0xf1,0xa2,0x6, 0xe4,0x33,0xb4,0x1, 0x23,0xa, 0x5d, -0x7e,0x73,0x1e,0x8a,0xa, 0x7, 0x2d,0x5, 0x3e,0x4, 0x49,0x20,0x4, 0xe4,0x74,0x2, -0xac,0xbe,0x49,0x35,0x4, 0xe4,0x2d,0x32,0x7e,0x24,0x0, 0x5, 0x12,0x1a,0xed,0x7d, -0xf3,0xbe,0xf4,0x0, 0x0, 0x58,0x2, 0x7d,0xf1,0x12,0x2e,0x4d,0x7d,0x53,0x2d,0x5f, -0xbd,0x5e,0x8, 0x2, 0xb, 0xf0,0xb, 0xd0,0xbe,0xd0,0x9, 0x28,0xb6,0xb, 0xe0,0xbe, -0xe0,0x1a,0x28,0xac,0xbe,0x80,0x1, 0x38,0x5, 0xbe,0x90,0x1, 0x28,0x4, 0xa, 0x7f, -0xb, 0x74,0xbe,0x80,0x1, 0x78,0x9, 0xbe,0x90,0x1, 0x78,0x4, 0xa, 0x7f,0xb, 0x74, -0x7c,0xbf,0xda,0x79,0xda,0xd8,0x22,0xca,0x1b,0xa9,0x31,0xe5,0x6, 0xa9,0xd5,0xea, -0xa9,0xc5,0xea,0xa9,0x30,0xe5,0x47,0x7e,0x25,0x74,0x49,0x32,0x0, 0x1, 0xbe,0x34, -0x0, 0x0, 0x28,0x7, 0xb, 0x24,0x1b,0x34,0x1b,0x28,0x30,0xa9,0xd0,0x9e,0xa9,0xd4, -0x9e,0x7e,0x35,0x1d,0xb, 0x34,0x7a,0x35,0x1d,0x5, 0x1f,0x5, 0x1f,0x7e,0x73,0x3e, -0x30,0xbe,0x71,0x1f,0x38,0x2, 0xd2,0x1f,0x7e,0x37,0x3e,0x3f,0xbe,0x34,0x0, 0x0, -0x28,0x6, 0x1b,0x34,0x7a,0x37,0x3e,0x3f,0xa9,0xd0,0x9e,0xa9,0xd7,0x9e,0xa9,0x34, -0xe5,0x5, 0xa9,0xc4,0xcd,0xc2,0x95,0xa9,0x32,0xe5,0x3, 0xa9,0xc2,0xcd,0xa9,0x33, -0xe5,0x3, 0xa9,0xc3,0xcd,0xa9,0x37,0xe5,0x3, 0xa9,0xc7,0xcd,0xa9,0x36,0xe5,0x3, -0xa9,0xc6,0xcd,0xda,0x1b,0x32,0xc2,0x9a,0xa9,0xd4,0xa6,0xc2,0x88,0xd2,0xa8,0x22, -0x7e,0x14,0xd7,0xe8,0x7e,0x4, 0x0, 0xff,0x7e,0x34,0x47,0x52,0x7e,0x24,0x55,0x50, -0x79,0x30,0x0, 0x2, 0x1b,0xa, 0x20,0x7e,0x34,0x45,0x20,0x7e,0x24,0x41,0x44,0x79, -0x30,0x0, 0x6, 0x79,0x20,0x0, 0x4, 0x7e,0x34,0x99,0x33,0x7e,0x24,0x66,0xcc,0x79, -0x30,0x0, 0xa, 0x79,0x20,0x0, 0x8, 0x7e,0x34,0x41,0x47,0x7e,0x24,0x46,0x4c,0x79, -0x30,0x0, 0xe, 0x79,0x20,0x0, 0xc, 0x22,0x7c,0x7b,0xa9,0xc4,0xca,0xa9,0xc5,0xca, -0xbe,0x70,0x8, 0x50,0x8, 0xa, 0x57,0x2e,0x54,0x0, 0x8, 0xf5,0xcc,0xa9,0xd0,0xce, -0xa9,0xc0,0xc9,0xd2,0x8, 0x12,0x26,0xbd,0xa9,0xc2,0xea,0x75,0xc1,0x6, 0x75,0xc2, -0xc, 0xd2,0x6, 0x12,0x3f,0xdc,0xa9,0xc1,0xc4,0xa9,0xd2,0xc4,0xa9,0xc2,0xe1,0x22, -0xd2,0xcd,0x7e,0x34,0x0, 0xed,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0x9e,0x7e,0x34, -0x20,0x5f,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0x9c,0x7e,0x34,0x21,0x0, 0x7e,0xf, -0x3d,0xd8,0x79,0x30,0x0, 0xaa,0x7e,0x34,0x84,0xc0,0x7e,0xf, 0x3d,0xd8,0x79,0x30, -0x0, 0xa0,0x7e,0x34,0x4, 0x8e,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0xa2,0x7e,0x34, -0x29,0x90,0x7e,0xf, 0x3d,0xd8,0x79,0x30,0x0, 0xa4,0x7e,0x34,0x6c,0xd1,0x7e,0xf, -0x3d,0xd8,0x79,0x30,0x0, 0xa6,0x7e,0x34,0x3, 0x64,0x7e,0xf, 0x3d,0xd8,0x79,0x30, -0x0, 0xa8,0x22,0xa9,0xc6,0xeb,0xa9,0xd6,0xac,0xa9,0xd6,0xec,0xd2,0x86,0xa9,0xc2, -0xeb,0xa9,0xd2,0xac,0xa9,0xd2,0xec,0xd2,0x82,0x22,0x75,0x9a,0x2f,0xa9,0xd1,0x99, -0xd2,0x9c,0xa9,0xd6,0xdf,0x22,0xc2,0x8e,0x43,0x89,0x20,0x75,0x8d,0x1, 0x75,0x8b, -0x0, 0xd2,0x8e,0xd2,0xab,0x22,0x75,0xb7,0x0, 0x75,0xb8,0x0, 0x75,0xf7,0x0, 0x75, -0xf8,0x0, 0xa9,0xd0,0xb7,0xd2,0xb8,0xa9,0xd5,0xb7,0xd2,0xbd,0xa9,0xd0,0xf7,0xd2, -0xf8,0xa9,0xc1,0xb7,0xc2,0xb9,0xa9,0xc3,0xb7,0xc2,0xbb,0xa9,0xc6,0xb7,0xc2,0xbe, -0x22,0xa9,0xd0,0x99,0xa9,0xc6,0xdf,0x22,0x7e,0x37,0x3e,0x2c,0xb, 0x34,0x7a,0x37, -0x3e,0x2c,0xbe,0x34,0xff,0x0, 0x40,0x8, 0x7e,0x34,0xff,0x0, 0x7a,0x37,0x3e,0x2c, -0x22,0x7f,0x70,0xd2,0xc9,0x75,0xf2,0x30,0x75,0xf3,0x80,0x75,0xf4,0xc, 0x75,0xf5, -0x1, 0x6c,0xaa,0xe5,0xf5,0x54,0x80,0xb4,0x80,0xf9,0xe5,0xf6,0xa, 0x4a,0x7f,0x17, -0x2d,0x34,0x7a,0x1b,0xb0,0xb, 0xa0,0xbe,0xa0,0xd, 0x40,0xe7,0xc2,0xc9,0x22,0xd2, -0xc8,0x43,0xed,0xf, 0xc2,0xea,0x75,0xb3,0x13,0xa9,0xd1,0xb4,0xa9,0xc0,0xb4,0x22, -0x7d,0x39,0x7c,0xd7,0x7e,0x30,0x2, 0xac,0x3d,0x2d,0x18,0x6d,0x0, 0x7e,0x70,0x2, -0xac,0x7f,0x2e,0x37,0x1f,0x2a,0x6d,0x22,0x74,0x1, 0x7c,0x9b,0x7f,0x61,0x7f,0x70, -0x6c,0x88,0x80,0x40,0x74,0x2, 0xac,0xb8,0x7f,0x16,0x2d,0x35,0xb, 0x1a,0xb0,0x5e, -0xb4,0x1, 0xff,0xbe,0xb4,0x0, 0xff,0x28,0xc, 0x7d,0x9b,0x9e,0x94,0x0, 0xff,0x7e, -0xa4,0x0, 0xff,0x80,0x4, 0x6d,0x99,0x7d,0xab,0x7d,0x39,0x7c,0x37,0x7f,0x17,0x2d, -0x35,0x7a,0x1b,0x30,0x7d,0x3a,0x74,0x2, 0xac,0xb8,0x7f,0x7, 0x2d,0x15,0x39,0x70, -0x0, 0x1, 0xb, 0x80,0xbc,0x98,0x38,0xbc,0x22,0x7c,0xab,0x7f,0x70,0x9f,0x11,0x30, -0x6, 0x22,0x6c,0x33,0x80,0x1a,0xa, 0x3, 0x7f,0x67,0x2d,0xd0,0x7e,0x6b,0xb0,0x7e, -0x68,0x0, 0x1, 0x60,0x5, 0x2f,0x66,0x14,0x78,0xfb,0x4d,0x3d,0x4d,0x2c,0xb, 0x30, -0xbc,0xa3,0x38,0xe2,0x22,0x7e,0x8, 0x2, 0xa8,0x7e,0x34,0x0, 0x8, 0xe4,0x12,0x1d, -0xd3,0x7e,0x8, 0x2, 0xb0,0x7e,0x34,0x0, 0x24,0x74,0x3f,0x12,0x1d,0xd3,0xd2,0x6, -0x7e,0x8, 0x1f,0x0, 0x74,0x23,0x71,0xb9,0x7e,0x8, 0x2, 0xa8,0x7a,0xf, 0x2, 0xd4, -0x7f,0x1, 0x6d,0x0, 0x7a,0x17,0x2, 0xd8,0x7d,0x32,0x7a,0x37,0x2, 0xda,0x7e,0x18, -0x2, 0xb0,0x7a,0x1f,0x2, 0xe0,0x6c,0x77,0xa, 0x27,0x9, 0x62,0x1f,0x0, 0xbe,0x60, -0x24,0x50,0xc, 0xa, 0x27,0x9, 0x52,0x1f,0x72,0xa, 0x16,0x19,0x51,0x2, 0xb0,0xb, -0x70,0xbe,0x70,0x23,0x40,0xe2,0x91,0x5a,0x12,0x13,0xa2,0x6d,0x33,0x7a,0x37,0x2, -0xd8,0x7a,0x37,0x2, 0xda,0x91,0x5a,0x2, 0x13,0xa2,0xa9,0xc6,0xea,0x7e,0x8, 0x2, -0xd4,0xe4,0x12,0x13,0xa2,0xa9,0xd6,0xea,0x7e,0x8, 0x2, 0xd4,0xe4,0x22,0xca,0xc8, -0xca,0x79,0x7f,0x70,0x7e,0xd, 0x29,0x7e,0x34,0x0, 0x48,0x74,0xff,0x12,0x1d,0xd3, -0x80,0x6b,0xa, 0x1c,0x7e,0x1d,0x25,0x2d,0x31,0x7e,0x1b,0x30,0xa, 0x33,0x2e,0x34, -0x1d,0x8a,0x12,0x4a,0x70,0x7c,0x3b,0xa, 0x33,0x7e,0x24,0x0, 0x3, 0x12,0x1a,0xed, -0x7c,0xa5,0x7a,0xa1,0x2d,0xb1,0x6, 0x60,0x5, 0x3e,0x4, 0x14,0x78,0xfb,0x6e,0x4, -0xff,0xff,0x7e,0x70,0x6, 0xac,0x7a,0x91,0xf2,0xb, 0xc0,0xbc,0xec,0x38,0xc3,0xa, -0x3c,0x2d,0x3f,0x7d,0x2e,0x7e,0x1b,0x30,0xa, 0x53,0xb1,0x25,0xf5,0x2d,0x2e,0x30, -0x24,0xb1,0x6, 0x60,0x5, 0x3e,0x4, 0x14,0x78,0xfb,0x6e,0x4, 0xff,0xff,0x7e,0x71, -0x2d,0x74,0x6, 0xac,0x7b,0x91,0xf2,0xb, 0xc0,0xbc,0xfc,0x38,0xd2,0xda,0x79,0xda, -0xc8,0x22,0xa, 0x29,0x2d,0x32,0x3e,0x34,0x7e,0x2d,0x29,0x2d,0x53,0xb, 0x2a,0x30, -0x5d,0x30,0x1b,0x2a,0x30,0x22,0xa, 0x43,0x1e,0x44,0x1e,0x44,0x1e,0x44,0x1e,0x44, -0x7a,0x91,0x2e,0xa, 0x33,0x7e,0x24,0x0, 0x10,0x12,0x1a,0xed,0x7c,0x25,0x7e,0x4, -0x0, 0x1, 0x7c,0xb2,0x22,0x7e,0x44,0x0, 0xc, 0x8d,0x54,0x2e,0x54,0x0, 0x3, 0x22, -0xca,0x79,0x7f,0x70,0x7c,0xf7,0x7c,0xeb,0x6c,0x33,0x80,0x3f,0xa, 0x3, 0x7e,0x1d, -0x25,0x2d,0x30,0x7e,0x1b,0x20,0xa, 0x32,0x2e,0x34,0x1d,0x8a,0x12,0x4a,0x70,0x7c, -0x2b,0xa, 0x32,0x7e,0x24,0x0, 0x3, 0x12,0x1a,0xed,0x7c,0x65,0x7a,0x61,0x2e,0xa, -0x52,0x7e,0x44,0x0, 0x3, 0x8d,0x54,0xf5,0x2d,0x7e,0x44,0x0, 0x1, 0x60,0x5, 0x3e, -0x44,0x14,0x78,0xfb,0x12,0xa7,0xa1,0xb1,0xbd,0xb, 0x30,0xbc,0xf3,0x38,0xbd,0x6c, -0x33,0x80,0x33,0xa, 0x33,0x2d,0x3f,0x7d,0x2e,0x7e,0x1b,0x20,0xa, 0x52,0xb1,0x25, -0x7c,0xab,0x7a,0xa1,0x2e,0xa, 0x32,0x7e,0x24,0x0, 0xc, 0x12,0x1a,0xed,0x7c,0xb5, -0xf5,0x2d,0x7e,0x44,0x0, 0x1, 0x60,0x5, 0x3e,0x44,0x14,0x78,0xfb,0x7e,0x70,0x2, -0xac,0xa7,0xb1,0xbd,0xb, 0x30,0xbc,0xe3,0x38,0xc9,0xda,0x79,0x22,0x7e,0x1d,0x29, -0x2d,0x35,0xb, 0x1a,0x0, 0x4d,0x4, 0x1b,0x1a,0x0, 0x22,0x12,0x27,0x70,0x50,0xfb, -0x22,0x7c,0xab,0x4c,0xaa,0x78,0x3, 0x74,0x10,0x22,0x7c,0xba,0xc4,0x3, 0x54,0xf8, -0x22,0x7c,0x5b,0x7d,0x13,0x6d,0x0, 0xa, 0x35,0x7e,0xb3,0x1f,0x27,0x2, 0x1d,0xd3, -0xca,0xf8,0x6d,0x44,0x7e,0x33,0x1e,0x8a,0x7e,0x23,0x38,0x9b,0xa, 0x32,0x7e,0x23, -0x1e,0x89,0xa, 0x22,0x2d,0x23,0xa, 0x33,0xad,0x32,0x7d,0x3, 0xa, 0x33,0x2d,0x30, -0x7e,0xb3,0x38,0x9c,0xb4,0xff,0x30,0x7e,0x78,0x15,0x4c,0x6c,0xff,0x80,0x22,0xa, -0x2f,0x2d,0x20,0x3e,0x24,0x7e,0x6f,0x3d,0xf9,0x2d,0xd2,0xb, 0x6a,0xd0,0x74,0x2, -0xac,0xbf,0x7f,0x57,0x2d,0xb5,0xb, 0x5a,0x20,0x9d,0x2d,0x59,0x25,0x15,0x94,0xb, -0xf0,0xbc,0x3f,0x38,0xda,0x80,0xa, 0x7d,0x53,0x3e,0x54,0x7e,0x7f,0x3d,0xf9,0x2d, -0xf5,0x6c,0xff,0x80,0x2b,0xa, 0x5f,0x2d,0x50,0x3e,0x54,0x7e,0x1f,0x3d,0xf9,0x2d, -0x35,0xb, 0x1a,0xd0,0x74,0x2, 0xac,0xbf,0x7f,0x17,0x2d,0x35,0xb, 0x1a,0xc0,0x7d, -0x3d,0x9d,0x3c,0x12,0x1e,0x5, 0x7d,0xb3,0xbd,0x4b,0x58,0x2, 0x7d,0x4b,0xb, 0xf0, -0xbc,0x3f,0x38,0xd1,0x7d,0x34,0xda,0xf8,0x22,0x7e,0x63,0x1e,0x8a,0x7e,0x33,0x1e, -0x89,0x7c,0x13,0xac,0x16,0x7e,0x27,0x1c,0x75,0x12,0x67,0x5e,0x6d,0x55,0x80,0x18, -0x7d,0x45,0x3e,0x44,0x7e,0x7f,0x3d,0xf9,0x2d,0xf4,0xb, 0x7a,0x40,0x6e,0x44,0xff, -0xff,0xb, 0x44,0x1b,0x7a,0x40,0xb, 0x54,0xbd,0x5, 0x38,0xe4,0x7e,0x2f,0x3d,0xf9, -0x7d,0x5, 0x7a,0x7, 0x2, 0xac,0x7e,0x4, 0x9, 0x74,0x7a,0x7, 0x2, 0xae,0x7e,0x4, -0x9, 0x74,0x7a,0x7, 0x2, 0xb0,0x7a,0x33,0x2, 0xa8,0x7a,0x63,0x2, 0xa9,0x7e,0x8, -0x2, 0xa8,0x7c,0xb5,0x7c,0x75,0x2, 0x7, 0x7d,0x7e,0x47,0x1c,0x77,0x6d,0xff,0x9d, -0xf4,0x6c,0x77,0x80,0x76,0x7e,0x63,0x18,0xd1,0xa, 0x26,0x7d,0x52,0x5e,0x54,0x0, -0x2, 0x68,0x2d,0x30,0x3, 0x2a,0x7e,0x30,0x2, 0xac,0x37,0x49,0xe1,0x5, 0xc8,0x49, -0x1, 0x4, 0x0, 0xbd,0x4, 0x8, 0xd, 0x7e,0xb3,0x18,0xda,0xb4,0x1, 0x12,0x7d,0x54, -0x2d,0x5e,0x80,0x8, 0xbd,0xf, 0x58,0x8, 0x7d,0x5e,0x9d,0x54,0x59,0x51,0x5, 0xc8, -0x7d,0x52,0x5e,0x54,0x0, 0x1, 0x68,0x31,0x30,0x5, 0x2e,0x7e,0x50,0x2, 0xac,0x57, -0x49,0xe2,0x6, 0x3a,0x49,0x12,0x4, 0x72,0xbd,0x14,0x8, 0x11,0x7e,0xb3,0x18,0xda, -0xb4,0x1, 0x16,0x7d,0x4, 0x2d,0xe, 0x59,0x2, 0x6, 0x3a,0x80,0xc, 0xbd,0x1f,0x58, -0x8, 0x7d,0x5e,0x9d,0x54,0x59,0x52,0x6, 0x3a,0xb, 0x70,0x7e,0x63,0x1e,0x90,0xa, -0x56,0x7e,0x63,0x1e,0x8f,0xa, 0x26,0x2d,0x25,0xa, 0x57,0xbd,0x52,0x58,0x2, 0xc1, -0xf5,0x22,0xca,0x79,0x7e,0x4, 0x7f,0xff,0x7d,0x20,0x7d,0x10,0x6d,0xaa,0x7d,0x4a, -0x7d,0x3a,0x7d,0xb0,0x75,0x25,0x0, 0x6c,0xee,0x7e,0x68,0x4, 0xe4,0x7e,0x78,0x5, -0x56,0xe4,0x7a,0xb3,0x9, 0x72,0x7a,0xb3,0x9, 0x73,0x7a,0xb3,0x19,0xda,0x7a,0xb3, -0x19,0xdc,0x7a,0xb3,0x19,0xdb,0x7a,0xb3,0x19,0xdd,0x6c,0xff,0x80,0x6d,0x12,0xd1, -0x69,0xbd,0x52,0x58,0x2, 0x7d,0x25,0xbd,0x54,0x8, 0x2, 0x7d,0x45,0x74,0x2, 0xac, -0xbf,0x7f,0x47,0x2d,0x95,0xb, 0x4a,0x50,0xbd,0x5b,0x58,0x2, 0x7d,0xb5,0xbd,0x5a, -0x8, 0x2, 0x7d,0xa5,0x12,0xd1,0x69,0x7e,0x87,0x1e,0x6f,0x7e,0x94,0x0, 0x3, 0xad, -0x98,0xbd,0x59,0x8, 0x2, 0x5, 0x25,0x12,0xd1,0x69,0xbe,0x57,0x3a,0x32,0x8, 0xb, -0x7e,0xb3,0x19,0xdb,0x4, 0x7a,0xb3,0x19,0xdb,0x80,0x1e,0x74,0x2, 0xac,0xbf,0x7f, -0x46,0x2d,0x95,0xb, 0x4a,0x90,0x6d,0x55,0x9e,0x57,0x3a,0x32,0xbd,0x95,0x58,0x9, -0x7e,0xb3,0x19,0xdd,0x4, 0x7a,0xb3,0x19,0xdd,0xb, 0xf0,0x7e,0xb3,0x1e,0x90,0xbc, -0xbf,0x38,0x8b,0x7a,0x27,0x9, 0x66,0x7a,0x47,0x9, 0x6a,0xe5,0x25,0x7a,0xb3,0x9, -0x73,0x7a,0xa7,0x9, 0x70,0x7a,0xb7,0x9, 0x6e,0x11,0xf4,0xac,0xbf,0x2d,0xd5,0x6c, -0xff,0x80,0x4d,0x74,0x2, 0xac,0xbf,0x7f,0x56,0x2d,0xb5,0xb, 0x5a,0xb0,0xbd,0xb1, -0x58,0x2, 0x7d,0x1b,0xbd,0xb3,0x8, 0x2, 0x7d,0x3b,0x7e,0x87,0x1e,0x6d,0x7e,0x94, -0x0, 0x3, 0xad,0x98,0xbd,0xb9,0x8, 0x2, 0xb, 0xe0,0xbe,0xb7,0x3a,0x32,0x8, 0xb, -0x7e,0xb3,0x19,0xda,0x4, 0x7a,0xb3,0x19,0xda,0x80,0x13,0x6d,0x55,0x9e,0x57,0x3a, -0x32,0xbd,0xb5,0x58,0x9, 0x7e,0xb3,0x19,0xdc,0x4, 0x7a,0xb3,0x19,0xdc,0xb, 0xf0, -0x7e,0xb3,0x1e,0x8f,0xbc,0xbf,0x38,0xab,0x7a,0x17,0x9, 0x64,0x7a,0x37,0x9, 0x68, -0x7a,0xe3,0x9, 0x72,0x11,0xf4,0xac,0xbf,0x2d,0xf5,0x6c,0xff,0x80,0x13,0x74,0x2, -0xac,0xbf,0x7f,0x67,0x2d,0xd5,0xb, 0x6a,0x50,0xbd,0x50,0x58,0x2, 0x7d,0x5, 0xb, -0xf0,0x7e,0xb3,0x1e,0x8f,0xbc,0xbf,0x38,0xe5,0x7a,0x7, 0x9, 0x6c,0xbd,0x12,0x58, -0x2, 0x7d,0x21,0x7a,0x27,0x9, 0x60,0xbd,0x43,0x58,0x2, 0x7d,0x43,0x7a,0x47,0x9, -0x62,0xda,0x79,0x22,0x7e,0xb3,0x1e,0x90,0x7e,0xf0,0x2, 0x22,0x7e,0x8, 0x2d,0x58, -0x21,0x2, 0x7f,0x70,0xb, 0x7a,0x30,0xe5,0x1f,0xa, 0x2b,0xbd,0x32,0x28,0x4, 0x9d, -0x32,0x80,0x2, 0x6d,0x33,0x1b,0x7a,0x30,0x22,0x7e,0x8, 0x3e,0x1e,0x21,0x2, 0x7e, -0x70,0xa, 0xac,0x7f,0x9, 0xb3,0x1c,0x89,0xf5,0x26,0x9, 0xc3,0x1c,0x8a,0x49,0xb3, -0x1c,0xe6,0x49,0xc3,0x1c,0xe8,0x7d,0x3b,0x9e,0x34,0x2, 0x1c,0x12,0x1e,0x5, 0x7d, -0xb3,0x7d,0x3c,0x9e,0x34,0x6, 0xdc,0x12,0x1e,0x5, 0x7d,0xc3,0xbe,0xb4,0x0, 0x23, -0x22,0x7d,0x12,0x7d,0x51,0xf5,0x39,0x7c,0x36,0x7c,0x25,0xa, 0x4, 0x7d,0x51,0xf5, -0x38,0x7d,0x53,0xf5,0x37,0xa9,0xc2,0xb4,0x22,0x74,0x2, 0xac,0xbf,0x7f,0x46,0x2d, -0x95,0xb, 0x4a,0x50,0x22,0x7e,0x18,0x5, 0xc8,0x7a,0x1f,0x6, 0xac,0x22,0x74,0x2, -0xac,0xbe,0x9, 0xd5,0x19,0xde,0x22,0xe5,0x44,0xa, 0x3b,0x1b,0x34,0x22,0xe5,0x45, -0xa, 0x3b,0x1b,0x34,0xe5,0x28,0xa, 0x8b,0xbd,0x83,0x22,0x7a,0x37,0x1e,0x6b,0x7a, -0x37,0x1e,0x6d,0x7a,0x37,0x1e,0x6f,0x22,0xe5,0x25,0x7e,0x71,0x26,0x2, 0x2d,0x89, -0x74,0x2, 0xac,0xbf,0x9, 0x75,0x19,0xdf,0xbc,0x7d,0x22,0xa, 0x5b,0xb, 0x55,0xe, -0x54,0xe, 0x54,0x7c,0xab,0x22,0xe5,0x26,0x7c,0x7c,0x2, 0x2d,0x89,0x7e,0x71,0x30, -0x74,0xa, 0xac,0xb7,0x22,0x7e,0xb3,0x3a,0xe4,0xbe,0xb0,0x0, 0x22,0x7e,0xb3,0x3a, -0xd6,0xbe,0xb0,0x0, 0x22,0x7e,0x73,0x2, 0xed,0xbe,0x71,0x47,0x22,0x7e,0xb3,0x2, -0xed,0xbe,0xb0,0x1, 0x22,0x7e,0x83,0x1c,0x58,0xbe,0x80,0x0, 0x22,0x12,0x17,0xa9, -0xe4,0x2, 0xf, 0xe9,0xe4,0x12,0x18,0x1b,0x2, 0x18,0x0, 0xd2,0x8, 0x12,0x26,0xbd, -0x74,0x1, 0x22,0xff,0xff,0xff,0xff,0xff, \ No newline at end of file diff --git a/drivers/input/touchscreen/focaltech_touch/include/firmware/fw_sample.i b/drivers/input/touchscreen/focaltech_touch/include/firmware/fw_sample.i deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8719_Pramboot_V0.5_20171221.i b/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8719_Pramboot_V0.5_20171221.i deleted file mode 100644 index bad039c7d273..000000000000 --- a/drivers/input/touchscreen/focaltech_touch/include/pramboot/FT8719_Pramboot_V0.5_20171221.i +++ /dev/null @@ -1,190 +0,0 @@ -0x2, 0x8, 0x69, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2, 0xb, 0x5a, 0x6d, 0x11, -0x7e, 0x18, 0xc6, 0x6, 0x1b, 0x1a, 0x10, 0x7e, 0x18, 0xc6, 0xe, 0xb, 0x1a, 0x30, 0x4d, 0x33, -0x78, 0xf5, 0x7e, 0x18, 0xc6, 0x8, 0xb, 0x1a, 0x50, 0x22, 0xff, 0x2, 0x7, 0xd8, 0x7e, 0x8, -0xc6, 0x0, 0xb, 0xa, 0x30, 0x70, 0x5, 0x5e, 0x70, 0xef, 0x80, 0x3, 0x4e, 0x70, 0x10, 0x1b, -0xa, 0x30, 0x22, 0x2, 0xb, 0x8a, 0xca, 0xf8, 0xe4, 0x7a, 0xb3, 0x2, 0xeb, 0x7e, 0x34, 0xf0, -0x0, 0x7e, 0x24, 0x0, 0x1, 0x7a, 0x1f, 0x2, 0x55, 0x74, 0x1f, 0x12, 0xa, 0x34, 0x7e, 0x34, -0xf0, 0x0, 0x7e, 0x24, 0x0, 0x1, 0x12, 0x9, 0xb5, 0xe4, 0x33, 0x7c, 0xfb, 0xbe, 0xf0, 0x1, -0x78, 0xa, 0x7e, 0xb3, 0x2, 0xeb, 0x44, 0x2, 0x7a, 0xb3, 0x2, 0xeb, 0x6c, 0xaa, 0xa, 0x3a, -0x19, 0xa3, 0x2, 0xe3, 0xb, 0xa0, 0xbe, 0xa0, 0x8, 0x78, 0xf3, 0x7e, 0x34, 0x0, 0x8, 0x7a, -0x37, 0x2, 0x59, 0x7e, 0x1f, 0x2, 0x55, 0x7e, 0x8, 0x2, 0xe3, 0x12, 0x3, 0x71, 0x6c, 0xaa, -0x6c, 0x77, 0xa, 0x2a, 0x19, 0x72, 0x2, 0xe3, 0xb, 0xa0, 0xbe, 0xa0, 0x8, 0x78, 0xf3, 0x7e, -0x34, 0x0, 0x8, 0x7a, 0x37, 0x2, 0xde, 0x7e, 0x1f, 0x2, 0x55, 0x7e, 0x8, 0x2, 0xe3, 0x12, -0xb, 0x6b, 0x7e, 0xf0, 0x1, 0x6c, 0xaa, 0xa, 0x3a, 0x9, 0xb3, 0x2, 0xe3, 0xbc, 0xba, 0x68, -0x4, 0x6c, 0xff, 0x80, 0x7, 0xb, 0xa0, 0xbe, 0xa0, 0x8, 0x40, 0xeb, 0xbe, 0xf0, 0x1, 0x78, -0xa, 0x7e, 0xb3, 0x2, 0xeb, 0x44, 0x4, 0x7a, 0xb3, 0x2, 0xeb, 0x7e, 0xb3, 0x2, 0xeb, 0x44, -0x1, 0x7a, 0xb3, 0x2, 0xeb, 0xda, 0xf8, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0xb, 0xe0, 0xf4, 0x1f, 0xeb, 0x43, 0x14, 0xbc, 0xcd, 0xe3, 0x32, 0x1c, 0xff, 0x0, 0xff, 0x0, -0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -0x7c, 0x6b, 0xc2, 0x2, 0x7e, 0xb3, 0x2, 0x39, 0x14, 0x78, 0x3, 0x2, 0x3, 0x6e, 0x1b, 0xb1, -0x78, 0x3, 0x2, 0x2, 0x56, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x3, 0x6e, 0x14, 0x78, 0x3, 0x2, -0x3, 0x6e, 0x14, 0x78, 0x3, 0x2, 0x2, 0xa6, 0x1b, 0xb1, 0x78, 0x3, 0x2, 0x2, 0xcd, 0x24, -0xf9, 0x78, 0x3, 0x2, 0x2, 0xe4, 0x24, 0xaf, 0x78, 0x3, 0x2, 0x3, 0x52, 0x24, 0xfd, 0x68, -0x41, 0x14, 0x78, 0x3, 0x2, 0x2, 0xe9, 0x14, 0x78, 0x3, 0x2, 0x3, 0x6e, 0x1b, 0xb2, 0x78, -0x3, 0x2, 0x3, 0x6e, 0x24, 0xda, 0x68, 0x2d, 0x24, 0xe6, 0x68, 0x26, 0x24, 0xeb, 0x68, 0x41, -0x24, 0xf3, 0x78, 0x3, 0x2, 0x3, 0x6e, 0x24, 0xe4, 0x78, 0x3, 0x2, 0x3, 0x60, 0x14, 0x78, -0x3, 0x2, 0x3, 0x6e, 0x24, 0xf4, 0x78, 0x3, 0x2, 0x3, 0x6e, 0x24, 0xa0, 0x68, 0x3, 0x2, -0x3, 0x70, 0x2, 0x3, 0x5a, 0xbe, 0x60, 0x4, 0x50, 0xb, 0xe4, 0x7a, 0xb3, 0x2, 0xf1, 0xa, -0x26, 0x19, 0x72, 0x2, 0x3b, 0xa5, 0xbe, 0x0, 0x2, 0x80, 0x3, 0x2, 0x3, 0x70, 0xd2, 0x2, -0x22, 0x7c, 0xb6, 0x24, 0x0, 0x78, 0x3, 0x2, 0x3, 0x70, 0x1b, 0xb1, 0x68, 0x1e, 0x14, 0x68, -0x1e, 0x14, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0xb, 0xb2, 0x78, 0x35, 0x30, 0x1, 0x7, 0x7e, 0x8, -0x0, 0x21, 0x2, 0x2, 0x73, 0x7e, 0x8, 0x1, 0x2d, 0x2, 0x2, 0x73, 0x2, 0x3, 0xf, 0x2, -0x3, 0x16, 0x2, 0x3, 0x2f, 0xa, 0x27, 0x7e, 0xf, 0x2, 0x50, 0xb, 0x16, 0xb, 0xa, 0x30, -0x2d, 0x32, 0x1b, 0xa, 0x30, 0x6d, 0x33, 0x7e, 0xf, 0x2, 0x50, 0x79, 0x30, 0x0, 0x6, 0x22, -0x7c, 0x57, 0x6e, 0x53, 0x2, 0xf1, 0x7a, 0x53, 0x2, 0xf1, 0x7e, 0x2f, 0x2, 0x50, 0x2e, 0x54, -0x0, 0x6, 0xb, 0x2a, 0x20, 0x7d, 0x12, 0xb, 0x14, 0x1b, 0x2a, 0x10, 0x7e, 0xf, 0x2, 0x50, -0x2d, 0x12, 0x39, 0x70, 0x0, 0x8, 0x7e, 0xf, 0x2, 0x50, 0x69, 0x50, 0x0, 0x4, 0x69, 0x20, -0x0, 0x6, 0xbd, 0x25, 0x50, 0x3, 0x2, 0x3, 0x70, 0xb2, 0x1, 0x7a, 0xf, 0x2, 0x4a, 0x7e, -0x34, 0x0, 0x2, 0x2, 0x3, 0x69, 0x7c, 0xb6, 0x1b, 0xb1, 0x68, 0x1e, 0x14, 0x68, 0x1e, 0xb, -0xb1, 0x68, 0x3, 0x2, 0x3, 0x70, 0x30, 0x1, 0x6, 0x7e, 0x8, 0x0, 0x21, 0x80, 0x4, 0x7e, -0x8, 0x1, 0x2d, 0x7a, 0xf, 0x2, 0x50, 0x2, 0x2, 0xfd, 0x2, 0x3, 0xf, 0xa, 0x57, 0x6d, -0x44, 0x7e, 0xf, 0x2, 0x50, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12, 0x79, 0x30, -0x0, 0x2, 0x1b, 0xa, 0x20, 0x7e, 0x1f, 0x2, 0x50, 0x7a, 0x1f, 0x2, 0x4a, 0xd2, 0x2, 0x7e, -0x34, 0x0, 0x1, 0x2, 0x3, 0x69, 0x75, 0xe6, 0x0, 0xe4, 0x7e, 0x34, 0x1, 0x4, 0x7e, 0x24, -0x0, 0xff, 0x7a, 0x1b, 0xb0, 0x7e, 0x34, 0x1, 0x5, 0x7a, 0x1b, 0xb0, 0x7e, 0x34, 0x1, 0x8, -0x7a, 0x1b, 0xb0, 0x7e, 0x34, 0x1, 0x9, 0x7a, 0x1b, 0xb0, 0xd2, 0x3, 0x22, 0xa5, 0xbe, 0x1, -0x5, 0x7a, 0x73, 0x2, 0x4e, 0x22, 0xa5, 0xbe, 0x2, 0x2, 0x80, 0x3, 0x2, 0x3, 0x70, 0x7a, -0x73, 0x2, 0x3a, 0x22, 0x7a, 0x73, 0x2, 0x47, 0x22, 0x1b, 0x61, 0x68, 0x22, 0x1b, 0x60, 0x68, -0x25, 0x1b, 0x60, 0x68, 0x3a, 0x1b, 0x60, 0x68, 0x43, 0xb, 0x62, 0x78, 0x73, 0xa, 0x37, 0x7d, -0x3, 0x6d, 0x11, 0x7e, 0x1f, 0x2, 0x50, 0x79, 0x11, 0x0, 0x2, 0x1b, 0x1a, 0x0, 0x22, 0xa, -0x57, 0x7c, 0xab, 0xe4, 0x80, 0x2, 0xa, 0x57, 0x6d, 0x44, 0x7e, 0xf, 0x2, 0x50, 0x69, 0x30, -0x0, 0x2, 0xb, 0xa, 0x20, 0x2f, 0x12, 0x79, 0x30, 0x0, 0x2, 0x1b, 0xa, 0x20, 0x22, 0x7c, -0x67, 0x6c, 0x77, 0x7e, 0xf, 0x2, 0x50, 0x79, 0x30, 0x0, 0x4, 0x22, 0xa, 0x27, 0x7e, 0xf, -0x2, 0x50, 0xb, 0x16, 0xb, 0xa, 0x30, 0x2d, 0x32, 0x1b, 0xa, 0x30, 0x7e, 0x34, 0x0, 0x3, -0x80, 0x17, 0x7e, 0x34, 0x0, 0x4, 0x7a, 0x37, 0x2, 0x45, 0xe4, 0x7a, 0xb3, 0x2, 0xf1, 0x22, -0xe4, 0x7a, 0xb3, 0x2, 0xeb, 0x7e, 0x34, 0x0, 0x5, 0x7a, 0x37, 0x2, 0x45, 0x22, 0xd2, 0x2, -0x22, 0xca, 0x79, 0x7f, 0x50, 0x7f, 0x41, 0x7e, 0x47, 0x2, 0x59, 0x7e, 0x18, 0xc6, 0x0, 0xb, -0x1a, 0x50, 0x54, 0x1f, 0x1b, 0x1a, 0x50, 0x7f, 0x14, 0x5e, 0x34, 0x0, 0x7f, 0x7d, 0x53, 0x7e, -0x74, 0x0, 0x80, 0x9d, 0x75, 0xbd, 0x47, 0x38, 0x2, 0x80, 0x3c, 0x7a, 0x77, 0x2, 0x5b, 0x7f, -0x14, 0x7f, 0x5, 0x12, 0x8, 0xf6, 0x9d, 0x47, 0x7d, 0x37, 0x6d, 0x22, 0x2f, 0x41, 0x2d, 0xb7, -0x80, 0x1b, 0x7e, 0x54, 0x0, 0x80, 0x7a, 0x57, 0x2, 0x5b, 0x7f, 0x14, 0x7f, 0x5, 0x12, 0x8, -0xf6, 0x9e, 0x44, 0x0, 0x80, 0x2e, 0xb4, 0x0, 0x80, 0x2e, 0x48, 0x0, 0x80, 0xbe, 0x44, 0x0, -0x80, 0x50, 0xdf, 0x4d, 0x44, 0x68, 0xb, 0x7a, 0x47, 0x2, 0x5b, 0x7f, 0x14, 0x7f, 0x5, 0x12, -0x8, 0xf6, 0xd3, 0xda, 0x79, 0x22, 0xd2, 0x5, 0x12, 0xb, 0x45, 0xe4, 0x12, 0x0, 0x2e, 0x74, -0x60, 0x12, 0xb, 0x4, 0x74, 0x1, 0x12, 0x0, 0x2e, 0x12, 0xa, 0xb9, 0x40, 0xfb, 0x22, 0xff, -0x56, 0x30, 0x2e, 0x32, 0x44, 0x65, 0x63, 0x20, 0x32, 0x31, 0x20, 0x32, 0x30, 0x31, 0x37, 0x0, -0x46, 0x54, 0x53, 0x38, 0x37, 0x31, 0x39, 0x5f, 0x70, 0x72, 0x61, 0x6d, 0x62, 0x6f, 0x6f, 0x74, -0x0, 0x0, 0x12, 0xb, 0x7b, 0x7e, 0x37, 0x2, 0x45, 0x1b, 0x34, 0x68, 0x65, 0x1b, 0x35, 0x78, -0x3, 0x2, 0x4, 0xc5, 0x1b, 0x34, 0x78, 0x3, 0x2, 0x4, 0xf3, 0x1b, 0x34, 0x78, 0x3, 0x2, -0x5, 0x8b, 0x2e, 0x34, 0x0, 0x3, 0x68, 0x3, 0x2, 0x5, 0xa3, 0x6d, 0x33, 0x7a, 0x37, 0x2, -0x45, 0x7a, 0x37, 0x2, 0x48, 0x30, 0x4, 0x5, 0x12, 0xa, 0xed, 0xc2, 0x4, 0x7e, 0xf, 0x2, -0x4a, 0x69, 0x30, 0x0, 0x4, 0x7a, 0x37, 0x2, 0x59, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, -0x2e, 0x14, 0x0, 0x8, 0x12, 0x3, 0x71, 0xd2, 0x4, 0x7e, 0x2f, 0x2, 0x4a, 0x69, 0x12, 0x0, -0x4, 0x69, 0x32, 0x0, 0x2, 0xb, 0x2a, 0x20, 0x12, 0x7, 0x85, 0x2e, 0x34, 0x10, 0x0, 0x2, -0x5, 0x85, 0x6d, 0x33, 0x7a, 0x37, 0x2, 0x45, 0x7e, 0x34, 0x1, 0x0, 0x7a, 0x37, 0x2, 0xde, -0x7e, 0xf, 0x2, 0x4a, 0x69, 0x30, 0x0, 0x2, 0xb, 0xa, 0x20, 0x2e, 0x14, 0x0, 0x8, 0x12, -0xb, 0x6b, 0x20, 0x0, 0x3, 0x2, 0x5, 0xa3, 0x7e, 0x1f, 0x2, 0x4a, 0x29, 0xb1, 0x0, 0x8, -0xf5, 0x91, 0x2, 0x5, 0xa3, 0x6d, 0x33, 0x7a, 0x37, 0x2, 0x45, 0x7a, 0x37, 0x2, 0x48, 0x7e, -0x18, 0x2, 0xf1, 0x7a, 0x1f, 0x2, 0x57, 0x7e, 0xf, 0x2, 0x4a, 0x69, 0x30, 0x0, 0x2, 0xb, -0xa, 0x20, 0x69, 0x10, 0x0, 0x4, 0x12, 0x5, 0xbd, 0x12, 0xa, 0xed, 0x7e, 0x34, 0xf0, 0x55, -0x2, 0x5, 0x85, 0x6d, 0x33, 0x7a, 0x37, 0x2, 0x45, 0x7a, 0x37, 0x2, 0x48, 0x7e, 0xd3, 0x2, -0x4e, 0xbe, 0xd0, 0xa, 0x78, 0x15, 0xe4, 0x12, 0x8, 0xb0, 0x7e, 0xf0, 0x10, 0x7c, 0xbf, 0x12, -0xa, 0x34, 0xb, 0xf0, 0xbe, 0xf0, 0x17, 0x78, 0xf4, 0x80, 0x63, 0xbe, 0xd0, 0xb, 0x78, 0x11, -0x7e, 0xe0, 0x2, 0x7c, 0xbe, 0x12, 0xa, 0x34, 0xb, 0xe0, 0xbe, 0xe0, 0x17, 0x78, 0xf4, 0x80, -0x4d, 0xbe, 0xd0, 0xc, 0x78, 0x6, 0xe4, 0x12, 0xa, 0x34, 0x80, 0x42, 0xbe, 0xd0, 0xd, 0x78, -0x11, 0x7e, 0xd0, 0x12, 0x7c, 0xbd, 0x12, 0xa, 0x34, 0xb, 0xd0, 0xbe, 0xd0, 0x15, 0x78, 0xf4, -0x80, 0x2c, 0x7e, 0x73, 0x2, 0x4e, 0xa, 0x37, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x73, 0x2, 0x54, -0x6c, 0xcc, 0x80, 0x12, 0x7e, 0xb3, 0x2, 0x54, 0x12, 0xa, 0x34, 0x7e, 0xb3, 0x2, 0x54, 0x4, -0x7a, 0xb3, 0x2, 0x54, 0xb, 0xc0, 0x7e, 0x73, 0x2, 0x3a, 0xbc, 0x7c, 0x38, 0xe6, 0x12, 0xa, -0xed, 0x7e, 0x34, 0xf0, 0xaa, 0x7a, 0x37, 0x2, 0x48, 0x80, 0x18, 0x6d, 0x33, 0x7a, 0x37, 0x2, -0x45, 0x7a, 0x37, 0x2, 0x48, 0x12, 0x0, 0x46, 0x7e, 0x34, 0xf0, 0xaa, 0x7a, 0x37, 0x2, 0x48, -0x12, 0xa, 0xed, 0x20, 0x3, 0x3, 0x2, 0x4, 0x25, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xa, 0x9a, -0x7e, 0x34, 0x13, 0x88, 0x12, 0xa, 0x9a, 0x75, 0xe9, 0xff, 0x2, 0x4, 0x25, 0xca, 0x3b, 0x7a, -0x17, 0x2, 0x55, 0x7f, 0x31, 0xe4, 0x7a, 0xb3, 0x2, 0x5b, 0x7e, 0x37, 0x2, 0x55, 0xbe, 0x34, -0x0, 0x0, 0x38, 0x5b, 0x7e, 0x34, 0xff, 0xff, 0x7a, 0x37, 0x2, 0x55, 0x74, 0x1, 0x7a, 0xb3, -0x2, 0x5b, 0x80, 0x4b, 0x7e, 0x34, 0x0, 0x80, 0x7a, 0x37, 0x2, 0xde, 0x7f, 0x13, 0x7e, 0x8, -0x2, 0x5c, 0x12, 0xb, 0x6b, 0x7e, 0x37, 0x2, 0x55, 0x9e, 0x34, 0x0, 0x80, 0x7a, 0x37, 0x2, -0x55, 0x2e, 0x38, 0x0, 0x80, 0x6d, 0x33, 0x7a, 0x37, 0x2, 0xdc, 0x7e, 0x37, 0x2, 0xdc, 0x9, -0x63, 0x2, 0x5c, 0x7e, 0xf, 0x2, 0x57, 0x7e, 0xb, 0x70, 0x6c, 0x76, 0x7a, 0xb, 0x70, 0x7e, -0x37, 0x2, 0xdc, 0xb, 0x34, 0x7a, 0x37, 0x2, 0xdc, 0xbe, 0x34, 0x0, 0x80, 0x78, 0xdc, 0x7e, -0x37, 0x2, 0x55, 0xbe, 0x34, 0x0, 0x80, 0x38, 0xab, 0x7e, 0xb3, 0x2, 0x5b, 0x60, 0x6, 0xb, -0x34, 0x7a, 0x37, 0x2, 0x55, 0x7e, 0x37, 0x2, 0x55, 0x7a, 0x37, 0x2, 0xde, 0x7f, 0x13, 0x7e, -0x8, 0x2, 0x5c, 0x12, 0xb, 0x6b, 0x6d, 0x33, 0x80, 0x1a, 0x7e, 0x37, 0x2, 0xdc, 0x9, 0x63, -0x2, 0x5c, 0x7e, 0xf, 0x2, 0x57, 0x7e, 0xb, 0x70, 0x6c, 0x76, 0x7a, 0xb, 0x70, 0x7e, 0x37, -0x2, 0xdc, 0xb, 0x34, 0x7a, 0x37, 0x2, 0xdc, 0x7e, 0x37, 0x2, 0x55, 0xbe, 0x37, 0x2, 0xdc, -0x38, 0xd8, 0xda, 0x3b, 0x22, 0x7c, 0x7b, 0x7e, 0xa0, 0xef, 0x7e, 0xb3, 0x2, 0x39, 0x24, 0xfd, -0x68, 0x31, 0x1b, 0xb1, 0x68, 0x75, 0x14, 0x68, 0x77, 0x24, 0xa0, 0x68, 0x34, 0x1b, 0xb2, 0x68, -0x36, 0x24, 0x9e, 0x68, 0x2c, 0x24, 0xe3, 0x68, 0x48, 0x24, 0xf4, 0x68, 0x4a, 0x24, 0x65, 0x78, -0x63, 0xa5, 0xbf, 0x0, 0x5, 0x7e, 0xa0, 0x87, 0x80, 0x5a, 0xa5, 0xbf, 0x1, 0x56, 0x7e, 0xa0, -0xa9, 0x80, 0x51, 0xa, 0x17, 0x7e, 0x1f, 0x2, 0x50, 0x2d, 0x31, 0x29, 0xa1, 0x0, 0x8, 0x80, -0x43, 0x7e, 0xa3, 0x2, 0xf1, 0x80, 0x3d, 0xa5, 0xbf, 0x0, 0xa, 0x7e, 0x37, 0x2, 0x48, 0xa, -0x56, 0x7c, 0xab, 0x80, 0x2f, 0xa5, 0xbf, 0x1, 0x2b, 0x7e, 0x57, 0x2, 0x48, 0x7c, 0xab, 0x80, -0x23, 0x7e, 0xa3, 0x2, 0xeb, 0x80, 0x1d, 0xa5, 0xbf, 0x0, 0x5, 0x7e, 0xb3, 0x2, 0xec, 0x22, -0xa5, 0xbf, 0x1, 0x7, 0x7e, 0xb3, 0x2, 0xec, 0x64, 0xff, 0x22, 0x7e, 0xa0, 0x5, 0x80, 0x4, -0x7e, 0xa3, 0x2, 0xf4, 0x7c, 0xba, 0x22, 0x9f, 0x22, 0x7d, 0x23, 0x1b, 0x24, 0x7e, 0x78, 0xc6, -0xa, 0x1b, 0x7a, 0x20, 0x7e, 0x78, 0xc6, 0x0, 0xb, 0x7a, 0x20, 0x4e, 0x50, 0x20, 0x1b, 0x7a, -0x20, 0x6d, 0x22, 0x7e, 0x78, 0xc6, 0x6, 0x1b, 0x7a, 0x20, 0x80, 0x23, 0x7e, 0x78, 0xc6, 0xc, -0xb, 0x7a, 0x20, 0x5e, 0x24, 0x0, 0xff, 0xbe, 0x24, 0x0, 0x0, 0x28, 0x12, 0x7e, 0x78, 0xc6, -0x8, 0xb, 0x7a, 0x20, 0x7d, 0xf5, 0x2d, 0xf1, 0x7d, 0xe0, 0x7a, 0x7b, 0x50, 0xb, 0x2c, 0x7d, -0xf3, 0x6d, 0xee, 0xbf, 0x27, 0x40, 0xd5, 0x7e, 0x14, 0x0, 0x1, 0x7e, 0x18, 0xc6, 0x4, 0x1b, -0x1a, 0x10, 0x74, 0x1, 0x12, 0x0, 0x2e, 0x7e, 0x8, 0xc6, 0x0, 0xb, 0xa, 0x30, 0x5e, 0x70, -0x1f, 0x1b, 0xa, 0x30, 0x22, 0x6d, 0x0, 0x74, 0x10, 0x4d, 0x0, 0x78, 0xb, 0x4d, 0x22, 0x78, -0x27, 0x8d, 0x31, 0x7d, 0x12, 0x6d, 0x22, 0x22, 0x7d, 0x43, 0x7d, 0x32, 0x6d, 0x22, 0x2f, 0x11, -0x2d, 0x44, 0x50, 0x2, 0xa5, 0xf, 0xbf, 0x10, 0x40, 0x4, 0x9f, 0x10, 0xb, 0x90, 0x14, 0x78, -0xed, 0x7f, 0x1, 0x6d, 0x22, 0x7d, 0x34, 0x22, 0x7d, 0x41, 0x7d, 0x13, 0x8d, 0x24, 0x7d, 0x2, -0x2f, 0x0, 0x40, 0x4, 0xbd, 0x4, 0x40, 0x4, 0x9d, 0x4, 0xb, 0x14, 0x14, 0x78, 0xf1, 0x7d, -0x23, 0x7d, 0x31, 0x7d, 0x10, 0x6d, 0x0, 0x22, 0xca, 0x2b, 0xca, 0x1b, 0xca, 0xb, 0xd2, 0x0, -0x30, 0x90, 0x24, 0xc2, 0x90, 0x7e, 0x71, 0x91, 0x7e, 0xb3, 0x2, 0x4f, 0x70, 0x4, 0x7a, 0x73, -0x2, 0x39, 0x12, 0x1, 0x20, 0x7e, 0xb3, 0x2, 0x4f, 0x4, 0x7a, 0xb3, 0x2, 0x4f, 0x30, 0x2, -0x6, 0xe4, 0x12, 0x6, 0x85, 0xf5, 0x91, 0x30, 0x91, 0x10, 0xc2, 0x91, 0x7e, 0xb3, 0x2, 0x4f, -0x4, 0x7a, 0xb3, 0x2, 0x4f, 0x12, 0x6, 0x85, 0xf5, 0x91, 0xda, 0xb, 0xda, 0x1b, 0xda, 0x2b, -0x32, 0xd2, 0x5, 0x12, 0xb, 0x45, 0xe4, 0x12, 0x0, 0x2e, 0x74, 0x5, 0x12, 0xb, 0x4, 0x12, -0x0, 0xe, 0x7c, 0xab, 0x74, 0x1, 0x12, 0x0, 0x2e, 0x5e, 0xa0, 0xc3, 0xe4, 0x12, 0x0, 0x2e, -0x74, 0x1, 0x12, 0xb, 0x4, 0x7c, 0xba, 0x12, 0xb, 0x4, 0x74, 0x1, 0x12, 0x0, 0x2e, 0x12, -0xa, 0xb9, 0x40, 0xfb, 0xe4, 0x12, 0x0, 0x2e, 0x74, 0x5, 0x12, 0xb, 0x4, 0x12, 0x0, 0xe, -0x7a, 0xb3, 0x2, 0xf4, 0x74, 0x1, 0x2, 0x0, 0x2e, 0x75, 0x84, 0x1, 0x7e, 0x44, 0x1f, 0xff, -0xe4, 0x7a, 0x49, 0xb0, 0x1b, 0x44, 0x78, 0xf9, 0x7e, 0xf8, 0x2, 0xf5, 0xd2, 0x4, 0xd2, 0x0, -0xc2, 0x2, 0xc2, 0x3, 0x7e, 0x4, 0x0, 0xff, 0x7e, 0x14, 0xb, 0x97, 0xb, 0xa, 0x40, 0x5d, -0x44, 0x68, 0x1a, 0x69, 0x20, 0x0, 0x2, 0xb, 0xe, 0xb, 0x44, 0x80, 0xa, 0x7e, 0xb, 0xb0, -0x7a, 0x29, 0xb0, 0xb, 0x24, 0xb, 0xc, 0x1b, 0x44, 0x78, 0xf2, 0x80, 0xdf, 0x2, 0x4, 0x22, -0x7c, 0xab, 0xd2, 0x5, 0x12, 0xb, 0x45, 0x74, 0xd8, 0xa, 0x3a, 0x7d, 0x23, 0x6d, 0x33, 0x12, -0x9, 0x3a, 0x74, 0x1, 0x12, 0x0, 0x2e, 0x6d, 0x33, 0x7a, 0x37, 0x2, 0xf2, 0x12, 0xa, 0xb9, -0x50, 0xa, 0x7e, 0x37, 0x2, 0xf2, 0xbe, 0x34, 0xf, 0xa0, 0x28, 0xf1, 0x7e, 0x37, 0x2, 0xf2, -0xbe, 0x34, 0xf, 0xa0, 0x28, 0xf, 0xc2, 0x86, 0xc2, 0x87, 0x7e, 0x34, 0x13, 0x88, 0x12, 0xa, -0x9a, 0xd2, 0x86, 0xd2, 0x87, 0x22, 0x7f, 0x70, 0x7f, 0x61, 0xd2, 0x5, 0x12, 0xb, 0x45, 0x74, -0x2, 0x7f, 0x16, 0x12, 0x9, 0x3a, 0x6d, 0x33, 0x80, 0x1d, 0x7f, 0x7, 0x2d, 0x13, 0x7e, 0xb, -0x50, 0xa, 0x25, 0x7e, 0x8, 0xc6, 0x6, 0x1b, 0xa, 0x20, 0x7e, 0x8, 0xc6, 0xe, 0xb, 0xa, -0x20, 0x4d, 0x22, 0x78, 0xf5, 0xb, 0x34, 0x7e, 0x27, 0x2, 0x5b, 0xbd, 0x23, 0x38, 0xdb, 0x74, -0x1, 0x12, 0x0, 0x2e, 0x12, 0xa, 0xb9, 0x40, 0xfb, 0x22, 0x7c, 0xab, 0x7d, 0x12, 0x7c, 0xb3, -0x7a, 0xb3, 0x2, 0x5f, 0x7c, 0x36, 0x7c, 0x25, 0xa, 0x4, 0x6c, 0x22, 0x7c, 0xb3, 0x7a, 0xb3, -0x2, 0x5e, 0x6d, 0x22, 0x7c, 0xb7, 0x7a, 0xb3, 0x2, 0x5d, 0xe4, 0x12, 0x0, 0x2e, 0x7c, 0xba, -0x12, 0xb, 0x4, 0x7e, 0xb3, 0x2, 0x5f, 0x12, 0xb, 0x4, 0x7e, 0xb3, 0x2, 0x5e, 0x12, 0xb, -0x4, 0x7e, 0xb3, 0x2, 0x5d, 0x2, 0xb, 0x4, 0x7d, 0x12, 0x7a, 0x33, 0x2, 0xe2, 0x7c, 0x36, -0x7c, 0x25, 0xa, 0x4, 0x7a, 0x33, 0x2, 0xe1, 0x7a, 0x73, 0x2, 0xe0, 0x7e, 0x14, 0x0, 0xb, -0x7e, 0x18, 0xc6, 0x0, 0x1b, 0x1a, 0x10, 0xe4, 0x12, 0x0, 0x2e, 0x74, 0x3, 0x12, 0xb, 0x30, -0x7e, 0xb3, 0x2, 0xe2, 0x12, 0xb, 0x30, 0x7e, 0xb3, 0x2, 0xe1, 0x12, 0xb, 0x30, 0x7e, 0xb3, -0x2, 0xe0, 0x2, 0xb, 0x30, 0xd2, 0x5, 0x7e, 0x14, 0x0, 0x8, 0x7a, 0x17, 0x2, 0xde, 0x7e, -0x8, 0x2, 0xe3, 0x12, 0xb, 0x6b, 0x6c, 0xaa, 0xa, 0x3a, 0x9, 0xb3, 0x2, 0xe3, 0xbe, 0xb0, -0xff, 0x68, 0x4, 0xc2, 0x5, 0x80, 0x7, 0xb, 0xa0, 0xbe, 0xa0, 0x8, 0x40, 0xea, 0xa2, 0x5, -0x22, 0x7a, 0xb3, 0x2, 0xf5, 0x7e, 0x34, 0x0, 0x28, 0x12, 0xa, 0x9a, 0x6c, 0x33, 0x80, 0x14, -0xd2, 0x86, 0x7e, 0x34, 0x0, 0xa, 0x12, 0xa, 0x9a, 0xc2, 0x86, 0x7e, 0x34, 0x0, 0xa, 0x12, -0xa, 0x9a, 0xb, 0x30, 0x7e, 0x23, 0x2, 0xf5, 0xbc, 0x23, 0x38, 0xe4, 0x22, 0x6d, 0x22, 0x80, -0x1d, 0x7f, 0x20, 0xb, 0x14, 0x7e, 0x2b, 0xb0, 0xa, 0xfb, 0x7e, 0x28, 0xc6, 0x6, 0x1b, 0x2a, -0xf0, 0x7e, 0x28, 0xc6, 0xe, 0xb, 0x2a, 0x50, 0x4d, 0x55, 0x78, 0xf5, 0xb, 0x24, 0xbd, 0x32, -0x38, 0xdf, 0xd3, 0x22, 0x7c, 0xab, 0xd2, 0x5, 0x12, 0xb, 0x45, 0x74, 0x20, 0xca, 0xb8, 0xa, -0x3a, 0x6d, 0x22, 0x74, 0xc, 0x2f, 0x11, 0x14, 0x78, 0xfb, 0xda, 0xb8, 0x12, 0x9, 0x3a, 0x74, -0x1, 0x12, 0x0, 0x2e, 0x12, 0xa, 0xb9, 0x40, 0xfb, 0x22, 0xd2, 0xcf, 0x75, 0xcc, 0x0, 0x75, -0xec, 0xff, 0x75, 0xee, 0xff, 0x75, 0xeb, 0x3, 0x75, 0xac, 0xc0, 0xa9, 0xc5, 0xca, 0x75, 0xed, -0xf, 0x75, 0xad, 0xb0, 0xa9, 0xd7, 0x94, 0xa9, 0xd4, 0x94, 0x22, 0xd2, 0xc8, 0x75, 0xb3, 0x3, -0x7e, 0x8, 0xc6, 0x0, 0xb, 0xa, 0x30, 0x5e, 0x34, 0x0, 0xd3, 0x1b, 0xa, 0x30, 0xb, 0xa, -0x30, 0x4e, 0x70, 0x8, 0x1b, 0xa, 0x30, 0x2, 0x8, 0x21, 0x80, 0x14, 0x0, 0x0, 0x0, 0x0, -0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, -0x7d, 0x23, 0x1b, 0x34, 0x4d, 0x22, 0x78, 0xe4, 0x22, 0xe4, 0x12, 0x0, 0x2e, 0x74, 0x5, 0x12, -0xb, 0x4, 0x12, 0x0, 0xe, 0x7c, 0xab, 0x74, 0x1, 0x12, 0x0, 0x2e, 0x7c, 0xba, 0x30, 0xe0, -0x2, 0xd3, 0x22, 0xc3, 0x22, 0x6d, 0x33, 0x7a, 0x37, 0x2, 0xf2, 0xc2, 0x8c, 0xc2, 0x8d, 0x43, -0x89, 0x2, 0x75, 0x8c, 0x1, 0x75, 0x8a, 0x0, 0xd2, 0x8c, 0xd2, 0xa9, 0x22, 0x7e, 0xb3, 0x2, -0x47, 0xb4, 0xc, 0xf, 0xc2, 0x86, 0xc2, 0x87, 0x7e, 0x34, 0x0, 0x64, 0x12, 0xa, 0x9a, 0xd2, -0x86, 0xd2, 0x87, 0x22, 0xa, 0x1b, 0x7e, 0x18, 0xc6, 0x6, 0x1b, 0x1a, 0x10, 0x7e, 0x18, 0xc6, -0xe, 0xb, 0x1a, 0x30, 0x4d, 0x33, 0x78, 0xf5, 0xd3, 0x22, 0x75, 0x91, 0x0, 0xc2, 0x90, 0xc2, -0x91, 0x75, 0x92, 0x70, 0xd2, 0xe8, 0xc2, 0xc0, 0xa9, 0xd5, 0xb7, 0xd2, 0xbd, 0xd2, 0xad, 0x22, -0x1a, 0x1b, 0x7e, 0x18, 0xc6, 0x6, 0x1b, 0x1a, 0x10, 0x7e, 0x18, 0xc6, 0xe, 0xb, 0x1a, 0x30, -0x4d, 0x33, 0x78, 0xf5, 0x22, 0xe4, 0x12, 0x0, 0x2e, 0x30, 0x5, 0x4, 0x74, 0x6, 0x80, 0x2, -0x74, 0x4, 0x12, 0xb, 0x4, 0x74, 0x1, 0x2, 0x0, 0x2e, 0xca, 0x39, 0xc2, 0x8d, 0x7e, 0x37, -0x2, 0xf2, 0xb, 0x34, 0x7a, 0x37, 0x2, 0xf2, 0xda, 0x39, 0x32, 0x7f, 0x70, 0x12, 0x9, 0x78, -0x7f, 0x7, 0x7e, 0x37, 0x2, 0xde, 0x12, 0x7, 0x17, 0xd3, 0x22, 0x12, 0xa, 0x5a, 0x12, 0xa, -0x7b, 0x12, 0xb, 0x1a, 0x12, 0xa, 0xd5, 0xd2, 0xaf, 0x22, 0xca, 0xb8, 0xa9, 0xc0, 0x93, 0xe4, -0x7a, 0xb3, 0x2, 0x4f, 0xda, 0xb8, 0x32, 0x0, 0x1, 0x2, 0xeb, 0x0, 0x0, 0x1, 0x2, 0xf4, -0x0, 0x0, 0x1, 0x2, 0xec, 0x0, 0x0, 0x4, 0x2, 0xed, 0x0, 0x0, 0x9c, 0x0, 0x0, 0x1, -0x2, 0xf1, 0x0, 0x0, 0x2, 0x2, 0xf2, 0x0, 0x0, 0x0, 0x1, 0x2, 0x39, 0x0, 0x0, 0x1, -0x2, 0x3a, 0x0, 0x0, 0x2, 0x2, 0x45, 0x0, 0x0, 0x0, 0x1, 0x2, 0x47, 0x0, 0x0, 0x2, -0x2, 0x48, 0x0, 0x0, 0x0, 0x1, 0x2, 0x4e, 0xb, 0x0, 0x1, 0x2, 0x4f, 0x0, 0x0, 0x0, diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index b20ba6599273..7e480e236421 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -136,6 +136,18 @@ static const struct dmi_system_id rotated_screen[] = { DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"), }, }, + { + .ident = "Teclast X98 Pro", + .matches = { + /* + * Only match BIOS date, because the manufacturers + * BIOS does not report the board name at all + * (sometimes)... + */ + DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), + DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"), + }, + }, { .ident = "WinBook TW100", .matches = { diff --git a/drivers/input/touchscreen/nt36672c/nt36xxx.c b/drivers/input/touchscreen/nt36672c/nt36xxx.c index 88ba885906c6..fa50b2fe657b 100644 --- a/drivers/input/touchscreen/nt36672c/nt36xxx.c +++ b/drivers/input/touchscreen/nt36672c/nt36xxx.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -42,17 +43,6 @@ #ifndef NVT_SAVE_TESTDATA_IN_FILE #include "nt36xxx_mp_ctrlram.h" #endif -#if NVT_TOUCH_ESD_PROTECT -#include -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - -#if NVT_TOUCH_ESD_PROTECT -static struct delayed_work nvt_esd_check_work; -static struct workqueue_struct *nvt_esd_check_wq; -static unsigned long irq_timer = 0; -uint8_t esd_check = false; -uint8_t esd_retry = 0; -#endif /* #if NVT_TOUCH_ESD_PROTECT */ #if NVT_TOUCH_EXT_PROC extern int32_t nvt_extra_proc_init(void); @@ -86,9 +76,9 @@ static int32_t nvt_ts_resume(struct device *dev); extern int dsi_panel_lockdown_info_read(unsigned char *plockdowninfo); extern void dsi_panel_doubleclick_enable(bool on); static int32_t nvt_check_palm(uint8_t input_id, uint8_t *data); -extern void touch_irq_boost(void); -extern void lpm_disable_for_dev(bool on, char event_dev); +#if XIAOMI_ROI extern void xiaomi_touch_send_btn_tap_key(int status); +#endif uint32_t ENG_RST_ADDR = 0x7FFF80; uint32_t SWRST_N8_ADDR = 0; /* read from dtsi */ uint32_t SPI_RD_FAST_ADDR = 0; /* read from dtsi */ @@ -119,37 +109,6 @@ const uint16_t gesture_key_array[] = { }; #endif -#ifdef CONFIG_MTK_SPI -const struct mt_chip_conf spi_ctrdata = { - .setuptime = 25, - .holdtime = 25, - .high_time = 5, /* 10MHz (SPI_SPEED=100M / (high_time+low_time(10ns)))*/ - .low_time = 5, - .cs_idletime = 2, - .ulthgh_thrsh = 0, - .cpol = 0, - .cpha = 0, - .rx_mlsb = 1, - .tx_mlsb = 1, - .tx_endian = 0, - .rx_endian = 0, - .com_mod = DMA_TRANSFER, - .pause = 0, - .finish_intr = 1, - .deassert = 0, - .ulthigh = 0, - .tckdly = 0, -}; -#endif /*endif CONFIG_MTK_SPI*/ - -#ifdef CONFIG_SPI_MT65XX -const struct mtk_chip_config spi_ctrdata = { - .rx_mlsb = 1, - .tx_mlsb = 1, - .cs_pol = 0, -}; -#endif /*endif CONFIG_SPI_MT65XX*/ - static ssize_t nvt_cg_color_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -209,7 +168,6 @@ static void nvt_irq_enable(bool enable) } desc = irq_to_desc(ts->client->irq); - NVT_LOG("enable=%d, desc->depth=%d\n", enable, desc->depth); } /******************************************************* @@ -335,7 +293,6 @@ int32_t nvt_write_addr(uint32_t addr, uint8_t data) { int32_t ret = 0; uint8_t buf[4] = {0}; - NVT_ERR("nvt_write_addr enter\n"); /* ---set xdata index--- */ buf[0] = 0xFF; /* set index/page/addr command */ buf[1] = (addr >> 15) & 0xFF; @@ -646,8 +603,6 @@ int32_t nvt_read_pid(void) /* ---set xdata index to EVENT BUF ADDR--- */ nvt_set_page(ts->mmap->EVENT_BUF_ADDR); - NVT_LOG("PID=%04X\n", ts->nvt_pid); - return ret; } @@ -705,24 +660,18 @@ int32_t nvt_get_fw_info(void) ts->abs_x_max = TOUCH_DEFAULT_MAX_WIDTH; ts->abs_y_max = TOUCH_DEFAULT_MAX_HEIGHT; ts->max_button_num = TOUCH_KEY_NUM; - + if(retry_count < 3) { retry_count++; - NVT_ERR("retry_count=%d\n", retry_count); goto info_retry; } else { - NVT_ERR("Set default fw_ver=%d, x_num=%d, y_num=%d, " - "abs_x_max=%d, abs_y_max=%d, max_button_num=%d!\n", - ts->fw_ver, ts->x_num, ts->y_num, - ts->abs_x_max, ts->abs_y_max, ts->max_button_num); ret = -1; } } else { + ret = 0; } - NVT_LOG("FW type is 0x%02X, fw_ver=%d\n", buf[14], ts->fw_ver); - /* ---Get Novatek PID--- */ nvt_read_pid(); return ret; @@ -778,15 +727,6 @@ static ssize_t nvt_flash_read(struct file *file, char __user *buff, size_t count goto out; } -#if NVT_TOUCH_ESD_PROTECT - /* - * stop esd check work to avoid case that 0x77 report righ after here to enable esd check again - * finally lead to trigger esd recovery bootloader reset - */ - cancel_delayed_work_sync(&nvt_esd_check_work); - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - spi_wr = str[0] >> 7; memcpy(buf, str+2, ((str[0] & 0x7F) << 8) | str[1]); @@ -1302,90 +1242,6 @@ bool nvt_get_dbgfw_status(void) return ts->fw_debug; } -#if NVT_TOUCH_ESD_PROTECT -void nvt_esd_check_enable(uint8_t enable) -{ - /* update interrupt timer */ - irq_timer = jiffies; - /* clear esd_retry counter, if protect function is enabled */ - esd_retry = enable ? 0 : esd_retry; - /* enable/disable esd check flag */ - esd_check = enable; -} - -static uint8_t nvt_fw_recovery(uint8_t *point_data) -{ - uint8_t i = 0; - uint8_t detected = true; - - /* check pattern */ - for (i=1 ; i<7 ; i++) { - if (point_data[i] != 0x77) { - detected = false; - break; - } - } - - return detected; -} - -static void nvt_esd_check_func(struct work_struct *work) -{ - unsigned int timer = jiffies_to_msecs(jiffies - irq_timer); - - /* NVT_LOG("esd_check = %d (retry %d)\n", esd_check, esd_retry); */ /* DEBUG */ - - if ((timer > NVT_TOUCH_ESD_CHECK_PERIOD) && esd_check) { - mutex_lock(&ts->lock); - NVT_ERR("do ESD recovery, timer = %d, retry = %d\n", timer, esd_retry); - /* do esd recovery, reload fw */ - if (nvt_get_dbgfw_status()) { - if (nvt_update_firmware(DEFAULT_DEBUG_FW_NAME) < 0) { - NVT_ERR("use built-in fw"); - nvt_update_firmware(ts->fw_name); - } - } else { - nvt_update_firmware(ts->fw_name); - } - mutex_unlock(&ts->lock); - /* update interrupt timer */ - irq_timer = jiffies; - /* update esd_retry counter */ - esd_retry++; - } - - queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, - msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); -} -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - -#if NVT_TOUCH_WDT_RECOVERY -static uint8_t recovery_cnt = 0; -static uint8_t nvt_wdt_fw_recovery(uint8_t *point_data) -{ - uint32_t recovery_cnt_max = 10; - uint8_t recovery_enable = false; - uint8_t i = 0; - - recovery_cnt++; - - /* check pattern */ - for (i=1 ; i<7 ; i++) { - if ((point_data[i] != 0xFD) && (point_data[i] != 0xFE)) { - recovery_cnt = 0; - break; - } - } - - if (recovery_cnt > recovery_cnt_max){ - recovery_enable = true; - recovery_cnt = 0; - } - - return recovery_enable; -} -#endif /* #if NVT_TOUCH_WDT_RECOVERY */ - #if XIAOMI_ROI #define POINT_DATA_LEN 356 #define ROI_DATA_OFFSET 0x100 @@ -1415,25 +1271,20 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) #endif /* MT_PROTOCOL_B */ int32_t i = 0; int32_t finger_cnt = 0; + struct nvt_ts_data *ts_data = (struct nvt_ts_data *)data; #if WAKEUP_GESTURE if (bTouchIsAwake == 0) { pm_wakeup_event(&ts->input_dev->dev, 5000); } #endif - if (ts->debug_flag == TOUCH_IRQ_BOOST) - touch_irq_boost(); + pm_qos_update_request(&ts_data->pm_touch_req, 100); + pm_qos_update_request(&ts_data->pm_spi_req, 100); mutex_lock(&ts->lock); - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(true, 0x1); - } if (ts->dev_pm_suspend) { ret = wait_for_completion_timeout(&ts->dev_pm_suspend_completion, msecs_to_jiffies(500)); if (!ret) { NVT_ERR("system(spi) can't finished resuming procedure, skip it\n"); - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } goto XFER_ERROR; } } @@ -1441,9 +1292,6 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) ret = CTP_SPI_READ(ts->client, point_data, POINT_DATA_LEN + 1); if (ret < 0) { NVT_ERR("CTP_SPI_READ failed.(%d)\n", ret); - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } goto XFER_ERROR; } @@ -1456,43 +1304,10 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) printk("\n"); */ -#if NVT_TOUCH_WDT_RECOVERY - /* ESD protect by WDT */ - if (nvt_wdt_fw_recovery(point_data)) { - NVT_ERR("Recover for fw reset, %02X\n", point_data[1]); - if (nvt_get_dbgfw_status()) { - if (nvt_update_firmware(DEFAULT_DEBUG_FW_NAME) < 0) { - NVT_ERR("use built-in fw"); - nvt_update_firmware(ts->fw_name); - } - } else { - nvt_update_firmware(ts->fw_name); - } - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } - goto XFER_ERROR; - } -#endif /* #if NVT_TOUCH_WDT_RECOVERY */ - -#if NVT_TOUCH_ESD_PROTECT - /* ESD protect by FW handshake */ - if (nvt_fw_recovery(point_data)) { - nvt_esd_check_enable(true); - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } - goto XFER_ERROR; - } -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - #ifdef CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE input_id = (uint8_t)(point_data[1] >> 3); if (nvt_check_palm(input_id, point_data)) { - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } goto XFER_ERROR; /* to skip point data parsing */ } #endif @@ -1501,9 +1316,6 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) if (bTouchIsAwake == 0) { input_id = (uint8_t)(point_data[1] >> 3); nvt_ts_wakeup_gesture_report(input_id, point_data); - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } mutex_unlock(&ts->lock); return IRQ_HANDLED; } @@ -1519,10 +1331,6 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) if (((point_data[position] & 0x07) == 0x01) || ((point_data[position] & 0x07) == 0x02)) { /* finger down (enter & moving) */ -#if NVT_TOUCH_ESD_PROTECT - /* update interrupt timer */ - irq_timer = jiffies; -#endif /* #if NVT_TOUCH_ESD_PROTECT */ input_x = (uint32_t)(point_data[position + 1] << 4) + (uint32_t) (point_data[position + 3] >> 4); input_y = (uint32_t)(point_data[position + 2] << 4) + (uint32_t) (point_data[position + 3] & 0x0F); if ((input_x < 0) || (input_y < 0)) @@ -1562,9 +1370,6 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) if (finger_cnt == 0 && test_bit(i, ts->slot_map)) { input_report_key(ts->input_dev, BTN_TOUCH, 0); input_report_key(ts->input_dev, BTN_TOOL_FINGER, 0); - if (ts->debug_flag >= TOUCH_DISABLE_LPM) { - lpm_disable_for_dev(false, 0x1); - } #if XIAOMI_ROI roi_frame_cnt = 0; xiaomi_touch_send_btn_tap_key(0); @@ -1583,10 +1388,6 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) #if TOUCH_KEY_NUM > 0 if (point_data[61] == 0xF8) { -#if NVT_TOUCH_ESD_PROTECT - /* update interrupt timer */ - irq_timer = jiffies; -#endif /* #if NVT_TOUCH_ESD_PROTECT */ for (i = 0; i < ts->max_button_num; i++) { input_report_key(ts->input_dev, touch_key_array[i], ((point_data[62] >> i) & 0x01)); } @@ -1621,6 +1422,8 @@ static irqreturn_t nvt_ts_work_func(int irq, void *data) XFER_ERROR: mutex_unlock(&ts->lock); + pm_qos_update_request(&ts_data->pm_touch_req, PM_QOS_DEFAULT_VALUE); + pm_qos_update_request(&ts_data->pm_spi_req, PM_QOS_DEFAULT_VALUE); return IRQ_HANDLED; } @@ -1904,10 +1707,6 @@ static int nvt_touchfeature_set(uint8_t *touchfeature) return -ERESTARTSYS; } -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - ret = nvt_touchfeature_cmd_xsfer(touchfeature); if (ret < 0) NVT_ERR("send cmd via SPI failed, errno:%d", ret); @@ -2234,11 +2033,6 @@ static ssize_t tpdbg_write(struct file *file, const char __user *buf, goto out; } -#if NVT_TOUCH_ESD_PROTECT - cancel_delayed_work_sync(&nvt_esd_check_work); - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - cmd[size] = '\0'; if (!strncmp(cmd, "irq-disable", 11)) @@ -2282,9 +2076,6 @@ static ssize_t nvt_touch_test_write(struct file *file, const char __user *buf, case '0': ts->debug_flag = 0; break; - case '1': - ts->debug_flag = 1; - break; case '2': ts->debug_flag = 2; break; @@ -2493,18 +2284,6 @@ static int32_t nvt_ts_probe(struct platform_device *pdev) goto err_spi_setup; } -#ifdef CONFIG_MTK_SPI - /* old usage of MTK spi API */ - memcpy(&ts->spi_ctrl, &spi_ctrdata, sizeof(struct mt_chip_conf)); - ts->client->controller_data = (void *)&ts->spi_ctrl; -#endif - -#ifdef CONFIG_SPI_MT65XX - /* new usage of MTK spi API */ - memcpy(&ts->spi_ctrl, &spi_ctrdata, sizeof(struct mtk_chip_config)); - ts->client->controller_data = (void *)&ts->spi_ctrl; -#endif - NVT_LOG("mode=%d, max_speed_hz=%d\n", ts->client->mode, ts->client->max_speed_hz); ret = nvt_pinctrl_init(ts); @@ -2624,8 +2403,18 @@ static int32_t nvt_ts_probe(struct platform_device *pdev) if (ts->client->irq) { NVT_LOG("int_trigger_type=%d\n", ts->int_trigger_type); ts->irq_enabled = true; + ts->pm_spi_req.type = PM_QOS_REQ_AFFINE_IRQ; + irq_set_perf_affinity(ts->pm_spi_req.irq, IRQF_PERF_AFFINE); + pm_qos_add_request(&ts->pm_spi_req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + + ts->pm_touch_req.type = PM_QOS_REQ_AFFINE_IRQ; + ts->pm_touch_req.irq = ts->client->irq; + pm_qos_add_request(&ts->pm_touch_req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); ret = request_threaded_irq(ts->client->irq, NULL, nvt_ts_work_func, - ts->int_trigger_type | IRQF_ONESHOT, NVT_SPI_NAME, ts); + ts->int_trigger_type | IRQF_ONESHOT | IRQF_PRIME_AFFINE, + NVT_SPI_NAME, ts); if (ret != 0) { NVT_ERR("request irq failed. ret=%d\n", ret); goto err_int_request_failed; @@ -2663,19 +2452,6 @@ static int32_t nvt_ts_probe(struct platform_device *pdev) #endif queue_work(nvt_lockdown_wq, &ts->nvt_lockdown_work); - NVT_LOG("NVT_TOUCH_ESD_PROTECT is %d\n", NVT_TOUCH_ESD_PROTECT); -#if NVT_TOUCH_ESD_PROTECT - INIT_DELAYED_WORK(&nvt_esd_check_work, nvt_esd_check_func); - nvt_esd_check_wq = alloc_workqueue("nvt_esd_check_wq", WQ_MEM_RECLAIM, 1); - if (!nvt_esd_check_wq) { - NVT_ERR("nvt_esd_check_wq create workqueue failed\n"); - ret = -ENOMEM; - goto err_create_nvt_esd_check_wq_failed; - } - queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, - msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - /* ---set device node--- */ #if NVT_TOUCH_PROC ret = nvt_flash_proc_init(); @@ -2828,14 +2604,6 @@ nvt_extra_proc_deinit(); nvt_flash_proc_deinit(); err_flash_proc_init_failed: #endif -#if NVT_TOUCH_ESD_PROTECT - if (nvt_esd_check_wq) { - cancel_delayed_work_sync(&nvt_esd_check_work); - destroy_workqueue(nvt_esd_check_wq); - nvt_esd_check_wq = NULL; - } -err_create_nvt_esd_check_wq_failed: -#endif #if BOOT_UPDATE_FIRMWARE if (nvt_fwu_wq) { cancel_work_sync(&ts->nvt_fwu_work); @@ -2854,6 +2622,8 @@ nvt_flash_proc_deinit(); device_init_wakeup(&ts->input_dev->dev, 0); #endif free_irq(ts->client->irq, ts); + pm_qos_remove_request(&ts->pm_touch_req); + pm_qos_remove_request(&ts->pm_spi_req); err_int_request_failed: input_unregister_device(ts->input_dev); ts->input_dev = NULL; @@ -2922,15 +2692,6 @@ static int32_t nvt_ts_remove(struct platform_device *pdev) nvt_flash_proc_deinit(); #endif -#if NVT_TOUCH_ESD_PROTECT - if (nvt_esd_check_wq) { - cancel_delayed_work_sync(&nvt_esd_check_work); - nvt_esd_check_enable(false); - destroy_workqueue(nvt_esd_check_wq); - nvt_esd_check_wq = NULL; - } -#endif - #if BOOT_UPDATE_FIRMWARE if (nvt_fwu_wq) { cancel_work_sync(&ts->nvt_fwu_work); @@ -2945,6 +2706,8 @@ static int32_t nvt_ts_remove(struct platform_device *pdev) nvt_irq_enable(false); free_irq(ts->client->irq, ts); + pm_qos_remove_request(&ts->pm_touch_req); + pm_qos_remove_request(&ts->pm_spi_req); #if XIAOMI_ROI mutex_destroy(&ts->diffdata_lock); @@ -3001,15 +2764,6 @@ static void nvt_ts_shutdown(struct platform_device *pdev) nvt_flash_proc_deinit(); #endif -#if NVT_TOUCH_ESD_PROTECT - if (nvt_esd_check_wq) { - cancel_delayed_work_sync(&nvt_esd_check_work); - nvt_esd_check_enable(false); - destroy_workqueue(nvt_esd_check_wq); - nvt_esd_check_wq = NULL; - } -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - #if WAKEUP_GESTURE device_init_wakeup(&ts->input_dev->dev, 0); #endif @@ -3036,14 +2790,6 @@ static int32_t nvt_ts_suspend(struct device *dev) pm_stay_awake(dev); ts->ic_state = NVT_IC_SUSPEND_IN; -#if NVT_TOUCH_ESD_PROTECT - NVT_LOG("cancel delayed work sync\n"); - cancel_delayed_work_sync(&nvt_esd_check_work); - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - - NVT_LOG("start\n"); - if (!ts->db_wakeup) nvt_irq_enable(false); /*must before hold lock*/ @@ -3107,7 +2853,6 @@ static int32_t nvt_ts_suspend(struct device *dev) ts->ic_state = NVT_IC_SUSPEND_OUT; else NVT_ERR("IC state may error,caused by suspend/resume flow, please CHECK!!"); - NVT_LOG("end\n"); pm_relax(dev); return 0; } @@ -3138,22 +2883,12 @@ static int32_t nvt_ts_resume(struct device *dev) } if (bTouchIsAwake) { NVT_LOG("Touch is already resume\n"); -#if NVT_TOUCH_WDT_RECOVERY - mutex_lock(&ts->lock); - if (nvt_get_dbgfw_status()) { - ret = nvt_update_firmware(DEFAULT_DEBUG_FW_NAME); - } else { - ret = nvt_update_firmware(ts->fw_name); - } - mutex_unlock(&ts->lock); -#endif /* #if NVT_TOUCH_WDT_RECOVERY */ goto Exit; } ts->ic_state = NVT_IC_RESUME_IN; mutex_lock(&ts->lock); - NVT_LOG("start\n"); /* please make sure display reset(RESX) sequence and mipi dsi cmds sent before this */ #if NVT_TOUCH_SUPPORT_HW_RST @@ -3175,12 +2910,6 @@ static int32_t nvt_ts_resume(struct device *dev) nvt_irq_enable(true); -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); - queue_delayed_work(nvt_esd_check_wq, &nvt_esd_check_work, - msecs_to_jiffies(NVT_TOUCH_ESD_CHECK_PERIOD)); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - bTouchIsAwake = 1; #ifdef CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE if (ts->palm_sensor_switch && ts->palm_sensor_changed == false) { @@ -3207,7 +2936,6 @@ static int32_t nvt_ts_resume(struct device *dev) Exit: if (ts->dev_pm_suspend) pm_relax(dev); - NVT_LOG("end\n"); return 0; } @@ -3228,13 +2956,11 @@ static int nvt_drm_notifier_callback(struct notifier_block *self, unsigned long blank = evdata->data; if (event == MI_DRM_EARLY_EVENT_BLANK) { if (*blank == MI_DRM_BLANK_POWERDOWN) { - NVT_LOG("event=%lu, *blank=%d\n", event, *blank); flush_workqueue(ts_data->event_wq); nvt_ts_suspend(&ts_data->client->dev); } } else if (event == MI_DRM_EVENT_BLANK) { if (*blank == MI_DRM_BLANK_UNBLANK) { - NVT_LOG("event=%lu, *blank=%d\n", event, *blank); flush_workqueue(ts_data->event_wq); queue_work(ts_data->event_wq, &ts_data->resume_work); } @@ -3395,3 +3121,4 @@ late_initcall(nvt_driver_init); MODULE_DESCRIPTION("Novatek Touchscreen Driver"); MODULE_LICENSE("GPL"); + diff --git a/drivers/input/touchscreen/nt36672c/nt36xxx.h b/drivers/input/touchscreen/nt36672c/nt36xxx.h index 98ead5468e24..ded9ce8beb8a 100644 --- a/drivers/input/touchscreen/nt36672c/nt36xxx.h +++ b/drivers/input/touchscreen/nt36672c/nt36xxx.h @@ -28,7 +28,7 @@ #include #include #include - +#include #ifdef CONFIG_HAS_EARLYSUSPEND #include @@ -36,14 +36,6 @@ #include "nt36xxx_mem_map.h" -#ifdef CONFIG_MTK_SPI -#include "mtk_spi.h" -#endif - -#ifdef CONFIG_SPI_MT65XX -#include -#endif - #ifdef CONFIG_TOUCHSCREEN_XIAOMI_TOUCHFEATURE #include "../xiaomi/xiaomi_touch.h" #endif @@ -58,7 +50,6 @@ #define MI_DRM_NOTIFIER #define NVT_DEBUG 1 -#define TOUCH_DISABLE_LPM 1 #define TOUCH_IRQ_BOOST 2 /*---GPIO number---*/ @@ -119,13 +110,6 @@ extern const uint16_t gesture_key_array[]; #define DEFAULT_DEBUG_FW_NAME "novatek_debug_fw.bin" #define DEFAULT_DEBUG_MP_NAME "novatek_debug_mp.bin" - -/*---ESD Protect.---*/ -#define NVT_TOUCH_ESD_PROTECT 1 -#define NVT_TOUCH_ESD_CHECK_PERIOD 1500 /* ms */ -#define NVT_TOUCH_WDT_RECOVERY 1 -#define NVT_TOUCH_ESD_DISP_RECOVERY 1 - struct nvt_config_info { u8 tp_vendor; u8 tp_color; @@ -196,12 +180,6 @@ struct nvt_ts_data { uint8_t *xbuf; struct mutex xbuf_lock; bool irq_enabled; -#ifdef CONFIG_MTK_SPI - struct mt_chip_conf spi_ctrl; -#endif -#ifdef CONFIG_SPI_MT65XX - struct mtk_chip_config spi_ctrl; -#endif struct pinctrl *ts_pinctrl; struct pinctrl_state *pinctrl_state_active; struct pinctrl_state *pinctrl_state_suspend; @@ -236,6 +214,8 @@ struct nvt_ts_data { bool palm_sensor_changed; bool palm_sensor_switch; uint8_t debug_flag; + struct pm_qos_request pm_touch_req; + struct pm_qos_request pm_spi_req; }; #if NVT_TOUCH_PROC @@ -297,7 +277,4 @@ void nvt_set_dbgfw_status(bool enable); bool nvt_get_dbgfw_status(void); void nvt_match_fw(void); int32_t nvt_set_pocket_palm_switch(uint8_t pocket_palm_switch); -#if NVT_TOUCH_ESD_PROTECT -extern void nvt_esd_check_enable(uint8_t enable); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ #endif /* _LINUX_NVT_TOUCH_H */ diff --git a/drivers/input/touchscreen/nt36672c/nt36xxx_ext_proc.c b/drivers/input/touchscreen/nt36672c/nt36xxx_ext_proc.c index 365f32bb2d34..0c83524c0b28 100644 --- a/drivers/input/touchscreen/nt36672c/nt36xxx_ext_proc.c +++ b/drivers/input/touchscreen/nt36672c/nt36xxx_ext_proc.c @@ -327,10 +327,6 @@ static int32_t nvt_fw_version_open(struct inode *inode, struct file *file) NVT_LOG("++\n"); -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - if (nvt_get_fw_info()) { mutex_unlock(&ts->lock); return -EAGAIN; @@ -366,10 +362,6 @@ static int32_t nvt_baseline_open(struct inode *inode, struct file *file) NVT_LOG("++\n"); -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - if (nvt_clear_fw_status()) { mutex_unlock(&ts->lock); return -EAGAIN; @@ -421,10 +413,6 @@ static int32_t nvt_raw_open(struct inode *inode, struct file *file) NVT_LOG("++\n"); -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - if (nvt_clear_fw_status()) { mutex_unlock(&ts->lock); return -EAGAIN; @@ -479,10 +467,6 @@ static int32_t nvt_diff_open(struct inode *inode, struct file *file) NVT_LOG("++\n"); -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - if (nvt_clear_fw_status()) { mutex_unlock(&ts->lock); return -EAGAIN; @@ -541,10 +525,6 @@ static int32_t nvt_xiaomi_config_info_open(struct inode *inode, struct file *fil NVT_LOG("++\n"); -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - /*---set xdata index to EVENT BUF ADDR---*/ nvt_set_page(ts->mmap->EVENT_BUF_ADDR | 0x9C); diff --git a/drivers/input/touchscreen/nt36672c/nt36xxx_fw_update.c b/drivers/input/touchscreen/nt36672c/nt36xxx_fw_update.c index 79cd6fafb2ca..f5d4c522b64d 100644 --- a/drivers/input/touchscreen/nt36672c/nt36xxx_fw_update.c +++ b/drivers/input/touchscreen/nt36672c/nt36xxx_fw_update.c @@ -70,7 +70,6 @@ static int32_t nvt_get_fw_need_write_size(const struct firmware *fw_entry) /* check if there is end flag "NVT" at the end of this sector */ if (strncmp(&fw_entry->data[i * FLASH_SECTOR_SIZE - NVT_FLASH_END_FLAG_LEN], "NVT", NVT_FLASH_END_FLAG_LEN) == 0) { fw_need_write_size = i * FLASH_SECTOR_SIZE; - NVT_LOG("fw_need_write_size = %zu(0x%zx), NVT end flag\n", fw_need_write_size, fw_need_write_size); return 0; } @@ -176,8 +175,6 @@ static int32_t nvt_bin_header_parser(const u8 *fwdata, size_t fwsize) * ilm_dlm_num (ILM & DLM) + ovly_sec_num + info_sec_num */ partition = ilm_dlm_num + ovly_sec_num + info_sec_num; - NVT_LOG("ovly_info = %d, ilm_dlm_num = %d, ovly_sec_num = %d, info_sec_num = %d, partition = %d\n", - ovly_info, ilm_dlm_num, ovly_sec_num, info_sec_num, partition); /* allocated memory for header info */ bin_map = (struct nvt_ts_bin_map *)kzalloc((partition+1) * sizeof(struct nvt_ts_bin_map), GFP_KERNEL); @@ -317,7 +314,6 @@ static int32_t update_firmware_request(const char *filename) } while (1) { - NVT_LOG("filename is %s\n", filename); ret = request_firmware(&fw_entry, filename, &ts->client->dev); if (ret) { @@ -799,109 +795,6 @@ static void nvt_read_bld_hw_crc(void) return; } -#if NVT_TOUCH_ESD_DISP_RECOVERY -#define ILM_CRC_FLAG 0x01 -#define CRC_DONE 0x04 -static int32_t nvt_check_crc_done_ilm_err(void) -{ - uint8_t buf[8] = {0}; - - nvt_set_page(ts->mmap->BLD_ILM_DLM_CRC_ADDR); - buf[0] = ts->mmap->BLD_ILM_DLM_CRC_ADDR & 0x7F; - buf[1] = 0x00; - CTP_SPI_READ(ts->client, buf, 2); - - NVT_LOG("CRC DONE, ILM DLM FLAG = 0x%02X\n", buf[1]); - if (((buf[1] & ILM_CRC_FLAG) && (buf[1] & CRC_DONE)) || - (buf[1] == 0xFE)) - return 1; - else - return 0; -} - -#define DISP_OFF_ADDR 0x2800 -static int nvt_f2c_disp_off(void) -{ - uint8_t buf[8] = {0}; - int ret = 0; - uint8_t tmp_val = 0; - int32_t write_disp_off_retry = 0; - int32_t retry = 0; - - NVT_LOG("++\n"); - - /* SW Reset & Idle*/ - nvt_sw_reset_idle(); - - /*Setp1: Set REG CPU_IF_ADDR[15:0]*/ - nvt_write_addr(ts->mmap->CPU_IF_ADDR_LOW, DISP_OFF_ADDR & 0xFF); - nvt_write_addr(ts->mmap->CPU_IF_ADDR_HIGH, (DISP_OFF_ADDR >> 8) & 0xFF); - - /*Step2: Set REG FFM_ADDR[15:0]*/ - /* set FFM_ADDR to 0x20000*/ - nvt_write_addr(ts->mmap->FFM_ADDR_LOW, 0x00); - nvt_write_addr(ts->mmap->FFM_ADDR_MID, 0x00); - if (ts->hw_crc > 1) - nvt_write_addr(ts->mmap->FFM_ADDR_HIGH, 0x00); - - /*Step3: Set REG F2C_LENGT[H7:0]*/ - nvt_write_addr(ts->mmap->F2C_LENGTH, 1); - -nvt_write_disp_off_retry: - /*Step4: Set REG CPU_Polling_En=1, F2C_RW=1, CPU_IF_ADDR_INC=1, F2C_EN=1*/ - nvt_set_page(ts->mmap->FFM2CPU_CTL); - buf[0] = ts->mmap->FFM2CPU_CTL & 0x7F; - buf[1] = 0xFF; - ret = CTP_SPI_READ(ts->client, buf, 2); - if (ret) { - NVT_ERR("Read FFM2CPU control failed!\n"); - return ret; - } - tmp_val = buf[1] | 0x27; - nvt_write_addr(ts->mmap->FFM2CPU_CTL, tmp_val); - - /*Step5: wait F2C_EN = 0*/ - retry = 0; - while (1) { - nvt_set_page(ts->mmap->FFM2CPU_CTL); - buf[0] = ts->mmap->FFM2CPU_CTL & 0x7F; - buf[1] = 0xFF; - buf[2] = 0xFF; - ret = CTP_SPI_READ(ts->client, buf, 3); - if (ret) { - NVT_ERR("Read FFM2CPU control failed!\n"); - return ret; - } - - if ((buf[1] & 0x01) == 0x00) - break; - - usleep_range(1000, 1000); - retry++; - - if(unlikely(retry > 1)) { - NVT_ERR("Wait F2C_EN = 0 failed!\n"); - return -EIO; - } - } - - /*Step6: Check REG TH_CPU_CHK status (1: Success, 0: Fail), if 0, can Retry Step4.*/ - if (((buf[2] & 0x04) >> 2) != 0x01) { - write_disp_off_retry++; - if (write_disp_off_retry <= 3) { - goto nvt_write_disp_off_retry; - } else { - NVT_ERR("Write display off failed!, buf[1]=0x%02X, buf[2]=0x%02X\n", buf[1], buf[2]); - return -EIO; - } - } - NVT_LOG("--\n"); - - return ret; -} -#endif /* #if NVT_TOUCH_ESD_DISP_RECOVERY */ - - /******************************************************* Description: Novatek touchscreen Download_Firmware with HW CRC @@ -960,12 +853,6 @@ static int32_t nvt_download_firmware_hw_crc(void) if(unlikely(retry > 2)) { NVT_ERR("error, retry=%d\n", retry); nvt_read_bld_hw_crc(); -#if NVT_TOUCH_ESD_DISP_RECOVERY - if (nvt_check_crc_done_ilm_err()) { - NVT_ERR("set display off to trigger display esd recovery.\n"); - nvt_f2c_disp_off(); - } -#endif /* #if NVT_TOUCH_ESD_DISP_RECOVERY */ break; } } @@ -1089,9 +976,6 @@ int32_t nvt_update_firmware(const char *firmware_name) goto download_fail; } - NVT_LOG("Update firmware success! <%ld us>\n", - (end.tv_sec - start.tv_sec)*1000000L + (end.tv_usec - start.tv_usec)); - /* Get FW Info */ ret = nvt_get_fw_info(); if (ret) { diff --git a/drivers/input/touchscreen/nt36672c/nt36xxx_mp_ctrlram.c b/drivers/input/touchscreen/nt36672c/nt36xxx_mp_ctrlram.c index e0db8163d351..074f8e648dbd 100644 --- a/drivers/input/touchscreen/nt36672c/nt36xxx_mp_ctrlram.c +++ b/drivers/input/touchscreen/nt36672c/nt36xxx_mp_ctrlram.c @@ -1681,10 +1681,6 @@ static int32_t nvt_selftest_open(struct inode *inode, struct file *file) return -ERESTARTSYS; } -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - /*---Download MP FW---*/ if (nvt_get_dbgfw_status()) { if (nvt_update_firmware(DEFAULT_DEBUG_MP_NAME) < 0) { @@ -2089,10 +2085,6 @@ static int nvt_short_test(void) return -ERESTARTSYS; } -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - /*---Download MP FW---*/ if (nvt_get_dbgfw_status()) { if (nvt_update_firmware(DEFAULT_DEBUG_MP_NAME) < 0) { @@ -2210,10 +2202,6 @@ static int nvt_open_test(void) return -ERESTARTSYS; } -#if NVT_TOUCH_ESD_PROTECT - nvt_esd_check_enable(false); -#endif /* #if NVT_TOUCH_ESD_PROTECT */ - /*---Download MP FW---*/ if (nvt_get_dbgfw_status()) { if (nvt_update_firmware(DEFAULT_DEBUG_MP_NAME) < 0) { diff --git a/drivers/input/touchscreen/raydium_i2c_ts.c b/drivers/input/touchscreen/raydium_i2c_ts.c index 05c1054330b7..1a8c7403cfe6 100644 --- a/drivers/input/touchscreen/raydium_i2c_ts.c +++ b/drivers/input/touchscreen/raydium_i2c_ts.c @@ -419,6 +419,7 @@ static int raydium_i2c_write_object(struct i2c_client *client, enum raydium_bl_ack state) { int error; + static const u8 cmd[] = { 0xFF, 0x39 }; error = raydium_i2c_send(client, RM_CMD_BOOT_WRT, data, len); if (error) { @@ -427,7 +428,7 @@ static int raydium_i2c_write_object(struct i2c_client *client, return error; } - error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, NULL, 0); + error = raydium_i2c_send(client, RM_CMD_BOOT_ACK, cmd, sizeof(cmd)); if (error) { dev_err(&client->dev, "Ack obj command failed: %d\n", error); return error; diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c index b63d7fdf0cd2..85a1f465c097 100644 --- a/drivers/input/touchscreen/s6sy761.c +++ b/drivers/input/touchscreen/s6sy761.c @@ -145,8 +145,8 @@ static void s6sy761_report_coordinates(struct s6sy761_data *sdata, u8 major = event[4]; u8 minor = event[5]; u8 z = event[6] & S6SY761_MASK_Z; - u16 x = (event[1] << 3) | ((event[3] & S6SY761_MASK_X) >> 4); - u16 y = (event[2] << 3) | (event[3] & S6SY761_MASK_Y); + u16 x = (event[1] << 4) | ((event[3] & S6SY761_MASK_X) >> 4); + u16 y = (event[2] << 4) | (event[3] & S6SY761_MASK_Y); input_mt_slot(sdata->input, tid); diff --git a/drivers/input/touchscreen/stm/fts_lib/ftsTool.c b/drivers/input/touchscreen/stm/fts_lib/ftsTool.c new file mode 100644 index 000000000000..0893f82bd097 --- /dev/null +++ b/drivers/input/touchscreen/stm/fts_lib/ftsTool.c @@ -0,0 +1,798 @@ +/* + * + ************************************************************************** + ** STMicroelectronics ** + ************************************************************************** + ** marco.cali@st.com ** + ************************************************************************** + * * + * FTS Utility Functions * + * * + ************************************************************************** + ************************************************************************** + * + */ + +/*! + * \file ftsTool.c + * \brief Contains all the functions to support common operation inside the + * driver + */ + +#include "ftsCompensation.h" +#include "ftsCore.h" +#include "ftsError.h" +#include "ftsHardware.h" +#include "ftsIO.h" +#include "ftsSoftware.h" +#include "ftsTime.h" +#include "ftsTool.h" +#include "../fts.h" /* needed for the tag define */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * Print an array of byte in a HEX string and attach at the beginning a label. + * The function allocate memory that should be free outside the function itself + * @param label string to attach at the beginning + * @param buff pointer to the byte array that should be printed as HEX string + * @param count size of buff + * @param result pointer to the array of characters that compose the HEX final + * string + * @param size size of result + * @return pointer to the array of characters that compose the HEX string, + * (same address of result) + * @warning result MUST be allocated outside the function and should be + * big enough to contain the data converted as HEX! + */ +char *printHex(char *label, u8 *buff, int count, u8 *result, int size) +{ + int i, offset = 0; + + offset = scnprintf(result + offset, size - offset, "%s", label); + for (i = 0; i < count; i++) { + offset += + scnprintf(result + offset, + size - offset, "%02X ", buff[i]); + /* this append automatically a null terminator char */ + } + return result; +} + +/** + * Clear the FIFO from any event + * @return OK if success or an error code which specify the type of error + */ +int flushFIFO(void) +{ + int ret; + u8 sett = SPECIAL_FIFO_FLUSH; + + ret = writeSysCmd(SYS_CMD_SPECIAL, &sett, 1); /* flush the FIFO */ + if (ret < OK) { + pr_err("flushFIFO: ERROR %08X\n", ret); + return ret; + } + + pr_debug("FIFO flushed!\n"); + return OK; +} + + + +/** + * Convert an array of bytes to an array of u16 taking two bytes at time, + * src has LSB first. + * @param src pointer to the source byte array + * @param src_length size of src + * @param dst pointer to the destination array. + * @return the final size of dst (half of the source) or ERROR_OP_NOT_ALLOW + * if the size of src is not multiple of 2. + */ +int u8ToU16n(u8 *src, int src_length, u16 *dst) +{ + int i, j; + + if (src_length % 2 != 0) + return ERROR_OP_NOT_ALLOW; + else { + j = 0; + for (i = 0; i < src_length; i += 2) { + dst[j] = ((src[i + 1] & 0x00FF) << 8) + + (src[i] & 0x00FF); + j++; + } + } + + return src_length / 2; +} + +/** + * Convert an array of 2 bytes to a u16, src has LSB first (little endian). + * @param src pointer to the source byte array + * @param dst pointer to the destination u16. + * @return OK + */ +int u8ToU16(u8 *src, u16 *dst) +{ + *dst = (u16)(((src[1] & 0x00FF) << 8) + (src[0] & 0x00FF)); + return OK; +} + +/** + * Convert an array of 2 bytes to a u16, src has MSB first (big endian). + * @param src pointer to the source byte array + * @param dst pointer to the destination u16. + * @return OK + */ +int u8ToU16_be(u8 *src, u16 *dst) +{ + *dst = (u16)(((src[0] & 0x00FF) << 8) + (src[1] & 0x00FF)); + return OK; +} + +/** + * Convert an array of u16 to an array of u8, dst has MSB first (big endian). + * @param src pointer to the source array of u16 + * @param src_length size of src + * @param dst pointer to the destination array of u8. + * @return size of dst (src size multiply by 2) + */ +int u16ToU8n_be(u16 *src, int src_length, u8 *dst) +{ + int i, j = 0; + + for (i = 0; i < src_length; i++) { + dst[j] = (u8)(src[i] & 0xFF00) >> 8; + dst[j + 1] = (u8)(src[i] & 0x00FF); + j += 2; + } + + return src_length * 2; +} + +/** + * Convert a u16 to an array of 2 u8, dst has MSB first (big endian). + * @param src u16 to convert + * @param dst pointer to the destination array of 2 u8. + * @return OK + */ +int u16ToU8_be(u16 src, u8 *dst) +{ + dst[0] = (u8)((src & 0xFF00) >> 8); + dst[1] = (u8)(src & 0x00FF); + return OK; +} + + +/** + * Convert a u16 to an array of 2 u8, dst has LSB first (little endian). + * @param src u16 to convert + * @param dst pointer to the destination array of 2 u8. + * @return OK + */ +int u16ToU8(u16 src, u8 *dst) +{ + dst[1] = (u8)((src & 0xFF00) >> 8); + dst[0] = (u8)(src & 0x00FF); + return OK; +} + +/** + * Convert an array of bytes to a u32, src has LSB first (little endian). + * @param src array of bytes to convert + * @param dst pointer to the destination u32 variable. + * @return OK + */ +int u8ToU32(u8 *src, u32 *dst) +{ + *dst = (u32)(((src[3] & 0xFF) << 24) + ((src[2] & 0xFF) << 16) + + ((src[1] & 0xFF) << 8) + (src[0] & 0xFF)); + return OK; +} + +/** + * Convert an array of bytes to a u32, src has MSB first (big endian). + * @param src array of bytes to convert + * @param dst pointer to the destination u32 variable. + * @return OK + */ +int u8ToU32_be(u8 *src, u32 *dst) +{ + *dst = (u32)(((src[0] & 0xFF) << 24) + ((src[1] & 0xFF) << 16) + + ((src[2] & 0xFF) << 8) + (src[3] & 0xFF)); + return OK; +} + + +/** + * Convert a u32 to an array of 4 bytes, dst has LSB first (little endian). + * @param src u32 value to convert + * @param dst pointer to the destination array of 4 bytes. + * @return OK + */ +int u32ToU8(u32 src, u8 *dst) +{ + dst[3] = (u8)((src & 0xFF000000) >> 24); + dst[2] = (u8)((src & 0x00FF0000) >> 16); + dst[1] = (u8)((src & 0x0000FF00) >> 8); + dst[0] = (u8)(src & 0x000000FF); + return OK; +} + +/** + * Convert a u32 to an array of 4 bytes, dst has MSB first (big endian). + * @param src u32 value to convert + * @param dst pointer to the destination array of 4 bytes. + * @return OK + */ +int u32ToU8_be(u32 src, u8 *dst) +{ + dst[0] = (u8)((src & 0xFF000000) >> 24); + dst[1] = (u8)((src & 0x00FF0000) >> 16); + dst[2] = (u8)((src & 0x0000FF00) >> 8); + dst[3] = (u8)(src & 0x000000FF); + return OK; +} + +/** + * Execute a function passed as argment and retry it defined number of times if + * not successful + * @param code pointer to a function which return an int and doesn't have any + * parameters + * @param wait_before_retry interval of time in ms to wait between one trial + * and another one + * @param retry_count max number of retry to attemp + * @return last return value obtained from the last execution of the code + *function + */ +int attempt_function(int (*code)(void), unsigned long wait_before_retry, int + retry_count) +{ + int result; + int count = 0; + + do { + result = code(); + count++; + mdelay(wait_before_retry); + } while (count < retry_count && result < 0); + + + if (count == retry_count) + return result | ERROR_TIMEOUT; + else + return result; +} + +/** + * Enable all the possible sensing mode supported by the FW + * @return OK if success or an error code which specify the type of error + */ +int senseOn(void) +{ + int ret; + + ret = setScanMode(SCAN_MODE_ACTIVE, 0xFF); /* enable all */ + if (ret < OK) { + pr_err("senseOn: ERROR %08X\n", ret); + return ret; + } + + pr_info("senseOn: SENSE ON\n"); + return OK; +} + +/** + * Disable all the sensing mode + * @return OK if success or an error code which specify the type of error + */ +int senseOff(void) +{ + int ret; + + ret = setScanMode(SCAN_MODE_ACTIVE, 0x00); + if (ret < OK) { + pr_err("senseOff: ERROR %08X\n", ret); + return ret; + } + + pr_info("senseOff: SENSE OFF\n"); + return OK; +} + + + +/** + * Clean up the IC status executing a system reset and giving + * the possibility to re-enabling the sensing + * @param enableTouch if 1, re-enable the sensing and the interrupt of the IC + * @return OK if success or an error code which specify the type of error + */ +int cleanUp(int enableTouch) +{ + int res; + + pr_info("cleanUp: system reset...\n"); + res = fts_system_reset(); + if (res < OK) + return res; + if (enableTouch) { + pr_info("cleanUp: enabling touches...\n"); + res = senseOn(); /* already enable everything */ + if (res < OK) + return res; + pr_info("cleanUp: enabling interrupts...\n"); + res = fts_enableInterrupt(true); + if (res < OK) + return res; + } + return OK; +} + +/** + * Transform an array of short in a matrix of short with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of short where for each row there are + * columns elements + */ +short **array1dTo2d_short(short *data, int size, int columns) +{ + int i; + short **matrix = NULL; + + if (size != 0) + matrix = (short **)kmalloc_array(((int)(size / columns)), + sizeof(short *), GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) { + matrix[i] = (short *)kmalloc_array(columns, + sizeof(short), GFP_KERNEL); + if (!matrix[i]) + break; + } + + for (i = 0; i < size; i++) { + if (!matrix[i / columns]) + break; + matrix[i / columns][i % columns] = data[i]; + } + } + + return matrix; +} + +/** + * Transform an array of u16 in a matrix of u16 with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of u16 where for each row there are columns + * elements + */ +u16 **array1dTo2d_u16(u16 *data, int size, int columns) +{ + int i; + u16 **matrix = NULL; + + if (size != 0) + matrix = (u16 **)kmalloc_array(((int)(size / columns)), + sizeof(u16 *), GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) { + matrix[i] = (u16 *)kmalloc_array(columns, + sizeof(u16), GFP_KERNEL); + if (!matrix[i]) + break; + } + + for (i = 0; i < size; i++) { + if (!matrix[i / columns]) + break; + matrix[i / columns][i % columns] = data[i]; + } + } + + return matrix; +} + +/** + * Transform an array of u8 in a matrix of u8 with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of short where for each row there are + * columns elements + */ +u8 **array1dTo2d_u8(u8 *data, int size, int columns) +{ + int i; + u8 **matrix = NULL; + + if (size != 0) { + matrix = (u8 **)kmalloc_array(((int)(size / columns)), + sizeof(u8 *), GFP_KERNEL); + } + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) { + matrix[i] = (u8 *)kmalloc_array(columns, + sizeof(u8), GFP_KERNEL); + if (!matrix[i]) + break; + } + + for (i = 0; i < size; i++) { + if (!matrix[i / columns]) + break; + matrix[i / columns][i % columns] = data[i]; + } + } + + return matrix; +} + +/** + * Transform an array of i8 in a matrix of i8 with a defined number of + * columns and the resulting number of rows + * @param data array of bytes to convert + * @param size size of data + * @param columns number of columns that the resulting matrix should have. + * @return a reference to a matrix of short where for each row there are + * columns elements + */ +i8 **array1dTo2d_i8(i8 *data, int size, int columns) +{ + int i; + i8 **matrix = NULL; + + if (size != 0) + matrix = (i8 **)kmalloc_array(((int)(size / columns)), + sizeof(i8 *), GFP_KERNEL); + + if (matrix != NULL) { + for (i = 0; i < (int)(size / columns); i++) { + matrix[i] = (i8 *)kmalloc_array(columns, + sizeof(i8), GFP_KERNEL); + if (!matrix[i]) + break; + } + + for (i = 0; i < size; i++) { + if (!matrix[i / columns]) + break; + matrix[i / columns][i % columns] = data[i]; + } + } + + return matrix; +} + +/** + * Print in the kernel log a label followed by a matrix of short row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of short which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_short(char *label, short **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + pr_info("%s\n", label); + + if (matrix == NULL) + return; + + buff_len = (6 + 1) * column + 1; /* -32768 str len: 6 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + for (i = 0; i < row; i++) { + if (!matrix[i]) + break; + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of u16 row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u16 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_u16(char *label, u16 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + pr_info("%s\n", label); + + if (matrix == NULL) + return; + + buff_len = (5 + 1) * column + 1; /* 65535 str len: 5 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + for (i = 0; i < row; i++) { + if (!matrix[i]) + break; + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of u8 row x columns and + * free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u8 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_u8(char *label, u8 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + pr_info("%s\n", label); + + if (matrix == NULL) + return; + + buff_len = (3 + 1) * column + 1; /* 255 str len: 3 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + for (i = 0; i < row; i++) { + if (!matrix[i]) + break; + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of i8 row x columns and + * free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u8 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_i8(char *label, i8 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + pr_info("%s\n", label); + + if (matrix == NULL) + return; + + buff_len = (4 + 1) * column + 1; /* -128 str len: 4 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + for (i = 0; i < row; i++) { + if (!matrix[i]) + break; + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of u32 row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of u32 which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_u32(char *label, u32 **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + pr_info("%s\n", label); + + if (matrix == NULL) + return; + + buff_len = (10 + 1) * column + 1; /* 4294967295 str len: 10 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + for (i = 0; i < row; i++) { + if (!matrix[i]) + break; + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + +/** + * Print in the kernel log a label followed by a matrix of int row x columns + * and free its memory + * @param label pointer to the string to print before the actual matrix + * @param matrix reference to the matrix of int which contain the actual data + * @param row number of rows on which the matrix should be print + * @param column number of columns for each row + */ +void print_frame_int(char *label, int **matrix, int row, int column) +{ + int i, j; + int buff_len, index; + char *buff; + + pr_info("%s\n", label); + + if (matrix == NULL) + return; + + buff_len = (11 + 1) * column + 1; /* -2147483648 str len: 11 */ + buff = kzalloc(buff_len, GFP_KERNEL); + if (buff == NULL) { + pr_err("%s: fail to allocate buffer\n", __func__); + return; + } + + for (i = 0; i < row; i++) { + if (!matrix[i]) + break; + index = 0; + for (j = 0; j < column; j++) + index += scnprintf(buff + index, buff_len - index, + "%d ", matrix[i][j]); + pr_info("%s\n", buff); + kfree(matrix[i]); + } + kfree(matrix); + kfree(buff); +} + + +/** + * Convert an array of bytes to an u64, src has MSB first (big endian). + * @param src array of bytes + * @param dest pointer to the destination u64. + * @param size size of src (can be <= 8) + * @return OK if success or ERROR_OP_NOT_ALLOW if size exceed 8 + */ +int u8ToU64_be(u8 *src, u64 *dest, int size) +{ + int i = 0; + + /* u64 temp =0; */ + if (size > sizeof(u64)) + return ERROR_OP_NOT_ALLOW; + + *dest = 0; + for (i = 0; i < size; i++) + *dest |= (u64)(src[i]) << ((size - 1 - i) * 8); + + return OK; +} + +/** + * Convert an u64 to an array of bytes, dest has MSB first (big endian). + * @param src value of u64 + * @param dest pointer to the destination array of bytes. + * @param size size of src (can be <= 8) + * @return OK if success or ERROR_OP_NOT_ALLOW if size exceed 8 + */ +int u64ToU8_be(u64 src, u8 *dest, int size) +{ + int i = 0; + + if (size > sizeof(u64)) + return ERROR_OP_NOT_ALLOW; + else + for (i = 0; i < size; i++) + dest[i] = (u8)((src >> ((size - 1 - i) * 8)) & 0xFF); + + return OK; +} + + + +/*********** NEW API *************/ + +/** + * Convert a value of an id in a bitmask with a 1 in the position of the value + * of the id + * @param id Value of the ID to convert + * @param mask pointer to the bitmask that will be updated with the value of id + * @param size dimension in bytes of mask + * @return OK if success or ERROR_OP_NOT_ALLOW if size of mask is not enough to + * contain ID + */ +int fromIDtoMask(u8 id, u8 *mask, int size) +{ + if (((int)((id) / 8)) < size) { + pr_info("%s: ID = %d Index = %d Position = %d !\n", + __func__, id, ((int)((id) / 8)), (id % 8)); + mask[((int)((id) / 8))] |= 0x01 << (id % 8); + return OK; + } else { + pr_err("%s: Bitmask too small! Impossible contain ID = %d %d>=%d! ERROR %08X\n", + __func__, id, ((int)((id) / 8)), size, + ERROR_OP_NOT_ALLOW); + return ERROR_OP_NOT_ALLOW; + } +} diff --git a/drivers/input/touchscreen/sur40.c b/drivers/input/touchscreen/sur40.c index caa3aca2ea54..d5956854ac98 100644 --- a/drivers/input/touchscreen/sur40.c +++ b/drivers/input/touchscreen/sur40.c @@ -778,6 +778,7 @@ static int sur40_probe(struct usb_interface *interface, dev_err(&interface->dev, "Unable to register video controls."); v4l2_ctrl_handler_free(&sur40->hdl); + error = sur40->hdl.error; goto err_unreg_v4l2; } diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index d0cbe910ee9d..5d5941aca16a 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1348,24 +1348,26 @@ static void increase_address_space(struct protection_domain *domain, unsigned long flags; u64 *pte; + pte = (void *)get_zeroed_page(gfp); + if (!pte) + return; + spin_lock_irqsave(&domain->lock, flags); if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL)) /* address space already 64 bit large */ goto out; - pte = (void *)get_zeroed_page(gfp); - if (!pte) - goto out; - *pte = PM_LEVEL_PDE(domain->mode, iommu_virt_to_phys(domain->pt_root)); domain->pt_root = pte; domain->mode += 1; domain->updated = true; + pte = NULL; out: spin_unlock_irqrestore(&domain->lock, flags); + free_page((unsigned long)pte); return; } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 859b06424e5c..0948c425d652 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -259,7 +259,7 @@ #define DTE_IRQ_REMAP_INTCTL_MASK (0x3ULL << 60) #define DTE_IRQ_TABLE_LEN_MASK (0xfULL << 1) #define DTE_IRQ_REMAP_INTCTL (2ULL << 60) -#define DTE_IRQ_TABLE_LEN (8ULL << 1) +#define DTE_IRQ_TABLE_LEN (9ULL << 1) #define DTE_IRQ_REMAP_ENABLE 1ULL #define PAGE_MODE_NONE 0x00 @@ -410,7 +410,11 @@ extern bool amd_iommu_np_cache; /* Only true if all IOMMUs support device IOTLBs */ extern bool amd_iommu_iotlb_sup; -#define MAX_IRQS_PER_TABLE 256 +/* + * AMD IOMMU hardware only support 512 IRTEs despite + * the architectural limitation of 2048 entries. + */ +#define MAX_IRQS_PER_TABLE 512 #define IRQ_TABLE_ALIGNMENT 128 struct irq_remap_table { diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index d936ff765fe4..3f0c2c1ef0cb 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1029,8 +1029,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) { struct intel_iommu *iommu; u32 ver, sts; - int agaw = 0; - int msagaw = 0; + int agaw = -1; + int msagaw = -1; int err; if (!drhd->reg_base_addr) { @@ -1055,17 +1055,28 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) } err = -EINVAL; - agaw = iommu_calculate_agaw(iommu); - if (agaw < 0) { - pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n", - iommu->seq_id); - goto err_unmap; + if (cap_sagaw(iommu->cap) == 0) { + pr_info("%s: No supported address widths. Not attempting DMA translation.\n", + iommu->name); + drhd->ignored = 1; } - msagaw = iommu_calculate_max_sagaw(iommu); - if (msagaw < 0) { - pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n", - iommu->seq_id); - goto err_unmap; + + if (!drhd->ignored) { + agaw = iommu_calculate_agaw(iommu); + if (agaw < 0) { + pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n", + iommu->seq_id); + drhd->ignored = 1; + } + } + if (!drhd->ignored) { + msagaw = iommu_calculate_max_sagaw(iommu); + if (msagaw < 0) { + pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n", + iommu->seq_id); + drhd->ignored = 1; + agaw = -1; + } } iommu->agaw = agaw; iommu->msagaw = msagaw; @@ -1092,7 +1103,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) raw_spin_lock_init(&iommu->register_lock); - if (intel_iommu_enabled) { + /* + * This is only for hotplug; at boot time intel_iommu_enabled won't + * be set yet. When intel_iommu_init() runs, it registers the units + * present at boot time, then sets intel_iommu_enabled. + */ + if (intel_iommu_enabled && !drhd->ignored) { err = iommu_device_sysfs_add(&iommu->iommu, NULL, intel_iommu_groups, "%s", iommu->name); @@ -1107,6 +1123,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) } drhd->iommu = iommu; + iommu->drhd = drhd; return 0; @@ -1121,7 +1138,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) static void free_iommu(struct intel_iommu *iommu) { - if (intel_iommu_enabled) { + if (intel_iommu_enabled && !iommu->drhd->ignored) { iommu_device_unregister(&iommu->iommu); iommu_device_sysfs_remove(&iommu->iommu); } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 2a83fc31dd47..d2166dfc8b3f 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3364,6 +3364,12 @@ static int __init init_dmars(void) if (!ecap_pass_through(iommu->ecap)) hw_pass_through = 0; + + if (!intel_iommu_strict && cap_caching_mode(iommu->cap)) { + pr_info("Disable batched IOTLB flush due to virtualization"); + intel_iommu_strict = 1; + } + #ifdef CONFIG_INTEL_IOMMU_SVM if (pasid_enabled(iommu)) intel_svm_init(iommu); diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 9d2d03545bb0..cd2e5b44119a 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -1373,6 +1373,8 @@ static int intel_irq_remapping_alloc(struct irq_domain *domain, irq_data = irq_domain_get_irq_data(domain, virq + i); irq_cfg = irqd_cfg(irq_data); if (!irq_data || !irq_cfg) { + if (!i) + kfree(data); ret = -EINVAL; goto out_free_data; } diff --git a/drivers/iommu/io-pgtable-msm-secure.c b/drivers/iommu/io-pgtable-msm-secure.c index 0d5025842e35..1481c9a604c0 100644 --- a/drivers/iommu/io-pgtable-msm-secure.c +++ b/drivers/iommu/io-pgtable-msm-secure.c @@ -66,6 +66,7 @@ int msm_iommu_sec_pgtbl_init(void) /* Now allocate memory for the secure page tables */ attrs = DMA_ATTR_NO_KERNEL_MAPPING; dev.coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8); + arch_setup_dma_ops(&dev, 0, 0, NULL, 0); cpu_addr = dma_alloc_attrs(&dev, psize[0], &paddr, GFP_KERNEL, attrs); if (!cpu_addr) { pr_err("%s: Failed to allocate %d bytes for PTBL\n", diff --git a/drivers/iommu/io-pgtable.c b/drivers/iommu/io-pgtable.c index f4d1047e0e61..71f23d0a5d75 100644 --- a/drivers/iommu/io-pgtable.c +++ b/drivers/iommu/io-pgtable.c @@ -43,6 +43,9 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = { #ifdef CONFIG_IOMMU_IO_PGTABLE_FAST [ARM_V8L_FAST] = &io_pgtable_av8l_fast_init_fns, #endif +#ifdef CONFIG_MSM_TZ_SMMU + [ARM_MSM_SECURE] = &io_pgtable_arm_msm_secure_init_fns, +#endif }; static struct dentry *io_pgtable_top; diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 6d73f6d6ebe0..30d16576eb95 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -37,7 +37,6 @@ config ARM_GIC_V3 select GENERIC_IRQ_MULTI_HANDLER select IRQ_DOMAIN_HIERARCHY select PARTITION_PERCPU - select QCOM_SHOW_RESUME_IRQ select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_V3_ITS diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c index 23a3b877f7f1..ede02dc2bcd0 100644 --- a/drivers/irqchip/irq-alpine-msi.c +++ b/drivers/irqchip/irq-alpine-msi.c @@ -165,8 +165,7 @@ static int alpine_msix_middle_domain_alloc(struct irq_domain *domain, return 0; err_sgi: - while (--i >= 0) - irq_domain_free_irqs_parent(domain, virq, i); + irq_domain_free_irqs_parent(domain, virq, i - 1); alpine_msix_free_sgi(priv, sgi, nr_irqs); return err; } diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index d5cc32e80f5e..cd58c123f547 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -49,7 +49,6 @@ #define ITS_FLAGS_CMDQ_NEEDS_FLUSHING (1ULL << 0) #define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1) #define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2) -#define ITS_FLAGS_SAVE_SUSPEND_STATE (1ULL << 3) #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING (1 << 0) @@ -3240,9 +3239,6 @@ static int its_save_disable(void) list_for_each_entry(its, &its_nodes, entry) { void __iomem *base; - if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE)) - continue; - base = its->base; its->ctlr_save = readl_relaxed(base + GITS_CTLR); err = its_force_quiescent(base); @@ -3261,9 +3257,6 @@ static int its_save_disable(void) list_for_each_entry_continue_reverse(its, &its_nodes, entry) { void __iomem *base; - if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE)) - continue; - base = its->base; writel_relaxed(its->ctlr_save, base + GITS_CTLR); } @@ -3283,9 +3276,6 @@ static void its_restore_enable(void) void __iomem *base; int i; - if (!(its->flags & ITS_FLAGS_SAVE_SUSPEND_STATE)) - continue; - base = its->base; /* @@ -3293,7 +3283,10 @@ static void its_restore_enable(void) * don't restore it since writing to CBASER or BASER * registers is undefined according to the GIC v3 ITS * Specification. + * + * Firmware resuming with the ITS enabled is terminally broken. */ + WARN_ON(readl_relaxed(base + GITS_CTLR) & GITS_CTLR_ENABLE); ret = its_force_quiescent(base); if (ret) { pr_err("ITS@%pa: failed to quiesce on resume: %d\n", @@ -3558,9 +3551,6 @@ static int __init its_probe_one(struct resource *res, ctlr |= GITS_CTLR_ImDe; writel_relaxed(ctlr, its->base + GITS_CTLR); - if (GITS_TYPER_HCC(typer)) - its->flags |= ITS_FLAGS_SAVE_SUSPEND_STATE; - err = its_init_domain(handle, its); if (err) goto out_free_tables; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 34945830abdf..7e5e33175b36 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -826,7 +826,6 @@ static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq) MPIDR_TO_SGI_RS(cluster_id) | tlist << ICC_SGI1R_TARGET_LIST_SHIFT); - pr_devel("CPU%d: ICC_SGI1R_EL1 %llx\n", smp_processor_id(), val); gic_write_sgi1r(val); } diff --git a/drivers/irqchip/irq-mips-cpu.c b/drivers/irqchip/irq-mips-cpu.c index 66f97fde13d8..51e09f6c653c 100644 --- a/drivers/irqchip/irq-mips-cpu.c +++ b/drivers/irqchip/irq-mips-cpu.c @@ -201,6 +201,13 @@ static int mips_cpu_ipi_alloc(struct irq_domain *domain, unsigned int virq, if (ret) return ret; + ret = irq_domain_set_hwirq_and_chip(domain->parent, virq + i, hwirq, + &mips_mt_cpu_irq_controller, + NULL); + + if (ret) + return ret; + ret = irq_set_irq_type(virq + i, IRQ_TYPE_LEVEL_HIGH); if (ret) return ret; diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c index 4d78f870435e..71e635d6c64a 100644 --- a/drivers/isdn/hardware/mISDN/mISDNipac.c +++ b/drivers/isdn/hardware/mISDN/mISDNipac.c @@ -710,7 +710,7 @@ isac_release(struct isac_hw *isac) { if (isac->type & IPAC_TYPE_ISACX) WriteISAC(isac, ISACX_MASK, 0xff); - else + else if (isac->type != 0) WriteISAC(isac, ISAC_MASK, 0xff); if (isac->dch.timer.function != NULL) { del_timer(&isac->dch.timer); diff --git a/drivers/isdn/mISDN/Kconfig b/drivers/isdn/mISDN/Kconfig index c0730d5c734d..fb61181a5c4f 100644 --- a/drivers/isdn/mISDN/Kconfig +++ b/drivers/isdn/mISDN/Kconfig @@ -12,6 +12,7 @@ if MISDN != n config MISDN_DSP tristate "Digital Audio Processing of transparent data" depends on MISDN + select BITREVERSE help Enable support for digital audio processing capability. diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index b41c53418f97..12e17a112044 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -318,14 +318,15 @@ void led_trigger_event(struct led_trigger *trig, enum led_brightness brightness) { struct led_classdev *led_cdev; + unsigned long flags; if (!trig) return; - read_lock(&trig->leddev_list_lock); + read_lock_irqsave(&trig->leddev_list_lock, flags); list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) led_set_brightness(led_cdev, brightness); - read_unlock(&trig->leddev_list_lock); + read_unlock_irqrestore(&trig->leddev_list_lock, flags); } EXPORT_SYMBOL_GPL(led_trigger_event); @@ -336,11 +337,12 @@ static void led_trigger_blink_setup(struct led_trigger *trig, int invert) { struct led_classdev *led_cdev; + unsigned long flags; if (!trig) return; - read_lock(&trig->leddev_list_lock); + read_lock_irqsave(&trig->leddev_list_lock, flags); list_for_each_entry(led_cdev, &trig->led_cdevs, trig_list) { if (oneshot) led_blink_set_oneshot(led_cdev, delay_on, delay_off, @@ -348,7 +350,7 @@ static void led_trigger_blink_setup(struct led_trigger *trig, else led_blink_set(led_cdev, delay_on, delay_off); } - read_unlock(&trig->leddev_list_lock); + read_unlock_irqrestore(&trig->leddev_list_lock, flags); } void led_trigger_blink(struct led_trigger *trig, diff --git a/drivers/lightnvm/Kconfig b/drivers/lightnvm/Kconfig index 439bf90d084d..20706da7aa1c 100644 --- a/drivers/lightnvm/Kconfig +++ b/drivers/lightnvm/Kconfig @@ -19,6 +19,7 @@ if NVM config NVM_PBLK tristate "Physical Block Device Open-Channel SSD target" + select CRC32 help Allows an open-channel SSD to be exposed as a block device to the host. The target assumes the device exposes raw flash and must be diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c index 726f65677b5b..352bb535a293 100644 --- a/drivers/mailbox/msm_qmp.c +++ b/drivers/mailbox/msm_qmp.c @@ -978,7 +978,7 @@ static int qmp_mbox_probe(struct platform_device *pdev) mdev->name); ret = devm_request_irq(&pdev->dev, mdev->rx_irq_line, qmp_irq_handler, - IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND | IRQF_SHARED, + IRQF_TRIGGER_RISING | IRQF_SHARED, edge_node->name, mdev); if (ret < 0) { qmp_mbox_remove(pdev); diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index b0db05232d53..799e7f714eee 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1442,6 +1442,10 @@ EXPORT_SYMBOL_GPL(dm_bufio_get_block_size); sector_t dm_bufio_get_device_size(struct dm_bufio_client *c) { sector_t s = i_size_read(c->bdev->bd_inode) >> SECTOR_SHIFT; + if (s >= c->start) + s -= c->start; + else + s = 0; if (likely(c->sectors_per_block_bits >= 0)) s >>= c->sectors_per_block_bits; else @@ -1450,6 +1454,12 @@ sector_t dm_bufio_get_device_size(struct dm_bufio_client *c) } EXPORT_SYMBOL_GPL(dm_bufio_get_device_size); +struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c) +{ + return c->dm_io; +} +EXPORT_SYMBOL_GPL(dm_bufio_get_dm_io_client); + sector_t dm_bufio_get_block_number(struct dm_buffer *b) { return b->block; @@ -1931,7 +1941,7 @@ static int __init dm_bufio_init(void) dm_bufio_allocated_vmalloc = 0; dm_bufio_current_allocated = 0; - mem = (__u64)mult_frac(totalram_pages - totalhigh_pages, + mem = (__u64)mult_frac(totalram_pages() - totalhigh_pages(), DM_BUFIO_MEMORY_PERCENT, 100) << PAGE_SHIFT; if (mem > ULONG_MAX) diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 7335393b101b..63aea58286c5 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -2174,7 +2174,7 @@ static int crypt_wipe_key(struct crypt_config *cc) static void crypt_calculate_pages_per_client(void) { - unsigned long pages = (totalram_pages - totalhigh_pages) * DM_CRYPT_MEMORY_PERCENT / 100; + unsigned long pages = (totalram_pages() - totalhigh_pages()) * DM_CRYPT_MEMORY_PERCENT / 100; if (!dm_crypt_clients_n) return; diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c index 8e48920a3ffa..c596fc564a58 100644 --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -46,6 +46,7 @@ struct writeset { static void writeset_free(struct writeset *ws) { vfree(ws->bits); + ws->bits = NULL; } static int setup_on_disk_bitset(struct dm_disk_bitset *info, @@ -70,8 +71,6 @@ static size_t bitset_size(unsigned nr_bits) */ static int writeset_alloc(struct writeset *ws, dm_block_t nr_blocks) { - ws->md.nr_bits = nr_blocks; - ws->md.root = INVALID_WRITESET_ROOT; ws->bits = vzalloc(bitset_size(nr_blocks)); if (!ws->bits) { DMERR("%s: couldn't allocate in memory bitset", __func__); @@ -84,12 +83,14 @@ static int writeset_alloc(struct writeset *ws, dm_block_t nr_blocks) /* * Wipes the in-core bitset, and creates a new on disk bitset. */ -static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws) +static int writeset_init(struct dm_disk_bitset *info, struct writeset *ws, + dm_block_t nr_blocks) { int r; - memset(ws->bits, 0, bitset_size(ws->md.nr_bits)); + memset(ws->bits, 0, bitset_size(nr_blocks)); + ws->md.nr_bits = nr_blocks; r = setup_on_disk_bitset(info, ws->md.nr_bits, &ws->md.root); if (r) { DMERR("%s: setup_on_disk_bitset failed", __func__); @@ -133,7 +134,7 @@ static int writeset_test_and_set(struct dm_disk_bitset *info, { int r; - if (!test_and_set_bit(block, ws->bits)) { + if (!test_bit(block, ws->bits)) { r = dm_bitset_set_bit(info, ws->md.root, block, &ws->md.root); if (r) { /* FIXME: fail mode */ @@ -387,7 +388,7 @@ static void ws_dec(void *context, const void *value) static int ws_eq(void *context, const void *value1, const void *value2) { - return !memcmp(value1, value2, sizeof(struct writeset_metadata)); + return !memcmp(value1, value2, sizeof(struct writeset_disk)); } /*----------------------------------------------------------------*/ @@ -563,6 +564,15 @@ static int open_metadata(struct era_metadata *md) } disk = dm_block_data(sblock); + + /* Verify the data block size hasn't changed */ + if (le32_to_cpu(disk->data_block_size) != md->block_size) { + DMERR("changing the data block size (from %u to %llu) is not supported", + le32_to_cpu(disk->data_block_size), md->block_size); + r = -EINVAL; + goto bad; + } + r = dm_tm_open_with_sm(md->bm, SUPERBLOCK_LOCATION, disk->metadata_space_map_root, sizeof(disk->metadata_space_map_root), @@ -574,10 +584,10 @@ static int open_metadata(struct era_metadata *md) setup_infos(md); - md->block_size = le32_to_cpu(disk->data_block_size); md->nr_blocks = le32_to_cpu(disk->nr_blocks); md->current_era = le32_to_cpu(disk->current_era); + ws_unpack(&disk->current_writeset, &md->current_writeset->md); md->writeset_tree_root = le64_to_cpu(disk->writeset_tree_root); md->era_array_root = le64_to_cpu(disk->era_array_root); md->metadata_snap = le64_to_cpu(disk->metadata_snap); @@ -745,6 +755,12 @@ static int metadata_digest_lookup_writeset(struct era_metadata *md, ws_unpack(&disk, &d->writeset); d->value = cpu_to_le32(key); + /* + * We initialise another bitset info to avoid any caching side effects + * with the previous one. + */ + dm_disk_bitset_init(md->tm, &d->info); + d->nr_bits = min(d->writeset.nr_bits, md->nr_blocks); d->current_bit = 0; d->step = metadata_digest_transcribe_writeset; @@ -758,12 +774,6 @@ static int metadata_digest_start(struct era_metadata *md, struct digest *d) return 0; memset(d, 0, sizeof(*d)); - - /* - * We initialise another bitset info to avoid any caching side - * effects with the previous one. - */ - dm_disk_bitset_init(md->tm, &d->info); d->step = metadata_digest_lookup_writeset; return 0; @@ -801,6 +811,8 @@ static struct era_metadata *metadata_open(struct block_device *bdev, static void metadata_close(struct era_metadata *md) { + writeset_free(&md->writesets[0]); + writeset_free(&md->writesets[1]); destroy_persistent_data_objects(md); kfree(md); } @@ -838,6 +850,7 @@ static int metadata_resize(struct era_metadata *md, void *arg) r = writeset_alloc(&md->writesets[1], *new_size); if (r) { DMERR("%s: writeset_alloc failed for writeset 1", __func__); + writeset_free(&md->writesets[0]); return r; } @@ -848,6 +861,8 @@ static int metadata_resize(struct era_metadata *md, void *arg) &value, &md->era_array_root); if (r) { DMERR("%s: dm_array_resize failed", __func__); + writeset_free(&md->writesets[0]); + writeset_free(&md->writesets[1]); return r; } @@ -869,7 +884,6 @@ static int metadata_era_archive(struct era_metadata *md) } ws_pack(&md->current_writeset->md, &value); - md->current_writeset->md.root = INVALID_WRITESET_ROOT; keys[0] = md->current_era; __dm_bless_for_disk(&value); @@ -881,6 +895,7 @@ static int metadata_era_archive(struct era_metadata *md) return r; } + md->current_writeset->md.root = INVALID_WRITESET_ROOT; md->archived_writesets = true; return 0; @@ -897,7 +912,7 @@ static int metadata_new_era(struct era_metadata *md) int r; struct writeset *new_writeset = next_writeset(md); - r = writeset_init(&md->bitset_info, new_writeset); + r = writeset_init(&md->bitset_info, new_writeset, md->nr_blocks); if (r) { DMERR("%s: writeset_init failed", __func__); return r; @@ -950,7 +965,7 @@ static int metadata_commit(struct era_metadata *md) int r; struct dm_block *sblock; - if (md->current_writeset->md.root != SUPERBLOCK_LOCATION) { + if (md->current_writeset->md.root != INVALID_WRITESET_ROOT) { r = dm_bitset_flush(&md->bitset_info, md->current_writeset->md.root, &md->current_writeset->md.root); if (r) { @@ -1225,8 +1240,10 @@ static void process_deferred_bios(struct era *era) int r; struct bio_list deferred_bios, marked_bios; struct bio *bio; + struct blk_plug plug; bool commit_needed = false; bool failed = false; + struct writeset *ws = era->md->current_writeset; bio_list_init(&deferred_bios); bio_list_init(&marked_bios); @@ -1236,9 +1253,11 @@ static void process_deferred_bios(struct era *era) bio_list_init(&era->deferred_bios); spin_unlock(&era->deferred_lock); + if (bio_list_empty(&deferred_bios)) + return; + while ((bio = bio_list_pop(&deferred_bios))) { - r = writeset_test_and_set(&era->md->bitset_info, - era->md->current_writeset, + r = writeset_test_and_set(&era->md->bitset_info, ws, get_block(era, bio)); if (r < 0) { /* @@ -1246,7 +1265,6 @@ static void process_deferred_bios(struct era *era) * FIXME: finish. */ failed = true; - } else if (r == 0) commit_needed = true; @@ -1262,9 +1280,19 @@ static void process_deferred_bios(struct era *era) if (failed) while ((bio = bio_list_pop(&marked_bios))) bio_io_error(bio); - else - while ((bio = bio_list_pop(&marked_bios))) + else { + blk_start_plug(&plug); + while ((bio = bio_list_pop(&marked_bios))) { + /* + * Only update the in-core writeset if the on-disk one + * was updated too. + */ + if (commit_needed) + set_bit(get_block(era, bio), ws->bits); generic_make_request(bio); + } + blk_finish_plug(&plug); + } } static void process_rpc_calls(struct era *era) @@ -1485,15 +1513,6 @@ static int era_ctr(struct dm_target *ti, unsigned argc, char **argv) } era->md = md; - era->nr_blocks = calc_nr_blocks(era); - - r = metadata_resize(era->md, &era->nr_blocks); - if (r) { - ti->error = "couldn't resize metadata"; - era_destroy(era); - return -ENOMEM; - } - era->wq = alloc_ordered_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM); if (!era->wq) { ti->error = "could not create workqueue for metadata object"; @@ -1570,16 +1589,24 @@ static int era_preresume(struct dm_target *ti) dm_block_t new_size = calc_nr_blocks(era); if (era->nr_blocks != new_size) { - r = in_worker1(era, metadata_resize, &new_size); - if (r) + r = metadata_resize(era->md, &new_size); + if (r) { + DMERR("%s: metadata_resize failed", __func__); + return r; + } + + r = metadata_commit(era->md); + if (r) { + DMERR("%s: metadata_commit failed", __func__); return r; + } era->nr_blocks = new_size; } start_worker(era); - r = in_worker0(era, metadata_new_era); + r = in_worker0(era, metadata_era_rollover); if (r) { DMERR("%s: metadata_era_rollover failed", __func__); return r; diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 50aabb560e18..e671e8d870fe 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -240,6 +240,7 @@ struct dm_integrity_c { bool journal_uptodate; bool just_formatted; + bool legacy_recalculate; struct alg_spec internal_hash_alg; struct alg_spec journal_crypt_alg; @@ -345,6 +346,14 @@ static int dm_integrity_failed(struct dm_integrity_c *ic) return READ_ONCE(ic->failed); } +static bool dm_integrity_disable_recalculate(struct dm_integrity_c *ic) +{ + if ((ic->internal_hash_alg.key || ic->journal_mac_alg.key) && + !ic->legacy_recalculate) + return true; + return false; +} + static commit_id_t dm_integrity_commit_id(struct dm_integrity_c *ic, unsigned i, unsigned j, unsigned char seq) { @@ -1158,12 +1167,52 @@ static int dm_integrity_rw_tag(struct dm_integrity_c *ic, unsigned char *tag, se return 0; } -static void dm_integrity_flush_buffers(struct dm_integrity_c *ic) +struct flush_request { + struct dm_io_request io_req; + struct dm_io_region io_reg; + struct dm_integrity_c *ic; + struct completion comp; +}; + +static void flush_notify(unsigned long error, void *fr_) +{ + struct flush_request *fr = fr_; + if (unlikely(error != 0)) + dm_integrity_io_error(fr->ic, "flusing disk cache", -EIO); + complete(&fr->comp); +} + +static void dm_integrity_flush_buffers(struct dm_integrity_c *ic, bool flush_data) { int r; + + struct flush_request fr; + + if (!ic->meta_dev) + flush_data = false; + if (flush_data) { + fr.io_req.bi_op = REQ_OP_WRITE, + fr.io_req.bi_op_flags = REQ_PREFLUSH | REQ_SYNC, + fr.io_req.mem.type = DM_IO_KMEM, + fr.io_req.mem.ptr.addr = NULL, + fr.io_req.notify.fn = flush_notify, + fr.io_req.notify.context = &fr; + fr.io_req.client = dm_bufio_get_dm_io_client(ic->bufio), + fr.io_reg.bdev = ic->dev->bdev, + fr.io_reg.sector = 0, + fr.io_reg.count = 0, + fr.ic = ic; + init_completion(&fr.comp); + r = dm_io(&fr.io_req, 1, &fr.io_reg, NULL); + BUG_ON(r); + } + r = dm_bufio_write_dirty_buffers(ic->bufio); if (unlikely(r)) dm_integrity_io_error(ic, "writing tags", r); + + if (flush_data) + wait_for_completion(&fr.comp); } static void sleep_on_endio_wait(struct dm_integrity_c *ic) @@ -1857,7 +1906,7 @@ static void integrity_commit(struct work_struct *w) flushes = bio_list_get(&ic->flush_bio_list); if (unlikely(ic->mode != 'J')) { spin_unlock_irq(&ic->endio_wait.lock); - dm_integrity_flush_buffers(ic); + dm_integrity_flush_buffers(ic, true); goto release_flush_bios; } @@ -2068,7 +2117,7 @@ static void do_journal_write(struct dm_integrity_c *ic, unsigned write_start, complete_journal_op(&comp); wait_for_completion_io(&comp.comp); - dm_integrity_flush_buffers(ic); + dm_integrity_flush_buffers(ic, true); } static void integrity_writer(struct work_struct *w) @@ -2110,7 +2159,7 @@ static void recalc_write_super(struct dm_integrity_c *ic) { int r; - dm_integrity_flush_buffers(ic); + dm_integrity_flush_buffers(ic, false); if (dm_integrity_failed(ic)) return; @@ -2420,7 +2469,7 @@ static void dm_integrity_postsuspend(struct dm_target *ti) if (ic->meta_dev) queue_work(ic->writer_wq, &ic->writer_work); drain_workqueue(ic->writer_wq); - dm_integrity_flush_buffers(ic); + dm_integrity_flush_buffers(ic, true); } BUG_ON(!RB_EMPTY_ROOT(&ic->in_progress)); @@ -2474,6 +2523,7 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type, arg_count += !!ic->internal_hash_alg.alg_string; arg_count += !!ic->journal_crypt_alg.alg_string; arg_count += !!ic->journal_mac_alg.alg_string; + arg_count += ic->legacy_recalculate; DMEMIT("%s %llu %u %c %u", ic->dev->name, (unsigned long long)ic->start, ic->tag_size, ic->mode, arg_count); if (ic->meta_dev) @@ -2487,6 +2537,8 @@ static void dm_integrity_status(struct dm_target *ti, status_type_t type, DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors); DMEMIT(" journal_watermark:%u", (unsigned)watermark_percentage); DMEMIT(" commit_time:%u", ic->autocommit_msec); + if (ic->legacy_recalculate) + DMEMIT(" legacy_recalculate"); #define EMIT_ALG(a, n) \ do { \ @@ -2840,7 +2892,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error) journal_pages = roundup((__u64)ic->journal_sections * ic->journal_section_sectors, PAGE_SIZE >> SECTOR_SHIFT) >> (PAGE_SHIFT - SECTOR_SHIFT); journal_desc_size = journal_pages * sizeof(struct page_list); - if (journal_pages >= totalram_pages - totalhigh_pages || journal_desc_size > ULONG_MAX) { + if (journal_pages >= totalram_pages() - totalhigh_pages() || journal_desc_size > ULONG_MAX) { *error = "Journal doesn't fit into memory"; r = -ENOMEM; goto bad; @@ -3089,7 +3141,7 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) unsigned extra_args; struct dm_arg_set as; static const struct dm_arg _args[] = { - {0, 9, "Invalid number of feature args"}, + {0, 12, "Invalid number of feature args"}, }; unsigned journal_sectors, interleave_sectors, buffer_sectors, journal_watermark, sync_msec; bool recalculate; @@ -3219,6 +3271,8 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) goto bad; } else if (!strcmp(opt_string, "recalculate")) { recalculate = true; + } else if (!strcmp(opt_string, "legacy_recalculate")) { + ic->legacy_recalculate = true; } else { r = -EINVAL; ti->error = "Invalid argument"; @@ -3486,6 +3540,20 @@ static int dm_integrity_ctr(struct dm_target *ti, unsigned argc, char **argv) r = -ENOMEM; goto bad; } + } else { + if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) { + ti->error = "Recalculate can only be specified with internal_hash"; + r = -EINVAL; + goto bad; + } + } + + if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING) && + le64_to_cpu(ic->sb->recalc_sector) < ic->provided_data_sectors && + dm_integrity_disable_recalculate(ic)) { + ti->error = "Recalculating with HMAC is disabled for security reasons - if you really need it, use the argument \"legacy_recalculate\""; + r = -EOPNOTSUPP; + goto bad; } ic->bufio = dm_bufio_client_create(ic->meta_dev ? ic->meta_dev->bdev : ic->dev->bdev, diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 9a7072e4512e..8de7c78a0a4c 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -529,7 +529,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ * Grab our output buffer. */ nl = orig_nl = get_result_buffer(param, param_size, &len); - if (len < needed) { + if (len < needed || len < sizeof(nl->dev)) { param->flags |= DM_BUFFER_FULL_FLAG; goto out; } @@ -1575,6 +1575,7 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para if (!argc) { DMWARN("Empty message received."); + r = -EINVAL; goto out_argv; } diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index d3f28a9e3fd9..9e930a150aa2 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -137,6 +137,11 @@ struct dm_snapshot { * for them to be committed. */ struct bio_list bios_queued_during_merge; + + /* + * Flush data after merge. + */ + struct bio flush_bio; }; /* @@ -1061,6 +1066,17 @@ static void snapshot_merge_next_chunks(struct dm_snapshot *s) static void error_bios(struct bio *bio); +static int flush_data(struct dm_snapshot *s) +{ + struct bio *flush_bio = &s->flush_bio; + + bio_reset(flush_bio); + bio_set_dev(flush_bio, s->origin->bdev); + flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; + + return submit_bio_wait(flush_bio); +} + static void merge_callback(int read_err, unsigned long write_err, void *context) { struct dm_snapshot *s = context; @@ -1074,6 +1090,11 @@ static void merge_callback(int read_err, unsigned long write_err, void *context) goto shut; } + if (flush_data(s) < 0) { + DMERR("Flush after merge failed: shutting down merge"); + goto shut; + } + if (s->store->type->commit_merge(s->store, s->num_merging_chunks) < 0) { DMERR("Write error in exception store: shutting down merge"); @@ -1198,6 +1219,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->first_merging_chunk = 0; s->num_merging_chunks = 0; bio_list_init(&s->bios_queued_during_merge); + bio_init(&s->flush_bio, NULL, 0); /* Allocate hash table for COW data */ if (init_hash_tables(s)) { @@ -1391,6 +1413,8 @@ static void snapshot_dtr(struct dm_target *ti) mutex_destroy(&s->lock); + bio_uninit(&s->flush_bio); + dm_put_device(ti, s->cow); dm_put_device(ti, s->origin); diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c index 21de30b4e2a1..45b92a3d9d8e 100644 --- a/drivers/md/dm-stats.c +++ b/drivers/md/dm-stats.c @@ -85,7 +85,7 @@ static bool __check_shared_memory(size_t alloc_size) a = shared_memory_amount + alloc_size; if (a < shared_memory_amount) return false; - if (a >> PAGE_SHIFT > totalram_pages / DM_STATS_MEMORY_FACTOR) + if (a >> PAGE_SHIFT > totalram_pages() / DM_STATS_MEMORY_FACTOR) return false; #ifdef CONFIG_MMU if (a > (VMALLOC_END - VMALLOC_START) / DM_STATS_VMALLOC_FACTOR) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index cc2fbb015587..15c3a9db1ee0 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -434,14 +434,23 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode, { int r; dev_t dev; + unsigned int major, minor; + char dummy; struct dm_dev_internal *dd; struct dm_table *t = ti->table; BUG_ON(!t); - dev = dm_get_dev_t(path); - if (!dev) - return -ENODEV; + if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) { + /* Extract the major/minor numbers */ + dev = MKDEV(major, minor); + if (MAJOR(dev) != major || MINOR(dev) != minor) + return -EOVERFLOW; + } else { + dev = dm_get_dev_t(path); + if (!dev) + return -ENODEV; + } dd = find_device(&t->devices, dev); if (!dd) { @@ -885,10 +894,10 @@ void dm_table_set_type(struct dm_table *t, enum dm_queue_mode type) } EXPORT_SYMBOL_GPL(dm_table_set_type); -static int device_supports_dax(struct dm_target *ti, struct dm_dev *dev, +static int device_not_dax_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { - return bdev_dax_supported(dev->bdev, PAGE_SIZE); + return !bdev_dax_supported(dev->bdev, PAGE_SIZE); } static bool dm_table_supports_dax(struct dm_table *t) @@ -904,7 +913,7 @@ static bool dm_table_supports_dax(struct dm_table *t) return false; if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, device_supports_dax, NULL)) + ti->type->iterate_devices(ti, device_not_dax_capable, NULL)) return false; } @@ -1339,12 +1348,6 @@ void dm_table_event_callback(struct dm_table *t, void dm_table_event(struct dm_table *t) { - /* - * You can no longer call dm_table_event() from interrupt - * context, use a bottom half instead. - */ - BUG_ON(in_interrupt()); - mutex_lock(&_event_lock); if (t->event_fn) t->event_fn(t->event_context); @@ -1392,6 +1395,46 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector) return &t->targets[(KEYS_PER_NODE * n) + k]; } +/* + * type->iterate_devices() should be called when the sanity check needs to + * iterate and check all underlying data devices. iterate_devices() will + * iterate all underlying data devices until it encounters a non-zero return + * code, returned by whether the input iterate_devices_callout_fn, or + * iterate_devices() itself internally. + * + * For some target type (e.g. dm-stripe), one call of iterate_devices() may + * iterate multiple underlying devices internally, in which case a non-zero + * return code returned by iterate_devices_callout_fn will stop the iteration + * in advance. + * + * Cases requiring _any_ underlying device supporting some kind of attribute, + * should use the iteration structure like dm_table_any_dev_attr(), or call + * it directly. @func should handle semantics of positive examples, e.g. + * capable of something. + * + * Cases requiring _all_ underlying devices supporting some kind of attribute, + * should use the iteration structure like dm_table_supports_nowait() or + * dm_table_supports_discards(). Or introduce dm_table_all_devs_attr() that + * uses an @anti_func that handle semantics of counter examples, e.g. not + * capable of something. So: return !dm_table_any_dev_attr(t, anti_func, data); + */ +static bool dm_table_any_dev_attr(struct dm_table *t, + iterate_devices_callout_fn func, void *data) +{ + struct dm_target *ti; + unsigned int i; + + for (i = 0; i < dm_table_get_num_targets(t); i++) { + ti = dm_table_get_target(t, i); + + if (ti->type->iterate_devices && + ti->type->iterate_devices(ti, func, data)) + return true; + } + + return false; +} + static int count_device(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { @@ -1428,13 +1471,13 @@ bool dm_table_has_no_data_devices(struct dm_table *table) return true; } -static int device_is_zoned_model(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_not_zoned_model(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev); enum blk_zoned_model *zoned_model = data; - return q && blk_queue_zoned_model(q) == *zoned_model; + return !q || blk_queue_zoned_model(q) != *zoned_model; } static bool dm_table_supports_zoned_model(struct dm_table *t, @@ -1451,37 +1494,20 @@ static bool dm_table_supports_zoned_model(struct dm_table *t, return false; if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, device_is_zoned_model, &zoned_model)) + ti->type->iterate_devices(ti, device_not_zoned_model, &zoned_model)) return false; } return true; } -static int device_matches_zone_sectors(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_not_matches_zone_sectors(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev); unsigned int *zone_sectors = data; - return q && blk_queue_zone_sectors(q) == *zone_sectors; -} - -static bool dm_table_matches_zone_sectors(struct dm_table *t, - unsigned int zone_sectors) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, device_matches_zone_sectors, &zone_sectors)) - return false; - } - - return true; + return !q || blk_queue_zone_sectors(q) != *zone_sectors; } static int validate_hardware_zoned_model(struct dm_table *table, @@ -1501,7 +1527,7 @@ static int validate_hardware_zoned_model(struct dm_table *table, if (!zone_sectors || !is_power_of_2(zone_sectors)) return -EINVAL; - if (!dm_table_matches_zone_sectors(table, zone_sectors)) { + if (dm_table_any_dev_attr(table, device_not_matches_zone_sectors, &zone_sectors)) { DMERR("%s: zone sectors is not consistent across all devices", dm_device_name(table->md)); return -EINVAL; @@ -1739,29 +1765,12 @@ static int device_dax_write_cache_enabled(struct dm_target *ti, return false; } -static int dm_table_supports_dax_write_cache(struct dm_table *t) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, - device_dax_write_cache_enabled, NULL)) - return true; - } - - return false; -} - -static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int device_is_rotational(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev); - return q && blk_queue_nonrot(q); + return q && !blk_queue_nonrot(q); } static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev, @@ -1772,43 +1781,26 @@ static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev, return q && !blk_queue_add_random(q); } -static int queue_supports_sg_merge(struct dm_target *ti, struct dm_dev *dev, - sector_t start, sector_t len, void *data) +static int queue_no_sg_merge(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) { struct request_queue *q = bdev_get_queue(dev->bdev); - return q && !test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags); -} - -static bool dm_table_all_devices_attribute(struct dm_table *t, - iterate_devices_callout_fn func) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (!ti->type->iterate_devices || - !ti->type->iterate_devices(ti, func, NULL)) - return false; - } - - return true; + return q && test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags); } -static int device_no_partial_completion(struct dm_target *ti, struct dm_dev *dev, +static int device_is_partial_completion(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { char b[BDEVNAME_SIZE]; /* For now, NVMe devices are the only devices of this class */ - return (strncmp(bdevname(dev->bdev, b), "nvme", 4) == 0); + return (strncmp(bdevname(dev->bdev, b), "nvme", 4) != 0); } static bool dm_table_does_not_support_partial_completion(struct dm_table *t) { - return dm_table_all_devices_attribute(t, device_no_partial_completion); + return !dm_table_any_dev_attr(t, device_is_partial_completion, NULL); } static int device_not_write_same_capable(struct dm_target *ti, struct dm_dev *dev, @@ -1935,27 +1927,6 @@ static int device_requires_stable_pages(struct dm_target *ti, return q && bdi_cap_stable_pages_required(q->backing_dev_info); } -/* - * If any underlying device requires stable pages, a table must require - * them as well. Only targets that support iterate_devices are considered: - * don't want error, zero, etc to require stable pages. - */ -static bool dm_table_requires_stable_pages(struct dm_table *t) -{ - struct dm_target *ti; - unsigned i; - - for (i = 0; i < dm_table_get_num_targets(t); i++) { - ti = dm_table_get_target(t, i); - - if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, device_requires_stable_pages, NULL)) - return true; - } - - return false; -} - void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, struct queue_limits *limits) { @@ -1992,24 +1963,24 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, else blk_queue_flag_clear(QUEUE_FLAG_DAX, q); - if (dm_table_supports_dax_write_cache(t)) + if (dm_table_any_dev_attr(t, device_dax_write_cache_enabled, NULL)) dax_write_cache(t->md->dax_dev, true); /* Ensure that all underlying devices are non-rotational. */ - if (dm_table_all_devices_attribute(t, device_is_nonrot)) - blk_queue_flag_set(QUEUE_FLAG_NONROT, q); - else + if (dm_table_any_dev_attr(t, device_is_rotational, NULL)) blk_queue_flag_clear(QUEUE_FLAG_NONROT, q); + else + blk_queue_flag_set(QUEUE_FLAG_NONROT, q); if (!dm_table_supports_write_same(t)) q->limits.max_write_same_sectors = 0; if (!dm_table_supports_write_zeroes(t)) q->limits.max_write_zeroes_sectors = 0; - if (dm_table_all_devices_attribute(t, queue_supports_sg_merge)) - blk_queue_flag_clear(QUEUE_FLAG_NO_SG_MERGE, q); - else + if (dm_table_any_dev_attr(t, queue_no_sg_merge, NULL)) blk_queue_flag_set(QUEUE_FLAG_NO_SG_MERGE, q); + else + blk_queue_flag_clear(QUEUE_FLAG_NO_SG_MERGE, q); dm_table_verify_integrity(t); @@ -2018,8 +1989,11 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, /* * Some devices don't use blk_integrity but still want stable pages * because they do their own checksumming. + * If any underlying device requires stable pages, a table must require + * them as well. Only targets that support iterate_devices are considered: + * don't want error, zero, etc to require stable pages. */ - if (dm_table_requires_stable_pages(t)) + if (dm_table_any_dev_attr(t, device_requires_stable_pages, NULL)) q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES; else q->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES; @@ -2030,7 +2004,8 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not * have it set. */ - if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random)) + if (blk_queue_add_random(q) && + dm_table_any_dev_attr(t, device_is_not_random, NULL)) blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q); /* io_pages is used for readahead */ diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index c7b1936052f6..eb577df22c00 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -34,7 +34,7 @@ #define DM_VERITY_OPT_IGN_ZEROES "ignore_zero_blocks" #define DM_VERITY_OPT_AT_MOST_ONCE "check_at_most_once" -#define DM_VERITY_OPTS_MAX (2 + DM_VERITY_OPTS_FEC) +#define DM_VERITY_OPTS_MAX (3 + DM_VERITY_OPTS_FEC) static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE; @@ -545,15 +545,6 @@ static int verity_verify_io(struct dm_verity_io *io) return 0; } -/* - * Skip verity work in response to I/O error when system is shutting down. - */ -static inline bool verity_is_system_shutting_down(void) -{ - return system_state == SYSTEM_HALT || system_state == SYSTEM_POWER_OFF - || system_state == SYSTEM_RESTART; -} - /* * End one "io" structure with a given error. */ @@ -582,7 +573,7 @@ static void verity_end_io(struct bio *bio) struct dm_verity_io *io = bio->bi_private; if (bio->bi_status && - (!verity_fec_is_enabled(io->v) || verity_is_system_shutting_down())) { + (!verity_fec_is_enabled(io->v) || verity_is_system_shutting_down())) { verity_finish_io(io, bio->bi_status); return; } diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index 776aaf5951e4..a1d4166864d0 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -318,7 +318,7 @@ static int persistent_memory_claim(struct dm_writecache *wc) #else static int persistent_memory_claim(struct dm_writecache *wc) { - BUG(); + return -EOPNOTSUPP; } #endif @@ -1883,7 +1883,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv) struct wc_memory_superblock s; static struct dm_arg _args[] = { - {0, 10, "Invalid number of feature args"}, + {0, 16, "Invalid number of feature args"}, }; as.argc = argc; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 777574013c31..3b6b2b8b7324 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -464,7 +464,6 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo) static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx, struct block_device **bdev) - __acquires(md->io_barrier) { struct dm_target *tgt; struct dm_table *map; @@ -498,7 +497,6 @@ static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx, } static void dm_unprepare_ioctl(struct mapped_device *md, int srcu_idx) - __releases(md->io_barrier) { dm_put_live_table(md, srcu_idx); } @@ -519,7 +517,7 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, * subset of the parent bdev; require extra privileges. */ if (!capable(CAP_SYS_RAWIO)) { - DMWARN_LIMIT( + DMDEBUG_LIMIT( "%s: sending ioctl %x to DM device without required privilege.", current->comm, cmd); r = -ENOIOCTLCMD; diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index 4522e87d9d68..107f36b9155f 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -669,9 +669,27 @@ static void recv_daemon(struct md_thread *thread) * Takes the lock on the TOKEN lock resource so no other * node can communicate while the operation is underway. */ -static int lock_token(struct md_cluster_info *cinfo, bool mddev_locked) +static int lock_token(struct md_cluster_info *cinfo) { - int error, set_bit = 0; + int error; + + error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX); + if (error) { + pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n", + __func__, __LINE__, error); + } else { + /* Lock the receive sequence */ + mutex_lock(&cinfo->recv_mutex); + } + return error; +} + +/* lock_comm() + * Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel. + */ +static int lock_comm(struct md_cluster_info *cinfo, bool mddev_locked) +{ + int rv, set_bit = 0; struct mddev *mddev = cinfo->mddev; /* @@ -682,34 +700,19 @@ static int lock_token(struct md_cluster_info *cinfo, bool mddev_locked) */ if (mddev_locked && !test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state)) { - error = test_and_set_bit_lock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, + rv = test_and_set_bit_lock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); - WARN_ON_ONCE(error); + WARN_ON_ONCE(rv); md_wakeup_thread(mddev->thread); set_bit = 1; } - error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX); - if (set_bit) - clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); - if (error) - pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n", - __func__, __LINE__, error); - - /* Lock the receive sequence */ - mutex_lock(&cinfo->recv_mutex); - return error; -} - -/* lock_comm() - * Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel. - */ -static int lock_comm(struct md_cluster_info *cinfo, bool mddev_locked) -{ wait_event(cinfo->wait, !test_and_set_bit(MD_CLUSTER_SEND_LOCK, &cinfo->state)); - - return lock_token(cinfo, mddev_locked); + rv = lock_token(cinfo); + if (set_bit) + clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); + return rv; } static void unlock_comm(struct md_cluster_info *cinfo) @@ -789,9 +792,11 @@ static int sendmsg(struct md_cluster_info *cinfo, struct cluster_msg *cmsg, { int ret; - lock_comm(cinfo, mddev_locked); - ret = __sendmsg(cinfo, cmsg); - unlock_comm(cinfo); + ret = lock_comm(cinfo, mddev_locked); + if (!ret) { + ret = __sendmsg(cinfo, cmsg); + unlock_comm(cinfo); + } return ret; } @@ -1063,7 +1068,7 @@ static int metadata_update_start(struct mddev *mddev) return 0; } - ret = lock_token(cinfo, 1); + ret = lock_token(cinfo); clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); return ret; } @@ -1181,7 +1186,10 @@ static void update_size(struct mddev *mddev, sector_t old_dev_sectors) int raid_slot = -1; md_update_sb(mddev, 1); - lock_comm(cinfo, 1); + if (lock_comm(cinfo, 1)) { + pr_err("%s: lock_comm failed\n", __func__); + return; + } memset(&cmsg, 0, sizeof(cmsg)); cmsg.type = cpu_to_le32(METADATA_UPDATED); @@ -1330,7 +1338,8 @@ static int add_new_disk(struct mddev *mddev, struct md_rdev *rdev) cmsg.type = cpu_to_le32(NEWDISK); memcpy(cmsg.uuid, uuid, 16); cmsg.raid_slot = cpu_to_le32(rdev->desc_nr); - lock_comm(cinfo, 1); + if (lock_comm(cinfo, 1)) + return -EAGAIN; ret = __sendmsg(cinfo, &cmsg); if (ret) { unlock_comm(cinfo); diff --git a/drivers/md/md.c b/drivers/md/md.c index a4e7e6c025d9..09f0d8e70b70 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -474,8 +474,10 @@ static void md_submit_flush_data(struct work_struct *ws) * could wait for this and below md_handle_request could wait for those * bios because of suspend check */ + spin_lock_irq(&mddev->lock); mddev->last_flush = mddev->start_flush; mddev->flush_bio = NULL; + spin_unlock_irq(&mddev->lock); wake_up(&mddev->sb_wait); if (bio->bi_iter.bi_size == 0) { @@ -6564,8 +6566,10 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev) goto busy; kick_rdev: - if (mddev_is_clustered(mddev)) - md_cluster_ops->remove_disk(mddev, rdev); + if (mddev_is_clustered(mddev)) { + if (md_cluster_ops->remove_disk(mddev, rdev)) + goto busy; + } md_kick_rdev_from_array(rdev); set_bit(MD_SB_CHANGE_DEVS, &mddev->sb_flags); @@ -6895,6 +6899,7 @@ static int update_raid_disks(struct mddev *mddev, int raid_disks) return -EINVAL; if (mddev->sync_thread || test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) || + test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) || mddev->reshape_position != MaxSector) return -EBUSY; @@ -7214,8 +7219,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, err = -EBUSY; goto out; } - WARN_ON_ONCE(test_bit(MD_CLOSING, &mddev->flags)); - set_bit(MD_CLOSING, &mddev->flags); + if (test_and_set_bit(MD_CLOSING, &mddev->flags)) { + mutex_unlock(&mddev->open_mutex); + err = -EBUSY; + goto out; + } did_set_md_closing = true; mutex_unlock(&mddev->open_mutex); sync_blockdev(bdev); @@ -9238,8 +9246,11 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev) } } - if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) - update_raid_disks(mddev, le32_to_cpu(sb->raid_disks)); + if (mddev->raid_disks != le32_to_cpu(sb->raid_disks)) { + ret = update_raid_disks(mddev, le32_to_cpu(sb->raid_disks)); + if (ret) + pr_warn("md: updating array disks failed. %d\n", ret); + } /* Finally set the event to be up to date */ mddev->events = le64_to_cpu(sb->events); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 02c5e390f89f..8e0f936b3e37 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1138,7 +1138,7 @@ static void raid10_read_request(struct mddev *mddev, struct bio *bio, struct md_rdev *err_rdev = NULL; gfp_t gfp = GFP_NOIO; - if (r10_bio->devs[slot].rdev) { + if (slot >= 0 && r10_bio->devs[slot].rdev) { /* * This is an error retry, but we cannot * safely dereference the rdev in the r10_bio, @@ -1547,6 +1547,7 @@ static void __make_request(struct mddev *mddev, struct bio *bio, int sectors) r10_bio->mddev = mddev; r10_bio->sector = bio->bi_iter.bi_sector; r10_bio->state = 0; + r10_bio->read_slot = -1; memset(r10_bio->devs, 0, sizeof(r10_bio->devs[0]) * conf->copies); if (bio_data_dir(bio) == READ) diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index 43cfd1dbda01..afca47b97c2a 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1180,12 +1180,15 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, rc = dvb_create_media_graph(&client->adapter, true); if (rc < 0) { pr_err("dvb_create_media_graph failed %d\n", rc); - goto client_error; + goto media_graph_error; } pr_info("DVB interface registered.\n"); return 0; +media_graph_error: + smsdvb_debugfs_release(client); + client_error: dvb_unregister_frontend(&client->frontend); diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c index 008a082cb8ad..dddc5ef50dd4 100644 --- a/drivers/media/i2c/max2175.c +++ b/drivers/media/i2c/max2175.c @@ -511,7 +511,7 @@ static void max2175_set_bbfilter(struct max2175 *ctx) } } -static bool max2175_set_csm_mode(struct max2175 *ctx, +static int max2175_set_csm_mode(struct max2175 *ctx, enum max2175_csm_mode new_mode) { int ret = max2175_poll_csm_ready(ctx); diff --git a/drivers/media/i2c/ov5670.c b/drivers/media/i2c/ov5670.c index 53dd30d96e69..62dfdcb6e0bd 100644 --- a/drivers/media/i2c/ov5670.c +++ b/drivers/media/i2c/ov5670.c @@ -2081,7 +2081,8 @@ static int ov5670_init_controls(struct ov5670 *ov5670) /* By default, V4L2_CID_PIXEL_RATE is read only */ ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops, - V4L2_CID_PIXEL_RATE, 0, + V4L2_CID_PIXEL_RATE, + link_freq_configs[0].pixel_rate, link_freq_configs[0].pixel_rate, 1, link_freq_configs[0].pixel_rate); diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c index fd5c52b21436..a1d738969d7b 100644 --- a/drivers/media/pci/cx23885/cx23885-core.c +++ b/drivers/media/pci/cx23885/cx23885-core.c @@ -2084,6 +2084,10 @@ static struct { * 0x1451 is PCI ID for the IOMMU found on Ryzen */ { PCI_VENDOR_ID_AMD, 0x1451 }, + /* According to sudo lspci -nn, + * 0x1423 is the PCI ID for the IOMMU found on Kaveri + */ + { PCI_VENDOR_ID_AMD, 0x1423 }, }; static bool cx23885_does_need_dma_reset(void) diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c index 2f0171134f7e..e04fe9f17b7a 100644 --- a/drivers/media/pci/cx25821/cx25821-core.c +++ b/drivers/media/pci/cx25821/cx25821-core.c @@ -986,8 +986,10 @@ int cx25821_riscmem_alloc(struct pci_dev *pci, __le32 *cpu; dma_addr_t dma = 0; - if (NULL != risc->cpu && risc->size < size) + if (risc->cpu && risc->size < size) { pci_free_consistent(pci, risc->size, risc->cpu, risc->dma); + risc->cpu = NULL; + } if (NULL == risc->cpu) { cpu = pci_zalloc_consistent(pci, size, &dma); if (NULL == cpu) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index ca1a4d8e972e..cdf4d07343a7 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -801,6 +801,7 @@ static void cio2_vb2_return_all_buffers(struct cio2_queue *q, atomic_dec(&q->bufs_queued); vb2_buffer_done(&q->bufs[i]->vbb.vb2_buf, state); + q->bufs[i] = NULL; } } } @@ -1245,29 +1246,15 @@ static int cio2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_format *fmt) { struct cio2_queue *q = container_of(sd, struct cio2_queue, subdev); - struct v4l2_subdev_format format; - int ret; - - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); - return 0; - } - if (fmt->pad == CIO2_PAD_SINK) { - format.which = V4L2_SUBDEV_FORMAT_ACTIVE; - ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, - &format); + mutex_lock(&q->subdev_lock); - if (ret) - return ret; - /* update colorspace etc */ - q->subdev_fmt.colorspace = format.format.colorspace; - q->subdev_fmt.ycbcr_enc = format.format.ycbcr_enc; - q->subdev_fmt.quantization = format.format.quantization; - q->subdev_fmt.xfer_func = format.format.xfer_func; - } + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + fmt->format = *v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + else + fmt->format = q->subdev_fmt; - fmt->format = q->subdev_fmt; + mutex_unlock(&q->subdev_lock); return 0; } @@ -1284,6 +1271,9 @@ static int cio2_subdev_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_format *fmt) { struct cio2_queue *q = container_of(sd, struct cio2_queue, subdev); + struct v4l2_mbus_framefmt *mbus; + u32 mbus_code = fmt->format.code; + unsigned int i; /* * Only allow setting sink pad format; @@ -1292,16 +1282,29 @@ static int cio2_subdev_set_fmt(struct v4l2_subdev *sd, if (fmt->pad == CIO2_PAD_SOURCE) return cio2_subdev_get_fmt(sd, cfg, fmt); - if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) { - *v4l2_subdev_get_try_format(sd, cfg, fmt->pad) = fmt->format; - } else { - /* It's the sink, allow changing frame size */ - q->subdev_fmt.width = fmt->format.width; - q->subdev_fmt.height = fmt->format.height; - q->subdev_fmt.code = fmt->format.code; - fmt->format = q->subdev_fmt; + if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) + mbus = v4l2_subdev_get_try_format(sd, cfg, fmt->pad); + else + mbus = &q->subdev_fmt; + + fmt->format.code = formats[0].mbus_code; + + for (i = 0; i < ARRAY_SIZE(formats); i++) { + if (formats[i].mbus_code == mbus_code) { + fmt->format.code = mbus_code; + break; + } } + fmt->format.width = min_t(u32, fmt->format.width, CIO2_IMAGE_MAX_WIDTH); + fmt->format.height = min_t(u32, fmt->format.height, + CIO2_IMAGE_MAX_LENGTH); + fmt->format.field = V4L2_FIELD_NONE; + + mutex_lock(&q->subdev_lock); + *mbus = fmt->format; + mutex_unlock(&q->subdev_lock); + return 0; } @@ -1549,6 +1552,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q) /* Initialize miscellaneous variables */ mutex_init(&q->lock); + mutex_init(&q->subdev_lock); /* Initialize formats to default values */ fmt = &q->subdev_fmt; @@ -1666,6 +1670,7 @@ static int cio2_queue_init(struct cio2_device *cio2, struct cio2_queue *q) fail_subdev_media_entity: cio2_fbpt_exit(q, &cio2->pci_dev->dev); fail_fbpt: + mutex_destroy(&q->subdev_lock); mutex_destroy(&q->lock); return r; @@ -1679,6 +1684,7 @@ static void cio2_queue_exit(struct cio2_device *cio2, struct cio2_queue *q) v4l2_device_unregister_subdev(&q->subdev); media_entity_cleanup(&q->subdev.entity); cio2_fbpt_exit(q, &cio2->pci_dev->dev); + mutex_destroy(&q->subdev_lock); mutex_destroy(&q->lock); } diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.h b/drivers/media/pci/intel/ipu3/ipu3-cio2.h index 240635be7a31..b73c016d8a1b 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.h +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.h @@ -334,6 +334,7 @@ struct cio2_queue { /* Subdev, /dev/v4l-subdevX */ struct v4l2_subdev subdev; + struct mutex subdev_lock; /* Serialise acces to subdev_fmt field */ struct media_pad subdev_pads[CIO2_PADS]; struct v4l2_mbus_framefmt subdev_fmt; atomic_t frame_sequence; diff --git a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c index f33c0de3e849..019bbc18cede 100644 --- a/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c +++ b/drivers/media/pci/netup_unidvb/netup_unidvb_spi.c @@ -184,7 +184,7 @@ int netup_spi_init(struct netup_unidvb_dev *ndev) struct spi_master *master; struct netup_spi *nspi; - master = spi_alloc_master(&ndev->pci_dev->dev, + master = devm_spi_alloc_master(&ndev->pci_dev->dev, sizeof(struct netup_spi)); if (!master) { dev_err(&ndev->pci_dev->dev, @@ -217,6 +217,7 @@ int netup_spi_init(struct netup_unidvb_dev *ndev) ndev->pci_slot, ndev->pci_func); if (!spi_new_device(master, &netup_spi_board)) { + spi_unregister_master(master); ndev->spi = NULL; dev_err(&ndev->pci_dev->dev, "%s(): unable to create SPI device\n", __func__); @@ -235,13 +236,13 @@ void netup_spi_release(struct netup_unidvb_dev *ndev) if (!spi) return; + spi_unregister_master(spi->master); spin_lock_irqsave(&spi->lock, flags); reg = readw(&spi->regs->control_stat); writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat); reg = readw(&spi->regs->control_stat); writew(reg & ~NETUP_SPI_CTRL_IMASK, &spi->regs->control_stat); spin_unlock_irqrestore(&spi->lock, flags); - spi_unregister_master(spi->master); ndev->spi = NULL; } diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c index 66acfd35ffc6..8680eb08b654 100644 --- a/drivers/media/pci/saa7134/saa7134-empress.c +++ b/drivers/media/pci/saa7134/saa7134-empress.c @@ -293,8 +293,11 @@ static int empress_init(struct saa7134_dev *dev) q->lock = &dev->lock; q->dev = &dev->pci->dev; err = vb2_queue_init(q); - if (err) + if (err) { + video_device_release(dev->empress_dev); + dev->empress_dev = NULL; return err; + } dev->empress_dev->queue = q; video_set_drvdata(dev->empress_dev, dev); diff --git a/drivers/media/pci/saa7146/mxb.c b/drivers/media/pci/saa7146/mxb.c index 6b5582b7c595..6e25654da256 100644 --- a/drivers/media/pci/saa7146/mxb.c +++ b/drivers/media/pci/saa7146/mxb.c @@ -653,16 +653,17 @@ static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio * struct mxb *mxb = (struct mxb *)dev->ext_priv; DEB_D("VIDIOC_S_AUDIO %d\n", a->index); - if (mxb_inputs[mxb->cur_input].audioset & (1 << a->index)) { - if (mxb->cur_audinput != a->index) { - mxb->cur_audinput = a->index; - tea6420_route(mxb, a->index); - if (mxb->cur_audinput == 0) - mxb_update_audmode(mxb); - } - return 0; + if (a->index >= 32 || + !(mxb_inputs[mxb->cur_input].audioset & (1 << a->index))) + return -EINVAL; + + if (mxb->cur_audinput != a->index) { + mxb->cur_audinput = a->index; + tea6420_route(mxb, a->index); + if (mxb->cur_audinput == 0) + mxb_update_audmode(mxb); } - return -EINVAL; + return 0; } #ifdef CONFIG_VIDEO_ADV_DEBUG diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c b/drivers/media/pci/solo6x10/solo6x10-g723.c index 2ac33b5cc454..f06e6d35d846 100644 --- a/drivers/media/pci/solo6x10/solo6x10-g723.c +++ b/drivers/media/pci/solo6x10/solo6x10-g723.c @@ -410,7 +410,7 @@ int solo_g723_init(struct solo_dev *solo_dev) ret = snd_ctl_add(card, snd_ctl_new1(&kctl, solo_dev)); if (ret < 0) - return ret; + goto snd_error; ret = solo_snd_pcm_init(solo_dev); if (ret < 0) diff --git a/drivers/media/platform/msm/cvp/hfi_response_handler.c b/drivers/media/platform/msm/cvp/hfi_response_handler.c index e6ef20647100..a2a7435d9c12 100644 --- a/drivers/media/platform/msm/cvp/hfi_response_handler.c +++ b/drivers/media/platform/msm/cvp/hfi_response_handler.c @@ -491,7 +491,7 @@ static int hfi_process_session_cvp_msg(u32 device_id, } session_id = (void *)(uintptr_t)get_msg_session_id(pkt); core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list); - inst = cvp_get_inst_from_id(core, (unsigned int)session_id); + inst = cvp_get_inst_from_id(core, (uintptr_t)session_id); if (!inst) { dprintk(CVP_ERR, "%s: invalid session\n", __func__); diff --git a/drivers/media/platform/msm/cvp/msm_cvp_debug.c b/drivers/media/platform/msm/cvp/msm_cvp_debug.c index 2beee35ba585..651e0af1fbeb 100644 --- a/drivers/media/platform/msm/cvp/msm_cvp_debug.c +++ b/drivers/media/platform/msm/cvp/msm_cvp_debug.c @@ -9,7 +9,7 @@ #include "msm_cvp_common.h" #include "cvp_core_hfi.h" -int msm_cvp_debug = CVP_ERR | CVP_WARN | CVP_FW; +int msm_cvp_debug = CVP_ERR | CVP_WARN; EXPORT_SYMBOL(msm_cvp_debug); int msm_cvp_debug_out = CVP_OUT_PRINTK; diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c index 79ca03ac449c..3f64119e8c08 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c @@ -103,6 +103,7 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *mtkdev) void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev) { pm_runtime_disable(dev->pm.dev); + put_device(dev->pm.larbvdec); } void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) diff --git a/drivers/media/platform/mtk-vpu/mtk_vpu.c b/drivers/media/platform/mtk-vpu/mtk_vpu.c index f8d35e3ac1dc..ccfe5552db5c 100644 --- a/drivers/media/platform/mtk-vpu/mtk_vpu.c +++ b/drivers/media/platform/mtk-vpu/mtk_vpu.c @@ -856,7 +856,7 @@ static int mtk_vpu_probe(struct platform_device *pdev) /* Set PTCM to 96K and DTCM to 32K */ vpu_cfg_writel(vpu, 0x2, VPU_TCM_CFG); - vpu->enable_4GB = !!(totalram_pages > (SZ_2G >> PAGE_SHIFT)); + vpu->enable_4GB = !!(totalram_pages() > (SZ_2G >> PAGE_SHIFT)); dev_info(dev, "4GB mode %u\n", vpu->enable_4GB); if (vpu->enable_4GB) { diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c index 406ac673ad84..0281b8e53fef 100644 --- a/drivers/media/platform/pxa_camera.c +++ b/drivers/media/platform/pxa_camera.c @@ -1452,6 +1452,9 @@ static int pxac_vb2_prepare(struct vb2_buffer *vb) struct pxa_camera_dev *pcdev = vb2_get_drv_priv(vb->vb2_queue); struct pxa_buffer *buf = vb2_to_pxa_buffer(vb); int ret = 0; +#ifdef DEBUG + int i; +#endif switch (pcdev->channels) { case 1: diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index c9bb0d023db4..e81ebeb0506e 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -901,6 +901,7 @@ int msm_video_register(struct camss_video *video, struct v4l2_device *v4l2_dev, video->nformats = ARRAY_SIZE(formats_rdi_8x96); } } else { + ret = -EINVAL; goto error_video_register; } diff --git a/drivers/media/platform/vsp1/vsp1_drm.c b/drivers/media/platform/vsp1/vsp1_drm.c index 8d86f618ec77..8824c4ce67f1 100644 --- a/drivers/media/platform/vsp1/vsp1_drm.c +++ b/drivers/media/platform/vsp1/vsp1_drm.c @@ -243,7 +243,7 @@ static int vsp1_du_pipeline_setup_brx(struct vsp1_device *vsp1, brx = &vsp1->bru->entity; else if (pipe->brx && !drm_pipe->force_brx_release) brx = pipe->brx; - else if (!vsp1->bru->entity.pipe) + else if (vsp1_feature(vsp1, VSP1_HAS_BRU) && !vsp1->bru->entity.pipe) brx = &vsp1->bru->entity; else brx = &vsp1->brs->entity; @@ -460,9 +460,9 @@ static int vsp1_du_pipeline_setup_inputs(struct vsp1_device *vsp1, * make sure it is present in the pipeline's list of entities if it * wasn't already. */ - if (!use_uif) { + if (drm_pipe->uif && !use_uif) { drm_pipe->uif->pipe = NULL; - } else if (!drm_pipe->uif->pipe) { + } else if (drm_pipe->uif && !drm_pipe->uif->pipe) { drm_pipe->uif->pipe = pipe; list_add_tail(&drm_pipe->uif->list_pipe, &pipe->entities); } diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c index 4e6530ee809a..022f84569d0e 100644 --- a/drivers/media/platform/vsp1/vsp1_drv.c +++ b/drivers/media/platform/vsp1/vsp1_drv.c @@ -882,8 +882,10 @@ static int vsp1_probe(struct platform_device *pdev) } done: - if (ret) + if (ret) { pm_runtime_disable(&pdev->dev); + rcar_fcp_put(vsp1->fcp); + } return ret; } diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c index db429e0b9ca4..389398bd1df0 100644 --- a/drivers/media/radio/radio-iris-transport.c +++ b/drivers/media/radio/radio-iris-transport.c @@ -14,15 +14,19 @@ #include #include #include +#include #include -#include #include #include + + struct radio_data { struct radio_hci_dev *hdev; struct tasklet_struct rx_task; - struct smd_channel *fm_channel; + struct rpmsg_endpoint *fm_channel; + unsigned char *data; + int length; }; struct radio_data hs; DEFINE_MUTEX(fm_smd_enable); @@ -46,44 +50,29 @@ static void radio_hci_smd_recv_event(unsigned long temp) int rc; struct sk_buff *skb; unsigned char *buf; - struct radio_data *hsmd = &hs; - - len = smd_read_avail(hsmd->fm_channel); - - while (len) { - skb = alloc_skb(len, GFP_ATOMIC); - if (!skb) { - FMDERR("Memory not allocated for the socket\n"); - return; - } - - buf = kmalloc(len, GFP_ATOMIC); - if (!buf) { - kfree_skb(skb); - return; - } - - rc = smd_read(hsmd->fm_channel, (void *)buf, len); - - memcpy(skb_put(skb, len), buf, len); - - skb_orphan(skb); - skb->dev = (struct net_device *)hs.hdev; - - rc = radio_hci_recv_frame(skb); - - kfree(buf); - len = smd_read_avail(hsmd->fm_channel); + FMDBG("smd_recv event: is called\n"); + len = hs.length; + buf = hs.data; + skb = alloc_skb(len, GFP_ATOMIC); + if (!skb) { + FMDERR("Memory not allocated for the socket\n"); + return; } + + memcpy(skb_put(skb, len), buf, len); + skb_orphan(skb); + skb->dev = (struct net_device *)hs.hdev; + rc = radio_hci_recv_frame(skb); + kfree(buf); } static int radio_hci_smd_send_frame(struct sk_buff *skb) { int len = 0; + FMDBG("hci_send_frame: is called\n"); + FM_INFO("skb %pK\n", skb); - FMDBG("skb %pK\n", skb); - - len = smd_write(hs.fm_channel, skb->data, skb->len); + len = rpmsg_send(hs.fm_channel, skb->data, skb->len); if (len < skb->len) { FMDERR("Failed to write Data %d\n", len); kfree_skb(skb); @@ -118,107 +107,128 @@ static void send_disable_event(struct work_struct *worker) kfree(worker); } -static void radio_hci_smd_notify_cmd(void *data, unsigned int event) -{ - struct radio_hci_dev *hdev = (struct radio_hci_dev *)data; - - FMDBG("data %p event %u\n", data, event); - - if (!hdev) { - FMDERR("Frame for unknown HCI device (hdev=NULL)\n"); - return; - } - - switch (event) { - case SMD_EVENT_DATA: - tasklet_schedule(&hs.rx_task); - break; - case SMD_EVENT_OPEN: - break; - case SMD_EVENT_CLOSE: - reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC); - if (reset_worker) { - INIT_WORK(reset_worker, send_disable_event); - schedule_work(reset_worker); - } - break; - default: - break; - } -} - static int radio_hci_smd_register_dev(struct radio_data *hsmd) { struct radio_hci_dev *hdev; - int rc; - - FMDBG("hsmd: %pK\n", hsmd); - + FMDBG("smd_register event: is called\n"); if (hsmd == NULL) return -ENODEV; - hdev = kmalloc(sizeof(struct radio_hci_dev), GFP_KERNEL); if (hdev == NULL) return -ENODEV; tasklet_init(&hsmd->rx_task, radio_hci_smd_recv_event, - (unsigned long) hsmd); - hdev->send = radio_hci_smd_send_frame; + (unsigned long) hsmd); + hdev->send = radio_hci_smd_send_frame; hdev->destruct = radio_hci_smd_destruct; hdev->close_smd = radio_hci_smd_exit; - /* Open the SMD Channel and device and register the callback function */ - rc = smd_named_open_on_edge("APPS_FM", SMD_APPS_WCNSS, - &hsmd->fm_channel, hdev, radio_hci_smd_notify_cmd); - - if (rc < 0) { - FMDERR("Cannot open the command channel\n"); - hsmd->hdev = NULL; - kfree(hdev); - return -ENODEV; - } - - smd_disable_read_intr(hsmd->fm_channel); - if (radio_hci_register_dev(hdev) < 0) { FMDERR("Can't register HCI device\n"); - smd_close(hsmd->fm_channel); hsmd->hdev = NULL; kfree(hdev); return -ENODEV; } - hsmd->hdev = hdev; return 0; } static void radio_hci_smd_deregister(void) { + FM_INFO("smd_deregister: is called\n"); radio_hci_unregister_dev(); kfree(hs.hdev); hs.hdev = NULL; - - smd_close(hs.fm_channel); hs.fm_channel = 0; fmsmd_set = 0; } -static int radio_hci_smd_init(void) + +static int qcom_smd_fm_callback(struct rpmsg_device *rpdev, + void *data, int len, void *priv, u32 addr) +{ + FM_INFO("fm_callback: is called\n"); + if (!len) { + FMDERR("length received is NULL\n"); + return -EINVAL; + } + + hs.data = kmemdup((unsigned char *)data, len, GFP_ATOMIC); + if (!hs.data) { + FMDERR("Memory not allocated\n"); + return -ENOMEM; + } + + hs.length = len; + tasklet_schedule(&hs.rx_task); + return 0; +} + +static int qcom_smd_fm_probe(struct rpmsg_device *rpdev) { int ret; + FM_INFO("fm_probe: is called\n"); if (chan_opened) { FMDBG("Channel is already opened\n"); return 0; } - /* this should be called with fm_smd_enable lock held */ + hs.fm_channel = rpdev->ept; ret = radio_hci_smd_register_dev(&hs); if (ret < 0) { - FMDERR("Failed to register smd device\n"); + FMDERR("Failed to register with rpmsg device\n"); chan_opened = false; return ret; } + FMDBG("probe succeeded\n"); + chan_opened = true; + return ret; +} + +static void qcom_smd_fm_remove(struct rpmsg_device *rpdev) +{ + FM_INFO("fm_remove: is called\n"); + reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC); + if (reset_worker) { + INIT_WORK(reset_worker, send_disable_event); + schedule_work(reset_worker); + } +} + + +static const struct rpmsg_device_id qcom_smd_fm_match[] = { + { "APPS_FM" }, + {} +}; + + +static struct rpmsg_driver qcom_smd_fm_driver = { + .probe = qcom_smd_fm_probe, + .remove = qcom_smd_fm_remove, + .callback = qcom_smd_fm_callback, + .id_table = qcom_smd_fm_match, + .drv = { + .name = "qcom_smd_fm", + }, +}; + +static int radio_hci_smd_init(void) +{ + int ret = 0; + + FM_INFO("smd_init : is called\n"); + if (chan_opened) { + FMDBG("Channel is already opened\n"); + return 0; + } + + ret = register_rpmsg_driver(&qcom_smd_fm_driver); + if (ret < 0) { + FMDERR("%s: Failed to register with rpmsg\n", __func__); + return ret; + } + chan_opened = true; return ret; } @@ -232,6 +242,7 @@ static void radio_hci_smd_exit(void) /* this should be called with fm_smd_enable lock held */ radio_hci_smd_deregister(); + unregister_rpmsg_driver(&qcom_smd_fm_driver); chan_opened = false; } @@ -256,7 +267,11 @@ static int hcismd_fm_set_enable(const char *val, const struct kernel_param *kp) } done: mutex_unlock(&fm_smd_enable); + return ret; } + +MODULE_ALIAS("rpmsg:APPS_FM"); + MODULE_DESCRIPTION("FM SMD driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c index 8b97fd1f0cea..d9d6f7feb4bf 100644 --- a/drivers/media/rc/bpf-lirc.c +++ b/drivers/media/rc/bpf-lirc.c @@ -75,6 +75,8 @@ lirc_mode2_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_map_delete_elem_proto; case BPF_FUNC_ktime_get_ns: return &bpf_ktime_get_ns_proto; + case BPF_FUNC_ktime_get_boot_ns: + return &bpf_ktime_get_boot_ns_proto; case BPF_FUNC_tail_call: return &bpf_tail_call_proto; case BPF_FUNC_get_prandom_u32: diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c index f1dfb8409432..845583e2af4d 100644 --- a/drivers/media/rc/mceusb.c +++ b/drivers/media/rc/mceusb.c @@ -685,11 +685,18 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, u8 *buf, int buf_len, data[0], data[1]); break; case MCE_RSP_EQIRCFS: + if (!data[0] && !data[1]) { + dev_dbg(dev, "%s: no carrier", inout); + break; + } + // prescaler should make sense + if (data[0] > 8) + break; period = DIV_ROUND_CLOSEST((1U << data[0] * 2) * (data[1] + 1), 10); if (!period) break; - carrier = (1000 * 1000) / period; + carrier = USEC_PER_SEC / period; dev_dbg(dev, "%s carrier of %u Hz (period %uus)", inout, carrier, period); break; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index cf3df733d960..6ea6038b9d36 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -1875,6 +1875,8 @@ int rc_register_device(struct rc_dev *dev) goto out_raw; } + dev->registered = true; + rc = device_add(&dev->dev); if (rc) goto out_rx_free; @@ -1884,8 +1886,6 @@ int rc_register_device(struct rc_dev *dev) dev->device_name ?: "Unspecified device", path ?: "N/A"); kfree(path); - dev->registered = true; - /* * once the the input device is registered in rc_setup_rx_device, * userspace can open the input device and rc_open() will be called diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c index f500cea228a9..0114e81fa6fa 100644 --- a/drivers/media/rc/sunxi-cir.c +++ b/drivers/media/rc/sunxi-cir.c @@ -129,6 +129,8 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id) } else if (status & REG_RXINT_RPEI_EN) { ir_raw_event_set_idle(ir->rc, true); ir_raw_event_handle(ir->rc); + } else { + ir_raw_event_handle(ir->rc); } spin_unlock(&ir->ir_lock); diff --git a/drivers/media/tuners/qm1d1c0042.c b/drivers/media/tuners/qm1d1c0042.c index 83ca5dc047ea..baa9950783b6 100644 --- a/drivers/media/tuners/qm1d1c0042.c +++ b/drivers/media/tuners/qm1d1c0042.c @@ -343,8 +343,10 @@ static int qm1d1c0042_init(struct dvb_frontend *fe) if (val == reg_initval[reg_index][0x00]) break; } - if (reg_index >= QM1D1C0042_NUM_REG_ROWS) + if (reg_index >= QM1D1C0042_NUM_REG_ROWS) { + ret = -EINVAL; goto failed; + } memcpy(state->regs, reg_initval[reg_index], QM1D1C0042_NUM_REGS); usleep_range(2000, 3000); diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 0750a975bcb8..316edb2dd6c4 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -436,7 +436,7 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap) ep = usb_pipe_endpoint(d->udev, lme_int->lme_urb->pipe); if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK) - lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa), + lme_int->lme_urb->pipe = usb_rcvbulkpipe(d->udev, 0xa); lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; diff --git a/drivers/media/usb/dvb-usb/gp8psk.c b/drivers/media/usb/dvb-usb/gp8psk.c index 13e96b0aeb0f..d97eab01cb8c 100644 --- a/drivers/media/usb/dvb-usb/gp8psk.c +++ b/drivers/media/usb/dvb-usb/gp8psk.c @@ -185,7 +185,7 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) static int gp8psk_power_ctrl(struct dvb_usb_device *d, int onoff) { - u8 status, buf; + u8 status = 0, buf; int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); if (onoff) { diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c index 69445c8e38e2..d0f95a5cb4d2 100644 --- a/drivers/media/usb/em28xx/em28xx-core.c +++ b/drivers/media/usb/em28xx/em28xx-core.c @@ -955,14 +955,10 @@ int em28xx_alloc_urbs(struct em28xx *dev, enum em28xx_mode mode, int xfer_bulk, usb_bufs->buf[i] = kzalloc(sb_size, GFP_KERNEL); if (!usb_bufs->buf[i]) { - em28xx_uninit_usb_xfer(dev, mode); - for (i--; i >= 0; i--) kfree(usb_bufs->buf[i]); - kfree(usb_bufs->buf); - usb_bufs->buf = NULL; - + em28xx_uninit_usb_xfer(dev, mode); return -ENOMEM; } diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index c9a2b29a60a5..93212ed80bf8 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -1585,6 +1585,7 @@ int gspca_dev_probe2(struct usb_interface *intf, input_unregister_device(gspca_dev->input_dev); #endif v4l2_ctrl_handler_free(gspca_dev->vdev.ctrl_handler); + v4l2_device_unregister(&gspca_dev->v4l2_dev); kfree(gspca_dev->usb_buf); kfree(gspca_dev); return ret; diff --git a/drivers/media/usb/msi2500/msi2500.c b/drivers/media/usb/msi2500/msi2500.c index 65ef755adfdc..b2adde978c9b 100644 --- a/drivers/media/usb/msi2500/msi2500.c +++ b/drivers/media/usb/msi2500/msi2500.c @@ -1250,7 +1250,7 @@ static int msi2500_probe(struct usb_interface *intf, } dev->master = master; - master->bus_num = 0; + master->bus_num = -1; master->num_chipselect = 1; master->transfer_one_message = msi2500_transfer_one_message; spi_master_set_devdata(master, dev); diff --git a/drivers/media/usb/tm6000/tm6000-dvb.c b/drivers/media/usb/tm6000/tm6000-dvb.c index 3db2fd7f5d7c..e4f2160f46ff 100644 --- a/drivers/media/usb/tm6000/tm6000-dvb.c +++ b/drivers/media/usb/tm6000/tm6000-dvb.c @@ -149,6 +149,10 @@ static int tm6000_start_stream(struct tm6000_core *dev) if (ret < 0) { printk(KERN_ERR "tm6000: error %i in %s during pipe reset\n", ret, __func__); + + kfree(dvb->bulk_urb->transfer_buffer); + usb_free_urb(dvb->bulk_urb); + dvb->bulk_urb = NULL; return ret; } else printk(KERN_ERR "tm6000: pipe resetted\n"); diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index 96055de6e8ce..62f012841971 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c @@ -463,11 +463,12 @@ static int tm6000_alloc_urb_buffers(struct tm6000_core *dev) if (dev->urb_buffer) return 0; - dev->urb_buffer = kmalloc_array(num_bufs, sizeof(void *), GFP_KERNEL); + dev->urb_buffer = kmalloc_array(num_bufs, sizeof(*dev->urb_buffer), + GFP_KERNEL); if (!dev->urb_buffer) return -ENOMEM; - dev->urb_dma = kmalloc_array(num_bufs, sizeof(dma_addr_t *), + dev->urb_dma = kmalloc_array(num_bufs, sizeof(*dev->urb_dma), GFP_KERNEL); if (!dev->urb_dma) return -ENOMEM; diff --git a/drivers/media/usb/usbtv/usbtv-audio.c b/drivers/media/usb/usbtv/usbtv-audio.c index 4ce38246ed64..95657a7029c9 100644 --- a/drivers/media/usb/usbtv/usbtv-audio.c +++ b/drivers/media/usb/usbtv/usbtv-audio.c @@ -399,7 +399,7 @@ void usbtv_audio_free(struct usbtv *usbtv) cancel_work_sync(&usbtv->snd_trigger); if (usbtv->snd && usbtv->udev) { - snd_card_free(usbtv->snd); + snd_card_free_when_closed(usbtv->snd); usbtv->snd = NULL; } } diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 38c73cdbef70..998ce712978a 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -940,7 +940,10 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, unsigned int i; extra_size = roundup(extra_size, sizeof(*entity->pads)); - num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; + if (num_pads) + num_inputs = type & UVC_TERM_OUTPUT ? num_pads : num_pads - 1; + else + num_inputs = 0; size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads + num_inputs; entity = kzalloc(size, GFP_KERNEL); @@ -956,7 +959,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, for (i = 0; i < num_inputs; ++i) entity->pads[i].flags = MEDIA_PAD_FL_SINK; - if (!UVC_ENTITY_IS_OTERM(entity)) + if (!UVC_ENTITY_IS_OTERM(entity) && num_pads) entity->pads[num_pads-1].flags = MEDIA_PAD_FL_SOURCE; entity->bNrInPins = num_inputs; diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index 0921c95a1dca..06167c51af12 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c @@ -253,7 +253,9 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, goto done; /* After the probe, update fmt with the values returned from - * negotiation with the device. + * negotiation with the device. Some devices return invalid bFormatIndex + * and bFrameIndex values, in which case we can only assume they have + * accepted the requested format as-is. */ for (i = 0; i < stream->nformats; ++i) { if (probe->bFormatIndex == stream->format[i].index) { @@ -262,11 +264,10 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, } } - if (i == stream->nformats) { - uvc_trace(UVC_TRACE_FORMAT, "Unknown bFormatIndex %u\n", + if (i == stream->nformats) + uvc_trace(UVC_TRACE_FORMAT, + "Unknown bFormatIndex %u, using default\n", probe->bFormatIndex); - return -EINVAL; - } for (i = 0; i < format->nframes; ++i) { if (probe->bFrameIndex == format->frame[i].bFrameIndex) { @@ -275,11 +276,10 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream, } } - if (i == format->nframes) { - uvc_trace(UVC_TRACE_FORMAT, "Unknown bFrameIndex %u\n", + if (i == format->nframes) + uvc_trace(UVC_TRACE_FORMAT, + "Unknown bFrameIndex %u, using default\n", probe->bFrameIndex); - return -EINVAL; - } fmt->fmt.pix.width = frame->wWidth; fmt->fmt.pix.height = frame->wHeight; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 02f24e7ce891..dd2bbe1a3f55 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -3029,7 +3029,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func) { char sbuf[128]; - void *mbuf = NULL; + void *mbuf = NULL, *array_buf = NULL; void *parg = (void *)arg; long err = -EINVAL; bool has_array_args; @@ -3088,20 +3088,14 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, has_array_args = err; if (has_array_args) { - /* - * When adding new types of array args, make sure that the - * parent argument to ioctl (which contains the pointer to the - * array) fits into sbuf (so that mbuf will still remain - * unused up to here). - */ - mbuf = kvmalloc(array_size, GFP_KERNEL); + array_buf = kvmalloc(array_size, GFP_KERNEL); err = -ENOMEM; - if (NULL == mbuf) + if (array_buf == NULL) goto out_array_args; err = -EFAULT; - if (copy_from_user(mbuf, user_ptr, array_size)) + if (copy_from_user(array_buf, user_ptr, array_size)) goto out_array_args; - *kernel_ptr = mbuf; + *kernel_ptr = array_buf; } /* Handles IOCTL */ @@ -3120,7 +3114,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, if (has_array_args) { *kernel_ptr = (void __force *)user_ptr; - if (copy_to_user(user_ptr, mbuf, array_size)) + if (copy_to_user(user_ptr, array_buf, array_size)) err = -EFAULT; goto out_array_args; } @@ -3142,6 +3136,7 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, } out: + kvfree(array_buf); kvfree(mbuf); return err; } diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index 475e5b3790ed..be3d978648f5 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -381,8 +381,10 @@ static int aemif_probe(struct platform_device *pdev) */ for_each_available_child_of_node(np, child_np) { ret = of_aemif_parse_abus_config(pdev, child_np); - if (ret < 0) + if (ret < 0) { + of_node_put(child_np); goto error; + } } } else if (pdata && pdata->num_abus_data > 0) { for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) { @@ -408,8 +410,10 @@ static int aemif_probe(struct platform_device *pdev) for_each_available_child_of_node(np, child_np) { ret = of_platform_populate(child_np, NULL, dev_lookup, dev); - if (ret < 0) + if (ret < 0) { + of_node_put(child_np); goto error; + } } } else if (pdata) { for (i = 0; i < pdata->num_sub_devices; i++) { diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index b1564cacd19e..20ae8652adf4 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -469,7 +469,6 @@ static void memstick_check(struct work_struct *work) host->card = card; if (device_register(&card->dev)) { put_device(&card->dev); - kfree(host->card); host->card = NULL; } } else diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index 627d6e62fe31..4559593ecd5a 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -762,8 +762,10 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto error3; dev->mmio = pci_ioremap_bar(pdev, 0); - if (!dev->mmio) + if (!dev->mmio) { + error = -ENOMEM; goto error4; + } dev->irq = pdev->irq; spin_lock_init(&dev->irq_lock); @@ -789,12 +791,14 @@ static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id) &dev->dummy_dma_page_physical_address, GFP_KERNEL); r592_stop_dma(dev , 0); - if (request_irq(dev->irq, &r592_irq, IRQF_SHARED, - DRV_NAME, dev)) + error = request_irq(dev->irq, &r592_irq, IRQF_SHARED, + DRV_NAME, dev); + if (error) goto error6; r592_update_card_detect(dev); - if (memstick_add_host(host)) + error = memstick_add_host(host); + if (error) goto error7; message("driver successfully loaded"); diff --git a/drivers/mfd/bd9571mwv.c b/drivers/mfd/bd9571mwv.c index fab3cdc27ed6..19d57a45134c 100644 --- a/drivers/mfd/bd9571mwv.c +++ b/drivers/mfd/bd9571mwv.c @@ -185,9 +185,9 @@ static int bd9571mwv_probe(struct i2c_client *client, return ret; } - ret = mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, bd9571mwv_cells, - ARRAY_SIZE(bd9571mwv_cells), NULL, 0, - regmap_irq_get_domain(bd->irq_data)); + ret = devm_mfd_add_devices(bd->dev, PLATFORM_DEVID_AUTO, + bd9571mwv_cells, ARRAY_SIZE(bd9571mwv_cells), + NULL, 0, regmap_irq_get_domain(bd->irq_data)); if (ret) { regmap_del_irq_chip(bd->irq, bd->irq_data); return ret; diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c index 69df27769c21..3ba8cfa4b3b7 100644 --- a/drivers/mfd/sprd-sc27xx-spi.c +++ b/drivers/mfd/sprd-sc27xx-spi.c @@ -212,7 +212,7 @@ static int sprd_pmic_probe(struct spi_device *spi) } ret = devm_regmap_add_irq_chip(&spi->dev, ddata->regmap, ddata->irq, - IRQF_ONESHOT | IRQF_NO_SUSPEND, 0, + IRQF_ONESHOT, 0, &ddata->irq_chip, &ddata->irq_data); if (ret) { dev_err(&spi->dev, "Failed to add PMIC irq chip %d\n", ret); @@ -228,9 +228,34 @@ static int sprd_pmic_probe(struct spi_device *spi) return ret; } + device_init_wakeup(&spi->dev, true); return 0; } +#ifdef CONFIG_PM_SLEEP +static int sprd_pmic_suspend(struct device *dev) +{ + struct sprd_pmic *ddata = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(ddata->irq); + + return 0; +} + +static int sprd_pmic_resume(struct device *dev) +{ + struct sprd_pmic *ddata = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(ddata->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(sprd_pmic_pm_ops, sprd_pmic_suspend, sprd_pmic_resume); + static const struct of_device_id sprd_pmic_match[] = { { .compatible = "sprd,sc2731", .data = &sc2731_data }, {}, @@ -242,6 +267,7 @@ static struct spi_driver sprd_pmic_driver = { .name = "sc27xx-pmic", .bus = &spi_bus_type, .of_match_table = sprd_pmic_match, + .pm = &sprd_pmic_pm_ops, }, .probe = sprd_pmic_probe, }; diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c index fd789d2eb0f5..9f7ae1e1ebcd 100644 --- a/drivers/mfd/wm831x-auxadc.c +++ b/drivers/mfd/wm831x-auxadc.c @@ -98,11 +98,10 @@ static int wm831x_auxadc_read_irq(struct wm831x *wm831x, wait_for_completion_timeout(&req->done, msecs_to_jiffies(500)); mutex_lock(&wm831x->auxadc_lock); - - list_del(&req->list); ret = req->val; out: + list_del(&req->list); mutex_unlock(&wm831x->auxadc_lock); kfree(req); diff --git a/drivers/misc/aspeed-lpc-snoop.c b/drivers/misc/aspeed-lpc-snoop.c index c10be21a1663..b4a776bf44bc 100644 --- a/drivers/misc/aspeed-lpc-snoop.c +++ b/drivers/misc/aspeed-lpc-snoop.c @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -71,6 +72,7 @@ struct aspeed_lpc_snoop_channel { struct aspeed_lpc_snoop { struct regmap *regmap; int irq; + struct clk *clk; struct aspeed_lpc_snoop_channel chan[NUM_SNOOP_CHANNELS]; }; @@ -286,22 +288,42 @@ static int aspeed_lpc_snoop_probe(struct platform_device *pdev) return -ENODEV; } + lpc_snoop->clk = devm_clk_get(dev, NULL); + if (IS_ERR(lpc_snoop->clk)) { + rc = PTR_ERR(lpc_snoop->clk); + if (rc != -EPROBE_DEFER) + dev_err(dev, "couldn't get clock\n"); + return rc; + } + rc = clk_prepare_enable(lpc_snoop->clk); + if (rc) { + dev_err(dev, "couldn't enable clock\n"); + return rc; + } + rc = aspeed_lpc_snoop_config_irq(lpc_snoop, pdev); if (rc) - return rc; + goto err; rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 0, port); if (rc) - return rc; + goto err; /* Configuration of 2nd snoop channel port is optional */ if (of_property_read_u32_index(dev->of_node, "snoop-ports", 1, &port) == 0) { rc = aspeed_lpc_enable_snoop(lpc_snoop, dev, 1, port); - if (rc) + if (rc) { aspeed_lpc_disable_snoop(lpc_snoop, 0); + goto err; + } } + return 0; + +err: + clk_disable_unprepare(lpc_snoop->clk); + return rc; } @@ -313,6 +335,8 @@ static int aspeed_lpc_snoop_remove(struct platform_device *pdev) aspeed_lpc_disable_snoop(lpc_snoop, 0); aspeed_lpc_disable_snoop(lpc_snoop, 1); + clk_disable_unprepare(lpc_snoop->clk); + return 0; } diff --git a/drivers/misc/cardreader/rts5227.c b/drivers/misc/cardreader/rts5227.c index f0e845c8e6a7..d3ce9fe08eaf 100644 --- a/drivers/misc/cardreader/rts5227.c +++ b/drivers/misc/cardreader/rts5227.c @@ -339,6 +339,11 @@ static int rts522a_extra_init_hw(struct rtsx_pcr *pcr) { rts5227_extra_init_hw(pcr); + /* Power down OCP for power consumption */ + if (!pcr->card_exist) + rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, + OC_POWER_DOWN); + rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG, FUNC_FORCE_UPME_XMT_DBG); rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04); diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c index 38766968bfa2..182feab6da25 100644 --- a/drivers/misc/eeprom/eeprom_93xx46.c +++ b/drivers/misc/eeprom/eeprom_93xx46.c @@ -38,6 +38,10 @@ static const struct eeprom_93xx46_devtype_data atmel_at93c46d_data = { EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH, }; +static const struct eeprom_93xx46_devtype_data microchip_93lc46b_data = { + .quirks = EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE, +}; + struct eeprom_93xx46_dev { struct spi_device *spi; struct eeprom_93xx46_platform_data *pdata; @@ -58,6 +62,11 @@ static inline bool has_quirk_instruction_length(struct eeprom_93xx46_dev *edev) return edev->pdata->quirks & EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH; } +static inline bool has_quirk_extra_read_cycle(struct eeprom_93xx46_dev *edev) +{ + return edev->pdata->quirks & EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE; +} + static int eeprom_93xx46_read(void *priv, unsigned int off, void *val, size_t count) { @@ -99,6 +108,11 @@ static int eeprom_93xx46_read(void *priv, unsigned int off, dev_dbg(&edev->spi->dev, "read cmd 0x%x, %d Hz\n", cmd_addr, edev->spi->max_speed_hz); + if (has_quirk_extra_read_cycle(edev)) { + cmd_addr <<= 1; + bits += 1; + } + spi_message_init(&m); t[0].tx_buf = (char *)&cmd_addr; @@ -366,6 +380,7 @@ static void select_deassert(void *context) static const struct of_device_id eeprom_93xx46_of_table[] = { { .compatible = "eeprom-93xx46", }, { .compatible = "atmel,at93c46d", .data = &atmel_at93c46d_data, }, + { .compatible = "microchip,93lc46b", .data = µchip_93lc46b_data, }, {} }; MODULE_DEVICE_TABLE(of, eeprom_93xx46_of_table); @@ -523,3 +538,4 @@ MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Driver for 93xx46 EEPROMs"); MODULE_AUTHOR("Anatolij Gustschin "); MODULE_ALIAS("spi:93xx46"); +MODULE_ALIAS("spi:eeprom-93xx46"); diff --git a/drivers/misc/lkdtm/Makefile b/drivers/misc/lkdtm/Makefile index 939651b16ffa..02ce8ffe290c 100644 --- a/drivers/misc/lkdtm/Makefile +++ b/drivers/misc/lkdtm/Makefile @@ -14,7 +14,7 @@ CFLAGS_rodata.o += $(DISABLE_LTO) OBJCOPYFLAGS := OBJCOPYFLAGS_rodata_objcopy.o := \ - --rename-section .text=.rodata,alloc,readonly,load + --rename-section .noinstr.text=.rodata,alloc,readonly,load targets += rodata.o rodata_objcopy.o $(obj)/rodata_objcopy.o: $(obj)/rodata.o FORCE $(call if_changed,objcopy) diff --git a/drivers/misc/lkdtm/rodata.c b/drivers/misc/lkdtm/rodata.c index 58d180af72cf..baacb876d1d9 100644 --- a/drivers/misc/lkdtm/rodata.c +++ b/drivers/misc/lkdtm/rodata.c @@ -5,7 +5,7 @@ */ #include "lkdtm.h" -void notrace lkdtm_rodata_do_nothing(void) +void noinstr lkdtm_rodata_do_nothing(void) { /* Does nothing. We just want an architecture agnostic "return". */ } diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 64e318f589b4..0d23efcc74ff 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -138,11 +138,11 @@ static inline u8 mei_cl_me_id(const struct mei_cl *cl) * * @cl: host client * - * Return: mtu + * Return: mtu or 0 if client is not connected */ static inline size_t mei_cl_mtu(const struct mei_cl *cl) { - return cl->me_cl->props.max_msg_length; + return cl->me_cl ? cl->me_cl->props.max_msg_length : 0; } /** diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 92c3c16994ec..abdfbd72281b 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -3720,8 +3720,8 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data, (uint32_t)(__qseecom_uvirt_to_kphys( data, (uintptr_t)req->resp_buf)); } else { - send_data_req.req_ptr = (uint32_t)req->cmd_req_buf; - send_data_req.rsp_ptr = (uint32_t)req->resp_buf; + send_data_req.req_ptr = (uintptr_t)req->cmd_req_buf; + send_data_req.rsp_ptr = (uintptr_t)req->resp_buf; } send_data_req.req_len = req->cmd_req_len; @@ -4025,7 +4025,7 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, data->client.app_arch == ELFCLASS64)) || (data->type == QSEECOM_LISTENER_SERVICE)) { update = (struct qseecom_sg_entry *)field; - for (j = 0; j < sg_ptr->nents; j++) { + for_each_sg(sg, sg, sg_ptr->nents, j) { /* * Check if sg list PA is under 4GB */ @@ -4045,7 +4045,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup, update->len = cleanup ? 0 : sg->length; update++; len += sg->length; - sg = sg_next(sg); } } else { pr_err("QSEE app arch %u is not supported\n", @@ -4137,11 +4136,10 @@ static int __qseecom_allocate_sg_list_buffer(struct qseecom_dev_handle *data, buf_hdr->nents_total = sg_ptr->nents; /* save the left sg entries into new allocated buf */ sg_entry = (struct qseecom_sg_entry_64bit *)buf; - for (i = 0; i < sg_ptr->nents; i++) { + for_each_sg(sg, sg, sg_ptr->nents, i) { sg_entry->phys_addr = (uint64_t)sg_dma_address(sg); sg_entry->len = sg->length; sg_entry++; - sg = sg_next(sg); } data->client.sec_buf_fd[fd_idx].is_sec_buf_fd = true; @@ -4257,14 +4255,13 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup, goto err; /* 64bit app uses 64bit address */ update_64bit = (struct qseecom_sg_entry_64bit *)field; - for (j = 0; j < sg_ptr->nents; j++) { + for_each_sg(sg, sg, sg_ptr->nents, j) { update_64bit->phys_addr = cleanup ? 0 : (uint64_t)sg_dma_address(sg); update_64bit->len = cleanup ? 0 : (uint32_t)sg->length; update_64bit++; len += sg->length; - sg = sg_next(sg); } } cleanup: @@ -7037,11 +7034,10 @@ static int __qseecom_qteec_handle_pre_alc_fd(struct qseecom_dev_handle *data, } *(uint32_t *)buf = sg_ptr->nents; sg_entry = (struct qseecom_sg_entry *) (buf + sizeof(uint32_t)); - for (i = 0; i < sg_ptr->nents; i++) { + for_each_sg(sg, sg, sg_ptr->nents, i) { sg_entry->phys_addr = (uint32_t)sg_dma_address(sg); sg_entry->len = sg->length; sg_entry++; - sg = sg_next(sg); } data->client.sec_buf_fd[fd_idx].is_sec_buf_fd = true; data->client.sec_buf_fd[fd_idx].vbase = buf; diff --git a/drivers/misc/vmw_vmci/vmci_context.c b/drivers/misc/vmw_vmci/vmci_context.c index bc089e634a75..26e20b091160 100644 --- a/drivers/misc/vmw_vmci/vmci_context.c +++ b/drivers/misc/vmw_vmci/vmci_context.c @@ -751,7 +751,7 @@ static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context, return VMCI_ERROR_MORE_DATA; } - dbells = kmalloc(data_size, GFP_ATOMIC); + dbells = kzalloc(data_size, GFP_ATOMIC); if (!dbells) return VMCI_ERROR_NO_MEM; diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c index 5e0d1ac67f73..9bc97d6a651d 100644 --- a/drivers/misc/vmw_vmci/vmci_queue_pair.c +++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c @@ -552,6 +552,9 @@ static struct vmci_queue *qp_host_alloc_queue(u64 size) queue_page_size = num_pages * sizeof(*queue->kernel_if->u.h.page); + if (queue_size + queue_page_size > KMALLOC_MAX_SIZE) + return NULL; + queue = kzalloc(queue_size + queue_page_size, GFP_KERNEL); if (queue) { queue->q_header = NULL; @@ -645,7 +648,7 @@ static void qp_release_pages(struct page **pages, for (i = 0; i < num_pages; i++) { if (dirty) - set_page_dirty(pages[i]); + set_page_dirty_lock(pages[i]); put_page(pages[i]); pages[i] = NULL; diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index a33a78c0f655..449803228ed5 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -410,11 +410,6 @@ void mmc_remove_card(struct mmc_card *card) mmc_remove_card_debugfs(card); #endif - if (host->cqe_enabled) { - host->cqe_ops->cqe_disable(host); - host->cqe_enabled = false; - } - if (mmc_card_present(card)) { if (mmc_host_is_spi(card->host)) { pr_info("%s: SPI card removed\n", @@ -429,6 +424,10 @@ void mmc_remove_card(struct mmc_card *card) if (host->ops->exit_dbg_mode) host->ops->exit_dbg_mode(host); + if (host->cqe_enabled) { + host->cqe_ops->cqe_disable(host); + host->cqe_enabled = false; + } + put_device(&card->dev); } - diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index e6ad8e5319a6..242a5dbf4068 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -475,10 +475,6 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) /* EXT_CSD value is in units of 10ms, but we store in ms */ card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME]; - /* Some eMMC set the value too low so set a minimum */ - if (card->ext_csd.part_time && - card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME) - card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME; /* Sleep / awake timeout in 100ns units */ if (sa_shift > 0 && sa_shift <= 0x17) @@ -667,6 +663,17 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) card->ext_csd.data_sector_size = 512; } + /* + * GENERIC_CMD6_TIME is to be used "unless a specific timeout is defined + * when accessing a specific field", so use it here if there is no + * PARTITION_SWITCH_TIME. + */ + if (!card->ext_csd.part_time) + card->ext_csd.part_time = card->ext_csd.generic_cmd6_time; + /* Some eMMC set the value too low so set a minimum */ + if (card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME) + card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME; + /* eMMC v5 or later */ if (card->ext_csd.rev >= 7) { memcpy(card->ext_csd.fwrev, &ext_csd[EXT_CSD_FIRMWARE_VERSION], diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 75311efc954e..b2f46831863f 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c @@ -24,6 +24,8 @@ #include "sdio_cis.h" #include "sdio_ops.h" +#define SDIO_READ_CIS_TIMEOUT_MS (10 * 1000) /* 10s */ + static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, const unsigned char *buf, unsigned size) { @@ -271,6 +273,8 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) do { unsigned char tpl_code, tpl_link; + unsigned long timeout = jiffies + + msecs_to_jiffies(SDIO_READ_CIS_TIMEOUT_MS); ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code); if (ret) @@ -329,6 +333,8 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) prev = &this->next; if (ret == -ENOENT) { + if (time_after(jiffies, timeout)) + break; /* warn about unknown tuples */ pr_warn_ratelimited("%s: queuing unknown" " CIS tuple 0x%02x (%u bytes)\n", diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 9ecf86ba4bb0..967e47770af6 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -928,13 +928,13 @@ static void msdc_track_cmd_data(struct msdc_host *host, static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq) { unsigned long flags; - bool ret; - ret = cancel_delayed_work(&host->req_timeout); - if (!ret) { - /* delay work already running */ - return; - } + /* + * No need check the return value of cancel_delayed_work, as only ONE + * path will go here! + */ + cancel_delayed_work(&host->req_timeout); + spin_lock_irqsave(&host->lock, flags); host->mrq = NULL; spin_unlock_irqrestore(&host->lock, flags); @@ -952,7 +952,7 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, bool done = false; bool sbc_error; unsigned long flags; - u32 *rsp = cmd->resp; + u32 *rsp; if (mrq->sbc && cmd == mrq->cmd && (events & (MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR @@ -973,6 +973,7 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, if (done) return true; + rsp = cmd->resp; sdr_clr_bits(host->base + MSDC_INTEN, cmd_ints_mask); @@ -1154,7 +1155,7 @@ static void msdc_data_xfer_next(struct msdc_host *host, static bool msdc_data_xfer_done(struct msdc_host *host, u32 events, struct mmc_request *mrq, struct mmc_data *data) { - struct mmc_command *stop = data->stop; + struct mmc_command *stop; unsigned long flags; bool done; unsigned int check_data = events & @@ -1170,6 +1171,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events, if (done) return true; + stop = data->stop; if (check_data || (stop && stop->error)) { dev_dbg(host->dev, "DMA status: 0x%8X\n", diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index add1e70195ea..7125687faf76 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -659,7 +659,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) ret = mmc_of_parse(mmc); if (ret) - goto out_clk_disable; + goto out_free_dma; mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 61f0faddfd88..e8ab582551f8 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -764,6 +764,7 @@ int renesas_sdhi_remove(struct platform_device *pdev) tmio_mmc_host_remove(host); renesas_sdhi_clk_disable(host); + tmio_mmc_host_free(host); return 0; } diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index 74eea8247490..6e2685c9e9cb 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -180,8 +180,8 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host, mmc_get_dma_dir(data))) goto force_pio; - /* This DMAC cannot handle if buffer is not 8-bytes alignment */ - if (!IS_ALIGNED(sg_dma_address(sg), 8)) + /* This DMAC cannot handle if buffer is not 128-bytes alignment */ + if (!IS_ALIGNED(sg_dma_address(sg), 128)) goto force_pio_with_unmap; if (data->flags & MMC_DATA_READ) { diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index bd502f4f4704..5099353e6f13 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1370,9 +1370,10 @@ static int sdhci_esdhc_imx_remove(struct platform_device *pdev) struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = sdhci_pltfm_priv(pltfm_host); - int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); + int dead; pm_runtime_get_sync(&pdev->dev); + dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 1b7cd144fb01..a34b17b284a5 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -28,6 +28,7 @@ static const struct sdhci_ops sdhci_dwcmshc_ops = { static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .ops = &sdhci_dwcmshc_ops, .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; static int dwcmshc_probe(struct platform_device *pdev) diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index fafb02644efd..ca34fa424634 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -170,7 +170,12 @@ static void xenon_reset_exit(struct sdhci_host *host, /* Disable tuning request and auto-retuning again */ xenon_retune_setup(host); - xenon_set_acg(host, true); + /* + * The ACG should be turned off at the early init time, in order + * to solve a possible issues with the 1.8V regulator stabilization. + * The feature is enabled in later stage. + */ + xenon_set_acg(host, false); xenon_set_sdclk_off_idle(host, sdhc_id, false); diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index cdfeb15b6f05..ef3aa8b52078 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1866,10 +1866,12 @@ static int usdhi6_probe(struct platform_device *pdev) ret = mmc_add_host(mmc); if (ret < 0) - goto e_clk_off; + goto e_release_dma; return 0; +e_release_dma: + usdhi6_dma_release(host); e_clk_off: clk_disable_unprepare(host->clk); e_free_mmc: diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index c29205ee82e2..c24a26fbbffb 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c @@ -231,7 +231,7 @@ static int mtdpart_setup_real(char *s) struct cmdline_mtd_partition *this_mtd; struct mtd_partition *parts; int mtd_id_len, num_parts; - char *p, *mtd_id, *semicol; + char *p, *mtd_id, *semicol, *open_parenth; /* * Replace the first ';' by a NULL char so strrchr can work @@ -241,6 +241,14 @@ static int mtdpart_setup_real(char *s) if (semicol) *semicol = '\0'; + /* + * make sure that part-names with ":" will not be handled as + * part of the mtd-id with an ":" + */ + open_parenth = strchr(s, '('); + if (open_parenth) + *open_parenth = '\0'; + mtd_id = s; /* @@ -250,6 +258,10 @@ static int mtdpart_setup_real(char *s) */ p = strrchr(s, ':'); + /* Restore the '(' now. */ + if (open_parenth) + *open_parenth = '('; + /* Restore the ';' now. */ if (semicol) *semicol = ';'; diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index 9fcbcf4b217b..2726f1824233 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -1578,6 +1578,8 @@ static int check_flash_errors(struct qcom_nand_host *host, int cw_cnt) struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); int i; + nandc_read_buffer_sync(nandc, true); + for (i = 0; i < cw_cnt; i++) { u32 flash = le32_to_cpu(nandc->reg_read_buf[i]); diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index 04cedd3a2bf6..a92f531ad23a 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -473,7 +473,7 @@ static int cqspi_read_setup(struct spi_nor *nor) /* Setup dummy clock cycles */ dummy_clk = nor->read_dummy; if (dummy_clk > CQSPI_DUMMY_CLKS_MAX) - dummy_clk = CQSPI_DUMMY_CLKS_MAX; + return -EOPNOTSUPP; if (dummy_clk / 8) { reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB); diff --git a/drivers/mtd/spi-nor/hisi-sfc.c b/drivers/mtd/spi-nor/hisi-sfc.c index dea7b0c4b339..184ba5069ac5 100644 --- a/drivers/mtd/spi-nor/hisi-sfc.c +++ b/drivers/mtd/spi-nor/hisi-sfc.c @@ -408,8 +408,10 @@ static int hisi_spi_nor_register_all(struct hifmc_host *host) for_each_available_child_of_node(dev->of_node, np) { ret = hisi_spi_nor_register(np, host); - if (ret) + if (ret) { + of_node_put(np); goto fail; + } if (host->num_chip == HIFMC_MAX_CHIP_NUM) { dev_warn(dev, "Flash device number exceeds the maximum chipselect number\n"); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a59333b87eaf..c21c4291921f 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1268,7 +1268,39 @@ static void bond_upper_dev_unlink(struct bonding *bond, struct slave *slave) slave->dev->flags &= ~IFF_SLAVE; } -static struct slave *bond_alloc_slave(struct bonding *bond) +static void slave_kobj_release(struct kobject *kobj) +{ + struct slave *slave = to_slave(kobj); + struct bonding *bond = bond_get_bond_by_slave(slave); + + cancel_delayed_work_sync(&slave->notify_work); + if (BOND_MODE(bond) == BOND_MODE_8023AD) + kfree(SLAVE_AD_INFO(slave)); + + kfree(slave); +} + +static struct kobj_type slave_ktype = { + .release = slave_kobj_release, +#ifdef CONFIG_SYSFS + .sysfs_ops = &slave_sysfs_ops, +#endif +}; + +static int bond_kobj_init(struct slave *slave) +{ + int err; + + err = kobject_init_and_add(&slave->kobj, &slave_ktype, + &(slave->dev->dev.kobj), "bonding_slave"); + if (err) + kobject_put(&slave->kobj); + + return err; +} + +static struct slave *bond_alloc_slave(struct bonding *bond, + struct net_device *slave_dev) { struct slave *slave = NULL; @@ -1276,11 +1308,17 @@ static struct slave *bond_alloc_slave(struct bonding *bond) if (!slave) return NULL; + slave->bond = bond; + slave->dev = slave_dev; + + if (bond_kobj_init(slave)) + return NULL; + if (BOND_MODE(bond) == BOND_MODE_8023AD) { SLAVE_AD_INFO(slave) = kzalloc(sizeof(struct ad_slave_info), GFP_KERNEL); if (!SLAVE_AD_INFO(slave)) { - kfree(slave); + kobject_put(&slave->kobj); return NULL; } } @@ -1289,17 +1327,6 @@ static struct slave *bond_alloc_slave(struct bonding *bond) return slave; } -static void bond_free_slave(struct slave *slave) -{ - struct bonding *bond = bond_get_bond_by_slave(slave); - - cancel_delayed_work_sync(&slave->notify_work); - if (BOND_MODE(bond) == BOND_MODE_8023AD) - kfree(SLAVE_AD_INFO(slave)); - - kfree(slave); -} - static void bond_fill_ifbond(struct bonding *bond, struct ifbond *info) { info->bond_mode = BOND_MODE(bond); @@ -1487,14 +1514,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, bond->dev->addr_assign_type == NET_ADDR_RANDOM) bond_set_dev_addr(bond->dev, slave_dev); - new_slave = bond_alloc_slave(bond); + new_slave = bond_alloc_slave(bond, slave_dev); if (!new_slave) { res = -ENOMEM; goto err_undo_flags; } - new_slave->bond = bond; - new_slave->dev = slave_dev; /* Set the new_slave's queue_id to be zero. Queue ID mapping * is set via sysfs or module option if desired. */ @@ -1821,7 +1846,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, dev_set_mtu(slave_dev, new_slave->original_mtu); err_free: - bond_free_slave(new_slave); + kobject_put(&new_slave->kobj); err_undo_flags: /* Enslave of first slave has failed and we need to fix master's mac */ @@ -2009,7 +2034,7 @@ static int __bond_release_one(struct net_device *bond_dev, if (!netif_is_bond_master(slave_dev)) slave_dev->priv_flags &= ~IFF_BONDING; - bond_free_slave(slave); + kobject_put(&slave->kobj); return 0; } diff --git a/drivers/net/bonding/bond_sysfs_slave.c b/drivers/net/bonding/bond_sysfs_slave.c index 36dee305c687..9ec0498d7d54 100644 --- a/drivers/net/bonding/bond_sysfs_slave.c +++ b/drivers/net/bonding/bond_sysfs_slave.c @@ -125,7 +125,6 @@ static const struct slave_attribute *slave_attrs[] = { }; #define to_slave_attr(_at) container_of(_at, struct slave_attribute, attr) -#define to_slave(obj) container_of(obj, struct slave, kobj) static ssize_t slave_show(struct kobject *kobj, struct attribute *attr, char *buf) @@ -136,28 +135,15 @@ static ssize_t slave_show(struct kobject *kobj, return slave_attr->show(slave, buf); } -static const struct sysfs_ops slave_sysfs_ops = { +const struct sysfs_ops slave_sysfs_ops = { .show = slave_show, }; -static struct kobj_type slave_ktype = { -#ifdef CONFIG_SYSFS - .sysfs_ops = &slave_sysfs_ops, -#endif -}; - int bond_sysfs_slave_add(struct slave *slave) { const struct slave_attribute **a; int err; - err = kobject_init_and_add(&slave->kobj, &slave_ktype, - &(slave->dev->dev.kobj), "bonding_slave"); - if (err) { - kobject_put(&slave->kobj); - return err; - } - for (a = slave_attrs; *a; ++a) { err = sysfs_create_file(&slave->kobj, &((*a)->attr)); if (err) { @@ -175,6 +161,4 @@ void bond_sysfs_slave_del(struct slave *slave) for (a = slave_attrs; *a; ++a) sysfs_remove_file(&slave->kobj, &((*a)->attr)); - - kobject_put(&slave->kobj); } diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 24c6015f6c92..2278c5fff5c6 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -212,18 +212,6 @@ static const struct can_bittiming_const c_can_bittiming_const = { .brp_inc = 1, }; -static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_enable(priv->device); -} - -static inline void c_can_pm_runtime_disable(const struct c_can_priv *priv) -{ - if (priv->device) - pm_runtime_disable(priv->device); -} - static inline void c_can_pm_runtime_get_sync(const struct c_can_priv *priv) { if (priv->device) @@ -1318,7 +1306,6 @@ static const struct net_device_ops c_can_netdev_ops = { int register_c_can_dev(struct net_device *dev) { - struct c_can_priv *priv = netdev_priv(dev); int err; /* Deactivate pins to prevent DRA7 DCAN IP from being @@ -1328,28 +1315,19 @@ int register_c_can_dev(struct net_device *dev) */ pinctrl_pm_select_sleep_state(dev->dev.parent); - c_can_pm_runtime_enable(priv); - dev->flags |= IFF_ECHO; /* we support local echo */ dev->netdev_ops = &c_can_netdev_ops; err = register_candev(dev); - if (err) - c_can_pm_runtime_disable(priv); - else + if (!err) devm_can_led_init(dev); - return err; } EXPORT_SYMBOL_GPL(register_c_can_dev); void unregister_c_can_dev(struct net_device *dev) { - struct c_can_priv *priv = netdev_priv(dev); - unregister_candev(dev); - - c_can_pm_runtime_disable(priv); } EXPORT_SYMBOL_GPL(unregister_c_can_dev); diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c index 406b4847e5dc..7efb60b50876 100644 --- a/drivers/net/can/c_can/c_can_pci.c +++ b/drivers/net/can/c_can/c_can_pci.c @@ -239,12 +239,13 @@ static void c_can_pci_remove(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); struct c_can_priv *priv = netdev_priv(dev); + void __iomem *addr = priv->base; unregister_c_can_dev(dev); free_c_can_dev(dev); - pci_iounmap(pdev, priv->base); + pci_iounmap(pdev, addr); pci_disable_msi(pdev); pci_clear_master(pdev); pci_release_regions(pdev); diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index b5145a7f874c..f2b0408ce87d 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -385,6 +386,7 @@ static int c_can_plat_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); + pm_runtime_enable(priv->device); ret = register_c_can_dev(dev); if (ret) { dev_err(&pdev->dev, "registering %s failed (err=%d)\n", @@ -397,6 +399,7 @@ static int c_can_plat_probe(struct platform_device *pdev) return 0; exit_free_device: + pm_runtime_disable(priv->device); free_c_can_dev(dev); exit: dev_err(&pdev->dev, "probe failed\n"); @@ -407,9 +410,10 @@ static int c_can_plat_probe(struct platform_device *pdev) static int c_can_plat_remove(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); + struct c_can_priv *priv = netdev_priv(dev); unregister_c_can_dev(dev); - + pm_runtime_disable(priv->device); free_c_can_dev(dev); return 0; diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 1545f2b299d0..8738d37f7273 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -493,9 +493,13 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 */ struct sk_buff *skb = priv->echo_skb[idx]; struct canfd_frame *cf = (struct canfd_frame *)skb->data; - u8 len = cf->len; - *len_ptr = len; + /* get the real payload length for netdev statistics */ + if (cf->can_id & CAN_RTR_FLAG) + *len_ptr = 0; + else + *len_ptr = cf->len; + priv->echo_skb[idx] = NULL; return skb; @@ -520,7 +524,11 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx) if (!skb) return 0; - netif_rx(skb); + skb_get(skb); + if (netif_rx(skb) == NET_RX_SUCCESS) + dev_consume_skb_any(skb); + else + dev_kfree_skb_any(skb); return len; } @@ -571,11 +579,11 @@ static void can_restart(struct net_device *dev) } cf->can_id |= CAN_ERR_RESTARTED; - netif_rx(skb); - stats->rx_packets++; stats->rx_bytes += cf->can_dlc; + netif_rx_ni(skb); + restart: netdev_dbg(dev, "restarted\n"); priv->can_stats.restarts++; @@ -1134,7 +1142,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); struct can_ctrlmode cm = {.flags = priv->ctrlmode}; - struct can_berr_counter bec; + struct can_berr_counter bec = { }; enum can_state state = priv->state; if (priv->do_get_state) @@ -1227,6 +1235,7 @@ static void can_dellink(struct net_device *dev, struct list_head *head) static struct rtnl_link_ops can_link_ops __read_mostly = { .kind = "can", + .netns_refund = true, .maxtype = IFLA_CAN_MAX, .policy = can_policy, .setup = can_setup, diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 0be8db6ab319..d4dfa0247ebb 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -301,8 +301,7 @@ static const struct flexcan_devtype_data fsl_vf610_devtype_data = { static const struct flexcan_devtype_data fsl_ls1021a_r2_devtype_data = { .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | - FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_BROKEN_PERR_STATE | - FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, + FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, }; static const struct can_bittiming_const flexcan_bittiming_const = { @@ -423,11 +422,17 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) static int flexcan_chip_freeze(struct flexcan_priv *priv) { struct flexcan_regs __iomem *regs = priv->regs; - unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; + unsigned int timeout; + u32 bitrate = priv->can.bittiming.bitrate; u32 reg; + if (bitrate) + timeout = 1000 * 1000 * 10 / bitrate; + else + timeout = FLEXCAN_TIMEOUT_US / 10; + reg = priv->read(®s->mcr); - reg |= FLEXCAN_MCR_HALT; + reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT; priv->write(reg, ®s->mcr); while (timeout-- && !(priv->read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) @@ -1253,10 +1258,14 @@ static int register_flexcandev(struct net_device *dev) if (err) goto out_chip_disable; - /* set freeze, halt and activate FIFO, restrict register access */ + /* set freeze, halt */ + err = flexcan_chip_freeze(priv); + if (err) + goto out_chip_disable; + + /* activate FIFO, restrict register access */ reg = priv->read(®s->mcr); - reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | - FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; + reg |= FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; priv->write(reg, ®s->mcr); /* Currently we only support newer versions of this core diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index deb274a19ba0..e87c3bb82081 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -520,9 +520,6 @@ static int m_can_do_rx_poll(struct net_device *dev, int quota) } while ((rxfs & RXFS_FFL_MASK) && (quota > 0)) { - if (rxfs & RXFS_RFL) - netdev_warn(dev, "Rx FIFO 0 Message Lost\n"); - m_can_read_fifo(dev, rxfs); quota--; @@ -675,7 +672,7 @@ static int m_can_handle_state_change(struct net_device *dev, unsigned int ecr; switch (new_state) { - case CAN_STATE_ERROR_ACTIVE: + case CAN_STATE_ERROR_WARNING: /* error warning state */ priv->can.can_stats.error_warning++; priv->can.state = CAN_STATE_ERROR_WARNING; @@ -704,7 +701,7 @@ static int m_can_handle_state_change(struct net_device *dev, __m_can_get_berr_counter(dev, &bec); switch (new_state) { - case CAN_STATE_ERROR_ACTIVE: + case CAN_STATE_ERROR_WARNING: /* error warning state */ cf->can_id |= CAN_ERR_CRTL; cf->data[1] = (bec.txerr > bec.rxerr) ? @@ -976,7 +973,7 @@ static const struct can_bittiming_const m_can_bittiming_const_31X = { .name = KBUILD_MODNAME, .tseg1_min = 2, /* Time segment 1 = prop_seg + phase_seg1 */ .tseg1_max = 256, - .tseg2_min = 1, /* Time segment 2 = phase_seg2 */ + .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ .tseg2_max = 128, .sjw_max = 128, .brp_min = 1, diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c index 5696d7e80751..4bc5d522c74b 100644 --- a/drivers/net/can/peak_canfd/peak_canfd.c +++ b/drivers/net/can/peak_canfd/peak_canfd.c @@ -256,8 +256,7 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv, cf_len = get_can_dlc(pucan_msg_get_dlc(msg)); /* if this frame is an echo, */ - if ((rx_msg_flags & PUCAN_MSG_LOOPED_BACK) && - !(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE)) { + if (rx_msg_flags & PUCAN_MSG_LOOPED_BACK) { unsigned long flags; spin_lock_irqsave(&priv->echo_lock, flags); @@ -271,7 +270,13 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv, netif_wake_queue(priv->ndev); spin_unlock_irqrestore(&priv->echo_lock, flags); - return 0; + + /* if this frame is only an echo, stop here. Otherwise, + * continue to push this application self-received frame into + * its own rx queue. + */ + if (!(rx_msg_flags & PUCAN_MSG_SELF_RECEIVE)) + return 0; } /* otherwise, it should be pushed into rx fifo */ diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/rx-offload.c index 5f7e97d54733..5cf4171df1f4 100644 --- a/drivers/net/can/rx-offload.c +++ b/drivers/net/can/rx-offload.c @@ -281,7 +281,7 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload, if (skb_queue_len(&offload->skb_queue) > offload->skb_queue_len_max) { - kfree_skb(skb); + dev_kfree_skb_any(skb); return -ENOBUFS; } @@ -326,7 +326,7 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload, { if (skb_queue_len(&offload->skb_queue) > offload->skb_queue_len_max) { - kfree_skb(skb); + dev_kfree_skb_any(skb); return -ENOBUFS; } diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c index e22696190583..bed5ffa75b27 100644 --- a/drivers/net/can/softing/softing_main.c +++ b/drivers/net/can/softing/softing_main.c @@ -393,8 +393,13 @@ static int softing_netdev_open(struct net_device *ndev) /* check or determine and set bittime */ ret = open_candev(ndev); - if (!ret) - ret = softing_startstop(ndev, 1); + if (ret) + return ret; + + ret = softing_startstop(ndev, 1); + if (ret < 0) + close_candev(ndev); + return ret; } diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index db6ea936dc3f..81a3fdd5e010 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -903,7 +903,8 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->base)) { dev_err(&pdev->dev, "hecc ioremap failed\n"); - return PTR_ERR(priv->base); + err = PTR_ERR(priv->base); + goto probe_exit_candev; } /* handle hecc-ram memory */ @@ -916,7 +917,8 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->hecc_ram = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->hecc_ram)) { dev_err(&pdev->dev, "hecc-ram ioremap failed\n"); - return PTR_ERR(priv->hecc_ram); + err = PTR_ERR(priv->hecc_ram); + goto probe_exit_candev; } /* handle mbx memory */ @@ -929,13 +931,14 @@ static int ti_hecc_probe(struct platform_device *pdev) priv->mbx = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->mbx)) { dev_err(&pdev->dev, "mbx ioremap failed\n"); - return PTR_ERR(priv->mbx); + err = PTR_ERR(priv->mbx); + goto probe_exit_candev; } irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq) { dev_err(&pdev->dev, "No irq resource\n"); - goto probe_exit; + goto probe_exit_candev; } priv->ndev = ndev; @@ -988,7 +991,7 @@ static int ti_hecc_probe(struct platform_device *pdev) clk_put(priv->clk); probe_exit_candev: free_candev(ndev); -probe_exit: + return err; } diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index cc2e224661b3..6a57169c2715 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -71,21 +71,27 @@ enum gs_can_identify_mode { }; /* data types passed between host and device */ + +/* The firmware on the original USB2CAN by Geschwister Schneider + * Technologie Entwicklungs- und Vertriebs UG exchanges all data + * between the host and the device in host byte order. This is done + * with the struct gs_host_config::byte_order member, which is sent + * first to indicate the desired byte order. + * + * The widely used open source firmware candleLight doesn't support + * this feature and exchanges the data in little endian byte order. + */ struct gs_host_config { - u32 byte_order; + __le32 byte_order; } __packed; -/* All data exchanged between host and device is exchanged in host byte order, - * thanks to the struct gs_host_config byte_order member, which is sent first - * to indicate the desired byte order. - */ struct gs_device_config { u8 reserved1; u8 reserved2; u8 reserved3; u8 icount; - u32 sw_version; - u32 hw_version; + __le32 sw_version; + __le32 hw_version; } __packed; #define GS_CAN_MODE_NORMAL 0 @@ -95,26 +101,26 @@ struct gs_device_config { #define GS_CAN_MODE_ONE_SHOT BIT(3) struct gs_device_mode { - u32 mode; - u32 flags; + __le32 mode; + __le32 flags; } __packed; struct gs_device_state { - u32 state; - u32 rxerr; - u32 txerr; + __le32 state; + __le32 rxerr; + __le32 txerr; } __packed; struct gs_device_bittiming { - u32 prop_seg; - u32 phase_seg1; - u32 phase_seg2; - u32 sjw; - u32 brp; + __le32 prop_seg; + __le32 phase_seg1; + __le32 phase_seg2; + __le32 sjw; + __le32 brp; } __packed; struct gs_identify_mode { - u32 mode; + __le32 mode; } __packed; #define GS_CAN_FEATURE_LISTEN_ONLY BIT(0) @@ -125,23 +131,23 @@ struct gs_identify_mode { #define GS_CAN_FEATURE_IDENTIFY BIT(5) struct gs_device_bt_const { - u32 feature; - u32 fclk_can; - u32 tseg1_min; - u32 tseg1_max; - u32 tseg2_min; - u32 tseg2_max; - u32 sjw_max; - u32 brp_min; - u32 brp_max; - u32 brp_inc; + __le32 feature; + __le32 fclk_can; + __le32 tseg1_min; + __le32 tseg1_max; + __le32 tseg2_min; + __le32 tseg2_max; + __le32 sjw_max; + __le32 brp_min; + __le32 brp_max; + __le32 brp_inc; } __packed; #define GS_CAN_FLAG_OVERFLOW 1 struct gs_host_frame { u32 echo_id; - u32 can_id; + __le32 can_id; u8 can_dlc; u8 channel; @@ -337,13 +343,13 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) if (!skb) return; - cf->can_id = hf->can_id; + cf->can_id = le32_to_cpu(hf->can_id); cf->can_dlc = get_can_dlc(hf->can_dlc); memcpy(cf->data, hf->data, 8); /* ERROR frames tell us information about the controller */ - if (hf->can_id & CAN_ERR_FLAG) + if (le32_to_cpu(hf->can_id) & CAN_ERR_FLAG) gs_update_state(dev, cf); netdev->stats.rx_packets++; @@ -426,11 +432,11 @@ static int gs_usb_set_bittiming(struct net_device *netdev) if (!dbt) return -ENOMEM; - dbt->prop_seg = bt->prop_seg; - dbt->phase_seg1 = bt->phase_seg1; - dbt->phase_seg2 = bt->phase_seg2; - dbt->sjw = bt->sjw; - dbt->brp = bt->brp; + dbt->prop_seg = cpu_to_le32(bt->prop_seg); + dbt->phase_seg1 = cpu_to_le32(bt->phase_seg1); + dbt->phase_seg2 = cpu_to_le32(bt->phase_seg2); + dbt->sjw = cpu_to_le32(bt->sjw); + dbt->brp = cpu_to_le32(bt->brp); /* request bit timings */ rc = usb_control_msg(interface_to_usbdev(intf), @@ -511,7 +517,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, cf = (struct can_frame *)skb->data; - hf->can_id = cf->can_id; + hf->can_id = cpu_to_le32(cf->can_id); hf->can_dlc = cf->can_dlc; memcpy(hf->data, cf->data, cf->can_dlc); @@ -581,6 +587,7 @@ static int gs_can_open(struct net_device *netdev) int rc, i; struct gs_device_mode *dm; u32 ctrlmode; + u32 flags = 0; rc = open_candev(netdev); if (rc) @@ -648,24 +655,24 @@ static int gs_can_open(struct net_device *netdev) /* flags */ ctrlmode = dev->can.ctrlmode; - dm->flags = 0; if (ctrlmode & CAN_CTRLMODE_LOOPBACK) - dm->flags |= GS_CAN_MODE_LOOP_BACK; + flags |= GS_CAN_MODE_LOOP_BACK; else if (ctrlmode & CAN_CTRLMODE_LISTENONLY) - dm->flags |= GS_CAN_MODE_LISTEN_ONLY; + flags |= GS_CAN_MODE_LISTEN_ONLY; /* Controller is not allowed to retry TX * this mode is unavailable on atmels uc3c hardware */ if (ctrlmode & CAN_CTRLMODE_ONE_SHOT) - dm->flags |= GS_CAN_MODE_ONE_SHOT; + flags |= GS_CAN_MODE_ONE_SHOT; if (ctrlmode & CAN_CTRLMODE_3_SAMPLES) - dm->flags |= GS_CAN_MODE_TRIPLE_SAMPLE; + flags |= GS_CAN_MODE_TRIPLE_SAMPLE; /* finally start device */ - dm->mode = GS_CAN_MODE_START; + dm->mode = cpu_to_le32(GS_CAN_MODE_START); + dm->flags = cpu_to_le32(flags); rc = usb_control_msg(interface_to_usbdev(dev->iface), usb_sndctrlpipe(interface_to_usbdev(dev->iface), 0), GS_USB_BREQ_MODE, @@ -745,9 +752,9 @@ static int gs_usb_set_identify(struct net_device *netdev, bool do_identify) return -ENOMEM; if (do_identify) - imode->mode = GS_CAN_IDENTIFY_ON; + imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_ON); else - imode->mode = GS_CAN_IDENTIFY_OFF; + imode->mode = cpu_to_le32(GS_CAN_IDENTIFY_OFF); rc = usb_control_msg(interface_to_usbdev(dev->iface), usb_sndctrlpipe(interface_to_usbdev(dev->iface), @@ -798,6 +805,7 @@ static struct gs_can *gs_make_candev(unsigned int channel, struct net_device *netdev; int rc; struct gs_device_bt_const *bt_const; + u32 feature; bt_const = kmalloc(sizeof(*bt_const), GFP_KERNEL); if (!bt_const) @@ -838,14 +846,14 @@ static struct gs_can *gs_make_candev(unsigned int channel, /* dev settup */ strcpy(dev->bt_const.name, "gs_usb"); - dev->bt_const.tseg1_min = bt_const->tseg1_min; - dev->bt_const.tseg1_max = bt_const->tseg1_max; - dev->bt_const.tseg2_min = bt_const->tseg2_min; - dev->bt_const.tseg2_max = bt_const->tseg2_max; - dev->bt_const.sjw_max = bt_const->sjw_max; - dev->bt_const.brp_min = bt_const->brp_min; - dev->bt_const.brp_max = bt_const->brp_max; - dev->bt_const.brp_inc = bt_const->brp_inc; + dev->bt_const.tseg1_min = le32_to_cpu(bt_const->tseg1_min); + dev->bt_const.tseg1_max = le32_to_cpu(bt_const->tseg1_max); + dev->bt_const.tseg2_min = le32_to_cpu(bt_const->tseg2_min); + dev->bt_const.tseg2_max = le32_to_cpu(bt_const->tseg2_max); + dev->bt_const.sjw_max = le32_to_cpu(bt_const->sjw_max); + dev->bt_const.brp_min = le32_to_cpu(bt_const->brp_min); + dev->bt_const.brp_max = le32_to_cpu(bt_const->brp_max); + dev->bt_const.brp_inc = le32_to_cpu(bt_const->brp_inc); dev->udev = interface_to_usbdev(intf); dev->iface = intf; @@ -862,28 +870,29 @@ static struct gs_can *gs_make_candev(unsigned int channel, /* can settup */ dev->can.state = CAN_STATE_STOPPED; - dev->can.clock.freq = bt_const->fclk_can; + dev->can.clock.freq = le32_to_cpu(bt_const->fclk_can); dev->can.bittiming_const = &dev->bt_const; dev->can.do_set_bittiming = gs_usb_set_bittiming; dev->can.ctrlmode_supported = 0; - if (bt_const->feature & GS_CAN_FEATURE_LISTEN_ONLY) + feature = le32_to_cpu(bt_const->feature); + if (feature & GS_CAN_FEATURE_LISTEN_ONLY) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY; - if (bt_const->feature & GS_CAN_FEATURE_LOOP_BACK) + if (feature & GS_CAN_FEATURE_LOOP_BACK) dev->can.ctrlmode_supported |= CAN_CTRLMODE_LOOPBACK; - if (bt_const->feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) + if (feature & GS_CAN_FEATURE_TRIPLE_SAMPLE) dev->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES; - if (bt_const->feature & GS_CAN_FEATURE_ONE_SHOT) + if (feature & GS_CAN_FEATURE_ONE_SHOT) dev->can.ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT; SET_NETDEV_DEV(netdev, &intf->dev); - if (dconf->sw_version > 1) - if (bt_const->feature & GS_CAN_FEATURE_IDENTIFY) + if (le32_to_cpu(dconf->sw_version) > 1) + if (feature & GS_CAN_FEATURE_IDENTIFY) netdev->ethtool_ops = &gs_usb_ethtool_ops; kfree(bt_const); @@ -918,7 +927,7 @@ static int gs_usb_probe(struct usb_interface *intf, if (!hconf) return -ENOMEM; - hconf->byte_order = 0x0000beef; + hconf->byte_order = cpu_to_le32(0x0000beef); /* send host config */ rc = usb_control_msg(interface_to_usbdev(intf), diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index 7ab87a758754..218fadc91155 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -367,7 +367,7 @@ static const struct can_bittiming_const kvaser_usb_hydra_kcan_bittiming_c = { .tseg2_max = 32, .sjw_max = 16, .brp_min = 1, - .brp_max = 4096, + .brp_max = 8192, .brp_inc = 1, }; diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c index 1b0afeaf1a3c..896f5b022729 100644 --- a/drivers/net/can/usb/mcba_usb.c +++ b/drivers/net/can/usb/mcba_usb.c @@ -337,8 +337,6 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb, if (!ctx) return NETDEV_TX_BUSY; - can_put_echo_skb(skb, priv->netdev, ctx->ndx); - if (cf->can_id & CAN_EFF_FLAG) { /* SIDH | SIDL | EIDH | EIDL * 28 - 21 | 20 19 18 x x x 17 16 | 15 - 8 | 7 - 0 @@ -368,6 +366,8 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb, if (cf->can_id & CAN_RTR_FLAG) usb_msg.dlc |= MCBA_DLC_RTR_MASK; + can_put_echo_skb(skb, priv->netdev, ctx->ndx); + err = mcba_usb_xmit(priv, (struct mcba_usb_msg *)&usb_msg, ctx); if (err) goto xmit_failed; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index afc8d978124e..c235d1e6bc52 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -138,14 +138,55 @@ void peak_usb_get_ts_time(struct peak_time_ref *time_ref, u32 ts, ktime_t *time) /* protect from getting time before setting now */ if (ktime_to_ns(time_ref->tv_host)) { u64 delta_us; + s64 delta_ts = 0; + + /* General case: dev_ts_1 < dev_ts_2 < ts, with: + * + * - dev_ts_1 = previous sync timestamp + * - dev_ts_2 = last sync timestamp + * - ts = event timestamp + * - ts_period = known sync period (theoretical) + * ~ dev_ts2 - dev_ts1 + * *but*: + * + * - time counters wrap (see adapter->ts_used_bits) + * - sometimes, dev_ts_1 < ts < dev_ts2 + * + * "normal" case (sync time counters increase): + * must take into account case when ts wraps (tsw) + * + * < ts_period > < > + * | | | + * ---+--------+----+-------0-+--+--> + * ts_dev_1 | ts_dev_2 | + * ts tsw + */ + if (time_ref->ts_dev_1 < time_ref->ts_dev_2) { + /* case when event time (tsw) wraps */ + if (ts < time_ref->ts_dev_1) + delta_ts = BIT_ULL(time_ref->adapter->ts_used_bits); + + /* Otherwise, sync time counter (ts_dev_2) has wrapped: + * handle case when event time (tsn) hasn't. + * + * < ts_period > < > + * | | | + * ---+--------+--0-+---------+--+--> + * ts_dev_1 | ts_dev_2 | + * tsn ts + */ + } else if (time_ref->ts_dev_1 < ts) { + delta_ts = -BIT_ULL(time_ref->adapter->ts_used_bits); + } - delta_us = ts - time_ref->ts_dev_2; - if (ts < time_ref->ts_dev_2) - delta_us &= (1 << time_ref->adapter->ts_used_bits) - 1; + /* add delay between last sync and event timestamps */ + delta_ts += (signed int)(ts - time_ref->ts_dev_2); - delta_us += time_ref->ts_total; + /* add time from beginning to last sync */ + delta_ts += time_ref->ts_total; - delta_us *= time_ref->adapter->us_per_ts_scale; + /* convert ticks number into microseconds */ + delta_us = delta_ts * time_ref->adapter->us_per_ts_scale; delta_us >>= time_ref->adapter->us_per_ts_shift; *time = ktime_add_us(time_ref->tv_host_0, delta_us); @@ -823,7 +864,7 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, if (dev->adapter->dev_set_bus) { err = dev->adapter->dev_set_bus(dev, 0); if (err) - goto lbl_unregister_candev; + goto adap_dev_free; } /* get device number early */ @@ -835,6 +876,10 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, return 0; +adap_dev_free: + if (dev->adapter->dev_free) + dev->adapter->dev_free(dev); + lbl_unregister_candev: unregister_candev(netdev); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c index 41988358f63c..40ac37fe9dcd 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c @@ -476,12 +476,18 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) { struct pucan_rx_msg *rm = (struct pucan_rx_msg *)rx_msg; - struct peak_usb_device *dev = usb_if->dev[pucan_msg_get_channel(rm)]; - struct net_device *netdev = dev->netdev; + struct peak_usb_device *dev; + struct net_device *netdev; struct canfd_frame *cfd; struct sk_buff *skb; const u16 rx_msg_flags = le16_to_cpu(rm->flags); + if (pucan_msg_get_channel(rm) >= ARRAY_SIZE(usb_if->dev)) + return -ENOMEM; + + dev = usb_if->dev[pucan_msg_get_channel(rm)]; + netdev = dev->netdev; + if (rx_msg_flags & PUCAN_MSG_EXT_DATA_LEN) { /* CANFD frame case */ skb = alloc_canfd_skb(netdev, &cfd); @@ -514,11 +520,11 @@ static int pcan_usb_fd_decode_canmsg(struct pcan_usb_fd_if *usb_if, else memcpy(cfd->data, rm->d, cfd->len); - peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low)); - netdev->stats.rx_packets++; netdev->stats.rx_bytes += cfd->len; + peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(rm->ts_low)); + return 0; } @@ -527,15 +533,21 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) { struct pucan_status_msg *sm = (struct pucan_status_msg *)rx_msg; - struct peak_usb_device *dev = usb_if->dev[pucan_stmsg_get_channel(sm)]; - struct pcan_usb_fd_device *pdev = - container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_usb_fd_device *pdev; enum can_state new_state = CAN_STATE_ERROR_ACTIVE; enum can_state rx_state, tx_state; - struct net_device *netdev = dev->netdev; + struct peak_usb_device *dev; + struct net_device *netdev; struct can_frame *cf; struct sk_buff *skb; + if (pucan_stmsg_get_channel(sm) >= ARRAY_SIZE(usb_if->dev)) + return -ENOMEM; + + dev = usb_if->dev[pucan_stmsg_get_channel(sm)]; + pdev = container_of(dev, struct pcan_usb_fd_device, dev); + netdev = dev->netdev; + /* nothing should be sent while in BUS_OFF state */ if (dev->can.state == CAN_STATE_BUS_OFF) return 0; @@ -574,11 +586,11 @@ static int pcan_usb_fd_decode_status(struct pcan_usb_fd_if *usb_if, if (!skb) return -ENOMEM; - peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low)); - netdev->stats.rx_packets++; netdev->stats.rx_bytes += cf->can_dlc; + peak_usb_netif_rx(skb, &usb_if->time_ref, le32_to_cpu(sm->ts_low)); + return 0; } @@ -587,9 +599,14 @@ static int pcan_usb_fd_decode_error(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) { struct pucan_error_msg *er = (struct pucan_error_msg *)rx_msg; - struct peak_usb_device *dev = usb_if->dev[pucan_ermsg_get_channel(er)]; - struct pcan_usb_fd_device *pdev = - container_of(dev, struct pcan_usb_fd_device, dev); + struct pcan_usb_fd_device *pdev; + struct peak_usb_device *dev; + + if (pucan_ermsg_get_channel(er) >= ARRAY_SIZE(usb_if->dev)) + return -EINVAL; + + dev = usb_if->dev[pucan_ermsg_get_channel(er)]; + pdev = container_of(dev, struct pcan_usb_fd_device, dev); /* keep a trace of tx and rx error counters for later use */ pdev->bec.txerr = er->tx_err_cnt; @@ -603,11 +620,17 @@ static int pcan_usb_fd_decode_overrun(struct pcan_usb_fd_if *usb_if, struct pucan_msg *rx_msg) { struct pcan_ufd_ovr_msg *ov = (struct pcan_ufd_ovr_msg *)rx_msg; - struct peak_usb_device *dev = usb_if->dev[pufd_omsg_get_channel(ov)]; - struct net_device *netdev = dev->netdev; + struct peak_usb_device *dev; + struct net_device *netdev; struct can_frame *cf; struct sk_buff *skb; + if (pufd_omsg_get_channel(ov) >= ARRAY_SIZE(usb_if->dev)) + return -EINVAL; + + dev = usb_if->dev[pufd_omsg_get_channel(ov)]; + netdev = dev->netdev; + /* allocate an skb to store the error frame */ skb = alloc_can_err_skb(netdev, &cf); if (!skb) @@ -724,6 +747,9 @@ static int pcan_usb_fd_encode_msg(struct peak_usb_device *dev, u16 tx_msg_size, tx_msg_flags; u8 can_dlc; + if (cfd->len > CANFD_MAX_DLEN) + return -EINVAL; + tx_msg_size = ALIGN(sizeof(struct pucan_tx_msg) + cfd->len, 4); tx_msg->size = cpu_to_le16(tx_msg_size); tx_msg->type = cpu_to_le16(PUCAN_MSG_CAN_TX); diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c index ed6828821fbd..ccd758ba3fb0 100644 --- a/drivers/net/can/vxcan.c +++ b/drivers/net/can/vxcan.c @@ -49,6 +49,7 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev) struct net_device *peer; struct canfd_frame *cfd = (struct canfd_frame *)skb->data; struct net_device_stats *peerstats, *srcstats = &dev->stats; + u8 len; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; @@ -71,12 +72,13 @@ static netdev_tx_t vxcan_xmit(struct sk_buff *skb, struct net_device *dev) skb->dev = peer; skb->ip_summed = CHECKSUM_UNNECESSARY; + len = cfd->len; if (netif_rx_ni(skb) == NET_RX_SUCCESS) { srcstats->tx_packets++; - srcstats->tx_bytes += cfd->len; + srcstats->tx_bytes += len; peerstats = &peer->stats; peerstats->rx_packets++; - peerstats->rx_bytes += cfd->len; + peerstats->rx_bytes += len; } out_unlock: diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 294be86420b6..7eaeab65d39f 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -507,12 +507,27 @@ void b53_imp_vlan_setup(struct dsa_switch *ds, int cpu_port) } EXPORT_SYMBOL(b53_imp_vlan_setup); +static void b53_port_set_learning(struct b53_device *dev, int port, + bool learning) +{ + u16 reg; + + b53_read16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, ®); + if (learning) + reg &= ~BIT(port); + else + reg |= BIT(port); + b53_write16(dev, B53_CTRL_PAGE, B53_DIS_LEARNING, reg); +} + int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) { struct b53_device *dev = ds->priv; unsigned int cpu_port = ds->ports[port].cpu_dp->index; u16 pvlan; + b53_port_set_learning(dev, port, false); + /* Clear the Rx and Tx disable bits and set to no spanning tree */ b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), 0); @@ -620,6 +635,7 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port) b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl); b53_brcm_hdr_setup(dev->ds, port); + b53_port_set_learning(dev, port, false); } static void b53_enable_mib(struct b53_device *dev) @@ -1142,7 +1158,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port, if ((is5325(dev) || is5365(dev)) && vlan->vid_begin == 0) return -EOPNOTSUPP; - if (vlan->vid_end > dev->num_vlans) + if (vlan->vid_end >= dev->num_vlans) return -ERANGE; b53_enable_vlan(dev, true, dev->vlan_filtering_enabled); @@ -1517,6 +1533,8 @@ int b53_br_join(struct dsa_switch *ds, int port, struct net_device *br) b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan); dev->ports[port].vlan_ctl_mask = pvlan; + b53_port_set_learning(dev, port, true); + return 0; } EXPORT_SYMBOL(b53_br_join); @@ -1564,6 +1582,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br) vl->untag |= BIT(port) | BIT(cpu_port); b53_set_vlan_entry(dev, pvid, vl); } + b53_port_set_learning(dev, port, false); } EXPORT_SYMBOL(b53_br_leave); diff --git a/drivers/net/dsa/b53/b53_regs.h b/drivers/net/dsa/b53/b53_regs.h index c90985c294a2..b2c539a42154 100644 --- a/drivers/net/dsa/b53/b53_regs.h +++ b/drivers/net/dsa/b53/b53_regs.h @@ -115,6 +115,7 @@ #define B53_UC_FLOOD_MASK 0x32 #define B53_MC_FLOOD_MASK 0x34 #define B53_IPMC_FLOOD_MASK 0x36 +#define B53_DIS_LEARNING 0x3c /* * Override Ports 0-7 State on devices with xMII interfaces (8 bit) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index c0bba680d4a8..3deda0321c00 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -173,11 +173,6 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, reg &= ~P_TXQ_PSM_VDD(port); core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL); - /* Enable learning */ - reg = core_readl(priv, CORE_DIS_LEARN); - reg &= ~BIT(port); - core_writel(priv, reg, CORE_DIS_LEARN); - /* Enable Broadcom tags for that port if requested */ if (priv->brcm_tag_mask & BIT(port)) b53_brcm_hdr_setup(ds, port); @@ -423,15 +418,19 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds) /* Find our integrated MDIO bus node */ dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio"); priv->master_mii_bus = of_mdio_find_bus(dn); - if (!priv->master_mii_bus) + if (!priv->master_mii_bus) { + of_node_put(dn); return -EPROBE_DEFER; + } get_device(&priv->master_mii_bus->dev); priv->master_mii_dn = dn; priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev); - if (!priv->slave_mii_bus) + if (!priv->slave_mii_bus) { + of_node_put(dn); return -ENOMEM; + } priv->slave_mii_bus->priv = priv; priv->slave_mii_bus->name = "sf2 slave mii"; @@ -483,8 +482,10 @@ static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, int port) * in bits 15:8 and the patch level in bits 7:0 which is exactly what * the REG_PHY_REVISION register layout is. */ - - return priv->hw_params.gphy_rev; + if (priv->int_phy_mask & BIT(port)) + return priv->hw_params.gphy_rev; + else + return 0; } static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6fa8aa69b418..67c0ad3b8079 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1658,7 +1658,11 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, if (!entry.portvec) entry.state = MV88E6XXX_G1_ATU_DATA_STATE_UNUSED; } else { - entry.portvec |= BIT(port); + if (state == MV88E6XXX_G1_ATU_DATA_STATE_UC_STATIC) + entry.portvec = BIT(port); + else + entry.portvec |= BIT(port); + entry.state = state; } @@ -2630,10 +2634,17 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) return err; } +/* prod_id for switch families which do not have a PHY model number */ +static const u16 family_prod_id_table[] = { + [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, + [MV88E6XXX_FAMILY_6390] = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, +}; + static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg) { struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; struct mv88e6xxx_chip *chip = mdio_bus->chip; + u16 prod_id; u16 val; int err; @@ -2644,23 +2655,12 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg) err = chip->info->ops->phy_read(chip, bus, phy, reg, &val); mutex_unlock(&chip->reg_lock); - if (reg == MII_PHYSID2) { - /* Some internal PHYs don't have a model number. */ - if (chip->info->family != MV88E6XXX_FAMILY_6165) - /* Then there is the 6165 family. It gets is - * PHYs correct. But it can also have two - * SERDES interfaces in the PHY address - * space. And these don't have a model - * number. But they are not PHYs, so we don't - * want to give them something a PHY driver - * will recognise. - * - * Use the mv88e6390 family model number - * instead, for anything which really could be - * a PHY, - */ - if (!(val & 0x3f0)) - val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4; + /* Some internal PHYs don't have a model number. */ + if (reg == MII_PHYSID2 && !(val & 0x3f0) && + chip->info->family < ARRAY_SIZE(family_prod_id_table)) { + prod_id = family_prod_id_table[chip->info->family]; + if (prod_id) + val |= prod_id >> 4; } return err ? err : val; diff --git a/drivers/net/dsa/mv88e6xxx/global1_vtu.c b/drivers/net/dsa/mv88e6xxx/global1_vtu.c index 7a6667e0b9f9..e17158139aa8 100644 --- a/drivers/net/dsa/mv88e6xxx/global1_vtu.c +++ b/drivers/net/dsa/mv88e6xxx/global1_vtu.c @@ -127,11 +127,9 @@ static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip, * Offset 0x08: VTU/STU Data Register 2 * Offset 0x09: VTU/STU Data Register 3 */ - -static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip, - struct mv88e6xxx_vtu_entry *entry) +static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip, + u16 *regs) { - u16 regs[3]; int i; /* Read all 3 VTU/STU Data registers */ @@ -144,12 +142,45 @@ static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip, return err; } - /* Extract MemberTag and PortState data */ + return 0; +} + +static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_vtu_entry *entry) +{ + u16 regs[3]; + int err; + int i; + + err = mv88e6185_g1_vtu_stu_data_read(chip, regs); + if (err) + return err; + + /* Extract MemberTag data */ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { unsigned int member_offset = (i % 4) * 4; - unsigned int state_offset = member_offset + 2; entry->member[i] = (regs[i / 4] >> member_offset) & 0x3; + } + + return 0; +} + +static int mv88e6185_g1_stu_data_read(struct mv88e6xxx_chip *chip, + struct mv88e6xxx_vtu_entry *entry) +{ + u16 regs[3]; + int err; + int i; + + err = mv88e6185_g1_vtu_stu_data_read(chip, regs); + if (err) + return err; + + /* Extract PortState data */ + for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { + unsigned int state_offset = (i % 4) * 4 + 2; + entry->state[i] = (regs[i / 4] >> state_offset) & 0x3; } @@ -322,6 +353,10 @@ int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip, if (err) return err; + err = mv88e6185_g1_stu_data_read(chip, entry); + if (err) + return err; + /* VTU DBNum[3:0] are located in VTU Operation 3:0 * VTU DBNum[7:4] are located in VTU Operation 11:8 */ @@ -347,16 +382,20 @@ int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip, return err; if (entry->valid) { - /* Fetch (and mask) VLAN PortState data from the STU */ - err = mv88e6xxx_g1_vtu_stu_get(chip, entry); + err = mv88e6185_g1_vtu_data_read(chip, entry); if (err) return err; - err = mv88e6185_g1_vtu_data_read(chip, entry); + err = mv88e6xxx_g1_vtu_fid_read(chip, entry); if (err) return err; - err = mv88e6xxx_g1_vtu_fid_read(chip, entry); + /* Fetch VLAN PortState data from the STU */ + err = mv88e6xxx_g1_vtu_stu_get(chip, entry); + if (err) + return err; + + err = mv88e6185_g1_stu_data_read(chip, entry); if (err) return err; } diff --git a/drivers/net/ethernet/allwinner/sun4i-emac.c b/drivers/net/ethernet/allwinner/sun4i-emac.c index c458b81ba63a..d249a4309da2 100644 --- a/drivers/net/ethernet/allwinner/sun4i-emac.c +++ b/drivers/net/ethernet/allwinner/sun4i-emac.c @@ -847,13 +847,13 @@ static int emac_probe(struct platform_device *pdev) db->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(db->clk)) { ret = PTR_ERR(db->clk); - goto out_iounmap; + goto out_dispose_mapping; } ret = clk_prepare_enable(db->clk); if (ret) { dev_err(&pdev->dev, "Error couldn't enable clock (%d)\n", ret); - goto out_iounmap; + goto out_dispose_mapping; } ret = sunxi_sram_claim(&pdev->dev); @@ -910,6 +910,8 @@ static int emac_probe(struct platform_device *pdev) sunxi_sram_release(&pdev->dev); out_clk_disable_unprepare: clk_disable_unprepare(db->clk); +out_dispose_mapping: + irq_dispose_mapping(ndev->irq); out_iounmap: iounmap(db->membase); out: @@ -928,6 +930,7 @@ static int emac_remove(struct platform_device *pdev) unregister_netdev(ndev); sunxi_sram_release(&pdev->dev); clk_disable_unprepare(db->clk); + irq_dispose_mapping(ndev->irq); iounmap(db->membase); free_netdev(ndev); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 3c3222e2dcfc..9aea4cf19d0c 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -2433,16 +2433,9 @@ static int ena_device_init(struct ena_com_dev *ena_dev, struct pci_dev *pdev, goto err_mmio_read_less; } - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(dma_width)); + rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(dma_width)); if (rc) { - dev_err(dev, "pci_set_dma_mask failed 0x%x\n", rc); - goto err_mmio_read_less; - } - - rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(dma_width)); - if (rc) { - dev_err(dev, "err_pci_set_consistent_dma_mask failed 0x%x\n", - rc); + dev_err(dev, "dma_set_mask_and_coherent failed %d\n", rc); goto err_mmio_read_less; } @@ -3183,6 +3176,12 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; } + rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(ENA_MAX_PHYS_ADDR_SIZE_BITS)); + if (rc) { + dev_err(&pdev->dev, "dma_set_mask_and_coherent failed %d\n", rc); + goto err_disable_device; + } + pci_set_master(pdev); ena_dev = vzalloc(sizeof(*ena_dev)); diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index f5ad12c10934..da84660ceae1 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -1548,8 +1548,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) } pci_set_master(pdev); - ioaddr = pci_resource_start(pdev, 0); - if (!ioaddr) { + if (!pci_resource_len(pdev, 0)) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("card has no PCI IO resources, aborting\n"); err = -ENODEV; @@ -1562,6 +1561,8 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) pr_err("architecture does not support 32bit PCI busmaster DMA\n"); goto err_disable_dev; } + + ioaddr = pci_resource_start(pdev, 0); if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("io address range already allocated\n"); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index b40d4377cc71..b2cd3bdba9f8 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -1279,10 +1279,18 @@ #define MDIO_PMA_10GBR_FECCTRL 0x00ab #endif +#ifndef MDIO_PMA_RX_CTRL1 +#define MDIO_PMA_RX_CTRL1 0x8051 +#endif + #ifndef MDIO_PCS_DIG_CTRL #define MDIO_PCS_DIG_CTRL 0x8000 #endif +#ifndef MDIO_PCS_DIGITAL_STAT +#define MDIO_PCS_DIGITAL_STAT 0x8010 +#endif + #ifndef MDIO_AN_XNP #define MDIO_AN_XNP 0x0016 #endif @@ -1358,6 +1366,8 @@ #define XGBE_KR_TRAINING_ENABLE BIT(1) #define XGBE_PCS_CL37_BP BIT(12) +#define XGBE_PCS_PSEQ_STATE_MASK 0x1c +#define XGBE_PCS_PSEQ_STATE_POWER_GOOD 0x10 #define XGBE_AN_CL37_INT_CMPLT BIT(0) #define XGBE_AN_CL37_INT_MASK 0x01 @@ -1375,6 +1385,10 @@ #define XGBE_PMA_CDR_TRACK_EN_OFF 0x00 #define XGBE_PMA_CDR_TRACK_EN_ON 0x01 +#define XGBE_PMA_RX_RST_0_MASK BIT(4) +#define XGBE_PMA_RX_RST_0_RESET_ON 0x10 +#define XGBE_PMA_RX_RST_0_RESET_OFF 0x00 + /* Bit setting and getting macros * The get macro will extract the current bit field value from within * the variable diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 5519eff58441..80cf6af822f7 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1444,6 +1444,7 @@ static void xgbe_stop(struct xgbe_prv_data *pdata) return; netif_tx_stop_all_queues(netdev); + netif_carrier_off(pdata->netdev); xgbe_stop_timers(pdata); flush_workqueue(pdata->dev_workqueue); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 8a3a60bb2688..156a0bc8ab01 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -1345,7 +1345,7 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) &an_restart); if (an_restart) { xgbe_phy_config_aneg(pdata); - return; + goto adjust_link; } if (pdata->phy.link) { @@ -1396,7 +1396,6 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) pdata->phy_if.phy_impl.stop(pdata); pdata->phy.link = 0; - netif_carrier_off(pdata->netdev); xgbe_phy_adjust_link(pdata); } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 3ceb4f95ca7c..54753c8a6a9d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -912,6 +912,9 @@ static bool xgbe_phy_belfuse_phy_quirks(struct xgbe_prv_data *pdata) if ((phy_id & 0xfffffff0) != 0x03625d10) return false; + /* Reset PHY - wait for self-clearing reset bit to clear */ + genphy_soft_reset(phy_data->phydev); + /* Disable RGMII mode */ phy_write(phy_data->phydev, 0x18, 0x7007); reg = phy_read(phy_data->phydev, 0x18); @@ -1942,6 +1945,27 @@ static void xgbe_phy_set_redrv_mode(struct xgbe_prv_data *pdata) xgbe_phy_put_comm_ownership(pdata); } +static void xgbe_phy_rx_reset(struct xgbe_prv_data *pdata) +{ + int reg; + + reg = XMDIO_READ_BITS(pdata, MDIO_MMD_PCS, MDIO_PCS_DIGITAL_STAT, + XGBE_PCS_PSEQ_STATE_MASK); + if (reg == XGBE_PCS_PSEQ_STATE_POWER_GOOD) { + /* Mailbox command timed out, reset of RX block is required. + * This can be done by asseting the reset bit and wait for + * its compeletion. + */ + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_ON); + ndelay(20); + XMDIO_WRITE_BITS(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_RX_CTRL1, + XGBE_PMA_RX_RST_0_MASK, XGBE_PMA_RX_RST_0_RESET_OFF); + usleep_range(40, 50); + netif_err(pdata, link, pdata->netdev, "firmware mailbox reset performed\n"); + } +} + static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int cmd, unsigned int sub_cmd) { @@ -1949,9 +1973,11 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, unsigned int wait; /* Log if a previous command did not complete */ - if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) + if (XP_IOREAD_BITS(pdata, XP_DRIVER_INT_RO, STATUS)) { netif_dbg(pdata, link, pdata->netdev, "firmware mailbox not ready for command\n"); + xgbe_phy_rx_reset(pdata); + } /* Construct the command */ XP_SET_BITS(s0, XP_DRIVER_SCRATCH_0, COMMAND, cmd); @@ -1973,6 +1999,9 @@ static void xgbe_phy_perform_ratechange(struct xgbe_prv_data *pdata, netif_dbg(pdata, link, pdata->netdev, "firmware mailbox command did not complete\n"); + + /* Reset on error */ + xgbe_phy_rx_reset(pdata); } static void xgbe_phy_rrc(struct xgbe_prv_data *pdata) @@ -2569,6 +2598,14 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) if (reg & MDIO_STAT1_LSTATUS) return 1; + if (pdata->phy.autoneg == AUTONEG_ENABLE && + phy_data->port_mode == XGBE_PORT_MODE_BACKPLANE) { + if (!test_bit(XGBE_LINK_INIT, &pdata->dev_state)) { + netif_carrier_off(pdata->netdev); + *an_restart = 1; + } + } + /* No link, attempt a receiver reset cycle */ if (phy_data->rrc_count++ > XGBE_RRC_FREQUENCY) { phy_data->rrc_count = 0; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 47bcbcf58048..0c93a552b921 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -181,9 +181,9 @@ #define XGBE_DMA_SYS_AWCR 0x30303030 /* DMA cache settings - PCI device */ -#define XGBE_DMA_PCI_ARCR 0x00000003 -#define XGBE_DMA_PCI_AWCR 0x13131313 -#define XGBE_DMA_PCI_AWARCR 0x00000313 +#define XGBE_DMA_PCI_ARCR 0x000f0f0f +#define XGBE_DMA_PCI_AWCR 0x0f0f0f0f +#define XGBE_DMA_PCI_AWARCR 0x00000f0f /* DMA channel interrupt modes */ #define XGBE_IRQ_MODE_EDGE 0 diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c index e3ae29e523f0..daf841ae337d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c @@ -50,8 +50,10 @@ static int aq_ndev_open(struct net_device *ndev) if (err < 0) goto err_exit; err = aq_nic_start(aq_nic); - if (err < 0) + if (err < 0) { + aq_nic_stop(aq_nic); goto err_exit; + } err_exit: if (err < 0) diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index dd63b993ce7b..d83ad06bf199 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -1902,13 +1902,16 @@ static int alx_resume(struct device *dev) if (!netif_running(alx->dev)) return 0; - netif_device_attach(alx->dev); rtnl_lock(); err = __alx_open(alx, true); rtnl_unlock(); + if (err) + return err; - return err; + netif_device_attach(alx->dev); + + return 0; } static SIMPLE_DEV_PM_OPS(alx_pm_ops, alx_suspend, alx_resume); diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 88f8d31e4c83..7aeb2805fec4 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2389,7 +2389,8 @@ static int b44_init_one(struct ssb_device *sdev, goto err_out_free_dev; } - if (dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30))) { + err = dma_set_mask_and_coherent(sdev->dma_dev, DMA_BIT_MASK(30)); + if (err) { dev_err(sdev->dev, "Required 30BIT DMA mask unsupported by the system\n"); goto err_out_powerdown; diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 9a614c5cdfa2..0c69becc3c17 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2507,6 +2507,7 @@ static int bcm_sysport_probe(struct platform_device *pdev) /* HW supported features, none enabled by default */ dev->hw_features |= NETIF_F_RXCSUM | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + dev->max_mtu = UMAC_MAX_MTU_SIZE; /* Request the WOL interrupt and advertise suspend if available */ priv->wol_irq_disabled = 1; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 01d28ede1fb2..44ed2f6e2d96 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -6298,9 +6298,10 @@ void bnxt_tx_disable(struct bnxt *bp) txr->dev_state = BNXT_DEV_STATE_CLOSING; } } + /* Drop carrier first to prevent TX timeout */ + netif_carrier_off(bp->dev); /* Stop all TX queues */ netif_tx_disable(bp->dev); - netif_carrier_off(bp->dev); } void bnxt_tx_enable(struct bnxt *bp) @@ -8021,7 +8022,8 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev) if (dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)) != 0 && dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)) != 0) { dev_err(&pdev->dev, "System does not support DMA, aborting\n"); - goto init_err_disable; + rc = -EIO; + goto init_err_release; } pci_set_master(pdev); @@ -9120,6 +9122,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) create_singlethread_workqueue("bnxt_pf_wq"); if (!bnxt_pf_wq) { dev_err(&pdev->dev, "Unable to create workqueue.\n"); + rc = -ENOMEM; goto init_err_pci_clean; } } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 1ea81c23039f..511240e8246f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -2300,7 +2300,7 @@ static int bnxt_get_module_eeprom(struct net_device *dev, /* Read A2 portion of the EEPROM */ if (length) { start -= ETH_MODULE_SFF_8436_LEN; - rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 1, + rc = bnxt_read_sfp_module_eeprom_info(bp, I2C_DEV_ADDR_A2, 0, start, length, data); } return rc; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index c7667017c1a3..c3e824f5e50e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -3593,8 +3593,10 @@ static int bcmgenet_probe(struct platform_device *pdev) clk_disable_unprepare(priv->clk); err = register_netdev(dev); - if (err) + if (err) { + bcmgenet_mii_exit(dev); goto err; + } return err; diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h b/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h index b248966837b4..7aad40b2aa73 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h +++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h @@ -412,7 +412,7 @@ | CN6XXX_INTR_M0UNWI_ERR \ | CN6XXX_INTR_M1UPB0_ERR \ | CN6XXX_INTR_M1UPWI_ERR \ - | CN6XXX_INTR_M1UPB0_ERR \ + | CN6XXX_INTR_M1UNB0_ERR \ | CN6XXX_INTR_M1UNWI_ERR \ | CN6XXX_INTR_INSTR_DB_OF_ERR \ | CN6XXX_INTR_SLIST_DB_OF_ERR \ diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index 20b6e1b3f5e3..5c26d50fe0e9 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -3176,6 +3176,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports, GFP_KERNEL | __GFP_COMP); if (!avail) { CH_ALERT(adapter, "free list queue 0 initialization failed\n"); + ret = -ENOMEM; goto err; } if (avail < q->fl[0].size) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c index c91e155c147c..544c88f19f24 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c @@ -1400,11 +1400,25 @@ int cudbg_collect_sge_indirect(struct cudbg_init *pdbg_init, struct cudbg_buffer temp_buff = { 0 }; struct sge_qbase_reg_field *sge_qbase; struct ireg_buf *ch_sge_dbg; + u8 padap_running = 0; int i, rc; + u32 size; - rc = cudbg_get_buff(pdbg_init, dbg_buff, - sizeof(*ch_sge_dbg) * 2 + sizeof(*sge_qbase), - &temp_buff); + /* Accessing SGE_QBASE_MAP[0-3] and SGE_QBASE_INDEX regs can + * lead to SGE missing doorbells under heavy traffic. So, only + * collect them when adapter is idle. + */ + for_each_port(padap, i) { + padap_running = netif_running(padap->port[i]); + if (padap_running) + break; + } + + size = sizeof(*ch_sge_dbg) * 2; + if (!padap_running) + size += sizeof(*sge_qbase); + + rc = cudbg_get_buff(pdbg_init, dbg_buff, size, &temp_buff); if (rc) return rc; @@ -1426,7 +1440,8 @@ int cudbg_collect_sge_indirect(struct cudbg_init *pdbg_init, ch_sge_dbg++; } - if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5) { + if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5 && + !padap_running) { sge_qbase = (struct sge_qbase_reg_field *)ch_sge_dbg; /* 1 addr reg SGE_QBASE_INDEX and 4 data reg * SGE_QBASE_MAP[0-3] diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c index a62c96001761..9160b44c68bb 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c @@ -626,7 +626,8 @@ int set_filter_wr(struct adapter *adapter, int fidx) FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) | FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) | FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld)); - fwr->smac_sel = f->smt->idx; + if (f->fs.newsmac) + fwr->smac_sel = f->smt->idx; fwr->rx_chan_rx_rpl_iq = htons(FW_FILTER_WR_RX_CHAN_V(0) | FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id)); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h index de9ad311dacd..ea0758de8ac8 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h @@ -44,6 +44,9 @@ #define MAX_ULD_QSETS 16 +/* ulp_mem_io + ulptx_idata + payload + padding */ +#define MAX_IMM_ULPTX_WR_LEN (32 + 8 + 256 + 8) + /* CPL message priority levels */ enum { CPL_PRIORITY_DATA = 0, /* data messages */ diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 7801f2aeeb30..0a2d10a000ca 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -2084,17 +2084,22 @@ int t4_mgmt_tx(struct adapter *adap, struct sk_buff *skb) * @skb: the packet * * Returns true if a packet can be sent as an offload WR with immediate - * data. We currently use the same limit as for Ethernet packets. + * data. + * FW_OFLD_TX_DATA_WR limits the payload to 255 bytes due to 8-bit field. + * However, FW_ULPTX_WR commands have a 256 byte immediate only + * payload limit. */ static inline int is_ofld_imm(const struct sk_buff *skb) { struct work_request_hdr *req = (struct work_request_hdr *)skb->data; unsigned long opcode = FW_WR_OP_G(ntohl(req->wr_hi)); - if (opcode == FW_CRYPTO_LOOKASIDE_WR) + if (unlikely(opcode == FW_ULPTX_WR)) + return skb->len <= MAX_IMM_ULPTX_WR_LEN; + else if (opcode == FW_CRYPTO_LOOKASIDE_WR) return skb->len <= SGE_MAX_WR_LEN; else - return skb->len <= MAX_IMM_TX_PKT_LEN; + return skb->len <= MAX_IMM_OFLD_TX_DATA_WR_LEN; } /** diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index abc2a66754bd..812f4b743d97 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2093,7 +2093,8 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x1190, 0x1194, 0x11a0, 0x11a4, 0x11b0, 0x11b4, - 0x11fc, 0x1274, + 0x11fc, 0x123c, + 0x1254, 0x1274, 0x1280, 0x133c, 0x1800, 0x18fc, 0x3000, 0x302c, diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 50222b7b81f3..8b07890b0b23 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -143,6 +143,8 @@ struct board_info { u32 wake_state; int ip_summed; + + struct regulator *power_supply; }; /* debug code */ @@ -1460,7 +1462,7 @@ dm9000_probe(struct platform_device *pdev) if (ret) { dev_err(dev, "failed to request reset gpio %d: %d\n", reset_gpios, ret); - return -ENODEV; + goto out_regulator_disable; } /* According to manual PWRST# Low Period Min 1ms */ @@ -1472,14 +1474,18 @@ dm9000_probe(struct platform_device *pdev) if (!pdata) { pdata = dm9000_parse_dt(&pdev->dev); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto out_regulator_disable; + } } /* Init network device */ ndev = alloc_etherdev(sizeof(struct board_info)); - if (!ndev) - return -ENOMEM; + if (!ndev) { + ret = -ENOMEM; + goto out_regulator_disable; + } SET_NETDEV_DEV(ndev, &pdev->dev); @@ -1490,6 +1496,8 @@ dm9000_probe(struct platform_device *pdev) db->dev = &pdev->dev; db->ndev = ndev; + if (!IS_ERR(power)) + db->power_supply = power; spin_lock_init(&db->lock); mutex_init(&db->addr_lock); @@ -1716,6 +1724,10 @@ dm9000_probe(struct platform_device *pdev) dm9000_release_board(pdev, db); free_netdev(ndev); +out_regulator_disable: + if (!IS_ERR(power)) + regulator_disable(power); + return ret; } @@ -1775,10 +1787,13 @@ static int dm9000_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); + struct board_info *dm = to_dm9000_board(ndev); unregister_netdev(ndev); - dm9000_release_board(pdev, netdev_priv(ndev)); + dm9000_release_board(pdev, dm); free_netdev(ndev); /* free device structure */ + if (dm->power_supply) + regulator_disable(dm->power_supply); dev_dbg(&pdev->dev, "released and freed device\n"); return 0; diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c index 60da0499ad66..a2280c4be0f5 100644 --- a/drivers/net/ethernet/ethoc.c +++ b/drivers/net/ethernet/ethoc.c @@ -1213,7 +1213,7 @@ static int ethoc_probe(struct platform_device *pdev) ret = mdiobus_register(priv->mdio); if (ret) { dev_err(&netdev->dev, "failed to register MDIO bus\n"); - goto free2; + goto free3; } ret = ethoc_mdio_probe(netdev); @@ -1245,6 +1245,7 @@ static int ethoc_probe(struct platform_device *pdev) netif_napi_del(&priv->napi); error: mdiobus_unregister(priv->mdio); +free3: mdiobus_free(priv->mdio); free2: clk_disable_unprepare(priv->clk); diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index e4fc38cbe853..964407deca35 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -1333,6 +1333,7 @@ static int ftgmac100_poll(struct napi_struct *napi, int budget) */ if (unlikely(priv->need_mac_restart)) { ftgmac100_start_hw(priv); + priv->need_mac_restart = false; /* Re-enable "bad" interrupts */ iowrite32(FTGMAC100_INT_BAD, @@ -1884,6 +1885,8 @@ static int ftgmac100_probe(struct platform_device *pdev) return 0; err_ncsi_dev: + if (priv->ndev) + ncsi_unregister_dev(priv->ndev); err_register_netdev: ftgmac100_destroy_mdio(netdev); err_setup_mdio: @@ -1904,6 +1907,8 @@ static int ftgmac100_remove(struct platform_device *pdev) netdev = platform_get_drvdata(pdev); priv = netdev_priv(netdev); + if (priv->ndev) + ncsi_unregister_dev(priv->ndev); unregister_netdev(netdev); clk_disable_unprepare(priv->clk); diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 7e892b1cbd3d..09a762eb4f09 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -382,9 +382,16 @@ static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) u64 ns; unsigned long flags; + mutex_lock(&adapter->ptp_clk_mutex); + /* Check the ptp clock */ + if (!adapter->ptp_clk_on) { + mutex_unlock(&adapter->ptp_clk_mutex); + return -EINVAL; + } spin_lock_irqsave(&adapter->tmreg_lock, flags); ns = timecounter_read(&adapter->tc); spin_unlock_irqrestore(&adapter->tmreg_lock, flags); + mutex_unlock(&adapter->ptp_clk_mutex); *ts = ns_to_timespec64(ns); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c index c8e5d889bd81..21de56345503 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c @@ -223,3 +223,4 @@ static struct platform_driver fs_enet_bb_mdio_driver = { }; module_platform_driver(fs_enet_bb_mdio_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c index 1582d82483ec..4e6a9c5d8af5 100644 --- a/drivers/net/ethernet/freescale/fs_enet/mii-fec.c +++ b/drivers/net/ethernet/freescale/fs_enet/mii-fec.c @@ -224,3 +224,4 @@ static struct platform_driver fs_enet_fec_mdio_driver = { }; module_platform_driver(fs_enet_fec_mdio_driver); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 8db0924ec681..4feab06b7ad7 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -485,7 +485,11 @@ static struct net_device_stats *gfar_get_stats(struct net_device *dev) static int gfar_set_mac_addr(struct net_device *dev, void *p) { - eth_mac_addr(dev, p); + int ret; + + ret = eth_mac_addr(dev, p); + if (ret) + return ret; gfar_set_mac_for_addr(dev, 0, dev->dev_addr); @@ -2940,6 +2944,10 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus, if (lstatus & BD_LFLAG(RXBD_LAST)) size -= skb->len; + WARN(size < 0, "gianfar: rx fragment size underflow"); + if (size < 0) + return false; + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, rxb->page_offset + RXBUF_ALIGNMENT, size, GFAR_RXB_TRUESIZE); @@ -3101,6 +3109,17 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) if (lstatus & BD_LFLAG(RXBD_EMPTY)) break; + /* lost RXBD_LAST descriptor due to overrun */ + if (skb && + (lstatus & BD_LFLAG(RXBD_FIRST))) { + /* discard faulty buffer */ + dev_kfree_skb(skb); + skb = NULL; + rx_queue->stats.rx_dropped++; + + /* can continue normally */ + } + /* order rx buffer descriptor reads */ rmb(); diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index 5de6f7c73c1f..d43173917ce4 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -3902,6 +3902,7 @@ static int ucc_geth_probe(struct platform_device* ofdev) INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work); netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, 64); dev->mtu = 1500; + dev->max_mtu = 1518; ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT); ugeth->phy_interface = phy_interface; @@ -3947,12 +3948,12 @@ static int ucc_geth_remove(struct platform_device* ofdev) struct device_node *np = ofdev->dev.of_node; unregister_netdev(dev); - free_netdev(dev); ucc_geth_memclean(ugeth); if (of_phy_is_fixed_link(np)) of_phy_deregister_fixed_link(np); of_node_put(ugeth->ug_info->tbi_node); of_node_put(ugeth->ug_info->phy_node); + free_netdev(dev); return 0; } diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h index 5da19b440a6a..bf25e49d4fe3 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.h +++ b/drivers/net/ethernet/freescale/ucc_geth.h @@ -580,7 +580,14 @@ struct ucc_geth_tx_global_pram { u32 vtagtable[0x8]; /* 8 4-byte VLAN tags */ u32 tqptr; /* a base pointer to the Tx Queues Memory Region */ - u8 res2[0x80 - 0x74]; + u8 res2[0x78 - 0x74]; + u64 snums_en; + u32 l2l3baseptr; /* top byte consists of a few other bit fields */ + + u16 mtu[8]; + u8 res3[0xa8 - 0x94]; + u32 wrrtablebase; /* top byte is reserved */ + u8 res4[0xc0 - 0xac]; } __packed; /* structure representing Extended Filtering Global Parameters in PRAM */ diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 4de65a9de0a6..b7fe3e849872 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -1677,8 +1677,10 @@ static int hns_nic_clear_all_rx_fetch(struct net_device *ndev) for (j = 0; j < fetch_num; j++) { /* alloc one skb and init */ skb = hns_assemble_skb(ndev); - if (!skb) + if (!skb) { + ret = -ENOMEM; goto out; + } rd = &tx_ring_data(priv, skb->queue_mapping); hns_nic_net_xmit_hw(ndev, skb, rd); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 1fa0cd527ead..f453cebf758c 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -419,6 +419,10 @@ static void __lb_other_process(struct hns_nic_ring_data *ring_data, /* for mutl buffer*/ new_skb = skb_copy(skb, GFP_ATOMIC); dev_kfree_skb_any(skb); + if (!new_skb) { + netdev_err(ndev, "skb alloc failed\n"); + return; + } skb = new_skb; check_ok = 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h index be9dc08ccf67..4f56ffcdfc93 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h @@ -102,7 +102,7 @@ struct hclgevf_mbx_arq_ring { #define hclge_mbx_ring_ptr_move_crq(crq) \ (crq->next_to_use = (crq->next_to_use + 1) % crq->desc_num) #define hclge_mbx_tail_ptr_move_arq(arq) \ - (arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE) + (arq.tail = (arq.tail + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) #define hclge_mbx_head_ptr_move_arq(arq) \ - (arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_SIZE) + (arq.head = (arq.head + 1) % HCLGE_MBX_MAX_ARQ_MSG_NUM) #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d575dd9a329d..16ab000454f9 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -5182,12 +5182,19 @@ void hclge_reset_tqp(struct hnae3_handle *handle, u16 queue_id) void hclge_reset_vf_queue(struct hclge_vport *vport, u16 queue_id) { + struct hnae3_handle *handle = &vport->nic; struct hclge_dev *hdev = vport->back; int reset_try_times = 0; int reset_status; u16 queue_gid; int ret; + if (queue_id >= handle->kinfo.num_tqps) { + dev_warn(&hdev->pdev->dev, "Invalid vf queue id(%u)\n", + queue_id); + return; + } + queue_gid = hclge_covert_handle_qid_global(&vport->nic, queue_id); ret = hclge_send_reset_tqp_cmd(hdev, queue_gid, true); diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index d8115a9333e0..9f72cd3b1d24 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -212,8 +212,13 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter, if (!ltb->buff) return; + /* VIOS automatically unmaps the long term buffer at remote + * end for the following resets: + * FAILOVER, MOBILITY, TIMEOUT. + */ if (adapter->reset_reason != VNIC_RESET_FAILOVER && - adapter->reset_reason != VNIC_RESET_MOBILITY) + adapter->reset_reason != VNIC_RESET_MOBILITY && + adapter->reset_reason != VNIC_RESET_TIMEOUT) send_request_unmap(adapter, ltb->map_id); dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); } @@ -1087,19 +1092,13 @@ static int __ibmvnic_open(struct net_device *netdev) rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); if (rc) { - for (i = 0; i < adapter->req_rx_queues; i++) - napi_disable(&adapter->napi[i]); + ibmvnic_napi_disable(adapter); release_resources(adapter); return rc; } netif_tx_start_all_queues(netdev); - if (prev_state == VNIC_CLOSED) { - for (i = 0; i < adapter->req_rx_queues; i++) - napi_schedule(&adapter->napi[i]); - } - adapter->state = VNIC_OPEN; return rc; } @@ -1257,10 +1256,8 @@ static int __ibmvnic_close(struct net_device *netdev) adapter->state = VNIC_CLOSING; rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN); - if (rc) - return rc; adapter->state = VNIC_CLOSED; - return 0; + return rc; } static int ibmvnic_close(struct net_device *netdev) @@ -1523,6 +1520,9 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) skb_copy_from_linear_data(skb, dst, skb->len); } + /* post changes to long_term_buff *dst before VIOS accessing it */ + dma_wmb(); + tx_pool->consumer_index = (tx_pool->consumer_index + 1) % tx_pool->num_buffers; @@ -1755,7 +1755,7 @@ static int do_reset(struct ibmvnic_adapter *adapter, u64 old_num_rx_queues, old_num_tx_queues; u64 old_num_rx_slots, old_num_tx_slots; struct net_device *netdev = adapter->netdev; - int i, rc; + int rc; netdev_dbg(adapter->netdev, "Re-setting driver (%d)\n", rwi->reset_reason); @@ -1873,13 +1873,11 @@ static int do_reset(struct ibmvnic_adapter *adapter, /* refresh device's multicast list */ ibmvnic_set_multi(netdev); - /* kick napi */ - for (i = 0; i < adapter->req_rx_queues; i++) - napi_schedule(&adapter->napi[i]); - if (adapter->reset_reason != VNIC_RESET_FAILOVER && - adapter->reset_reason != VNIC_RESET_CHANGE_PARAM) + adapter->reset_reason != VNIC_RESET_CHANGE_PARAM) { call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, netdev); + call_netdevice_notifiers(NETDEV_RESEND_IGMP, netdev); + } netif_carrier_on(netdev); @@ -2156,6 +2154,12 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget) if (!pending_scrq(adapter, adapter->rx_scrq[scrq_num])) break; + /* The queue entry at the current index is peeked at above + * to determine that there is a valid descriptor awaiting + * processing. We want to be sure that the current slot + * holds a valid descriptor before reading its contents. + */ + dma_rmb(); next = ibmvnic_next_scrq(adapter, adapter->rx_scrq[scrq_num]); rx_buff = (struct ibmvnic_rx_buff *)be64_to_cpu(next-> @@ -2180,6 +2184,8 @@ static int ibmvnic_poll(struct napi_struct *napi, int budget) offset = be16_to_cpu(next->rx_comp.off_frame_data); flags = next->rx_comp.flags; skb = rx_buff->skb; + /* load long_term_buff before copying to skb */ + dma_rmb(); skb_copy_to_linear_data(skb, rx_buff->data + offset, length); @@ -2560,6 +2566,9 @@ static int reset_sub_crq_queues(struct ibmvnic_adapter *adapter) { int i, rc; + if (!adapter->tx_scrq || !adapter->rx_scrq) + return -EINVAL; + for (i = 0; i < adapter->req_tx_queues; i++) { netdev_dbg(adapter->netdev, "Re-setting tx_scrq[%d]\n", i); rc = reset_one_sub_crq_queue(adapter, adapter->tx_scrq[i]); @@ -2775,13 +2784,18 @@ static int ibmvnic_complete_tx(struct ibmvnic_adapter *adapter, unsigned int pool = scrq->pool_index; int num_entries = 0; + /* The queue entry at the current index is peeked at above + * to determine that there is a valid descriptor awaiting + * processing. We want to be sure that the current slot + * holds a valid descriptor before reading its contents. + */ + dma_rmb(); + next = ibmvnic_next_scrq(adapter, scrq); for (i = 0; i < next->tx_comp.num_comps; i++) { - if (next->tx_comp.rcs[i]) { + if (next->tx_comp.rcs[i]) dev_err(dev, "tx error %x\n", next->tx_comp.rcs[i]); - continue; - } index = be32_to_cpu(next->tx_comp.correlators[i]); if (index & IBMVNIC_TSO_POOL_MASK) { tx_pool = &adapter->tso_pool[pool]; @@ -3171,6 +3185,11 @@ static union sub_crq *ibmvnic_next_scrq(struct ibmvnic_adapter *adapter, } spin_unlock_irqrestore(&scrq->lock, flags); + /* Ensure that the entire buffer descriptor has been + * loaded before reading its contents + */ + dma_rmb(); + return entry; } @@ -4413,6 +4432,12 @@ static void ibmvnic_tasklet(void *data) while (!done) { /* Pull all the valid messages off the CRQ */ while ((crq = ibmvnic_next_crq(adapter)) != NULL) { + /* This barrier makes sure ibmvnic_next_crq()'s + * crq->generic.first & IBMVNIC_CRQ_CMD_RSP is loaded + * before ibmvnic_handle_crq()'s + * switch(gen_crq->first) and switch(gen_crq->cmd). + */ + dma_rmb(); ibmvnic_handle_crq(crq, adapter); crq->generic.first = 0; } @@ -4459,6 +4484,9 @@ static int ibmvnic_reset_crq(struct ibmvnic_adapter *adapter) } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); /* Clean out the queue */ + if (!crq->msgs) + return -EINVAL; + memset(crq->msgs, 0, PAGE_SIZE); crq->cur = 0; crq->active = false; diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index b9309302c29e..16653e94009e 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -899,6 +899,8 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) } else { data &= ~IGP02E1000_PM_D0_LPLU; ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); + if (ret_val) + return ret_val; /* LPLU and SmartSpeed are mutually exclusive. LPLU is used * during Dx states where the power conservation is most * important. During driver activity we should enable diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 7216825e049c..6bbe7afdf30c 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5922,15 +5922,19 @@ static void e1000_reset_task(struct work_struct *work) struct e1000_adapter *adapter; adapter = container_of(work, struct e1000_adapter, reset_task); + rtnl_lock(); /* don't run the task if already down */ - if (test_bit(__E1000_DOWN, &adapter->state)) + if (test_bit(__E1000_DOWN, &adapter->state)) { + rtnl_unlock(); return; + } if (!(adapter->flags & FLAG_RESTART_NOW)) { e1000e_dump(adapter); e_err("Reset adapter unexpectedly\n"); } e1000e_reinit_locked(adapter); + rtnl_unlock(); } /** diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index f84e2c2d02c0..3c921dfc2056 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -127,6 +127,7 @@ enum i40e_state_t { __I40E_RESET_INTR_RECEIVED, __I40E_REINIT_REQUESTED, __I40E_PF_RESET_REQUESTED, + __I40E_PF_RESET_AND_REBUILD_REQUESTED, __I40E_CORE_RESET_REQUESTED, __I40E_GLOBAL_RESET_REQUESTED, __I40E_EMP_RESET_REQUESTED, @@ -147,11 +148,15 @@ enum i40e_state_t { __I40E_CLIENT_SERVICE_REQUESTED, __I40E_CLIENT_L2_CHANGE, __I40E_CLIENT_RESET, + __I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */ + __I40E_VFS_RELEASING, /* This must be last as it determines the size of the BITMAP */ __I40E_STATE_SIZE__, }; #define I40E_PF_RESET_FLAG BIT_ULL(__I40E_PF_RESET_REQUESTED) +#define I40E_PF_RESET_AND_REBUILD_FLAG \ + BIT_ULL(__I40E_PF_RESET_AND_REBUILD_REQUESTED) /* VSI state flags */ enum i40e_vsi_state_t { diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index a6b0f605a7d8..9148d93c5c63 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -796,6 +796,7 @@ static int i40e_get_link_ksettings(struct net_device *netdev, /* Set flow control settings */ ethtool_link_ksettings_add_link_mode(ks, supported, Pause); + ethtool_link_ksettings_add_link_mode(ks, supported, Asym_Pause); switch (hw->fc.requested_mode) { case I40E_FC_FULL: diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 3200c75b9ed2..fa0e7582159f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -42,6 +42,8 @@ static int i40e_setup_misc_vector(struct i40e_pf *pf); static void i40e_determine_queue_usage(struct i40e_pf *pf); static int i40e_setup_pf_filter_control(struct i40e_pf *pf); static void i40e_prep_for_reset(struct i40e_pf *pf, bool lock_acquired); +static void i40e_reset_and_rebuild(struct i40e_pf *pf, bool reinit, + bool lock_acquired); static int i40e_reset(struct i40e_pf *pf); static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired); static void i40e_fdir_sb_setup(struct i40e_pf *pf); @@ -2575,7 +2577,7 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) return; if (!test_and_clear_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state)) return; - if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) { + if (test_bit(__I40E_VF_DISABLE, pf->state)) { set_bit(__I40E_MACVLAN_SYNC_PENDING, pf->state); return; } @@ -2593,7 +2595,6 @@ static void i40e_sync_filters_subtask(struct i40e_pf *pf) } } } - clear_bit(__I40E_VF_DISABLE, pf->state); } /** @@ -3895,8 +3896,16 @@ static irqreturn_t i40e_intr(int irq, void *data) } if (icr0 & I40E_PFINT_ICR0_VFLR_MASK) { - ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; - set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); + /* disable any further VFLR event notifications */ + if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) { + u32 reg = rd32(hw, I40E_PFINT_ICR0_ENA); + + reg &= ~I40E_PFINT_ICR0_VFLR_MASK; + wr32(hw, I40E_PFINT_ICR0_ENA, reg); + } else { + ena_mask &= ~I40E_PFINT_ICR0_ENA_VFLR_MASK; + set_bit(__I40E_VFLR_EVENT_PENDING, pf->state); + } } if (icr0 & I40E_PFINT_ICR0_GRST_MASK) { @@ -6997,6 +7006,8 @@ int i40e_add_del_cloud_filter(struct i40e_vsi *vsi, if (filter->flags >= ARRAY_SIZE(flag_table)) return I40E_ERR_CONFIG; + memset(&cld_filter, 0, sizeof(cld_filter)); + /* copy element needed to add cloud filter from filter */ i40e_set_cld_element(filter, &cld_filter); @@ -7060,10 +7071,13 @@ int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi, return -EOPNOTSUPP; /* adding filter using src_port/src_ip is not supported at this stage */ - if (filter->src_port || filter->src_ipv4 || + if (filter->src_port || + (filter->src_ipv4 && filter->n_proto != ETH_P_IPV6) || !ipv6_addr_any(&filter->ip.v6.src_ip6)) return -EOPNOTSUPP; + memset(&cld_filter, 0, sizeof(cld_filter)); + /* copy element needed to add cloud filter from filter */ i40e_set_cld_element(filter, &cld_filter.element); @@ -7087,7 +7101,7 @@ int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi, cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_MAC_VLAN_PORT); } - } else if (filter->dst_ipv4 || + } else if ((filter->dst_ipv4 && filter->n_proto != ETH_P_IPV6) || !ipv6_addr_any(&filter->ip.v6.dst_ip6)) { cld_filter.element.flags = cpu_to_le16(I40E_AQC_ADD_CLOUD_FILTER_IP_PORT); @@ -7921,6 +7935,14 @@ void i40e_do_reset(struct i40e_pf *pf, u32 reset_flags, bool lock_acquired) dev_dbg(&pf->pdev->dev, "PFR requested\n"); i40e_handle_reset_warning(pf, lock_acquired); + } else if (reset_flags & I40E_PF_RESET_AND_REBUILD_FLAG) { + /* Request a PF Reset + * + * Resets PF and reinitializes PFs VSI. + */ + i40e_prep_for_reset(pf, lock_acquired); + i40e_reset_and_rebuild(pf, true, lock_acquired); + } else if (reset_flags & BIT_ULL(__I40E_REINIT_REQUESTED)) { int v; @@ -9381,7 +9403,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) { struct i40e_vsi *vsi = pf->vsi[pf->lan_vsi]; struct i40e_hw *hw = &pf->hw; - u8 set_fc_aq_fail = 0; i40e_status ret; u32 val; int v; @@ -9462,13 +9483,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) i40e_stat_str(&pf->hw, ret), i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); - /* make sure our flow control settings are restored */ - ret = i40e_set_fc(&pf->hw, &set_fc_aq_fail, true); - if (ret) - dev_dbg(&pf->pdev->dev, "setting flow control: ret = %s last_status = %s\n", - i40e_stat_str(&pf->hw, ret), - i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status)); - /* Rebuild the VSIs and VEBs that existed before reset. * They are still in our local switch element arrays, so only * need to rebuild the switch model in the HW. @@ -11089,6 +11103,8 @@ i40e_status i40e_set_partition_bw_setting(struct i40e_pf *pf) struct i40e_aqc_configure_partition_bw_data bw_data; i40e_status status; + memset(&bw_data, 0, sizeof(bw_data)); + /* Set the valid bit for this PF */ bw_data.pf_valid_bits = cpu_to_le16(BIT(pf->hw.pf_id)); bw_data.max_bw[pf->hw.pf_id] = pf->max_bw & I40E_ALT_BW_VALUE_MASK; @@ -11195,6 +11211,7 @@ static int i40e_sw_init(struct i40e_pf *pf) { int err = 0; int size; + u16 pow; /* Set default capability flags */ pf->flags = I40E_FLAG_RX_CSUM_ENABLED | @@ -11213,6 +11230,11 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->rss_table_size = pf->hw.func_caps.rss_table_size; pf->rss_size_max = min_t(int, pf->rss_size_max, pf->hw.func_caps.num_tx_qp); + + /* find the next higher power-of-2 of num cpus */ + pow = roundup_pow_of_two(num_online_cpus()); + pf->rss_size_max = min_t(int, pf->rss_size_max, pow); + if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; pf->alloc_rss_size = min_t(int, pf->rss_size_max, @@ -13605,7 +13627,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) int err; u32 val; u32 i; - u8 set_fc_aq_fail; err = pci_enable_device_mem(pdev); if (err) @@ -13885,24 +13906,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } INIT_LIST_HEAD(&pf->vsi[pf->lan_vsi]->ch_list); - /* Make sure flow control is set according to current settings */ - err = i40e_set_fc(hw, &set_fc_aq_fail, true); - if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_GET) - dev_dbg(&pf->pdev->dev, - "Set fc with err %s aq_err %s on get_phy_cap\n", - i40e_stat_str(hw, err), - i40e_aq_str(hw, hw->aq.asq_last_status)); - if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_SET) - dev_dbg(&pf->pdev->dev, - "Set fc with err %s aq_err %s on set_phy_config\n", - i40e_stat_str(hw, err), - i40e_aq_str(hw, hw->aq.asq_last_status)); - if (set_fc_aq_fail & I40E_SET_FC_AQ_FAIL_UPDATE) - dev_dbg(&pf->pdev->dev, - "Set fc with err %s aq_err %s on get_link_info\n", - i40e_stat_str(hw, err), - i40e_aq_str(hw, hw->aq.asq_last_status)); - /* if FDIR VSI was set up, start it now */ for (i = 0; i < pf->num_alloc_vsi; i++) { if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { @@ -13959,6 +13962,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (err) { dev_info(&pdev->dev, "setup of misc vector failed: %d\n", err); + i40e_cloud_filter_exit(pf); + i40e_fdir_teardown(pf); goto err_vsis; } } @@ -14155,6 +14160,11 @@ static void i40e_remove(struct pci_dev *pdev) while (test_bit(__I40E_RESET_RECOVERY_PENDING, pf->state)) usleep_range(1000, 2000); + if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { + set_bit(__I40E_VF_RESETS_DISABLED, pf->state); + i40e_free_vfs(pf); + pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; + } /* no more scheduling of any task */ set_bit(__I40E_SUSPENDED, pf->state); set_bit(__I40E_DOWN, pf->state); @@ -14168,11 +14178,6 @@ static void i40e_remove(struct pci_dev *pdev) */ i40e_notify_client_of_netdev_close(pf->vsi[pf->lan_vsi], false); - if (pf->flags & I40E_FLAG_SRIOV_ENABLED) { - i40e_free_vfs(pf); - pf->flags &= ~I40E_FLAG_SRIOV_ENABLED; - } - i40e_fdir_teardown(pf); /* If there is a switch structure or any orphans, remove them. diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index b5042d1a63c0..9ccbcd88bf1e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -3070,13 +3070,16 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags, l4_proto = ip.v4->protocol; } else if (*tx_flags & I40E_TX_FLAGS_IPV6) { + int ret; + tunnel |= I40E_TX_CTX_EXT_IP_IPV6; exthdr = ip.hdr + sizeof(*ip.v6); l4_proto = ip.v6->nexthdr; - if (l4.hdr != exthdr) - ipv6_skip_exthdr(skb, exthdr - skb->data, - &l4_proto, &frag_off); + ret = ipv6_skip_exthdr(skb, exthdr - skb->data, + &l4_proto, &frag_off); + if (ret < 0) + return -1; } /* define outer transport */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index bc4eda52372a..3c1533c627fd 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -137,6 +137,7 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf) **/ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) { + struct i40e_pf *pf = vf->pf; int i; i40e_vc_notify_vf_reset(vf); @@ -147,6 +148,11 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) * ensure a reset. */ for (i = 0; i < 20; i++) { + /* If PF is in VFs releasing state reset VF is impossible, + * so leave it. + */ + if (test_bit(__I40E_VFS_RELEASING, pf->state)) + return; if (i40e_reset_vf(vf, false)) return; usleep_range(10000, 20000); @@ -1204,7 +1210,8 @@ static void i40e_cleanup_reset_vf(struct i40e_vf *vf) * @vf: pointer to the VF structure * @flr: VFLR was issued or not * - * Returns true if the VF is reset, false otherwise. + * Returns true if the VF is in reset, resets successfully, or resets + * are disabled and false otherwise. **/ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) { @@ -1214,11 +1221,14 @@ bool i40e_reset_vf(struct i40e_vf *vf, bool flr) u32 reg; int i; + if (test_bit(__I40E_VF_RESETS_DISABLED, pf->state)) + return true; + /* If the VFs have been disabled, this means something else is * resetting the VF, so we shouldn't continue. */ if (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) - return false; + return true; i40e_trigger_vf_reset(vf, flr); @@ -1377,11 +1387,22 @@ void i40e_free_vfs(struct i40e_pf *pf) if (!pf->vf) return; + + set_bit(__I40E_VFS_RELEASING, pf->state); while (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) usleep_range(1000, 2000); i40e_notify_client_of_vf_enable(pf, 0); + /* Disable IOV before freeing resources. This lets any VF drivers + * running in the host get themselves cleaned up before we yank + * the carpet out from underneath their feet. + */ + if (!pci_vfs_assigned(pf->pdev)) + pci_disable_sriov(pf->pdev); + else + dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); + /* Amortize wait time by stopping all VFs at the same time */ for (i = 0; i < pf->num_alloc_vfs; i++) { if (test_bit(I40E_VF_STATE_INIT, &pf->vf[i].vf_states)) @@ -1397,15 +1418,6 @@ void i40e_free_vfs(struct i40e_pf *pf) i40e_vsi_wait_queues_disabled(pf->vsi[pf->vf[i].lan_vsi_idx]); } - /* Disable IOV before freeing resources. This lets any VF drivers - * running in the host get themselves cleaned up before we yank - * the carpet out from underneath their feet. - */ - if (!pci_vfs_assigned(pf->pdev)) - pci_disable_sriov(pf->pdev); - else - dev_warn(&pf->pdev->dev, "VFs are assigned - not disabling SR-IOV\n"); - /* free up VF resources */ tmp = pf->num_alloc_vfs; pf->num_alloc_vfs = 0; @@ -1434,6 +1446,7 @@ void i40e_free_vfs(struct i40e_pf *pf) } } clear_bit(__I40E_VF_DISABLE, pf->state); + clear_bit(__I40E_VFS_RELEASING, pf->state); } #ifdef CONFIG_PCI_IOV @@ -1563,7 +1576,7 @@ int i40e_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) if (num_vfs) { if (!(pf->flags & I40E_FLAG_VEB_MODE_ENABLED)) { pf->flags |= I40E_FLAG_VEB_MODE_ENABLED; - i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG); + i40e_do_reset_safe(pf, I40E_PF_RESET_AND_REBUILD_FLAG); } return i40e_pci_sriov_enable(pdev, num_vfs); } @@ -1571,7 +1584,7 @@ int i40e_pci_sriov_configure(struct pci_dev *pdev, int num_vfs) if (!pci_vfs_assigned(pf->pdev)) { i40e_free_vfs(pf); pf->flags &= ~I40E_FLAG_VEB_MODE_ENABLED; - i40e_do_reset_safe(pf, I40E_PF_RESET_FLAG); + i40e_do_reset_safe(pf, I40E_PF_RESET_AND_REBUILD_FLAG); } else { dev_warn(&pdev->dev, "Unable to free VFs because some are assigned to VMs.\n"); return -EINVAL; diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h b/drivers/net/ethernet/intel/ice/ice_controlq.h index 0f2cdb06e6ef..7960f0e4d872 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.h +++ b/drivers/net/ethernet/intel/ice/ice_controlq.h @@ -30,8 +30,8 @@ enum ice_ctl_q { ICE_CTL_Q_ADMIN, }; -/* Control Queue timeout settings - max delay 250ms */ -#define ICE_CTL_Q_SQ_CMD_TIMEOUT 2500 /* Count 2500 times */ +/* Control Queue timeout settings - max delay 1s */ +#define ICE_CTL_Q_SQ_CMD_TIMEOUT 10000 /* Count 10000 times */ #define ICE_CTL_Q_SQ_CMD_USEC 100 /* Check every 100usec */ struct ice_ctl_q_ring { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 4243ff4ec4b1..8fcd3ffb43e0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1943,7 +1943,8 @@ static inline bool ixgbe_page_is_reserved(struct page *page) return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page); } -static bool ixgbe_can_reuse_rx_page(struct ixgbe_rx_buffer *rx_buffer) +static bool ixgbe_can_reuse_rx_page(struct ixgbe_rx_buffer *rx_buffer, + int rx_buffer_pgcnt) { unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; struct page *page = rx_buffer->page; @@ -1954,7 +1955,7 @@ static bool ixgbe_can_reuse_rx_page(struct ixgbe_rx_buffer *rx_buffer) #if (PAGE_SIZE < 8192) /* if we are only owner of page we can reuse it */ - if (unlikely((page_ref_count(page) - pagecnt_bias) > 1)) + if (unlikely((rx_buffer_pgcnt - pagecnt_bias) > 1)) return false; #else /* The last offset is a bit aggressive in that we assume the @@ -2019,11 +2020,18 @@ static void ixgbe_add_rx_frag(struct ixgbe_ring *rx_ring, static struct ixgbe_rx_buffer *ixgbe_get_rx_buffer(struct ixgbe_ring *rx_ring, union ixgbe_adv_rx_desc *rx_desc, struct sk_buff **skb, - const unsigned int size) + const unsigned int size, + int *rx_buffer_pgcnt) { struct ixgbe_rx_buffer *rx_buffer; rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; + *rx_buffer_pgcnt = +#if (PAGE_SIZE < 8192) + page_count(rx_buffer->page); +#else + 0; +#endif prefetchw(rx_buffer->page); *skb = rx_buffer->skb; @@ -2053,9 +2061,10 @@ static struct ixgbe_rx_buffer *ixgbe_get_rx_buffer(struct ixgbe_ring *rx_ring, static void ixgbe_put_rx_buffer(struct ixgbe_ring *rx_ring, struct ixgbe_rx_buffer *rx_buffer, - struct sk_buff *skb) + struct sk_buff *skb, + int rx_buffer_pgcnt) { - if (ixgbe_can_reuse_rx_page(rx_buffer)) { + if (ixgbe_can_reuse_rx_page(rx_buffer, rx_buffer_pgcnt)) { /* hand second half of page back to the ring */ ixgbe_reuse_rx_page(rx_ring, rx_buffer); } else { @@ -2299,6 +2308,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, union ixgbe_adv_rx_desc *rx_desc; struct ixgbe_rx_buffer *rx_buffer; struct sk_buff *skb; + int rx_buffer_pgcnt; unsigned int size; /* return some buffers to hardware, one at a time is too slow */ @@ -2318,7 +2328,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, */ dma_rmb(); - rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size); + rx_buffer = ixgbe_get_rx_buffer(rx_ring, rx_desc, &skb, size, &rx_buffer_pgcnt); /* retrieve a buffer from the ring */ if (!skb) { @@ -2360,7 +2370,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, break; } - ixgbe_put_rx_buffer(rx_ring, rx_buffer, skb); + ixgbe_put_rx_buffer(rx_ring, rx_buffer, skb, rx_buffer_pgcnt); cleaned_count++; /* place incomplete frames back on ring for completion */ @@ -9477,8 +9487,10 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, ixgbe_atr_compute_perfect_hash_82599(&input->filter, mask); err = ixgbe_fdir_write_perfect_filter_82599(hw, &input->filter, input->sw_idx, queue); - if (!err) - ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx); + if (err) + goto err_out_w_lock; + + ixgbe_update_ethtool_fdir_entry(adapter, input, input->sw_idx); spin_unlock(&adapter->fdir_perfect_lock); if ((uhtid != 0x800) && (adapter->jump_tables[uhtid])) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 993f495e2bf7..9f804e2aba35 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -219,7 +219,7 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dev_kfree_skb_any(skb); spin_unlock_irqrestore(&lp->lock, flags); - return NETDEV_TX_BUSY; + return NETDEV_TX_OK; } } diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 30a16cf796c7..fda5dd8c71eb 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3022,7 +3022,9 @@ static int mvneta_txq_sw_init(struct mvneta_port *pp, } /* Setup XPS mapping */ - if (txq_number > 1) + if (pp->neta_armada3700) + cpu = 0; + else if (txq_number > 1) cpu = txq->id % num_present_cpus(); else cpu = pp->rxq_def % num_present_cpus(); @@ -3667,6 +3669,11 @@ static int mvneta_cpu_online(unsigned int cpu, struct hlist_node *node) node_online); struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); + /* Armada 3700's per-cpu interrupt for mvneta is broken, all interrupts + * are routed to CPU 0, so we don't need all the cpu-hotplug support + */ + if (pp->neta_armada3700) + return 0; spin_lock(&pp->lock); /* diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 04bee450eb3d..bc5cfe062b10 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -954,7 +954,7 @@ static void mvpp22_gop_init_rgmii(struct mvpp2_port *port) regmap_read(priv->sysctrl_base, GENCONF_CTRL0, &val); if (port->gop_id == 2) - val |= GENCONF_CTRL0_PORT0_RGMII | GENCONF_CTRL0_PORT1_RGMII; + val |= GENCONF_CTRL0_PORT0_RGMII; else if (port->gop_id == 3) val |= GENCONF_CTRL0_PORT1_RGMII_MII; regmap_write(priv->sysctrl_base, GENCONF_CTRL0, val); @@ -3363,6 +3363,7 @@ static int mvpp2_open(struct net_device *dev) if (!valid) { netdev_err(port->dev, "invalid configuration: no dt or link IRQ"); + err = -ENOENT; goto err_free_irq; } @@ -4265,8 +4266,6 @@ static void mvpp2_phylink_validate(struct net_device *dev, phylink_set(mask, Autoneg); phylink_set_port_modes(mask); - phylink_set(mask, Pause); - phylink_set(mask, Asym_Pause); switch (state->interface) { case PHY_INTERFACE_MODE_10GKR: diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c index 5692c6087bbb..dd590086fe6a 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.c @@ -29,16 +29,16 @@ static int mvpp2_prs_hw_write(struct mvpp2 *priv, struct mvpp2_prs_entry *pe) /* Clear entry invalidation bit */ pe->tcam[MVPP2_PRS_TCAM_INV_WORD] &= ~MVPP2_PRS_TCAM_INV_MASK; - /* Write tcam index - indirect access */ - mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index); - for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++) - mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam[i]); - /* Write sram index - indirect access */ mvpp2_write(priv, MVPP2_PRS_SRAM_IDX_REG, pe->index); for (i = 0; i < MVPP2_PRS_SRAM_WORDS; i++) mvpp2_write(priv, MVPP2_PRS_SRAM_DATA_REG(i), pe->sram[i]); + /* Write tcam index - indirect access */ + mvpp2_write(priv, MVPP2_PRS_TCAM_IDX_REG, pe->index); + for (i = 0; i < MVPP2_PRS_TCAM_WORDS; i++) + mvpp2_write(priv, MVPP2_PRS_TCAM_DATA_REG(i), pe->tcam[i]); + return 0; } @@ -405,6 +405,38 @@ static int mvpp2_prs_tcam_first_free(struct mvpp2 *priv, unsigned char start, return -EINVAL; } +/* Drop flow control pause frames */ +static void mvpp2_prs_drop_fc(struct mvpp2 *priv) +{ + unsigned char da[ETH_ALEN] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x01 }; + struct mvpp2_prs_entry pe; + unsigned int len; + + memset(&pe, 0, sizeof(pe)); + + /* For all ports - drop flow control frames */ + pe.index = MVPP2_PE_FC_DROP; + mvpp2_prs_tcam_lu_set(&pe, MVPP2_PRS_LU_MAC); + + /* Set match on DA */ + len = ETH_ALEN; + while (len--) + mvpp2_prs_tcam_data_byte_set(&pe, len, da[len], 0xff); + + mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_DROP_MASK, + MVPP2_PRS_RI_DROP_MASK); + + mvpp2_prs_sram_bits_set(&pe, MVPP2_PRS_SRAM_LU_GEN_BIT, 1); + mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_FLOWS); + + /* Mask all ports */ + mvpp2_prs_tcam_port_map_set(&pe, MVPP2_PRS_PORT_MASK); + + /* Update shadow table and hw entry */ + mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_MAC); + mvpp2_prs_hw_write(priv, &pe); +} + /* Enable/disable dropping all mac da's */ static void mvpp2_prs_mac_drop_all_set(struct mvpp2 *priv, int port, bool add) { @@ -1162,6 +1194,7 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv) mvpp2_prs_hw_write(priv, &pe); /* Create dummy entries for drop all and promiscuous modes */ + mvpp2_prs_drop_fc(priv); mvpp2_prs_mac_drop_all_set(priv, 0, false); mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_UNI_CAST, false); mvpp2_prs_mac_promisc_set(priv, 0, MVPP2_PRS_L2_MULTI_CAST, false); @@ -1647,8 +1680,9 @@ static int mvpp2_prs_pppoe_init(struct mvpp2 *priv) mvpp2_prs_sram_next_lu_set(&pe, MVPP2_PRS_LU_IP6); mvpp2_prs_sram_ri_update(&pe, MVPP2_PRS_RI_L3_IP6, MVPP2_PRS_RI_L3_PROTO_MASK); - /* Skip eth_type + 4 bytes of IPv6 header */ - mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 4, + /* Jump to DIP of IPV6 header */ + mvpp2_prs_sram_shift_set(&pe, MVPP2_ETH_TYPE_LEN + 8 + + MVPP2_MAX_L3_ADDR_SIZE, MVPP2_PRS_SRAM_OP_SEL_SHIFT_ADD); /* Set L3 offset */ mvpp2_prs_sram_offset_set(&pe, MVPP2_PRS_SRAM_UDF_TYPE_L3, diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.h index e22f6c85d380..4b68dd374733 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_prs.h @@ -129,7 +129,7 @@ #define MVPP2_PE_VID_EDSA_FLTR_DEFAULT (MVPP2_PRS_TCAM_SRAM_SIZE - 7) #define MVPP2_PE_VLAN_DBL (MVPP2_PRS_TCAM_SRAM_SIZE - 6) #define MVPP2_PE_VLAN_NONE (MVPP2_PRS_TCAM_SRAM_SIZE - 5) -/* reserved */ +#define MVPP2_PE_FC_DROP (MVPP2_PRS_TCAM_SRAM_SIZE - 4) #define MVPP2_PE_MAC_MC_PROMISCUOUS (MVPP2_PRS_TCAM_SRAM_SIZE - 3) #define MVPP2_PE_MAC_UC_PROMISCUOUS (MVPP2_PRS_TCAM_SRAM_SIZE - 2) #define MVPP2_PE_MAC_NON_PROMISCUOUS (MVPP2_PRS_TCAM_SRAM_SIZE - 1) diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index ff2fea0f8b75..0d6a4e47e7a5 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -1564,8 +1564,8 @@ static int pxa168_eth_remove(struct platform_device *pdev) mdiobus_unregister(pep->smi_bus); mdiobus_free(pep->smi_bus); - unregister_netdev(dev); cancel_work_sync(&pep->tx_timeout_task); + unregister_netdev(dev); free_netdev(dev); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index e639a365ac2d..7a99eb1572fd 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -47,7 +47,7 @@ #define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff) #define EN_ETHTOOL_WORD_MASK cpu_to_be32(0xffffffff) -static int mlx4_en_moderation_update(struct mlx4_en_priv *priv) +int mlx4_en_moderation_update(struct mlx4_en_priv *priv) { int i, t; int err = 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 5868ec11db1a..f3a0617733d8 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1384,8 +1384,10 @@ static void mlx4_en_tx_timeout(struct net_device *dev) } priv->port_stats.tx_timeout++; - en_dbg(DRV, priv, "Scheduling watchdog\n"); - queue_work(mdev->workqueue, &priv->watchdog_task); + if (!test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state)) { + en_dbg(DRV, priv, "Scheduling port restart\n"); + queue_work(mdev->workqueue, &priv->restart_task); + } } @@ -1739,6 +1741,7 @@ int mlx4_en_start_port(struct net_device *dev) mlx4_en_deactivate_cq(priv, cq); goto tx_err; } + clear_bit(MLX4_EN_TX_RING_STATE_RECOVERING, &tx_ring->state); if (t != TX_XDP) { tx_ring->tx_queue = netdev_get_tx_queue(dev, i); tx_ring->recycle_ring = NULL; @@ -1835,6 +1838,7 @@ int mlx4_en_start_port(struct net_device *dev) local_bh_enable(); } + clear_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state); netif_tx_start_all_queues(dev); netif_device_attach(dev); @@ -2005,7 +2009,7 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) static void mlx4_en_restart(struct work_struct *work) { struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, - watchdog_task); + restart_task); struct mlx4_en_dev *mdev = priv->mdev; struct net_device *dev = priv->dev; @@ -2387,7 +2391,7 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) if (netif_running(dev)) { mutex_lock(&mdev->state_lock); if (!mdev->device_up) { - /* NIC is probably restarting - let watchdog task reset + /* NIC is probably restarting - let restart task reset * the port */ en_dbg(DRV, priv, "Change MTU called with card down!?\n"); } else { @@ -2396,7 +2400,9 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu) if (err) { en_err(priv, "Failed restarting port:%d\n", priv->port); - queue_work(mdev->workqueue, &priv->watchdog_task); + if (!test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, + &priv->state)) + queue_work(mdev->workqueue, &priv->restart_task); } } mutex_unlock(&mdev->state_lock); @@ -2882,7 +2888,8 @@ static int mlx4_xdp_set(struct net_device *dev, struct bpf_prog *prog) if (err) { en_err(priv, "Failed starting port %d for XDP change\n", priv->port); - queue_work(mdev->workqueue, &priv->watchdog_task); + if (!test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state)) + queue_work(mdev->workqueue, &priv->restart_task); } } @@ -3280,7 +3287,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, priv->counter_index = MLX4_SINK_COUNTER_INDEX(mdev->dev); spin_lock_init(&priv->stats_lock); INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); - INIT_WORK(&priv->watchdog_task, mlx4_en_restart); + INIT_WORK(&priv->restart_task, mlx4_en_restart); INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); INIT_DELAYED_WORK(&priv->service_task, mlx4_en_service_task); @@ -3660,6 +3667,8 @@ int mlx4_en_reset_config(struct net_device *dev, en_err(priv, "Failed starting port\n"); } + if (!err) + err = mlx4_en_moderation_update(priv); out: mutex_unlock(&mdev->state_lock); kfree(tmp); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index e58052d07e39..29041d4a3f28 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -385,6 +385,35 @@ int mlx4_en_free_tx_buf(struct net_device *dev, struct mlx4_en_tx_ring *ring) return cnt; } +static void mlx4_en_handle_err_cqe(struct mlx4_en_priv *priv, struct mlx4_err_cqe *err_cqe, + u16 cqe_index, struct mlx4_en_tx_ring *ring) +{ + struct mlx4_en_dev *mdev = priv->mdev; + struct mlx4_en_tx_info *tx_info; + struct mlx4_en_tx_desc *tx_desc; + u16 wqe_index; + int desc_size; + + en_err(priv, "CQE error - cqn 0x%x, ci 0x%x, vendor syndrome: 0x%x syndrome: 0x%x\n", + ring->sp_cqn, cqe_index, err_cqe->vendor_err_syndrome, err_cqe->syndrome); + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, err_cqe, sizeof(*err_cqe), + false); + + wqe_index = be16_to_cpu(err_cqe->wqe_index) & ring->size_mask; + tx_info = &ring->tx_info[wqe_index]; + desc_size = tx_info->nr_txbb << LOG_TXBB_SIZE; + en_err(priv, "Related WQE - qpn 0x%x, wqe index 0x%x, wqe size 0x%x\n", ring->qpn, + wqe_index, desc_size); + tx_desc = ring->buf + (wqe_index << LOG_TXBB_SIZE); + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, tx_desc, desc_size, false); + + if (test_and_set_bit(MLX4_EN_STATE_FLAG_RESTARTING, &priv->state)) + return; + + en_err(priv, "Scheduling port restart\n"); + queue_work(mdev->workqueue, &priv->restart_task); +} + bool mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int napi_budget) { @@ -431,13 +460,10 @@ bool mlx4_en_process_tx_cq(struct net_device *dev, dma_rmb(); if (unlikely((cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) == - MLX4_CQE_OPCODE_ERROR)) { - struct mlx4_err_cqe *cqe_err = (struct mlx4_err_cqe *)cqe; - - en_err(priv, "CQE error - vendor syndrome: 0x%x syndrome: 0x%x\n", - cqe_err->vendor_err_syndrome, - cqe_err->syndrome); - } + MLX4_CQE_OPCODE_ERROR)) + if (!test_and_set_bit(MLX4_EN_TX_RING_STATE_RECOVERING, &ring->state)) + mlx4_en_handle_err_cqe(priv, (struct mlx4_err_cqe *)cqe, index, + ring); /* Skip over last polled CQE */ new_index = be16_to_cpu(cqe->wqe_index) & size_mask; diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 04ebce738db9..926407f0bbd9 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c @@ -1861,8 +1861,8 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) #define INIT_HCA_LOG_RD_OFFSET (INIT_HCA_QPC_OFFSET + 0x77) #define INIT_HCA_MCAST_OFFSET 0x0c0 #define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00) -#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12) -#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16) +#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x13) +#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x17) #define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18) #define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b) #define INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN 0x6 @@ -1870,7 +1870,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param) #define INIT_HCA_DRIVER_VERSION_SZ 0x40 #define INIT_HCA_FS_PARAM_OFFSET 0x1d0 #define INIT_HCA_FS_BASE_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x00) -#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x12) +#define INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x13) #define INIT_HCA_FS_A0_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x18) #define INIT_HCA_FS_LOG_TABLE_SZ_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x1b) #define INIT_HCA_FS_ETH_BITS_OFFSET (INIT_HCA_FS_PARAM_OFFSET + 0x21) diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.h b/drivers/net/ethernet/mellanox/mlx4/fw.h index 650ae08c71de..8f020f26ebf5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.h +++ b/drivers/net/ethernet/mellanox/mlx4/fw.h @@ -182,8 +182,8 @@ struct mlx4_init_hca_param { u64 cmpt_base; u64 mtt_base; u64 global_caps; - u16 log_mc_entry_sz; - u16 log_mc_hash_sz; + u8 log_mc_entry_sz; + u8 log_mc_hash_sz; u16 hca_core_clock; /* Internal Clock Frequency (in MHz) */ u8 log_num_qps; u8 log_num_srqs; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 240f9c9ca943..3d5597d5b10d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -271,6 +271,10 @@ struct mlx4_en_page_cache { } buf[MLX4_EN_CACHE_SIZE]; }; +enum { + MLX4_EN_TX_RING_STATE_RECOVERING, +}; + struct mlx4_en_priv; struct mlx4_en_tx_ring { @@ -317,6 +321,7 @@ struct mlx4_en_tx_ring { * Only queue_stopped might be used if BQL is not properly working. */ unsigned long queue_stopped; + unsigned long state; struct mlx4_hwq_resources sp_wqres; struct mlx4_qp sp_qp; struct mlx4_qp_context sp_context; @@ -530,6 +535,10 @@ struct mlx4_en_stats_bitmap { struct mutex mutex; /* for mutual access to stats bitmap */ }; +enum { + MLX4_EN_STATE_FLAG_RESTARTING, +}; + struct mlx4_en_priv { struct mlx4_en_dev *mdev; struct mlx4_en_port_profile *prof; @@ -595,7 +604,7 @@ struct mlx4_en_priv { struct mlx4_en_cq *rx_cq[MAX_RX_RINGS]; struct mlx4_qp drop_qp; struct work_struct rx_mode_task; - struct work_struct watchdog_task; + struct work_struct restart_task; struct work_struct linkstate_task; struct delayed_work stats_task; struct delayed_work service_task; @@ -643,6 +652,7 @@ struct mlx4_en_priv { u32 pflags; u8 rss_key[MLX4_EN_RSS_KEY_SIZE]; u8 rss_hash_fn; + unsigned long state; }; enum mlx4_en_wol { @@ -788,6 +798,7 @@ void mlx4_en_ptp_overflow_check(struct mlx4_en_dev *mdev); #define DEV_FEATURE_CHANGED(dev, new_features, feature) \ ((dev->features & feature) ^ (new_features & feature)) +int mlx4_en_moderation_update(struct mlx4_en_priv *priv); int mlx4_en_reset_config(struct net_device *dev, struct hwtstamp_config ts_config, netdev_features_t new_features); diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index a4c1ed65f620..550e4893253e 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -4990,6 +4990,7 @@ static int mlx4_do_mirror_rule(struct mlx4_dev *dev, struct res_fs_rule *fs_rule if (!fs_rule->mirr_mbox) { mlx4_err(dev, "rule mirroring mailbox is null\n"); + mlx4_free_cmd_mailbox(dev, mailbox); return -EINVAL; } memcpy(mailbox->buf, fs_rule->mirr_mbox, fs_rule->mirr_mbox_size); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index a383276eb816..3d824c20d2a4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -1460,6 +1460,7 @@ static int set_pflag_rx_cqe_compress(struct net_device *netdev, { struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; + int err; if (!MLX5_CAP_GEN(mdev, cqe_compression)) return -EOPNOTSUPP; @@ -1469,7 +1470,10 @@ static int set_pflag_rx_cqe_compress(struct net_device *netdev, return -EINVAL; } - mlx5e_modify_rx_cqe_compression_locked(priv, enable); + err = mlx5e_modify_rx_cqe_compression_locked(priv, enable); + if (err) + return err; + priv->channels.params.rx_cqe_compress_def = enable; return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index 7ddacc9e4fe4..c6eea6b6b1bb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -893,6 +893,7 @@ static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc, in = kvzalloc(inlen, GFP_KERNEL); if (!in) { kfree(ft->g); + ft->g = NULL; return -ENOMEM; } @@ -1033,6 +1034,7 @@ static int mlx5e_create_inner_ttc_table_groups(struct mlx5e_ttc_table *ttc) in = kvzalloc(inlen, GFP_KERNEL); if (!in) { kfree(ft->g); + ft->g = NULL; return -ENOMEM; } @@ -1312,6 +1314,7 @@ static int mlx5e_create_l2_table_groups(struct mlx5e_l2_table *l2_table) ft->g[ft->num_groups] = NULL; mlx5e_destroy_groups(ft); kvfree(in); + kfree(ft->g); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 7366033cd31c..2190daace873 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1999,12 +1999,15 @@ static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw) max_guarantee = evport->info.min_rate; } - return max_t(u32, max_guarantee / fw_max_bw_share, 1); + if (max_guarantee) + return max_t(u32, max_guarantee / fw_max_bw_share, 1); + return 0; } -static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider) +static int normalize_vports_min_rate(struct mlx5_eswitch *esw) { u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); + u32 divider = calculate_vports_min_rate_divider(esw); struct mlx5_vport *evport; u32 vport_max_rate; u32 vport_min_rate; @@ -2018,9 +2021,9 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider) continue; vport_min_rate = evport->info.min_rate; vport_max_rate = evport->info.max_rate; - bw_share = MLX5_MIN_BW_SHARE; + bw_share = 0; - if (vport_min_rate) + if (divider) bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate, divider, fw_max_bw_share); @@ -2045,7 +2048,6 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport, struct mlx5_vport *evport; u32 fw_max_bw_share; u32 previous_min_rate; - u32 divider; bool min_rate_supported; bool max_rate_supported; int err = 0; @@ -2071,8 +2073,7 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport, previous_min_rate = evport->info.min_rate; evport->info.min_rate = min_rate; - divider = calculate_vports_min_rate_divider(esw); - err = normalize_vports_min_rate(esw, divider); + err = normalize_vports_min_rate(esw); if (err) { evport->info.min_rate = previous_min_rate; goto unlock; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index b16e0f45d28c..a38a0c86705a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1004,6 +1004,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa destroy_ft: root->cmds->destroy_flow_table(root->dev, ft); free_ft: + rhltable_destroy(&ft->fgs_hash); kfree(ft); unlock_root: mutex_unlock(&root->chain_lock); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 5fac00ea6245..a2b25afa2472 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -51,6 +51,7 @@ #ifdef CONFIG_RFS_ACCEL #include #endif +#include #include #include "mlx5_core.h" #include "fs_core.h" @@ -211,7 +212,10 @@ static void mlx5_set_driver_version(struct mlx5_core_dev *dev) strncat(string, ",", remaining_size); remaining_size = max_t(int, 0, driver_ver_sz - strlen(string)); - strncat(string, DRIVER_VERSION, remaining_size); + + snprintf(string + strlen(string), remaining_size, "%u.%u.%u", + (u8)((LINUX_VERSION_CODE >> 16) & 0xff), (u8)((LINUX_VERSION_CODE >> 8) & 0xff), + (u16)(LINUX_VERSION_CODE & 0xffff)); /*Send the command*/ MLX5_SET(set_driver_version_in, in, opcode, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index e36d3e3675f9..9c3653e06886 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -331,6 +331,24 @@ static int give_pages(struct mlx5_core_dev *dev, u16 func_id, int npages, return err; } +static u32 fwp_fill_manage_pages_out(struct fw_page *fwp, u32 *out, u32 index, + u32 npages) +{ + u32 pages_set = 0; + unsigned int n; + + for_each_clear_bit(n, &fwp->bitmask, MLX5_NUM_4K_IN_PAGE) { + MLX5_ARRAY_SET64(manage_pages_out, out, pas, index + pages_set, + fwp->addr + (n * MLX5_ADAPTER_PAGE_SIZE)); + pages_set++; + + if (!--npages) + break; + } + + return pages_set; +} + static int reclaim_pages_cmd(struct mlx5_core_dev *dev, u32 *in, int in_size, u32 *out, int out_size) { @@ -354,8 +372,7 @@ static int reclaim_pages_cmd(struct mlx5_core_dev *dev, if (fwp->func_id != func_id) continue; - MLX5_ARRAY_SET64(manage_pages_out, out, pas, i, fwp->addr); - i++; + i += fwp_fill_manage_pages_out(fwp, out, i, npages - i); } MLX5_SET(manage_pages_out, out, output_num_entries, i); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 423c3e9925d0..049ca4ba49de 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -439,7 +439,8 @@ static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans) if (trans->core->fw_flash_in_progress) timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_DURING_FW_FLASH_MS); - queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, timeout); + queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, + timeout << trans->retries); } static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c index 07c1eb63415a..190c22cdc4d2 100644 --- a/drivers/net/ethernet/microchip/lan743x_ethtool.c +++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c @@ -659,7 +659,9 @@ static void lan743x_ethtool_get_wol(struct net_device *netdev, wol->supported = 0; wol->wolopts = 0; - phy_ethtool_get_wol(netdev->phydev, wol); + + if (netdev->phydev) + phy_ethtool_get_wol(netdev->phydev, wol); wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST | WAKE_MAGIC | WAKE_PHY | WAKE_ARP; @@ -688,9 +690,8 @@ static int lan743x_ethtool_set_wol(struct net_device *netdev, device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts); - phy_ethtool_set_wol(netdev->phydev, wol); - - return 0; + return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol) + : -ENETDOWN; } #endif /* CONFIG_PM */ diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 208341541087..df4519c04ba0 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -145,7 +145,8 @@ static void lan743x_intr_software_isr(void *context) int_sts = lan743x_csr_read(adapter, INT_STS); if (int_sts & INT_BIT_SW_GP_) { - lan743x_csr_write(adapter, INT_STS, INT_BIT_SW_GP_); + /* disable the interrupt to prevent repeated re-triggering */ + lan743x_csr_write(adapter, INT_EN_CLR, INT_BIT_SW_GP_); intr->software_isr_flag = 1; } } @@ -672,14 +673,12 @@ static int lan743x_intr_open(struct lan743x_adapter *adapter) static int lan743x_dp_write(struct lan743x_adapter *adapter, u32 select, u32 addr, u32 length, u32 *buf) { - int ret = -EIO; u32 dp_sel; int i; - mutex_lock(&adapter->dp_lock); if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, 1, 40, 100, 100)) - goto unlock; + return -EIO; dp_sel = lan743x_csr_read(adapter, DP_SEL); dp_sel &= ~DP_SEL_MASK_; dp_sel |= select; @@ -691,13 +690,10 @@ static int lan743x_dp_write(struct lan743x_adapter *adapter, lan743x_csr_write(adapter, DP_CMD, DP_CMD_WRITE_); if (lan743x_csr_wait_for_bit(adapter, DP_SEL, DP_SEL_DPRDY_, 1, 40, 100, 100)) - goto unlock; + return -EIO; } - ret = 0; -unlock: - mutex_unlock(&adapter->dp_lock); - return ret; + return 0; } static u32 lan743x_mac_mii_access(u16 id, u16 index, int read) @@ -1250,13 +1246,13 @@ static void lan743x_tx_release_desc(struct lan743x_tx *tx, goto clear_active; if (!(buffer_info->flags & TX_BUFFER_INFO_FLAG_TIMESTAMP_REQUESTED)) { - dev_kfree_skb(buffer_info->skb); + dev_kfree_skb_any(buffer_info->skb); goto clear_skb; } if (cleanup) { lan743x_ptp_unrequest_tx_timestamp(tx->adapter); - dev_kfree_skb(buffer_info->skb); + dev_kfree_skb_any(buffer_info->skb); } else { ignore_sync = (buffer_info->flags & TX_BUFFER_INFO_FLAG_IGNORE_SYNC) != 0; @@ -1566,7 +1562,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, if (required_number_of_descriptors > lan743x_tx_get_avail_desc(tx)) { if (required_number_of_descriptors > (tx->ring_size - 1)) { - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); } else { /* save to overflow buffer */ tx->overflow_skb = skb; @@ -1599,7 +1595,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, start_frame_length, do_timestamp, skb->ip_summed == CHECKSUM_PARTIAL)) { - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); goto unlock; } @@ -1619,7 +1615,7 @@ static netdev_tx_t lan743x_tx_xmit_frame(struct lan743x_tx *tx, * frame assembler clean up was performed inside * lan743x_tx_frame_add_fragment */ - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); goto unlock; } } @@ -2679,7 +2675,6 @@ static int lan743x_hardware_init(struct lan743x_adapter *adapter, adapter->intr.irq = adapter->pdev->irq; lan743x_csr_write(adapter, INT_EN_CLR, 0xFFFFFFFF); - mutex_init(&adapter->dp_lock); ret = lan743x_gpio_init(adapter); if (ret) diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h index 2d6eea18973e..77273be2d1ee 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.h +++ b/drivers/net/ethernet/microchip/lan743x_main.h @@ -702,9 +702,6 @@ struct lan743x_adapter { struct lan743x_csr csr; struct lan743x_intr intr; - /* lock, used to prevent concurrent access to data port */ - struct mutex dp_lock; - struct lan743x_gpio gpio; struct lan743x_ptp ptp; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index a29a6a618110..ea30da1c53f0 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -1549,10 +1549,8 @@ static int ocelot_netdevice_event(struct notifier_block *unused, struct net_device *dev = netdev_notifier_info_to_dev(ptr); int ret = 0; - if (!ocelot_netdevice_dev_check(dev)) - return 0; - if (event == NETDEV_PRECHANGEUPPER && + ocelot_netdevice_dev_check(dev) && netif_is_lag_master(info->upper_dev)) { struct netdev_lag_upper_info *lag_upper_info = info->upper_info; struct netlink_ext_ack *extack; diff --git a/drivers/net/ethernet/natsemi/macsonic.c b/drivers/net/ethernet/natsemi/macsonic.c index 0937fc2a928e..23c9394cd5d2 100644 --- a/drivers/net/ethernet/natsemi/macsonic.c +++ b/drivers/net/ethernet/natsemi/macsonic.c @@ -540,10 +540,14 @@ static int mac_sonic_platform_probe(struct platform_device *pdev) err = register_netdev(dev); if (err) - goto out; + goto undo_probe; return 0; +undo_probe: + dma_free_coherent(lp->device, + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), + lp->descriptors, lp->descriptors_laddr); out: free_netdev(dev); @@ -618,12 +622,16 @@ static int mac_sonic_nubus_probe(struct nubus_board *board) err = register_netdev(ndev); if (err) - goto out; + goto undo_probe; nubus_set_drvdata(board, ndev); return 0; +undo_probe: + dma_free_coherent(lp->device, + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), + lp->descriptors, lp->descriptors_laddr); out: free_netdev(ndev); return err; diff --git a/drivers/net/ethernet/natsemi/xtsonic.c b/drivers/net/ethernet/natsemi/xtsonic.c index e1b886e87a76..44171d7bb434 100644 --- a/drivers/net/ethernet/natsemi/xtsonic.c +++ b/drivers/net/ethernet/natsemi/xtsonic.c @@ -265,11 +265,14 @@ int xtsonic_probe(struct platform_device *pdev) sonic_msg_init(dev); if ((err = register_netdev(dev))) - goto out1; + goto undo_probe1; return 0; -out1: +undo_probe1: + dma_free_coherent(lp->device, + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), + lp->descriptors, lp->descriptors_laddr); release_region(dev->base_addr, SONIC_MEM_SIZE); out: free_netdev(dev); diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 65f69e562618..e2c280913fbb 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -1089,16 +1089,20 @@ static int pasemi_mac_open(struct net_device *dev) mac->tx = pasemi_mac_setup_tx_resources(dev); - if (!mac->tx) + if (!mac->tx) { + ret = -ENOMEM; goto out_tx_ring; + } /* We might already have allocated rings in case mtu was changed * before interface was brought up. */ if (dev->mtu > 1500 && !mac->num_cs) { pasemi_mac_setup_csrings(mac); - if (!mac->num_cs) + if (!mac->num_cs) { + ret = -ENOMEM; goto out_tx_ring; + } } /* Zero out rmon counters */ diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 59c70be22a84..42b99b182616 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -580,11 +580,6 @@ static const struct net_device_ops netxen_netdev_ops = { .ndo_set_features = netxen_set_features, }; -static inline bool netxen_function_zero(struct pci_dev *pdev) -{ - return (PCI_FUNC(pdev->devfn) == 0) ? true : false; -} - static inline void netxen_set_interrupt_mode(struct netxen_adapter *adapter, u32 mode) { @@ -680,7 +675,7 @@ static int netxen_setup_intr(struct netxen_adapter *adapter) netxen_initialize_interrupt_registers(adapter); netxen_set_msix_bit(pdev, 0); - if (netxen_function_zero(pdev)) { + if (adapter->portnum == 0) { if (!netxen_setup_msi_interrupts(adapter, num_msix)) netxen_set_interrupt_mode(adapter, NETXEN_MSI_MODE); else diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index 39787bb885c8..80afc8f36e00 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -2737,14 +2737,18 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, iwarp_info->partial_fpdus = kcalloc((u16)p_hwfn->p_rdma_info->num_qps, sizeof(*iwarp_info->partial_fpdus), GFP_KERNEL); - if (!iwarp_info->partial_fpdus) + if (!iwarp_info->partial_fpdus) { + rc = -ENOMEM; goto err; + } iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps; iwarp_info->mpa_intermediate_buf = kzalloc(buff_size, GFP_KERNEL); - if (!iwarp_info->mpa_intermediate_buf) + if (!iwarp_info->mpa_intermediate_buf) { + rc = -ENOMEM; goto err; + } /* The mpa_bufs array serves for pending RX packets received on the * mpa ll2 that don't have place on the tx ring and require later @@ -2754,8 +2758,10 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn, iwarp_info->mpa_bufs = kcalloc(data.input.rx_num_desc, sizeof(*iwarp_info->mpa_bufs), GFP_KERNEL); - if (!iwarp_info->mpa_bufs) + if (!iwarp_info->mpa_bufs) { + rc = -ENOMEM; goto err; + } INIT_LIST_HEAD(&iwarp_info->mpa_buf_pending_list); INIT_LIST_HEAD(&iwarp_info->mpa_buf_list); diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c index a96da16f3404..1976279800cd 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_fp.c +++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c @@ -1747,6 +1747,11 @@ netdev_features_t qede_features_check(struct sk_buff *skb, ntohs(udp_hdr(skb)->dest) != gnv_port)) return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); + } else if (l4_proto == IPPROTO_IPIP) { + /* IPIP tunnels are unknown to the device or at least unsupported natively, + * offloads for them can't be done trivially, so disable them for such skb. + */ + return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); } } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index cda5b0a9e948..10286215092f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c @@ -2251,7 +2251,8 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) /* Boot either flash image or firmware image from host file system */ if (qlcnic_load_fw_file == 1) { - if (qlcnic_83xx_load_fw_image_from_host(adapter)) + err = qlcnic_83xx_load_fw_image_from_host(adapter); + if (err) return err; } else { QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index dbd48012224f..ed34b7d1a9e1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -2508,6 +2508,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) qlcnic_sriov_vf_register_map(ahw); break; default: + err = -EINVAL; goto err_out_free_hw_res; } diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index f34ae8c75bc5..61a39d167c8b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c @@ -1426,6 +1426,7 @@ void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter) if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) { vfree(fw_dump->tmpl_hdr); + fw_dump->tmpl_hdr = NULL; if (qlcnic_83xx_md_check_extended_dump_capability(adapter)) extended = !qlcnic_83xx_extend_md_capab(adapter); @@ -1444,6 +1445,8 @@ void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter) struct qlcnic_83xx_dump_template_hdr *hdr; hdr = fw_dump->tmpl_hdr; + if (!hdr) + return; hdr->drv_cap_mask = 0x1f; fw_dump->cap_mask = 0x1f; dev_info(&pdev->dev, diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 1555c0dae490..0c9e6cb0e341 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -4237,7 +4237,9 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) return; switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33: + case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26: + case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30: + case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33: case RTL_GIGA_MAC_VER_37: case RTL_GIGA_MAC_VER_39: case RTL_GIGA_MAC_VER_43: @@ -4263,7 +4265,9 @@ static void r8168_pll_power_down(struct rtl8169_private *tp) static void r8168_pll_power_up(struct rtl8169_private *tp) { switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_33: + case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26: + case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30: + case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33: case RTL_GIGA_MAC_VER_37: case RTL_GIGA_MAC_VER_39: case RTL_GIGA_MAC_VER_43: @@ -4363,7 +4367,7 @@ static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) { - RTL_W8(tp, MaxTxPacketSize, 0x3f); + RTL_W8(tp, MaxTxPacketSize, 0x24); RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01); rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_512B); @@ -4371,7 +4375,7 @@ static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) { - RTL_W8(tp, MaxTxPacketSize, 0x0c); + RTL_W8(tp, MaxTxPacketSize, 0x3f); RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01); rtl_tx_performance_tweak(tp, PCI_EXP_DEVCTL_READRQ_4096B); @@ -6274,7 +6278,8 @@ static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp, opts[1] |= transport_offset << TCPHO_SHIFT; } else { if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return !eth_skb_pad(skb); + /* eth_skb_pad would free the skb on error */ + return !__skb_put_padto(skb, ETH_ZLEN, false); } return true; diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 441643670ac0..24638cb157ca 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -610,6 +610,8 @@ static struct sh_eth_cpu_data r7s72100_data = { EESR_TDE, .fdr_value = 0x0000070f, + .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5, + .no_psr = 1, .apr = 1, .mpr = 1, @@ -825,6 +827,8 @@ static struct sh_eth_cpu_data r7s9210_data = { .fdr_value = 0x0000070f, + .trscer_err_mask = DESC_I_RINT8 | DESC_I_RINT5, + .apr = 1, .mpr = 1, .tpauser = 1, @@ -1126,6 +1130,9 @@ static struct sh_eth_cpu_data sh771x_data = { EESIPR_CEEFIP | EESIPR_CELFIP | EESIPR_RRFIP | EESIPR_RTLFIP | EESIPR_RTSFIP | EESIPR_PREIP | EESIPR_CERFIP, + + .trscer_err_mask = DESC_I_RINT8, + .tsu = 1, .dual_port = 1, }; @@ -2620,10 +2627,10 @@ static int sh_eth_close(struct net_device *ndev) /* Free all the skbuffs in the Rx queue and the DMA buffer. */ sh_eth_ring_free(ndev); - pm_runtime_put_sync(&mdp->pdev->dev); - mdp->is_opened = 0; + pm_runtime_put(&mdp->pdev->dev); + return 0; } diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 027367b9cc48..3693a59b6d01 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -1386,14 +1386,17 @@ static int netsec_netdev_init(struct net_device *ndev) goto err1; /* set phy power down */ - data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR) | - BMCR_PDOWN; - netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data); + data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR); + netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, + data | BMCR_PDOWN); ret = netsec_reset_hardware(priv, true); if (ret) goto err2; + /* Restore phy power state */ + netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data); + return 0; err2: netsec_free_dring(priv, NETSEC_RING_RX); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index 03bda2e0b7a8..5020d5b28c6a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -35,7 +35,6 @@ #define PRG_ETH0_EXT_RMII_MODE 4 /* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */ -#define PRG_ETH0_CLK_M250_SEL_SHIFT 4 #define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4) #define PRG_ETH0_TXDLY_SHIFT 5 @@ -149,8 +148,9 @@ static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac) } clk_configs->m250_mux.reg = dwmac->regs + PRG_ETH0; - clk_configs->m250_mux.shift = PRG_ETH0_CLK_M250_SEL_SHIFT; - clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK; + clk_configs->m250_mux.shift = __ffs(PRG_ETH0_CLK_M250_SEL_MASK); + clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK >> + clk_configs->m250_mux.shift; clk = meson8b_dwmac_register_clk(dwmac, "m250_sel", mux_parent_names, MUX_CLK_NUM_PARENTS, &clk_mux_ops, &clk_configs->m250_mux.hw); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index ef13a462c36d..4382deaeb570 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -73,6 +73,7 @@ struct emac_variant { * @variant: reference to the current board variant * @regmap: regmap for using the syscon * @internal_phy_powered: Does the internal PHY is enabled + * @use_internal_phy: Is the internal PHY selected for use * @mux_handle: Internal pointer used by mdio-mux lib */ struct sunxi_priv_data { @@ -83,6 +84,7 @@ struct sunxi_priv_data { const struct emac_variant *variant; struct regmap_field *regmap_field; bool internal_phy_powered; + bool use_internal_phy; void *mux_handle; }; @@ -518,8 +520,11 @@ static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = { .dma_interrupt = sun8i_dwmac_dma_interrupt, }; +static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv); + static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) { + struct net_device *ndev = platform_get_drvdata(pdev); struct sunxi_priv_data *gmac = priv; int ret; @@ -533,13 +538,25 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) ret = clk_prepare_enable(gmac->tx_clk); if (ret) { - if (gmac->regulator) - regulator_disable(gmac->regulator); dev_err(&pdev->dev, "Could not enable AHB clock\n"); - return ret; + goto err_disable_regulator; + } + + if (gmac->use_internal_phy) { + ret = sun8i_dwmac_power_internal_phy(netdev_priv(ndev)); + if (ret) + goto err_disable_clk; } return 0; + +err_disable_clk: + clk_disable_unprepare(gmac->tx_clk); +err_disable_regulator: + if (gmac->regulator) + regulator_disable(gmac->regulator); + + return ret; } static void sun8i_dwmac_core_init(struct mac_device_info *hw, @@ -809,7 +826,6 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, struct sunxi_priv_data *gmac = priv->plat->bsp_priv; u32 reg, val; int ret = 0; - bool need_power_ephy = false; if (current_child ^ desired_child) { regmap_field_read(gmac->regmap_field, ®); @@ -817,13 +833,12 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID: dev_info(priv->device, "Switch mux to internal PHY"); val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT; - - need_power_ephy = true; + gmac->use_internal_phy = true; break; case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID: dev_info(priv->device, "Switch mux to external PHY"); val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN; - need_power_ephy = false; + gmac->use_internal_phy = false; break; default: dev_err(priv->device, "Invalid child ID %x\n", @@ -831,7 +846,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, return -EINVAL; } regmap_field_write(gmac->regmap_field, val); - if (need_power_ephy) { + if (gmac->use_internal_phy) { ret = sun8i_dwmac_power_internal_phy(priv); if (ret) return ret; @@ -977,17 +992,12 @@ static void sun8i_dwmac_exit(struct platform_device *pdev, void *priv) struct sunxi_priv_data *gmac = priv; if (gmac->variant->soc_has_internal_phy) { - /* sun8i_dwmac_exit could be called with mdiomux uninit */ - if (gmac->mux_handle) - mdio_mux_uninit(gmac->mux_handle); if (gmac->internal_phy_powered) sun8i_dwmac_unpower_internal_phy(gmac); } sun8i_dwmac_unset_syscon(gmac); - reset_control_put(gmac->rst_ephy); - clk_disable_unprepare(gmac->tx_clk); if (gmac->regulator) @@ -1169,6 +1179,8 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) plat_dat->init = sun8i_dwmac_init; plat_dat->exit = sun8i_dwmac_exit; plat_dat->setup = sun8i_dwmac_setup; + plat_dat->tx_fifo_size = 4096; + plat_dat->rx_fifo_size = 16384; ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv); if (ret) @@ -1200,12 +1212,32 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) return ret; dwmac_mux: + reset_control_put(gmac->rst_ephy); + clk_put(gmac->ephy_clk); sun8i_dwmac_unset_syscon(gmac); dwmac_exit: stmmac_pltfr_remove(pdev); return ret; } +static int sun8i_dwmac_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + struct sunxi_priv_data *gmac = priv->plat->bsp_priv; + + if (gmac->variant->soc_has_internal_phy) { + mdio_mux_uninit(gmac->mux_handle); + sun8i_dwmac_unpower_internal_phy(gmac); + reset_control_put(gmac->rst_ephy); + clk_put(gmac->ephy_clk); + } + + stmmac_pltfr_remove(pdev); + + return 0; +} + static const struct of_device_id sun8i_dwmac_match[] = { { .compatible = "allwinner,sun8i-h3-emac", .data = &emac_variant_h3 }, @@ -1223,7 +1255,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_match); static struct platform_driver sun8i_dwmac_driver = { .probe = sun8i_dwmac_probe, - .remove = stmmac_pltfr_remove, + .remove = sun8i_dwmac_remove, .driver = { .name = "dwmac-sun8i", .pm = &stmmac_pltfr_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index edb6053bd980..8c3780d1105f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -119,6 +119,23 @@ static void dwmac4_dma_init_channel(void __iomem *ioaddr, ioaddr + DMA_CHAN_INTR_ENA(chan)); } +static void dwmac410_dma_init_channel(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, u32 chan) +{ + u32 value; + + /* common channel control register config */ + value = readl(ioaddr + DMA_CHAN_CONTROL(chan)); + if (dma_cfg->pblx8) + value = value | DMA_BUS_MODE_PBL; + + writel(value, ioaddr + DMA_CHAN_CONTROL(chan)); + + /* Mask interrupts by writing to CSR7 */ + writel(DMA_CHAN_INTR_DEFAULT_MASK_4_10, + ioaddr + DMA_CHAN_INTR_ENA(chan)); +} + static void dwmac4_dma_init(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg, int atds) { @@ -461,7 +478,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = { const struct stmmac_dma_ops dwmac410_dma_ops = { .reset = dwmac4_dma_reset, .init = dwmac4_dma_init, - .init_chan = dwmac4_dma_init_channel, + .init_chan = dwmac410_dma_init_channel, .init_rx_chan = dwmac4_dma_init_rx_chan, .init_tx_chan = dwmac4_dma_init_tx_chan, .axi = dwmac4_dma_axi, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c index 49f5687879df..32461909264a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c @@ -63,10 +63,6 @@ void dwmac4_dma_stop_tx(void __iomem *ioaddr, u32 chan) value &= ~DMA_CONTROL_ST; writel(value, ioaddr + DMA_CHAN_TX_CONTROL(chan)); - - value = readl(ioaddr + GMAC_CONFIG); - value &= ~GMAC_CONFIG_TE; - writel(value, ioaddr + GMAC_CONFIG); } void dwmac4_dma_start_rx(void __iomem *ioaddr, u32 chan) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 2872684906e1..a1443d7197e8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1428,6 +1428,19 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv, u32 queue) stmmac_free_tx_buffer(priv, queue, i); } +/** + * stmmac_free_tx_skbufs - free TX skb buffers + * @priv: private structure + */ +static void stmmac_free_tx_skbufs(struct stmmac_priv *priv) +{ + u32 tx_queue_cnt = priv->plat->tx_queues_to_use; + u32 queue; + + for (queue = 0; queue < tx_queue_cnt; queue++) + dma_free_tx_skbufs(priv, queue); +} + /** * free_dma_rx_desc_resources - free RX dma desc resources * @priv: private structure @@ -2689,9 +2702,6 @@ static int stmmac_release(struct net_device *dev) struct stmmac_priv *priv = netdev_priv(dev); u32 chan; - if (priv->eee_enabled) - del_timer_sync(&priv->eee_ctrl_timer); - /* Stop and disconnect the PHY */ if (dev->phydev) { phy_stop(dev->phydev); @@ -2710,6 +2720,11 @@ static int stmmac_release(struct net_device *dev) if (priv->lpi_irq > 0) free_irq(priv->lpi_irq, dev); + if (priv->eee_enabled) { + priv->tx_path_in_lpi_mode = false; + del_timer_sync(&priv->eee_ctrl_timer); + } + /* Stop TX/RX DMA and clear the descriptors */ stmmac_stop_all_dma(priv); @@ -3581,6 +3596,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) { struct stmmac_priv *priv = netdev_priv(dev); int txfifosz = priv->plat->tx_fifo_size; + const int mtu = new_mtu; if (txfifosz == 0) txfifosz = priv->dma_cap.tx_fifo_size; @@ -3598,7 +3614,7 @@ static int stmmac_change_mtu(struct net_device *dev, int new_mtu) if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB)) return -EINVAL; - dev->mtu = new_mtu; + dev->mtu = mtu; netdev_update_features(dev); @@ -4497,6 +4513,11 @@ int stmmac_suspend(struct device *dev) for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) del_timer_sync(&priv->tx_queue[chan].txtimer); + if (priv->eee_enabled) { + priv->tx_path_in_lpi_mode = false; + del_timer_sync(&priv->eee_ctrl_timer); + } + /* Stop TX/RX DMA */ stmmac_stop_all_dma(priv); @@ -4545,6 +4566,8 @@ static void stmmac_reset_queues_param(struct stmmac_priv *priv) tx_q->cur_tx = 0; tx_q->dirty_tx = 0; tx_q->mss = 0; + + netdev_tx_reset_queue(netdev_get_tx_queue(priv->dev, queue)); } } @@ -4591,6 +4614,7 @@ int stmmac_resume(struct device *dev) stmmac_reset_queues_param(priv); + stmmac_free_tx_skbufs(priv); stmmac_clear_descriptors(priv); stmmac_hw_setup(ndev, false); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 37c0bc699cd9..cc1895a32b9d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -314,7 +314,12 @@ static int tc_setup_cbs(struct stmmac_priv *priv, priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_AVB; } else if (!qopt->enable) { - return stmmac_dma_qmode(priv, priv->ioaddr, queue, MTL_QUEUE_DCB); + ret = stmmac_dma_qmode(priv, priv->ioaddr, queue, + MTL_QUEUE_DCB); + if (ret) + return ret; + + priv->plat->tx_queues_cfg[queue].mode_to_use = MTL_QUEUE_DCB; } /* Port Transmit Rate and Speed Divider */ diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index d84501441edd..602a2025717a 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -3933,8 +3933,6 @@ static void niu_xmac_interrupt(struct niu *np) mp->rx_mcasts += RXMAC_MC_FRM_CNT_COUNT; if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP) mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT; - if (val & XRXMAC_STATUS_RXBCAST_CNT_EXP) - mp->rx_bcasts += RXMAC_BC_FRM_CNT_COUNT; if (val & XRXMAC_STATUS_RXHIST1_CNT_EXP) mp->rx_hist_cnt1 += RXMAC_HIST_CNT1_COUNT; if (val & XRXMAC_STATUS_RXHIST2_CNT_EXP) diff --git a/drivers/net/ethernet/sun/sunvnet_common.c b/drivers/net/ethernet/sun/sunvnet_common.c index baa3088b475c..59fc14b58c83 100644 --- a/drivers/net/ethernet/sun/sunvnet_common.c +++ b/drivers/net/ethernet/sun/sunvnet_common.c @@ -1353,27 +1353,12 @@ sunvnet_start_xmit_common(struct sk_buff *skb, struct net_device *dev, if (vio_version_after_eq(&port->vio, 1, 3)) localmtu -= VLAN_HLEN; - if (skb->protocol == htons(ETH_P_IP)) { - struct flowi4 fl4; - struct rtable *rt = NULL; - - memset(&fl4, 0, sizeof(fl4)); - fl4.flowi4_oif = dev->ifindex; - fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); - fl4.daddr = ip_hdr(skb)->daddr; - fl4.saddr = ip_hdr(skb)->saddr; - - rt = ip_route_output_key(dev_net(dev), &fl4); - if (!IS_ERR(rt)) { - skb_dst_set(skb, &rt->dst); - icmp_send(skb, ICMP_DEST_UNREACH, - ICMP_FRAG_NEEDED, - htonl(localmtu)); - } - } + if (skb->protocol == htons(ETH_P_IP)) + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(localmtu)); #if IS_ENABLED(CONFIG_IPV6) else if (skb->protocol == htons(ETH_P_IPV6)) - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu); + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, localmtu); #endif goto out_dropped; } diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index dc966ddb6d81..358f911fcd9d 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -2056,6 +2056,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /*bdx_hw_reset(priv); */ if (bdx_read_mac(priv)) { pr_err("load MAC address failed\n"); + err = -EFAULT; goto err_out_iomap; } SET_NETDEV_DEV(ndev, &pdev->dev); diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index d7543811dfae..10b301e79086 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -476,6 +476,7 @@ void cpts_unregister(struct cpts *cpts) ptp_clock_unregister(cpts->clock); cpts->clock = NULL; + cpts->phc_index = -1; cpts_write32(cpts, 0, int_enable); cpts_write32(cpts, 0, control); @@ -577,6 +578,7 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs, cpts->cc.read = cpts_systim_read; cpts->cc.mask = CLOCKSOURCE_MASK(32); cpts->info = cpts_info; + cpts->phc_index = -1; cpts_calc_mult_shift(cpts); /* save cc.mult original value as it can be modified diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index d0b5844c8a31..ce6fecf421f8 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -223,8 +223,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs, if (ip_tunnel_collect_metadata() || gs->collect_md) { __be16 flags; - flags = TUNNEL_KEY | TUNNEL_GENEVE_OPT | - (gnvh->oam ? TUNNEL_OAM : 0) | + flags = TUNNEL_KEY | (gnvh->oam ? TUNNEL_OAM : 0) | (gnvh->critical ? TUNNEL_CRIT_OPT : 0); tun_dst = udp_tun_rx_dst(skb, geneve_get_sk_family(gs), flags, @@ -840,6 +839,9 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 df; int err; + if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) + return -EINVAL; + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info, geneve->info.key.tp_dst, sport); @@ -883,6 +885,9 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; + if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) + return -EINVAL; + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info, geneve->info.key.tp_dst, sport); diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index bb9cd1262cc9..c31b15a5e0dd 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -550,8 +550,8 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, mtu < ntohs(iph->tot_len)) { netdev_dbg(dev, "packet too big, fragmentation needed\n"); memset(IPCB(skb), 0, sizeof(*IPCB(skb))); - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); goto err_rt; } diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 078027bbe002..a2b876abb03b 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -368,6 +368,7 @@ static int atusb_alloc_urbs(struct atusb *atusb, int n) return -ENOMEM; } usb_anchor_urb(urb, &atusb->idle_urbs); + usb_free_urb(urb); n--; } return 0; diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index e10e7b54ec4b..7e5892597533 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -198,7 +198,7 @@ EXPORT_SYMBOL_GPL(bcm_phy_enable_apd); int bcm_phy_set_eee(struct phy_device *phydev, bool enable) { - int val; + int val, mask = 0; /* Enable EEE at PHY level */ val = phy_read_mmd(phydev, MDIO_MMD_AN, BRCM_CL45VEN_EEE_CONTROL); @@ -217,10 +217,15 @@ int bcm_phy_set_eee(struct phy_device *phydev, bool enable) if (val < 0) return val; + if (phydev->supported & SUPPORTED_1000baseT_Full) + mask |= MDIO_EEE_1000T; + if (phydev->supported & SUPPORTED_100baseT_Full) + mask |= MDIO_EEE_100TX; + if (enable) - val |= (MDIO_EEE_100TX | MDIO_EEE_1000T); + val |= mask; else - val &= ~(MDIO_EEE_100TX | MDIO_EEE_1000T); + val &= ~mask; phy_write_mmd(phydev, MDIO_MMD_AN, BCM_CL45VEN_EEE_ADV, (u32)val); diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index bb6107f3b947..832a401c5fa5 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -2329,9 +2329,30 @@ static struct phy_driver marvell_drivers[] = { .get_stats = marvell_get_stats, }, { - .phy_id = MARVELL_PHY_ID_88E6390, + .phy_id = MARVELL_PHY_ID_88E6341_FAMILY, .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E6390", + .name = "Marvell 88E6341 Family", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .probe = m88e1510_probe, + .config_init = &marvell_config_init, + .config_aneg = &m88e6390_config_aneg, + .read_status = &marvell_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .did_interrupt = &m88e1121_did_interrupt, + .resume = &genphy_resume, + .suspend = &genphy_suspend, + .read_page = marvell_read_page, + .write_page = marvell_write_page, + .get_sset_count = marvell_get_sset_count, + .get_strings = marvell_get_strings, + .get_stats = marvell_get_stats, + }, + { + .phy_id = MARVELL_PHY_ID_88E6390_FAMILY, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E6390 Family", .features = PHY_GBIT_FEATURES, .flags = PHY_HAS_INTERRUPT, .probe = m88e6390_probe, @@ -2368,7 +2389,8 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK }, - { MARVELL_PHY_ID_88E6390, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E6341_FAMILY, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E6390_FAMILY, MARVELL_PHY_ID_MASK }, { } }; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index cc454b8c032c..dd4bf4265a5e 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -335,7 +335,10 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev, phydev->autoneg = autoneg; - phydev->speed = speed; + if (autoneg == AUTONEG_DISABLE) { + phydev->speed = speed; + phydev->duplex = duplex; + } phydev->advertising = advertising; @@ -344,8 +347,6 @@ int phy_ethtool_ksettings_set(struct phy_device *phydev, else phydev->advertising &= ~ADVERTISED_Autoneg; - phydev->duplex = duplex; - phydev->mdix_ctrl = cmd->base.eth_tp_mdix_ctrl; /* Restart the PHY */ diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 3eb034a5a659..8a1e9dba1249 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -998,7 +998,8 @@ static void __team_compute_features(struct team *team) unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM; - list_for_each_entry(port, &team->port_list, list) { + rcu_read_lock(); + list_for_each_entry_rcu(port, &team->port_list, list) { vlan_features = netdev_increment_features(vlan_features, port->dev->vlan_features, TEAM_VLAN_FEATURES); @@ -1012,6 +1013,7 @@ static void __team_compute_features(struct team *team) if (port->dev->hard_header_len > max_hard_header_len) max_hard_header_len = port->dev->hard_header_len; } + rcu_read_unlock(); team->dev->vlan_features = vlan_features; team->dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL | @@ -1027,9 +1029,7 @@ static void __team_compute_features(struct team *team) static void team_compute_features(struct team *team) { - mutex_lock(&team->lock); __team_compute_features(team); - mutex_unlock(&team->lock); netdev_change_features(team->dev); } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index d2ddef5b9dfb..89a241569677 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -77,6 +77,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -1450,7 +1458,7 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile, int i; if (it->nr_segs > MAX_SKB_FRAGS + 1) - return ERR_PTR(-ENOMEM); + return ERR_PTR(-EMSGSIZE); local_bh_disable(); skb = napi_get_frags(&tfile->napi); @@ -1992,12 +2000,15 @@ static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) struct tun_file *tfile = file->private_data; struct tun_struct *tun = tun_get(tfile); ssize_t result; + int noblock = 0; if (!tun) return -EBADFD; - result = tun_get_user(tun, tfile, NULL, from, - file->f_flags & O_NONBLOCK, false); + if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT)) + noblock = 1; + + result = tun_get_user(tun, tfile, NULL, from, noblock, false); tun_put(tun); return result; @@ -2218,10 +2229,15 @@ static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to) struct tun_file *tfile = file->private_data; struct tun_struct *tun = tun_get(tfile); ssize_t len = iov_iter_count(to), ret; + int noblock = 0; if (!tun) return -EBADFD; - ret = tun_do_read(tun, tfile, to, file->f_flags & O_NONBLOCK, NULL); + + if ((file->f_flags & O_NONBLOCK) || (iocb->ki_flags & IOCB_NOWAIT)) + noblock = 1; + + ret = tun_do_read(tun, tfile, to, noblock, NULL); ret = min_t(ssize_t, ret, len); if (ret > 0) iocb->ki_pos = ret; @@ -2860,6 +2876,45 @@ static int tun_set_ebpf(struct tun_struct *tun, struct tun_prog **prog_p, return __tun_set_ebpf(tun, prog_p, prog); } +/* Return correct value for tun->dev->addr_len based on tun->dev->type. */ +static unsigned char tun_get_addr_len(unsigned short type) +{ + switch (type) { + case ARPHRD_IP6GRE: + case ARPHRD_TUNNEL6: + return sizeof(struct in6_addr); + case ARPHRD_IPGRE: + case ARPHRD_TUNNEL: + case ARPHRD_SIT: + return 4; + case ARPHRD_ETHER: + return ETH_ALEN; + case ARPHRD_IEEE802154: + case ARPHRD_IEEE802154_MONITOR: + return IEEE802154_EXTENDED_ADDR_LEN; + case ARPHRD_PHONET_PIPE: + case ARPHRD_PPP: + case ARPHRD_NONE: + return 0; + case ARPHRD_6LOWPAN: + return EUI64_ADDR_LEN; + case ARPHRD_FDDI: + return FDDI_K_ALEN; + case ARPHRD_HIPPI: + return HIPPI_ALEN; + case ARPHRD_IEEE802: + return FC_ALEN; + case ARPHRD_ROSE: + return ROSE_ADDR_LEN; + case ARPHRD_NETROM: + return AX25_ADDR_LEN; + case ARPHRD_LOCALTLK: + return LTALK_ALEN; + default: + return 0; + } +} + static long __tun_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg, int ifreq_len) { @@ -3020,6 +3075,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EBUSY; } else { tun->dev->type = (int) arg; + tun->dev->addr_len = tun_get_addr_len(tun->dev->type); tun_debug(KERN_INFO, tun, "linktype set to %d\n", tun->dev->type); ret = 0; diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 78b16eb9e58c..f448e484a341 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -400,6 +400,8 @@ static int usbpn_probe(struct usb_interface *intf, const struct usb_device_id *i err = register_netdev(dev); if (err) { + /* Set disconnected flag so that disconnect() returns early. */ + pnd->disconnected = 1; usb_driver_release_interface(&usbpn_driver, data_intf); goto out; } diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 1de97b69ce4e..529c8fac1531 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -800,6 +800,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +/* Lenovo Powered USB-C Travel Hub (4X90S92381, based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x721e, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* ThinkPad USB-C Dock Gen 2 (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0xa387, USB_CLASS_COMM, diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 1f57a6a2b8a2..faca70c3647d 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1127,7 +1127,10 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) * accordingly. Otherwise, we should check here. */ if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) - delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus); + delayed_ndp_size = ctx->max_ndp_size + + max_t(u32, + ctx->tx_ndp_modulus, + ctx->tx_modulus + ctx->tx_remainder) - 1; else delayed_ndp_size = 0; @@ -1308,7 +1311,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) if (!(dev->driver_info->flags & FLAG_SEND_ZLP) && skb_out->len > ctx->min_tx_pkt) { padding_count = ctx->tx_curr_size - skb_out->len; - skb_put_zero(skb_out, padding_count); + if (!WARN_ON(padding_count > ctx->tx_curr_size)) + skb_put_zero(skb_out, padding_count); } else if (skb_out->len < ctx->tx_curr_size && (skb_out->len % dev->maxpacket) == 0) { skb_put_u8(skb_out, 0); /* force short packet */ @@ -1629,9 +1633,6 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. */ - netif_info(dev, link, dev->net, - "network connection: %sconnected\n", - !!event->wValue ? "" : "dis"); usbnet_link_change(dev, !!event->wValue, 0); break; diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index bff268b4a9a4..94f1c2422f84 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -625,7 +625,7 @@ static struct hso_serial *get_serial_by_index(unsigned index) return serial; } -static int get_free_serial_index(void) +static int obtain_minor(struct hso_serial *serial) { int index; unsigned long flags; @@ -633,8 +633,10 @@ static int get_free_serial_index(void) spin_lock_irqsave(&serial_table_lock, flags); for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { if (serial_table[index] == NULL) { + serial_table[index] = serial->parent; + serial->minor = index; spin_unlock_irqrestore(&serial_table_lock, flags); - return index; + return 0; } } spin_unlock_irqrestore(&serial_table_lock, flags); @@ -643,15 +645,12 @@ static int get_free_serial_index(void) return -1; } -static void set_serial_by_index(unsigned index, struct hso_serial *serial) +static void release_minor(struct hso_serial *serial) { unsigned long flags; spin_lock_irqsave(&serial_table_lock, flags); - if (serial) - serial_table[index] = serial->parent; - else - serial_table[index] = NULL; + serial_table[serial->minor] = NULL; spin_unlock_irqrestore(&serial_table_lock, flags); } @@ -2244,6 +2243,7 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) static void hso_serial_tty_unregister(struct hso_serial *serial) { tty_unregister_device(tty_drv, serial->minor); + release_minor(serial); } static void hso_serial_common_free(struct hso_serial *serial) @@ -2267,24 +2267,22 @@ static void hso_serial_common_free(struct hso_serial *serial) static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, int rx_size, int tx_size) { - int minor; int i; tty_port_init(&serial->port); - minor = get_free_serial_index(); - if (minor < 0) + if (obtain_minor(serial)) goto exit2; /* register our minor number */ serial->parent->dev = tty_port_register_device_attr(&serial->port, - tty_drv, minor, &serial->parent->interface->dev, + tty_drv, serial->minor, &serial->parent->interface->dev, serial->parent, hso_serial_dev_groups); - if (IS_ERR(serial->parent->dev)) + if (IS_ERR(serial->parent->dev)) { + release_minor(serial); goto exit2; + } - /* fill in specific data for later use */ - serial->minor = minor; serial->magic = HSO_SERIAL_MAGIC; spin_lock_init(&serial->serial_lock); serial->num_rx_urbs = num_urbs; @@ -2677,9 +2675,6 @@ static struct hso_device *hso_create_bulk_serial_device( serial->write_data = hso_std_serial_write_data; - /* and record this serial */ - set_serial_by_index(serial->minor, serial); - /* setup the proc dirs and files if needed */ hso_log_port(hso_dev); @@ -2736,9 +2731,6 @@ struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface, serial->shared_int->ref_count++; mutex_unlock(&serial->shared_int->shared_int_lock); - /* and record this serial */ - set_serial_by_index(serial->minor, serial); - /* setup the proc dirs and files if needed */ hso_log_port(hso_dev); @@ -3122,8 +3114,7 @@ static void hso_free_interface(struct usb_interface *interface) cancel_work_sync(&serial_table[i]->async_put_intf); cancel_work_sync(&serial_table[i]->async_get_intf); hso_serial_tty_unregister(serial); - kref_put(&serial_table[i]->ref, hso_serial_ref_free); - set_serial_by_index(i, NULL); + kref_put(&serial->parent->ref, hso_serial_ref_free); } } diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 3d71f1716390..8e2eb2061354 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -70,7 +70,7 @@ #define IPHETH_USBINTF_SUBCLASS 253 #define IPHETH_USBINTF_PROTO 1 -#define IPHETH_BUF_SIZE 1516 +#define IPHETH_BUF_SIZE 1514 #define IPHETH_IP_ALIGN 2 /* padding at front of URB */ #define IPHETH_TX_TIMEOUT (5 * HZ) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6e0b3dc14aa4..d08e1de26030 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -378,13 +378,6 @@ static ssize_t add_mux_store(struct device *d, struct device_attribute *attr, c goto err; } - /* we don't want to modify a running netdev */ - if (netif_running(dev->net)) { - netdev_err(dev->net, "Cannot change a running device\n"); - ret = -EBUSY; - goto err; - } - ret = qmimux_register_device(dev->net, mux_id); if (!ret) { info->flags |= QMI_WWAN_FLAG_MUX; @@ -414,13 +407,6 @@ static ssize_t del_mux_store(struct device *d, struct device_attribute *attr, c if (!rtnl_trylock()) return restart_syscall(); - /* we don't want to modify a running netdev */ - if (netif_running(dev->net)) { - netdev_err(dev->net, "Cannot change a running device\n"); - ret = -EBUSY; - goto err; - } - del_dev = qmimux_find_dev(dev, mux_id); if (!del_dev) { netdev_err(dev->net, "mux_id not present\n"); @@ -995,6 +981,7 @@ static const struct usb_device_id products[] = { {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0125)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0306)}, /* Quectel EP06/EG06/EM06 */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0512)}, /* Quectel EG12/EM12 */ + {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0620)}, /* Quectel EM160R-GL */ {QMI_MATCH_FF_FF_FF(0x2c7c, 0x0800)}, /* Quectel RM500Q-GL */ /* 3. Combined interface devices matching on interface number */ @@ -1029,7 +1016,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x05c6, 0x9011, 4)}, {QMI_FIXED_INTF(0x05c6, 0x9021, 1)}, {QMI_FIXED_INTF(0x05c6, 0x9022, 2)}, - {QMI_FIXED_INTF(0x05c6, 0x9025, 4)}, /* Alcatel-sbell ASB TL131 TDD LTE (China Mobile) */ + {QMI_QUIRK_SET_DTR(0x05c6, 0x9025, 4)}, /* Alcatel-sbell ASB TL131 TDD LTE (China Mobile) */ {QMI_FIXED_INTF(0x05c6, 0x9026, 3)}, {QMI_FIXED_INTF(0x05c6, 0x902e, 5)}, {QMI_FIXED_INTF(0x05c6, 0x9031, 5)}, @@ -1216,6 +1203,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1255, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1256, 4)}, {QMI_FIXED_INTF(0x19d2, 0x1270, 5)}, /* ZTE MF667 */ + {QMI_FIXED_INTF(0x19d2, 0x1275, 3)}, /* ZTE P685M */ {QMI_FIXED_INTF(0x19d2, 0x1401, 2)}, {QMI_FIXED_INTF(0x19d2, 0x1402, 2)}, /* ZTE MF60 */ {QMI_FIXED_INTF(0x19d2, 0x1424, 2)}, @@ -1283,12 +1271,14 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x0b3c, 0xc00a, 6)}, /* Olivetti Olicard 160 */ {QMI_FIXED_INTF(0x0b3c, 0xc00b, 4)}, /* Olivetti Olicard 500 */ {QMI_FIXED_INTF(0x1e2d, 0x0060, 4)}, /* Cinterion PLxx */ + {QMI_QUIRK_SET_DTR(0x1e2d, 0x006f, 8)}, /* Cinterion PLS83/PLS63 */ {QMI_FIXED_INTF(0x1e2d, 0x0053, 4)}, /* Cinterion PHxx,PXxx */ {QMI_FIXED_INTF(0x1e2d, 0x0063, 10)}, /* Cinterion ALASxx (1 RmNet) */ {QMI_FIXED_INTF(0x1e2d, 0x0082, 4)}, /* Cinterion PHxx,PXxx (2 RmNet) */ {QMI_FIXED_INTF(0x1e2d, 0x0082, 5)}, /* Cinterion PHxx,PXxx (2 RmNet) */ {QMI_FIXED_INTF(0x1e2d, 0x0083, 4)}, /* Cinterion PHxx,PXxx (1 RmNet + USB Audio)*/ {QMI_QUIRK_SET_DTR(0x1e2d, 0x00b0, 4)}, /* Cinterion CLS8 */ + {QMI_FIXED_INTF(0x1e2d, 0x00b7, 0)}, /* Cinterion MV31 RmNet */ {QMI_FIXED_INTF(0x413c, 0x81a2, 8)}, /* Dell Wireless 5806 Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81a3, 8)}, /* Dell Wireless 5570 HSPA+ (42Mbps) Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 1b1ec4197830..a27ea04cfa6c 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -2593,29 +2593,6 @@ static void __rtl_set_wol(struct r8152 *tp, u32 wolopts) device_set_wakeup_enable(&tp->udev->dev, false); } -static void r8153_mac_clk_spd(struct r8152 *tp, bool enable) -{ - /* MAC clock speed down */ - if (enable) { - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, - ALDPS_SPDWN_RATIO); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, - EEE_SPDWN_RATIO); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, - PKT_AVAIL_SPDWN_EN | SUSPEND_SPDWN_EN | - U1U2_SPDWN_EN | L1_SPDWN_EN); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, - PWRSAVE_SPDWN_EN | RXDV_SPDWN_EN | TX10MIDLE_EN | - TP100_SPDWN_EN | TP500_SPDWN_EN | EEE_SPDWN_EN | - TP1000_SPDWN_EN); - } else { - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0); - ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0); - } -} - static void r8153_u1u2en(struct r8152 *tp, bool enable) { u8 u1u2[8]; @@ -2847,11 +2824,9 @@ static void rtl8153_runtime_enable(struct r8152 *tp, bool enable) if (enable) { r8153_u1u2en(tp, false); r8153_u2p3en(tp, false); - r8153_mac_clk_spd(tp, true); rtl_runtime_suspend_enable(tp, true); } else { rtl_runtime_suspend_enable(tp, false); - r8153_mac_clk_spd(tp, false); switch (tp->version) { case RTL_VER_03: @@ -3413,7 +3388,6 @@ static void r8153_first_init(struct r8152 *tp) u32 ocp_data; int i; - r8153_mac_clk_spd(tp, false); rxdy_gated_en(tp, true); r8153_teredo_off(tp); @@ -3475,8 +3449,6 @@ static void r8153_enter_oob(struct r8152 *tp) u32 ocp_data; int i; - r8153_mac_clk_spd(tp, true); - ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); ocp_data &= ~NOW_IS_OOB; ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); @@ -4141,9 +4113,14 @@ static void r8153_init(struct r8152 *tp) ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001); + /* MAC clock speed down */ + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, 0); + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL2, 0); + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL3, 0); + ocp_write_word(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL4, 0); + r8153_power_cut_en(tp, false); r8153_u1u2en(tp, true); - r8153_mac_clk_spd(tp, false); usb_enable_lpm(tp->udev); /* rx aggregation */ @@ -5352,6 +5329,7 @@ static const struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x721e)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0xa387)}, {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index a22ae3137a3f..d3f79a4067e2 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -399,7 +399,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) reply_len = sizeof *phym; retval = rndis_query(dev, intf, u.buf, RNDIS_OID_GEN_PHYSICAL_MEDIUM, - 0, (void **) &phym, &reply_len); + reply_len, (void **)&phym, &reply_len); if (retval != 0 || !phym) { /* OID is optional so don't fail here. */ phym_unspec = cpu_to_le32(RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 2abbad1abaf2..fd1843fd256b 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -197,8 +197,7 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) if (rxq < rcv->real_num_rx_queues) { rq = &rcv_priv->rq[rxq]; rcv_xdp = rcu_access_pointer(rq->xdp_prog); - if (rcv_xdp) - skb_record_rx_queue(skb, rxq); + skb_record_rx_queue(skb, rxq); } if (likely(veth_forward_skb(rcv, skb, rq, rcv_xdp) == NET_RX_SUCCESS)) { diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b21223be93c8..0b1c6a8906b9 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -383,7 +383,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, struct receive_queue *rq, struct page *page, unsigned int offset, unsigned int len, unsigned int truesize, - bool hdr_valid) + bool hdr_valid, unsigned int metasize) { struct sk_buff *skb; struct virtio_net_hdr_mrg_rxbuf *hdr; @@ -405,6 +405,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, else hdr_padded_len = sizeof(struct padded_vnet_hdr); + /* hdr_valid means no XDP, so we can copy the vnet header */ if (hdr_valid) memcpy(hdr, p, hdr_len); @@ -417,6 +418,11 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, copy = skb_tailroom(skb); skb_put_data(skb, p, copy); + if (metasize) { + __skb_pull(skb, metasize); + skb_metadata_set(skb, metasize); + } + len -= copy; offset += copy; @@ -462,10 +468,6 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi, struct virtio_net_hdr_mrg_rxbuf *hdr; int err; - /* virtqueue want to use data area in-front of packet */ - if (unlikely(xdpf->metasize > 0)) - return -EOPNOTSUPP; - if (unlikely(xdpf->headroom < vi->hdr_len)) return -EOVERFLOW; @@ -656,6 +658,7 @@ static struct sk_buff *receive_small(struct net_device *dev, unsigned int delta = 0; struct page *xdp_page; int err; + unsigned int metasize = 0; len -= vi->hdr_len; stats->bytes += len; @@ -695,8 +698,8 @@ static struct sk_buff *receive_small(struct net_device *dev, xdp.data_hard_start = buf + VIRTNET_RX_PAD + vi->hdr_len; xdp.data = xdp.data_hard_start + xdp_headroom; - xdp_set_data_meta_invalid(&xdp); xdp.data_end = xdp.data + len; + xdp.data_meta = xdp.data; xdp.rxq = &rq->xdp_rxq; orig_data = xdp.data; act = bpf_prog_run_xdp(xdp_prog, &xdp); @@ -707,6 +710,7 @@ static struct sk_buff *receive_small(struct net_device *dev, /* Recalculate length in case bpf program changed it */ delta = orig_data - xdp.data; len = xdp.data_end - xdp.data; + metasize = xdp.data - xdp.data_meta; break; case XDP_TX: stats->xdp_tx++; @@ -752,6 +756,9 @@ static struct sk_buff *receive_small(struct net_device *dev, memcpy(skb_vnet_hdr(skb), buf, vi->hdr_len); } /* keep zeroed vnet hdr since packet was changed by bpf */ + if (metasize) + skb_metadata_set(skb, metasize); + err: return skb; @@ -772,8 +779,8 @@ static struct sk_buff *receive_big(struct net_device *dev, struct virtnet_rq_stats *stats) { struct page *page = buf; - struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, - PAGE_SIZE, true); + struct sk_buff *skb = + page_to_skb(vi, rq, page, 0, len, PAGE_SIZE, true, 0); stats->bytes += len - vi->hdr_len; if (unlikely(!skb)) @@ -805,6 +812,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, unsigned int truesize; unsigned int headroom = mergeable_ctx_to_headroom(ctx); int err; + unsigned int metasize = 0; head_skb = NULL; stats->bytes += len - vi->hdr_len; @@ -851,8 +859,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, data = page_address(xdp_page) + offset; xdp.data_hard_start = data - VIRTIO_XDP_HEADROOM + vi->hdr_len; xdp.data = data + vi->hdr_len; - xdp_set_data_meta_invalid(&xdp); xdp.data_end = xdp.data + (len - vi->hdr_len); + xdp.data_meta = xdp.data; xdp.rxq = &rq->xdp_rxq; act = bpf_prog_run_xdp(xdp_prog, &xdp); @@ -860,24 +868,27 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, switch (act) { case XDP_PASS: + metasize = xdp.data - xdp.data_meta; + /* recalculate offset to account for any header - * adjustments. Note other cases do not build an - * skb and avoid using offset + * adjustments and minus the metasize to copy the + * metadata in page_to_skb(). Note other cases do not + * build an skb and avoid using offset */ - offset = xdp.data - - page_address(xdp_page) - vi->hdr_len; + offset = xdp.data - page_address(xdp_page) - + vi->hdr_len - metasize; - /* recalculate len if xdp.data or xdp.data_end were - * adjusted + /* recalculate len if xdp.data, xdp.data_end or + * xdp.data_meta were adjusted */ - len = xdp.data_end - xdp.data + vi->hdr_len; + len = xdp.data_end - xdp.data + vi->hdr_len + metasize; /* We can only create skb based on xdp_page. */ if (unlikely(xdp_page != page)) { rcu_read_unlock(); put_page(page); - head_skb = page_to_skb(vi, rq, xdp_page, - offset, len, - PAGE_SIZE, false); + head_skb = page_to_skb(vi, rq, xdp_page, offset, + len, PAGE_SIZE, false, + metasize); return head_skb; } break; @@ -933,7 +944,8 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, goto err_skb; } - head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog); + head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog, + metasize); curr_skb = head_skb; if (unlikely(!curr_skb)) @@ -2077,14 +2089,16 @@ static int virtnet_set_channels(struct net_device *dev, get_online_cpus(); err = _virtnet_set_queues(vi, queue_pairs); - if (!err) { - netif_set_real_num_tx_queues(dev, queue_pairs); - netif_set_real_num_rx_queues(dev, queue_pairs); - - virtnet_set_affinity(vi); + if (err) { + put_online_cpus(); + goto err; } + virtnet_set_affinity(vi); put_online_cpus(); + netif_set_real_num_tx_queues(dev, queue_pairs); + netif_set_real_num_rx_queues(dev, queue_pairs); + err: return err; } diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index b55eeb8f8fa3..93899a7be9c5 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -336,8 +336,7 @@ static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev) return ret; } -static int vrf_finish_direct(struct net *net, struct sock *sk, - struct sk_buff *skb) +static void vrf_finish_direct(struct sk_buff *skb) { struct net_device *vrf_dev = skb->dev; @@ -356,7 +355,8 @@ static int vrf_finish_direct(struct net *net, struct sock *sk, skb_pull(skb, ETH_HLEN); } - return 1; + /* reset skb device */ + nf_reset(skb); } #if IS_ENABLED(CONFIG_IPV6) @@ -435,15 +435,41 @@ static struct sk_buff *vrf_ip6_out_redirect(struct net_device *vrf_dev, return skb; } +static int vrf_output6_direct_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + vrf_finish_direct(skb); + + return vrf_ip6_local_out(net, sk, skb); +} + static int vrf_output6_direct(struct net *net, struct sock *sk, struct sk_buff *skb) { + int err = 1; + skb->protocol = htons(ETH_P_IPV6); - return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, - net, sk, skb, NULL, skb->dev, - vrf_finish_direct, - !(IPCB(skb)->flags & IPSKB_REROUTED)); + if (!(IPCB(skb)->flags & IPSKB_REROUTED)) + err = nf_hook(NFPROTO_IPV6, NF_INET_POST_ROUTING, net, sk, skb, + NULL, skb->dev, vrf_output6_direct_finish); + + if (likely(err == 1)) + vrf_finish_direct(skb); + + return err; +} + +static int vrf_ip6_out_direct_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + int err; + + err = vrf_output6_direct(net, sk, skb); + if (likely(err == 1)) + err = vrf_ip6_local_out(net, sk, skb); + + return err; } static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev, @@ -456,18 +482,15 @@ static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev, skb->dev = vrf_dev; err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, - skb, NULL, vrf_dev, vrf_output6_direct); + skb, NULL, vrf_dev, vrf_ip6_out_direct_finish); if (likely(err == 1)) err = vrf_output6_direct(net, sk, skb); - /* reset skb device */ if (likely(err == 1)) - nf_reset(skb); - else - skb = NULL; + return skb; - return skb; + return NULL; } static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev, @@ -649,15 +672,41 @@ static struct sk_buff *vrf_ip_out_redirect(struct net_device *vrf_dev, return skb; } +static int vrf_output_direct_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + vrf_finish_direct(skb); + + return vrf_ip_local_out(net, sk, skb); +} + static int vrf_output_direct(struct net *net, struct sock *sk, struct sk_buff *skb) { + int err = 1; + skb->protocol = htons(ETH_P_IP); - return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, - net, sk, skb, NULL, skb->dev, - vrf_finish_direct, - !(IPCB(skb)->flags & IPSKB_REROUTED)); + if (!(IPCB(skb)->flags & IPSKB_REROUTED)) + err = nf_hook(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, skb, + NULL, skb->dev, vrf_output_direct_finish); + + if (likely(err == 1)) + vrf_finish_direct(skb); + + return err; +} + +static int vrf_ip_out_direct_finish(struct net *net, struct sock *sk, + struct sk_buff *skb) +{ + int err; + + err = vrf_output_direct(net, sk, skb); + if (likely(err == 1)) + err = vrf_ip_local_out(net, sk, skb); + + return err; } static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev, @@ -670,18 +719,15 @@ static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev, skb->dev = vrf_dev; err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk, - skb, NULL, vrf_dev, vrf_output_direct); + skb, NULL, vrf_dev, vrf_ip_out_direct_finish); if (likely(err == 1)) err = vrf_output_direct(net, sk, skb); - /* reset skb device */ if (likely(err == 1)) - nf_reset(skb); - else - skb = NULL; + return skb; - return skb; + return NULL; } static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev, diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index abf85f0ab72f..49e8c6d42cda 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -3180,6 +3180,9 @@ static void vxlan_config_apply(struct net_device *dev, dev->gso_max_segs = lowerdev->gso_max_segs; needed_headroom = lowerdev->hard_header_len; + needed_headroom += lowerdev->needed_headroom; + + dev->needed_tailroom = lowerdev->needed_tailroom; max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); @@ -3809,7 +3812,6 @@ static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_dev *vxlan, *next; struct net_device *dev, *aux; - unsigned int h; for_each_netdev_safe(net, dev, aux) if (dev->rtnl_link_ops == &vxlan_link_ops) @@ -3823,14 +3825,13 @@ static void vxlan_destroy_tunnels(struct net *net, struct list_head *head) unregister_netdevice_queue(vxlan->dev, head); } - for (h = 0; h < PORT_HASH_SIZE; ++h) - WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h])); } static void __net_exit vxlan_exit_batch_net(struct list_head *net_list) { struct net *net; LIST_HEAD(list); + unsigned int h; rtnl_lock(); list_for_each_entry(net, net_list, exit_list) @@ -3838,6 +3839,13 @@ static void __net_exit vxlan_exit_batch_net(struct list_head *net_list) unregister_netdevice_many(&list); rtnl_unlock(); + + list_for_each_entry(net, net_list, exit_list) { + struct vxlan_net *vn = net_generic(net, vxlan_net_id); + + for (h = 0; h < PORT_HASH_SIZE; ++h) + WARN_ON_ONCE(!hlist_empty(&vn->sock_list[h])); + } } static struct pernet_operations vxlan_net_ops = { diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 21190dfbabb1..17ed5107b90a 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -295,6 +295,7 @@ config SLIC_DS26522 tristate "Slic Maxim ds26522 card support" depends on SPI depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE || COMPILE_TEST + select BITREVERSE help This module initializes and configures the slic maxim card in T1 or E1 mode. diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index f6b000ddcd15..b7bfc0caa5dc 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -902,6 +902,7 @@ static ssize_t cosa_write(struct file *file, chan->tx_status = 1; spin_unlock_irqrestore(&cosa->lock, flags); up(&chan->wsem); + kfree(kbuf); return -ERESTARTSYS; } } diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 9ab04ef532f3..5df6e85e7ccb 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -201,14 +201,18 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) priv->rx_skbuff = kcalloc(priv->rx_ring_size, sizeof(*priv->rx_skbuff), GFP_KERNEL); - if (!priv->rx_skbuff) + if (!priv->rx_skbuff) { + ret = -ENOMEM; goto free_ucc_pram; + } priv->tx_skbuff = kcalloc(priv->tx_ring_size, sizeof(*priv->tx_skbuff), GFP_KERNEL); - if (!priv->tx_skbuff) + if (!priv->tx_skbuff) { + ret = -ENOMEM; goto free_rx_skbuff; + } priv->skb_curtx = 0; priv->skb_dirtytx = 0; diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 20d9b6585fba..d67623d61dc4 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -572,6 +572,13 @@ static void ppp_timer(struct timer_list *t) unsigned long flags; spin_lock_irqsave(&ppp->lock, flags); + /* mod_timer could be called after we entered this function but + * before we got the lock. + */ + if (timer_pending(&proto->timer)) { + spin_unlock_irqrestore(&ppp->lock, flags); + return; + } switch (proto->state) { case STOPPING: case REQ_SENT: diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index e5fc1b95cea6..fad5fc8b9edb 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -286,7 +286,6 @@ static int lapbeth_open(struct net_device *dev) return -ENODEV; } - netif_start_queue(dev); return 0; } @@ -294,8 +293,6 @@ static int lapbeth_close(struct net_device *dev) { int err; - netif_stop_queue(dev); - if ((err = lapb_unregister(dev)) != LAPB_OK) pr_err("lapb_unregister error: %d\n", err); diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 4907453f17f5..937f56d0a31d 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -915,6 +915,8 @@ static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) break; default: printk(KERN_WARNING "%s: LMC UNKNOWN CARD!\n", dev->name); + unregister_hdlc_device(dev); + return -EIO; break; } diff --git a/drivers/net/wireguard/ratelimiter.c b/drivers/net/wireguard/ratelimiter.c index 9baa930c8157..3fedd1d21f5e 100644 --- a/drivers/net/wireguard/ratelimiter.c +++ b/drivers/net/wireguard/ratelimiter.c @@ -170,9 +170,9 @@ int wg_ratelimiter_init(void) * we borrow their wisdom about good table sizes on different systems * dependent on RAM. This calculation here comes from there. */ - table_size = (totalram_pages > (1U << 30) / PAGE_SIZE) ? 8192 : + table_size = (totalram_pages() > (1U << 30) / PAGE_SIZE) ? 8192 : max_t(unsigned long, 16, roundup_pow_of_two( - (totalram_pages << PAGE_SHIFT) / + (totalram_pages() << PAGE_SHIFT) / (1U << 14) / sizeof(struct hlist_head))); max_entries = table_size * 8; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index faaca7fe9ad1..f32d35e03708 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3567,23 +3567,16 @@ bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar) static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb) { struct sk_buff_head *q = &ar->wmi_mgmt_tx_queue; - int ret = 0; - - spin_lock_bh(&ar->data_lock); - if (skb_queue_len(q) == ATH10K_MAX_NUM_MGMT_PENDING) { + if (skb_queue_len_lockless(q) >= ATH10K_MAX_NUM_MGMT_PENDING) { ath10k_warn(ar, "wmi mgmt tx queue is full\n"); - ret = -ENOSPC; - goto unlock; + return -ENOSPC; } - __skb_queue_tail(q, skb); + skb_queue_tail(q, skb); ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work); -unlock: - spin_unlock_bh(&ar->data_lock); - - return ret; + return 0; } static enum ath10k_mac_tx_path diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index e2d78f77edb7..241e6f0e1dfe 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -789,13 +789,14 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar) ret = ath10k_snoc_init_pipes(ar); if (ret) { ath10k_err(ar, "failed to initialize CE: %d\n", ret); - goto err_wlan_enable; + goto err_free_rri; } napi_enable(&ar->napi); return 0; -err_wlan_enable: +err_free_rri: + ath10k_ce_free_rri(ar); ath10k_snoc_wlan_disable(ar); return ret; diff --git a/drivers/net/wireless/ath/ath10k/usb.c b/drivers/net/wireless/ath/ath10k/usb.c index c64a03f164c0..16d5fe6d1e2e 100644 --- a/drivers/net/wireless/ath/ath10k/usb.c +++ b/drivers/net/wireless/ath/ath10k/usb.c @@ -1019,6 +1019,8 @@ static int ath10k_usb_probe(struct usb_interface *interface, ar_usb = ath10k_usb_priv(ar); ret = ath10k_usb_create(ar, interface); + if (ret) + goto err; ar_usb->ar = ar; ar->dev_id = product_id; @@ -1030,7 +1032,7 @@ static int ath10k_usb_probe(struct usb_interface *interface, ret = ath10k_core_register(ar, chip_id); if (ret) { ath10k_warn(ar, "failed to register driver core: %d\n", ret); - goto err; + goto err_usb_destroy; } /* TODO: remove this once USB support is fully implemented */ @@ -1038,6 +1040,9 @@ static int ath10k_usb_probe(struct usb_interface *interface, return 0; +err_usb_destroy: + ath10k_usb_destroy(ar); + err: ath10k_core_destroy(ar); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 7f435fa29f75..04dc5714aa72 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -449,13 +449,13 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) case WMI_TDLS_TEARDOWN_REASON_TX: case WMI_TDLS_TEARDOWN_REASON_RSSI: case WMI_TDLS_TEARDOWN_REASON_PTR_TIMEOUT: + rcu_read_lock(); station = ieee80211_find_sta_by_ifaddr(ar->hw, ev->peer_macaddr.addr, NULL); if (!station) { ath10k_warn(ar, "did not find station from tdls peer event"); - kfree(tb); - return; + goto exit; } arvif = ath10k_get_arvif(ar, __le32_to_cpu(ev->vdev_id)); ieee80211_tdls_oper_request( @@ -466,6 +466,9 @@ static void ath10k_wmi_event_tdls_peer(struct ath10k *ar, struct sk_buff *skb) ); break; } + +exit: + rcu_read_unlock(); kfree(tb); } @@ -1157,13 +1160,15 @@ static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len, switch (tag) { case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT: + arg->service_map_ext_valid = true; arg->service_map_ext_len = *(__le32 *)ptr; arg->service_map_ext = ptr + sizeof(__le32); return 0; default: break; } - return -EPROTO; + + return 0; } static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar, diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 3f3fbee631c3..41eb57be9222 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -5510,8 +5510,13 @@ void ath10k_wmi_event_service_available(struct ath10k *ar, struct sk_buff *skb) ret); } - ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map, - __le32_to_cpu(arg.service_map_ext_len)); + /* + * Initialization of "arg.service_map_ext_valid" to ZERO is necessary + * for the below logic to work. + */ + if (arg.service_map_ext_valid) + ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map, + __le32_to_cpu(arg.service_map_ext_len)); } static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index e341cfb3fcc2..6bd63d1cd039 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -6710,6 +6710,7 @@ struct wmi_svc_rdy_ev_arg { }; struct wmi_svc_avail_ev_arg { + bool service_map_ext_valid; __le32 service_map_ext_len; const __le32 *service_map_ext; }; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0fca44e91a71..de3befc2edd1 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -179,7 +179,8 @@ struct ath_frame_info { s8 txq; u8 keyix; u8 rtscts_rate; - u8 retries : 7; + u8 retries : 6; + u8 dyn_smps : 1; u8 baw_tracked : 1; u8 tx_power; enum ath9k_key_type keytype:2; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 0a6eb8a8c1ed..84fe68670949 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1236,8 +1236,11 @@ static ssize_t write_file_nf_override(struct file *file, ah->nf_override = val; - if (ah->curchan) + if (ah->curchan) { + ath9k_ps_wakeup(sc); ath9k_hw_loadnf(ah, ah->curchan); + ath9k_ps_restore(sc); + } return count; } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f19393e584dc..d567fbe79cff 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -973,7 +973,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, struct ath_htc_rx_status *rxstatus; struct ath_rx_status rx_stats; bool decrypt_error = false; - __be16 rs_datalen; + u16 rs_datalen; bool is_phyerr; if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4b7a7fc2a0fe..29f71457e26b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1324,6 +1324,11 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, is_40, is_sgi, is_sp); if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC)) info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC; + if (rix >= 8 && fi->dyn_smps) { + info->rates[i].RateFlags |= + ATH9K_RATESERIES_RTS_CTS; + info->flags |= ATH9K_TXDESC_CTSENA; + } info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, is_40, false); @@ -2206,6 +2211,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, fi->keyix = an->ps_key; else fi->keyix = ATH9K_TXKEYIX_INVALID; + fi->dyn_smps = sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC; fi->keytype = keytype; fi->framelen = framelen; fi->tx_power = txpower; diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index 1c0bf47f55d4..2bb03396f992 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -1,6 +1,7 @@ config WIL6210 tristate "Wilocity 60g WiFi card wil6210 support" select WANT_DEV_COREDUMP + select CRC32 depends on CFG80211 depends on PCI default n diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c index 44ab080d6518..88446258e775 100644 --- a/drivers/net/wireless/broadcom/b43/phy_n.c +++ b/drivers/net/wireless/broadcom/b43/phy_n.c @@ -5320,7 +5320,7 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) for (i = 0; i < 4; i++) { if (dev->phy.rev >= 3) - table[i] = coef[i]; + coef[i] = table[i]; else coef[i] = 0; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index bbdc6000afb9..96dc9e5ab23f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -5282,7 +5282,8 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif, return false; } -static bool brcmf_is_linkdown(const struct brcmf_event_msg *e) +static bool brcmf_is_linkdown(struct brcmf_cfg80211_vif *vif, + const struct brcmf_event_msg *e) { u32 event = e->event_code; u16 flags = e->flags; @@ -5291,6 +5292,8 @@ static bool brcmf_is_linkdown(const struct brcmf_event_msg *e) (event == BRCMF_E_DISASSOC_IND) || ((event == BRCMF_E_LINK) && (!(flags & BRCMF_EVENT_MSG_LINK)))) { brcmf_dbg(CONN, "Processing link down\n"); + clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state); return true; } return false; @@ -5581,7 +5584,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, } else brcmf_bss_connect_done(cfg, ndev, e, true); brcmf_net_setcarrier(ifp, true); - } else if (brcmf_is_linkdown(e)) { + } else if (brcmf_is_linkdown(ifp->vif, e)) { brcmf_dbg(CONN, "Linkdown\n"); if (!brcmf_is_ibssmode(ifp->vif)) { brcmf_bss_connect_done(cfg, ndev, e, false); diff --git a/drivers/net/wireless/cnss2/debug.h b/drivers/net/wireless/cnss2/debug.h index 1d7b488d2963..ca6d5b3faf02 100644 --- a/drivers/net/wireless/cnss2/debug.h +++ b/drivers/net/wireless/cnss2/debug.h @@ -23,29 +23,23 @@ extern void *cnss_ipc_log_long_context; } while (0) #define cnss_pr_err(_fmt, ...) do { \ - printk("%scnss: " _fmt, KERN_ERR, ##__VA_ARGS__); \ - cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\ + no_printk(_fmt, ##__VA_ARGS__); \ } while (0) #define cnss_pr_warn(_fmt, ...) do { \ - printk("%scnss: " _fmt, KERN_WARNING, ##__VA_ARGS__); \ - cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\ + no_printk(_fmt, ##__VA_ARGS__); \ } while (0) #define cnss_pr_info(_fmt, ...) do { \ - printk("%scnss: " _fmt, KERN_INFO, ##__VA_ARGS__); \ - cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\ + no_printk(_fmt, ##__VA_ARGS__); \ } while (0) #define cnss_pr_dbg(_fmt, ...) do { \ - printk("%scnss: " _fmt, KERN_DEBUG, ##__VA_ARGS__); \ - cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\ + no_printk(_fmt, ##__VA_ARGS__); \ } while (0) #define cnss_pr_vdbg(_fmt, ...) do { \ - printk("%scnss: " _fmt, KERN_DEBUG, ##__VA_ARGS__); \ - cnss_ipc_log_long_string("%scnss: " _fmt, "", \ - ##__VA_ARGS__); \ + no_printk(_fmt, ##__VA_ARGS__); \ } while (0) #ifdef CONFIG_CNSS2_DEBUG diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 74fd398e8a49..d53d5a8836a3 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include #include @@ -41,6 +41,7 @@ #define CNSS_QMI_TIMEOUT_DEFAULT 20000 #define CNSS_BDF_TYPE_DEFAULT CNSS_BDF_ELF #define CNSS_TIME_SYNC_PERIOD_DEFAULT 900000 +#define CNSS_MIN_TIME_SYNC_PERIOD 2000 static struct cnss_plat_data *plat_env; @@ -609,6 +610,38 @@ int cnss_driver_event_post(struct cnss_plat_data *plat_priv, return ret; } +/** + * cnss_get_timeout - Get timeout for corresponding type. + * @plat_priv: Pointer to platform driver context. + * @cnss_timeout_type: Timeout type. + * + * Return: Timeout in milliseconds. + */ +unsigned int cnss_get_timeout(struct cnss_plat_data *plat_priv, + enum cnss_timeout_type timeout_type) +{ + unsigned int qmi_timeout = cnss_get_qmi_timeout(plat_priv); + + switch (timeout_type) { + case CNSS_TIMEOUT_QMI: + return qmi_timeout; + case CNSS_TIMEOUT_POWER_UP: + return (qmi_timeout << 2); + case CNSS_TIMEOUT_IDLE_RESTART: + return ((qmi_timeout << 1) + WLAN_WD_TIMEOUT_MS); + case CNSS_TIMEOUT_CALIBRATION: + return (qmi_timeout << 2); + case CNSS_TIMEOUT_WLAN_WATCHDOG: + return ((qmi_timeout << 1) + WLAN_WD_TIMEOUT_MS); + case CNSS_TIMEOUT_RDDM: + return CNSS_RDDM_TIMEOUT_MS; + case CNSS_TIMEOUT_RECOVERY: + return RECOVERY_TIMEOUT; + default: + return qmi_timeout; + } +} + unsigned int cnss_get_boot_timeout(struct device *dev) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); @@ -618,7 +651,7 @@ unsigned int cnss_get_boot_timeout(struct device *dev) return 0; } - return cnss_get_qmi_timeout(plat_priv); + return cnss_get_timeout(plat_priv, CNSS_TIMEOUT_QMI); } EXPORT_SYMBOL(cnss_get_boot_timeout); @@ -644,13 +677,14 @@ int cnss_power_up(struct device *dev) if (plat_priv->device_id == QCA6174_DEVICE_ID) goto out; - timeout = cnss_get_boot_timeout(dev); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_POWER_UP); reinit_completion(&plat_priv->power_up_complete); ret = wait_for_completion_timeout(&plat_priv->power_up_complete, - msecs_to_jiffies(timeout) << 2); + msecs_to_jiffies(timeout)); if (!ret) { - cnss_pr_err("Timeout waiting for power up to complete\n"); + cnss_pr_err("Timeout (%ums) waiting for power up to complete\n", + timeout); ret = -EAGAIN; goto out; } @@ -716,10 +750,9 @@ int cnss_idle_restart(struct device *dev) goto out; } - timeout = cnss_get_boot_timeout(dev); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_IDLE_RESTART); ret = wait_for_completion_timeout(&plat_priv->power_up_complete, - msecs_to_jiffies((timeout << 1) + - WLAN_WD_TIMEOUT_MS)); + msecs_to_jiffies(timeout)); if (plat_priv->power_up_error) { ret = plat_priv->power_up_error; clear_bit(CNSS_DRIVER_IDLE_RESTART, &plat_priv->driver_state); @@ -729,7 +762,8 @@ int cnss_idle_restart(struct device *dev) } if (!ret) { - cnss_pr_err("Timeout waiting for idle restart to complete\n"); + cnss_pr_err("Timeout (%ums) waiting for idle restart to complete\n", + timeout); ret = -ETIMEDOUT; goto out; } @@ -753,6 +787,7 @@ EXPORT_SYMBOL(cnss_idle_restart); int cnss_idle_shutdown(struct device *dev) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + unsigned int timeout; int ret; if (!plat_priv) { @@ -772,10 +807,12 @@ int cnss_idle_shutdown(struct device *dev) goto skip_wait; reinit_completion(&plat_priv->recovery_complete); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_RECOVERY); ret = wait_for_completion_timeout(&plat_priv->recovery_complete, - msecs_to_jiffies(RECOVERY_TIMEOUT)); + msecs_to_jiffies(timeout)); if (!ret) { - cnss_pr_err("Timeout waiting for recovery to complete\n"); + cnss_pr_err("Timeout (%ums) waiting for recovery to complete\n", + timeout); CNSS_ASSERT(0); } @@ -1317,6 +1354,7 @@ EXPORT_SYMBOL(cnss_force_fw_assert); int cnss_force_collect_rddm(struct device *dev) { struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + unsigned int timeout; int ret = 0; if (!plat_priv) { @@ -1352,11 +1390,14 @@ int cnss_force_collect_rddm(struct device *dev) return ret; reinit_completion(&plat_priv->rddm_complete); - ret = wait_for_completion_timeout - (&plat_priv->rddm_complete, - msecs_to_jiffies(CNSS_RDDM_TIMEOUT_MS)); - if (!ret) + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_RDDM); + ret = wait_for_completion_timeout(&plat_priv->rddm_complete, + msecs_to_jiffies(timeout)); + if (!ret) { + cnss_pr_err("Timeout (%ums) waiting for RDDM to complete\n", + timeout); ret = -ETIMEDOUT; + } return ret; } @@ -2292,6 +2333,33 @@ static void cnss_unregister_bus_scale(struct cnss_plat_data *plat_priv) msm_bus_scale_unregister_client(bus_bw_info->bus_client); } +static ssize_t qtime_sync_period_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%u\n", + plat_priv->ctrl_params.time_sync_period); +} + +static ssize_t qtime_sync_period_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned int qtime_sync_period = 0; + + if (sscanf(buf, "%du", &qtime_sync_period) != 1) { + cnss_pr_err("Invalid qtime sync sysfs command\n"); + return -EINVAL; + } + + if (qtime_sync_period >= CNSS_MIN_TIME_SYNC_PERIOD) + cnss_pci_update_qtime_sync_period(dev, qtime_sync_period); + + return count; +} + static ssize_t recovery_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -2382,11 +2450,13 @@ static ssize_t fs_ready_store(struct device *dev, static DEVICE_ATTR_WO(fs_ready); static DEVICE_ATTR_WO(shutdown); static DEVICE_ATTR_WO(recovery); +static DEVICE_ATTR_RW(qtime_sync_period); static struct attribute *cnss_attrs[] = { &dev_attr_fs_ready.attr, &dev_attr_shutdown.attr, &dev_attr_recovery.attr, + &dev_attr_qtime_sync_period.attr, NULL, }; diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index b4001136c924..bb4edc38dc2c 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _CNSS_MAIN_H #define _CNSS_MAIN_H @@ -331,6 +331,16 @@ enum cnss_ce_index { CNSS_CE_COMMON, }; +enum cnss_timeout_type { + CNSS_TIMEOUT_QMI, + CNSS_TIMEOUT_POWER_UP, + CNSS_TIMEOUT_IDLE_RESTART, + CNSS_TIMEOUT_CALIBRATION, + CNSS_TIMEOUT_WLAN_WATCHDOG, + CNSS_TIMEOUT_RDDM, + CNSS_TIMEOUT_RECOVERY, +}; + struct cnss_plat_data { struct platform_device *plat_dev; void *bus_priv; @@ -364,6 +374,7 @@ struct cnss_plat_data { struct wlfw_rf_board_info board_info; struct wlfw_soc_info soc_info; struct wlfw_fw_version_info fw_version_info; + struct cnss_dev_mem_info dev_mem_info[CNSS_MAX_DEV_MEM_NUM]; char fw_build_id[QMI_WLFW_MAX_BUILD_ID_LEN + 1]; u32 otp_version; u32 fw_mem_seg_len; @@ -466,5 +477,8 @@ int cnss_minidump_add_region(struct cnss_plat_data *plat_priv, int cnss_minidump_remove_region(struct cnss_plat_data *plat_priv, enum cnss_fw_dump_type type, int seg_no, void *va, phys_addr_t pa, size_t size); - +unsigned int cnss_get_timeout(struct cnss_plat_data *plat_priv, + enum cnss_timeout_type); +int cnss_pci_update_qtime_sync_period(struct device *dev, + unsigned int qtime_sync_period); #endif /* _CNSS_MAIN_H */ diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 1d9f8a3b3dc3..78b4c4770a28 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -364,6 +364,31 @@ static struct cnss_misc_reg wlaon_reg_access_seq[] = { #define PCIE_REG_SIZE ARRAY_SIZE(pcie_reg_access_seq) #define WLAON_REG_SIZE ARRAY_SIZE(wlaon_reg_access_seq) +#if IS_ENABLED(CONFIG_PCI_MSM) +/** + * _cnss_pci_get_reg_dump() - Dump PCIe RC registers for debug + * @pci_priv: driver PCI bus context pointer + * @buf: destination buffer pointer + * @len: length of the buffer + * + * This function shall call corresponding PCIe root complex driver API + * to dump PCIe RC registers for debug purpose. + * + * Return: 0 for success, negative value for error + */ +static int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv, + u8 *buf, u32 len) +{ + return msm_pcie_reg_dump(pci_priv->pci_dev, buf, len); +} +#else +static int _cnss_pci_get_reg_dump(struct cnss_pci_data *pci_priv, + u8 *buf, u32 len) +{ + return 0; +} +#endif /* CONFIG_PCI_MSM */ + int cnss_pci_check_link_status(struct cnss_pci_data *pci_priv) { u16 device_id; @@ -930,15 +955,21 @@ EXPORT_SYMBOL(cnss_pci_link_down); int cnss_pci_get_reg_dump(struct device *dev, uint8_t *buffer, uint32_t len) { struct pci_dev *pci_dev = to_pci_dev(dev); + struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev); - if (!pci_dev) { - cnss_pr_err("pci_dev is NULL\n"); - return -EINVAL; + if (!pci_priv) { + cnss_pr_err("pci_priv is NULL\n"); + return -ENODEV; + } + + if (pci_priv->pci_link_state == PCI_LINK_DOWN) { + cnss_pr_dbg("No PCIe reg dump since PCIe device is suspended(D3)\n"); + return -EACCES; } - cnss_pr_dbg("Get pci reg dump for hang data\n"); + cnss_pr_dbg("Start to get PCIe reg dump\n"); - return msm_pcie_reg_dump(pci_dev, buffer, len); + return _cnss_pci_get_reg_dump(pci_priv, buffer, len); } EXPORT_SYMBOL(cnss_pci_get_reg_dump); @@ -1471,6 +1502,24 @@ static void cnss_pci_stop_time_sync_update(struct cnss_pci_data *pci_priv) cancel_delayed_work_sync(&pci_priv->time_sync_work); } +int cnss_pci_update_qtime_sync_period(struct device *dev, + unsigned int qtime_sync_period) +{ + struct cnss_plat_data *plat_priv = dev_get_drvdata(dev); + struct cnss_pci_data *pci_priv = plat_priv->bus_priv; + + if (!plat_priv || !pci_priv) + return -ENODEV; + + cnss_pci_stop_time_sync_update(pci_priv); + plat_priv->ctrl_params.time_sync_period = qtime_sync_period; + cnss_pci_start_time_sync_update(pci_priv); + cnss_pr_dbg("WLAN qtime sync period %u\n", + plat_priv->ctrl_params.time_sync_period); + + return 0; +} + int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv) { int ret = 0; @@ -2024,7 +2073,7 @@ static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv) } cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, false, false); - timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_QMI); ret = cnss_pci_start_mhi(pci_priv); if (ret) { @@ -2310,11 +2359,12 @@ int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops) cnss_pr_dbg("Start to wait for calibration to complete\n"); - timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_CALIBRATION); ret = wait_for_completion_timeout(&plat_priv->cal_complete, - msecs_to_jiffies(timeout) << 2); + msecs_to_jiffies(timeout)); if (!ret) { - cnss_pr_err("Timeout waiting for calibration to complete\n"); + cnss_pr_err("Timeout (%ums) waiting for calibration to complete\n", + timeout); if (!test_bit(CNSS_IN_REBOOT, &plat_priv->driver_state)) { cnss_pci_dump_bl_sram_mem(pci_priv); CNSS_ASSERT(0); @@ -2362,12 +2412,12 @@ void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops) if (plat_priv->device_id == QCA6174_DEVICE_ID) goto skip_wait_power_up; - timeout = cnss_get_qmi_timeout(plat_priv); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_WLAN_WATCHDOG); ret = wait_for_completion_timeout(&plat_priv->power_up_complete, - msecs_to_jiffies((timeout << 1) + - WLAN_WD_TIMEOUT_MS)); + msecs_to_jiffies(timeout)); if (!ret) { - cnss_pr_err("Timeout waiting for driver power up to complete\n"); + cnss_pr_err("Timeout (%ums) waiting for driver power up to complete\n", + timeout); CNSS_ASSERT(0); } @@ -2377,10 +2427,12 @@ void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops) goto skip_wait_recovery; reinit_completion(&plat_priv->recovery_complete); + timeout = cnss_get_timeout(plat_priv, CNSS_TIMEOUT_RECOVERY); ret = wait_for_completion_timeout(&plat_priv->recovery_complete, - msecs_to_jiffies(RECOVERY_TIMEOUT)); + msecs_to_jiffies(timeout)); if (!ret) { - cnss_pr_err("Timeout waiting for recovery to complete\n"); + cnss_pr_err("Timeout (%ums) waiting for recovery to complete\n", + timeout); CNSS_ASSERT(0); } @@ -3752,6 +3804,8 @@ int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info) sizeof(info->fw_build_timestamp)); memcpy(&info->device_version, &plat_priv->device_version, sizeof(info->device_version)); + memcpy(&info->dev_mem_info, &plat_priv->dev_mem_info, + sizeof(info->dev_mem_info)); return 0; } diff --git a/drivers/net/wireless/cnss2/power.c b/drivers/net/wireless/cnss2/power.c index 13e92c3be166..2cd59e83e58d 100644 --- a/drivers/net/wireless/cnss2/power.c +++ b/drivers/net/wireless/cnss2/power.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #include #include @@ -789,10 +789,17 @@ static int cnss_select_pinctrl_enable(struct cnss_plat_data *plat_priv) int ret = 0, bt_en_gpio = plat_priv->pinctrl_info.bt_en_gpio; u8 wlan_en_state = 0; - if (bt_en_gpio < 0 || plat_priv->device_id != QCA6490_DEVICE_ID || - plat_priv->device_id != QCA6390_DEVICE_ID) + if (bt_en_gpio < 0) goto set_wlan_en; + switch (plat_priv->device_id) { + case QCA6390_DEVICE_ID: + case QCA6490_DEVICE_ID: + break; + default: + goto set_wlan_en; + } + if (gpio_get_value(bt_en_gpio)) { cnss_pr_dbg("BT_EN_GPIO State: On\n"); ret = cnss_select_pinctrl_state(plat_priv, true); @@ -808,7 +815,9 @@ static int cnss_select_pinctrl_enable(struct cnss_plat_data *plat_priv) cnss_select_pinctrl_state(plat_priv, false); wlan_en_state = 0; } - /* 100 ms delay for BT_EN and WLAN_EN QCA6490 PMU sequencing */ + /* 100 ms delay for BT_EN and WLAN_EN QCA6490/QCA6390 PMU + * sequencing. + */ msleep(100); } set_wlan_en: diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index 21c11d56b445..b14e8f606967 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include #include @@ -393,7 +393,7 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv) struct wlfw_cap_resp_msg_v01 *resp; struct qmi_txn txn; char *fw_build_timestamp; - int ret = 0; + int ret = 0, i; cnss_pr_dbg("Sending target capability message, state: 0x%lx\n", plat_priv->driver_state); @@ -478,7 +478,17 @@ int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv) } if (resp->otp_version_valid) plat_priv->otp_version = resp->otp_version; - + if (resp->dev_mem_info_valid) { + for (i = 0; i < QMI_WLFW_MAX_DEV_MEM_NUM_V01; i++) { + plat_priv->dev_mem_info[i].start = + resp->dev_mem_info[i].start; + plat_priv->dev_mem_info[i].size = + resp->dev_mem_info[i].size; + cnss_pr_dbg("Device memory info[%d]: start = 0x%llx, size = 0x%llx\n", + i, plat_priv->dev_mem_info[i].start, + plat_priv->dev_mem_info[i].size); + } + } if (resp->fw_caps_valid) plat_priv->fw_pcie_gen_switch = !!(resp->fw_caps & QMI_WLFW_HOST_PCIE_GEN_SWITCH_V01); @@ -1838,8 +1848,6 @@ int cnss_wlfw_get_info_send_sync(struct cnss_plat_data *plat_priv, int type, unsigned int cnss_get_qmi_timeout(struct cnss_plat_data *plat_priv) { - cnss_pr_dbg("QMI timeout is %u ms\n", QMI_WLFW_TIMEOUT_MS); - return QMI_WLFW_TIMEOUT_MS; } diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c index 616dd1ffdc8e..ca3f998e08a7 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #include "wlan_firmware_service_v01.h" @@ -501,6 +501,32 @@ static struct qmi_elem_info wlfw_m3_segment_info_s_v01_ei[] = { }, }; +static struct qmi_elem_info wlfw_dev_mem_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_dev_mem_info_s_v01, + start), + }, + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, + .elem_size = sizeof(u64), + .array_type = NO_ARRAY, + .tlv_type = 0, + .offset = offsetof(struct wlfw_dev_mem_info_s_v01, + size), + }, + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + .tlv_type = QMI_COMMON_TLV_TYPE, + }, +}; + struct qmi_elem_info wlfw_ind_register_req_msg_v01_ei[] = { { .data_type = QMI_OPT_FLAG, @@ -1524,6 +1550,25 @@ struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[] = { .offset = offsetof(struct wlfw_cap_resp_msg_v01, rd_card_chain_cap), }, + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .array_type = NO_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + dev_mem_info_valid), + }, + { + .data_type = QMI_STRUCT, + .elem_len = QMI_WLFW_MAX_DEV_MEM_NUM_V01, + .elem_size = sizeof(struct wlfw_dev_mem_info_s_v01), + .array_type = STATIC_ARRAY, + .tlv_type = 0x1C, + .offset = offsetof(struct wlfw_cap_resp_msg_v01, + dev_mem_info), + .ei_array = wlfw_dev_mem_info_s_v01_ei, + }, { .data_type = QMI_EOTI, .array_type = NO_ARRAY, diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h index 9fe450a74dc0..d3a2dd6f0c31 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef WLAN_FIRMWARE_SERVICE_V01_H #define WLAN_FIRMWARE_SERVICE_V01_H @@ -115,6 +115,7 @@ #define QMI_WLFW_MAX_NUM_SHADOW_REG_V01 24 #define QMI_WLFW_MAC_ADDR_SIZE_V01 6 #define QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01 36 +#define QMI_WLFW_MAX_DEV_MEM_NUM_V01 4 #define QMI_WLFW_MAX_PLATFORM_NAME_LEN_V01 64 #define QMI_WLFW_MAX_NUM_SVC_V01 24 @@ -348,6 +349,11 @@ struct wlfw_m3_segment_info_s_v01 { char name[QMI_WLFW_MAX_STR_LEN_V01 + 1]; }; +struct wlfw_dev_mem_info_s_v01 { + u64 start; + u64 size; +}; + struct wlfw_ind_register_req_msg_v01 { u8 fw_ready_enable_valid; u8 fw_ready_enable; @@ -506,9 +512,12 @@ struct wlfw_cap_resp_msg_v01 { u64 fw_caps; u8 rd_card_chain_cap_valid; enum wlfw_rd_card_chain_cap_v01 rd_card_chain_cap; + u8 dev_mem_info_valid; + struct wlfw_dev_mem_info_s_v01 + dev_mem_info[QMI_WLFW_MAX_DEV_MEM_NUM_V01]; }; -#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 253 +#define WLFW_CAP_RESP_MSG_V01_MAX_MSG_LEN 320 extern struct qmi_elem_info wlfw_cap_resp_msg_v01_ei[]; struct wlfw_bdf_download_req_msg_v01 { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 798605c4f122..5287f21d7ba6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -520,7 +520,10 @@ static ssize_t iwl_dbgfs_os_device_timediff_read(struct file *file, const size_t bufsz = sizeof(buf); int pos = 0; + mutex_lock(&mvm->mutex); iwl_mvm_get_sync_time(mvm, &curr_gp2, &curr_os); + mutex_unlock(&mvm->mutex); + do_div(curr_os, NSEC_PER_USEC); diff = curr_os - curr_gp2; pos += scnprintf(buf + pos, bufsz - pos, "diff=%lld\n", diff); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 470fe628f6ba..baf1b04be3d9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -2916,7 +2916,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, /* this would be a mac80211 bug ... but don't crash */ if (WARN_ON_ONCE(!mvmvif->phy_ctxt)) - return -EINVAL; + return test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status) ? 0 : -EINVAL; /* * If we are in a STA removal flow and in DQA mode: diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 0e26619fb330..d932171617e6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -1192,6 +1192,7 @@ static void iwl_mvm_reprobe_wk(struct work_struct *wk) reprobe = container_of(wk, struct iwl_mvm_reprobe, work); if (device_reprobe(reprobe->dev)) dev_err(reprobe->dev, "reprobe failed!\n"); + put_device(reprobe->dev); kfree(reprobe); module_put(THIS_MODULE); } @@ -1242,7 +1243,7 @@ void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error) module_put(THIS_MODULE); return; } - reprobe->dev = mvm->trans->dev; + reprobe->dev = get_device(mvm->trans->dev); INIT_WORK(&reprobe->work, iwl_mvm_reprobe_wk); schedule_work(&reprobe->work); } else if (mvm->fwrt.cur_fw_img == IWL_UCODE_REGULAR && diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 6783b20d9681..a1cecf4a0e82 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -159,8 +159,10 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, /* Allocate IML */ iml_img = dma_alloc_coherent(trans->dev, trans->iml_len, &trans_pcie->iml_dma_addr, GFP_KERNEL); - if (!iml_img) - return -ENOMEM; + if (!iml_img) { + ret = -ENOMEM; + goto err_free_ctxt_info; + } memcpy(iml_img, trans->iml, trans->iml_len); @@ -177,6 +179,11 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, return 0; +err_free_ctxt_info: + dma_free_coherent(trans->dev, sizeof(*trans_pcie->ctxt_info_gen3), + trans_pcie->ctxt_info_gen3, + trans_pcie->ctxt_info_dma_addr); + trans_pcie->ctxt_info_gen3 = NULL; err_free_prph_info: dma_free_coherent(trans->dev, sizeof(*prph_info), diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 24da49615135..fcda33482887 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -2121,18 +2121,38 @@ static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr, void *buf, int dwords) { unsigned long flags; - int offs, ret = 0; + int offs = 0; u32 *vals = buf; - if (iwl_trans_grab_nic_access(trans, &flags)) { - iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); - for (offs = 0; offs < dwords; offs++) - vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT); - iwl_trans_release_nic_access(trans, &flags); - } else { - ret = -EBUSY; + while (offs < dwords) { + /* limit the time we spin here under lock to 1/2s */ + unsigned long end = jiffies + HZ / 2; + bool resched = false; + + if (iwl_trans_grab_nic_access(trans, &flags)) { + iwl_write32(trans, HBUS_TARG_MEM_RADDR, + addr + 4 * offs); + + while (offs < dwords) { + vals[offs] = iwl_read32(trans, + HBUS_TARG_MEM_RDAT); + offs++; + + if (time_after(jiffies, end)) { + resched = true; + break; + } + } + iwl_trans_release_nic_access(trans, &flags); + + if (resched) + cond_resched(); + } else { + return -EBUSY; + } } - return ret; + + return 0; } static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr, diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index b73582ec03a0..b1a71539ca3e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -631,6 +631,11 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq = trans_pcie->txq[txq_id]; + if (!txq) { + IWL_ERR(trans, "Trying to free a queue that wasn't allocated?\n"); + return; + } + spin_lock_bh(&txq->lock); while (txq->write_ptr != txq->read_ptr) { IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n", diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c index b704e4bce171..a04d59843022 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_usb.c @@ -1237,13 +1237,6 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->len < ETH_HLEN) goto drop; - ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); - if (!ctx) - goto busy; - - memset(ctx->buf, 0, BULK_BUF_SIZE); - buf = ctx->buf->data; - tx_control = 0; err = orinoco_process_xmit_skb(skb, dev, priv, &tx_control, @@ -1251,6 +1244,13 @@ static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev) if (err) goto drop; + ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0); + if (!ctx) + goto drop; + + memset(ctx->buf, 0, BULK_BUF_SIZE); + buf = ctx->buf->data; + { __le16 *tx_cntl = (__le16 *)buf; *tx_cntl = cpu_to_le16(tx_control); diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c index d87aeff70cef..c2cb1e711c06 100644 --- a/drivers/net/wireless/marvell/mwifiex/join.c +++ b/drivers/net/wireless/marvell/mwifiex/join.c @@ -877,6 +877,8 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); + if (req_ssid->ssid_len > IEEE80211_MAX_SSID_LEN) + req_ssid->ssid_len = IEEE80211_MAX_SSID_LEN; memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len); mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n", diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c index e48b47f42554..ceac611ef086 100644 --- a/drivers/net/wireless/marvell/mwifiex/main.c +++ b/drivers/net/wireless/marvell/mwifiex/main.c @@ -1474,6 +1474,8 @@ int mwifiex_shutdown_sw(struct mwifiex_adapter *adapter) priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); mwifiex_deauthenticate(priv, NULL); + mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN); + mwifiex_uninit_sw(adapter); if (adapter->if_ops.down_dev) diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 991b9cc18000..5907b34037c2 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -381,6 +381,8 @@ static void mwifiex_pcie_reset_prepare(struct pci_dev *pdev) clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &card->work_flags); clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &card->work_flags); mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__); + + card->pci_reset_ongoing = true; } /* @@ -409,6 +411,8 @@ static void mwifiex_pcie_reset_done(struct pci_dev *pdev) dev_err(&pdev->dev, "reinit failed: %d\n", ret); else mwifiex_dbg(adapter, INFO, "%s, successful\n", __func__); + + card->pci_reset_ongoing = false; } static const struct pci_error_handlers mwifiex_pcie_err_handler = { @@ -3000,7 +3004,19 @@ static void mwifiex_cleanup_pcie(struct mwifiex_adapter *adapter) int ret; u32 fw_status; - cancel_work_sync(&card->work); + /* Perform the cancel_work_sync() only when we're not resetting + * the card. It's because that function never returns if we're + * in reset path. If we're here when resetting the card, it means + * that we failed to reset the card (reset failure path). + */ + if (!card->pci_reset_ongoing) { + mwifiex_dbg(adapter, MSG, "performing cancel_work_sync()...\n"); + cancel_work_sync(&card->work); + mwifiex_dbg(adapter, MSG, "cancel_work_sync() done\n"); + } else { + mwifiex_dbg(adapter, MSG, + "skipped cancel_work_sync() because we're in card reset failure path\n"); + } ret = mwifiex_read_reg(adapter, reg->fw_status, &fw_status); if (fw_status == FIRMWARE_READY_PCIE) { diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h index f7ce9b6db6b4..72d0c01ff359 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.h +++ b/drivers/net/wireless/marvell/mwifiex/pcie.h @@ -391,6 +391,8 @@ struct pcie_service_card { struct mwifiex_msix_context share_irq_ctx; struct work_struct work; unsigned long work_flags; + + bool pci_reset_ongoing; }; static inline int diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index cc6840377bc2..57866c1e9c98 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -393,22 +393,27 @@ static void mt76_add_fragment(struct mt76_dev *dev, struct mt76_queue *q, void *data, int len, bool more) { - struct page *page = virt_to_head_page(data); - int offset = data - page_address(page); struct sk_buff *skb = q->rx_head; struct skb_shared_info *shinfo = skb_shinfo(skb); + int nr_frags = shinfo->nr_frags; - if (shinfo->nr_frags < ARRAY_SIZE(shinfo->frags)) { - offset += q->buf_offset; - skb_add_rx_frag(skb, shinfo->nr_frags, page, offset, len, - q->buf_size); + if (nr_frags < ARRAY_SIZE(shinfo->frags)) { + struct page *page = virt_to_head_page(data); + int offset = data - page_address(page) + q->buf_offset; + + skb_add_rx_frag(skb, nr_frags, page, offset, len, q->buf_size); + } else { + skb_free_frag(data); } if (more) return; q->rx_head = NULL; - dev->drv->rx_skb(dev, q - dev->q_rx, skb); + if (nr_frags < ARRAY_SIZE(shinfo->frags)) + dev->drv->rx_skb(dev, q - dev->q_rx, skb); + else + dev_kfree_skb(skb); } static int diff --git a/drivers/net/wireless/mediatek/mt7601u/dma.c b/drivers/net/wireless/mediatek/mt7601u/dma.c index 47cebb2ec05c..5aacabd32923 100644 --- a/drivers/net/wireless/mediatek/mt7601u/dma.c +++ b/drivers/net/wireless/mediatek/mt7601u/dma.c @@ -160,8 +160,7 @@ mt7601u_rx_process_entry(struct mt7601u_dev *dev, struct mt7601u_dma_buf_rx *e) if (new_p) { /* we have one extra ref from the allocator */ - __free_pages(e->p, MT_RX_ORDER); - + put_page(e->p); e->p = new_p; } } @@ -318,7 +317,6 @@ static int mt7601u_dma_submit_tx(struct mt7601u_dev *dev, } e = &q->e[q->end]; - e->skb = skb; usb_fill_bulk_urb(e->urb, usb_dev, snd_pipe, skb->data, skb->len, mt7601u_complete_tx, q); ret = usb_submit_urb(e->urb, GFP_ATOMIC); @@ -336,6 +334,7 @@ static int mt7601u_dma_submit_tx(struct mt7601u_dev *dev, q->end = (q->end + 1) % q->entries; q->used++; + e->skb = skb; if (q->used >= q->entries) ieee80211_stop_queue(dev->hw, skb_get_queue_mapping(skb)); diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index a7b341e95e76..0da95777f1c1 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -238,7 +238,8 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) rsi_set_len_qno(&data_desc->len_qno, (skb->len - FRAME_DESC_SZ), RSI_WIFI_MGMT_Q); - if ((skb->len - header_size) == EAPOL4_PACKET_LEN) { + if (((skb->len - header_size) == EAPOL4_PACKET_LEN) || + ((skb->len - header_size) == EAPOL4_PACKET_LEN - 2)) { data_desc->misc_flags |= RSI_DESC_REQUIRE_CFM_TO_HOST; xtend_desc->confirm_frame_type = EAPOL4_CONFIRM; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 81cc1044532d..f76a360cf1e3 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -153,9 +153,7 @@ static void rsi_handle_interrupt(struct sdio_func *function) if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED) return; - dev->sdio_irq_task = current; - rsi_interrupt_handler(adapter); - dev->sdio_irq_task = NULL; + rsi_set_event(&dev->rx_thread.event); } /** @@ -973,8 +971,6 @@ static int rsi_probe(struct sdio_func *pfunction, rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__); goto fail_kill_thread; } - skb_queue_head_init(&sdev->rx_q.head); - sdev->rx_q.num_rx_pkts = 0; sdio_claim_host(pfunction); if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) { diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c index 612c211e21a1..d66ae2f57314 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c @@ -60,39 +60,20 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word) return status; } +static void rsi_rx_handler(struct rsi_hw *adapter); + void rsi_sdio_rx_thread(struct rsi_common *common) { struct rsi_hw *adapter = common->priv; struct rsi_91x_sdiodev *sdev = adapter->rsi_dev; - struct sk_buff *skb; - int status; do { rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER); rsi_reset_event(&sdev->rx_thread.event); + rsi_rx_handler(adapter); + } while (!atomic_read(&sdev->rx_thread.thread_done)); - while (true) { - if (atomic_read(&sdev->rx_thread.thread_done)) - goto out; - - skb = skb_dequeue(&sdev->rx_q.head); - if (!skb) - break; - if (sdev->rx_q.num_rx_pkts > 0) - sdev->rx_q.num_rx_pkts--; - status = rsi_read_pkt(common, skb->data, skb->len); - if (status) { - rsi_dbg(ERR_ZONE, "Failed to read the packet\n"); - dev_kfree_skb(skb); - break; - } - dev_kfree_skb(skb); - } - } while (1); - -out: rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__); - skb_queue_purge(&sdev->rx_q.head); atomic_inc(&sdev->rx_thread.thread_done); complete_and_exit(&sdev->rx_thread.completion, 0); } @@ -113,10 +94,6 @@ static int rsi_process_pkt(struct rsi_common *common) u32 rcv_pkt_len = 0; int status = 0; u8 value = 0; - struct sk_buff *skb; - - if (dev->rx_q.num_rx_pkts >= RSI_MAX_RX_PKTS) - return 0; num_blks = ((adapter->interrupt_status & 1) | ((adapter->interrupt_status >> RECV_NUM_BLOCKS) << 1)); @@ -144,22 +121,19 @@ static int rsi_process_pkt(struct rsi_common *common) rcv_pkt_len = (num_blks * 256); - skb = dev_alloc_skb(rcv_pkt_len); - if (!skb) - return -ENOMEM; - - status = rsi_sdio_host_intf_read_pkt(adapter, skb->data, rcv_pkt_len); + status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer, + rcv_pkt_len); if (status) { rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n", __func__); - dev_kfree_skb(skb); return status; } - skb_put(skb, rcv_pkt_len); - skb_queue_tail(&dev->rx_q.head, skb); - dev->rx_q.num_rx_pkts++; - rsi_set_event(&dev->rx_thread.event); + status = rsi_read_pkt(common, dev->pktbuffer, rcv_pkt_len); + if (status) { + rsi_dbg(ERR_ZONE, "Failed to read the packet\n"); + return status; + } return 0; } @@ -251,12 +225,12 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) } /** - * rsi_interrupt_handler() - This function read and process SDIO interrupts. + * rsi_rx_handler() - Read and process SDIO interrupts. * @adapter: Pointer to the adapter structure. * * Return: None. */ -void rsi_interrupt_handler(struct rsi_hw *adapter) +static void rsi_rx_handler(struct rsi_hw *adapter) { struct rsi_common *common = adapter->priv; struct rsi_91x_sdiodev *dev = diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h index 66dcd2ec9051..fd11f16fc74f 100644 --- a/drivers/net/wireless/rsi/rsi_sdio.h +++ b/drivers/net/wireless/rsi/rsi_sdio.h @@ -110,11 +110,6 @@ struct receive_info { u32 buf_available_counter; }; -struct rsi_sdio_rx_q { - u8 num_rx_pkts; - struct sk_buff_head head; -}; - struct rsi_91x_sdiodev { struct sdio_func *pfunction; struct task_struct *sdio_irq_task; @@ -127,11 +122,10 @@ struct rsi_91x_sdiodev { u16 tx_blk_size; u8 write_fail; bool buff_status_updated; - struct rsi_sdio_rx_q rx_q; struct rsi_thread rx_thread; + u8 pktbuffer[8192] __aligned(4); }; -void rsi_interrupt_handler(struct rsi_hw *adapter); int rsi_init_sdio_slave_regs(struct rsi_hw *adapter); int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data); int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length); diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c index c1608f0bf6d0..0c5a15e2b8f9 100644 --- a/drivers/net/wireless/st/cw1200/main.c +++ b/drivers/net/wireless/st/cw1200/main.c @@ -384,6 +384,7 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, CW1200_LINK_ID_MAX, cw1200_skb_dtor, priv)) { + destroy_workqueue(priv->workqueue); ieee80211_free_hw(hw); return NULL; } @@ -395,6 +396,7 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, for (; i > 0; i--) cw1200_queue_deinit(&priv->tx_queue[i - 1]); cw1200_queue_stats_deinit(&priv->tx_queue_stats); + destroy_workqueue(priv->workqueue); ieee80211_free_hw(hw); return NULL; } diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 4a4f797bb10f..e10fff42751e 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -649,7 +649,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | WLCORE_QUIRK_DUAL_PROBE_TMPL | WLCORE_QUIRK_TKIP_HEADER_SPACE | - WLCORE_QUIRK_START_STA_FAILS | WLCORE_QUIRK_AP_ZERO_SESSION_ID; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; wl->mr_fw_name = WL127X_FW_NAME_MULTI; @@ -673,7 +672,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl->quirks |= WLCORE_QUIRK_LEGACY_NVS | WLCORE_QUIRK_DUAL_PROBE_TMPL | WLCORE_QUIRK_TKIP_HEADER_SPACE | - WLCORE_QUIRK_START_STA_FAILS | WLCORE_QUIRK_AP_ZERO_SESSION_ID; wl->plt_fw_name = WL127X_PLT_FW_NAME; wl->sr_fw_name = WL127X_FW_NAME_SINGLE; @@ -702,7 +700,6 @@ static int wl12xx_identify_chip(struct wl1271 *wl) wl->quirks |= WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | WLCORE_QUIRK_DUAL_PROBE_TMPL | WLCORE_QUIRK_TKIP_HEADER_SPACE | - WLCORE_QUIRK_START_STA_FAILS | WLCORE_QUIRK_AP_ZERO_SESSION_ID; wlcore_set_min_fw_ver(wl, WL128X_CHIP_VER, diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 43c7b37dec0c..e24ffdff5bdc 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -2875,21 +2875,8 @@ static int wlcore_join(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (is_ibss) ret = wl12xx_cmd_role_start_ibss(wl, wlvif); - else { - if (wl->quirks & WLCORE_QUIRK_START_STA_FAILS) { - /* - * TODO: this is an ugly workaround for wl12xx fw - * bug - we are not able to tx/rx after the first - * start_sta, so make dummy start+stop calls, - * and then call start_sta again. - * this should be fixed in the fw. - */ - wl12xx_cmd_role_start_sta(wl, wlvif); - wl12xx_cmd_role_stop_sta(wl, wlvif); - } - + else ret = wl12xx_cmd_role_start_sta(wl, wlvif); - } return ret; } diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index d4b1f66ef457..af7cf70b3832 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -559,9 +559,6 @@ wlcore_set_min_fw_ver(struct wl1271 *wl, unsigned int chip, /* Each RX/TX transaction requires an end-of-transaction transfer */ #define WLCORE_QUIRK_END_OF_TRANSACTION BIT(0) -/* the first start_role(sta) sometimes doesn't work on wl12xx */ -#define WLCORE_QUIRK_START_STA_FAILS BIT(1) - /* wl127x and SPI don't support SDIO block size alignment */ #define WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN BIT(2) diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index c960cb7e3251..3b5fdb24ef1b 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -162,13 +162,15 @@ irqreturn_t xenvif_interrupt(int irq, void *dev_id) { struct xenvif_queue *queue = dev_id; int old; + bool has_rx, has_tx; old = atomic_fetch_or(NETBK_COMMON_EOI, &queue->eoi_pending); WARN(old, "Interrupt while EOI pending\n"); - /* Use bitwise or as we need to call both functions. */ - if ((!xenvif_handle_tx_interrupt(queue) | - !xenvif_handle_rx_interrupt(queue))) { + has_tx = xenvif_handle_tx_interrupt(queue); + has_rx = xenvif_handle_rx_interrupt(queue); + + if (!has_rx && !has_tx) { atomic_andnot(NETBK_COMMON_EOI, &queue->eoi_pending); xen_irq_lateeoi(irq, XEN_EOI_FLAG_SPURIOUS); } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f228298c3bd0..41bdfb684d46 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1331,7 +1331,15 @@ int xenvif_tx_action(struct xenvif_queue *queue, int budget) NULL, queue->pages_to_map, nr_mops); - BUG_ON(ret); + if (ret) { + unsigned int i; + + netdev_err(queue->vif->dev, "Map fail: nr %u ret %d\n", + nr_mops, ret); + for (i = 0; i < nr_mops; ++i) + WARN_ON_ONCE(queue->tx_map_ops[i].status == + GNTST_okay); + } } work_done = xenvif_tx_submit(queue); diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c index 9b62f65b630e..48e2006f96ce 100644 --- a/drivers/net/xen-netback/rx.c +++ b/drivers/net/xen-netback/rx.c @@ -38,10 +38,15 @@ static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) RING_IDX prod, cons; struct sk_buff *skb; int needed; + unsigned long flags; + + spin_lock_irqsave(&queue->rx_queue.lock, flags); skb = skb_peek(&queue->rx_queue); - if (!skb) + if (!skb) { + spin_unlock_irqrestore(&queue->rx_queue.lock, flags); return false; + } needed = DIV_ROUND_UP(skb->len, XEN_PAGE_SIZE); if (skb_is_gso(skb)) @@ -49,6 +54,8 @@ static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) if (skb->sw_hash) needed++; + spin_unlock_irqrestore(&queue->rx_queue.lock, flags); + do { prod = queue->rx.sring->req_prod; cons = queue->rx.req_cons; diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index cd51492ae6c2..78c56149559c 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -777,12 +777,14 @@ static int xen_register_credit_watch(struct xenbus_device *dev, return -ENOMEM; snprintf(node, maxlen, "%s/rate", dev->nodename); vif->credit_watch.node = node; + vif->credit_watch.will_handle = NULL; vif->credit_watch.callback = xen_net_rate_changed; err = register_xenbus_watch(&vif->credit_watch); if (err) { pr_err("Failed to set watcher %s\n", vif->credit_watch.node); kfree(node); vif->credit_watch.node = NULL; + vif->credit_watch.will_handle = NULL; vif->credit_watch.callback = NULL; } return err; @@ -829,6 +831,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev, snprintf(node, maxlen, "%s/request-multicast-control", dev->otherend); vif->mcast_ctrl_watch.node = node; + vif->mcast_ctrl_watch.will_handle = NULL; vif->mcast_ctrl_watch.callback = xen_mcast_ctrl_changed; err = register_xenbus_watch(&vif->mcast_ctrl_watch); if (err) { @@ -836,6 +839,7 @@ static int xen_register_mcast_ctrl_watch(struct xenbus_device *dev, vif->mcast_ctrl_watch.node); kfree(node); vif->mcast_ctrl_watch.node = NULL; + vif->mcast_ctrl_watch.will_handle = NULL; vif->mcast_ctrl_watch.callback = NULL; } return err; @@ -1039,11 +1043,15 @@ static void connect(struct backend_info *be) xenvif_carrier_on(be->vif); unregister_hotplug_status_watch(be); - err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, - hotplug_status_changed, - "%s/%s", dev->nodename, "hotplug-status"); - if (!err) + if (xenbus_exists(XBT_NIL, dev->nodename, "hotplug-status")) { + err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, + NULL, hotplug_status_changed, + "%s/%s", dev->nodename, + "hotplug-status"); + if (err) + goto err; be->have_hotplug_status_watch = 1; + } netif_tx_wake_all_queues(be->vif->dev); diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c index a4e2c37c5c55..c3deed93c701 100644 --- a/drivers/nfc/nq-nci.c +++ b/drivers/nfc/nq-nci.c @@ -1085,135 +1085,6 @@ static const struct file_operations nfc_dev_fops = { #endif }; -/* - * function: get_nfcc_hw_info() - * - * @client: pointer to i2c_client - * @nqx_dev: pointer to nqx_dev structure - * @nci_reset_rsp_payload_len: payload length of NCI reset cmd - * - * Retrieves NFCC HW information based on the type of NFC chip - * used on the device. Depending on the nci_reset_rsp_payload_len - * value, core INIT command will be sent. - * - * NFC HW NCI version Send Core INIT cmd - * NQ3xx or old 1.0 Yes - * NQ4xx 2.0 No - * Sn1x0x 2.0 No - * - * Return: error codes in case of any failure, - * number of bytes read otherwise - */ -static int get_nfcc_hw_info(struct i2c_client *client, - struct nqx_dev *nqx_dev, char nci_reset_rsp_payload_len) -{ - int ret = 0; - - char *nci_init_cmd = NULL; - char *nci_init_rsp = NULL; - char *nci_reset_ntf = NULL; - char *nfcc_hw_info = NULL; - unsigned char nfcc_hw_info_len = 0; - - nci_init_cmd = kzalloc(NCI_INIT_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); - if (!nci_init_cmd) { - ret = -ENOMEM; - goto err_nfcc_hw_info; - } - - nci_init_rsp = kzalloc(NCI_INIT_RSP_LEN + 1, GFP_DMA | GFP_KERNEL); - if (!nci_init_rsp) { - ret = -ENOMEM; - goto err_nfcc_hw_info; - } - - nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); - if (!nci_reset_ntf) { - ret = -ENOMEM; - goto err_nfcc_hw_info; - } - - if (nci_reset_rsp_payload_len == NCI_1_0_RESET_RSP_PAYLOAD_LEN) { - /* - * Chipset is NQ330 or older. - * Send core INIT command to get HW info. - */ - nci_init_cmd[0] = 0x20; - nci_init_cmd[1] = 0x01; - nci_init_cmd[2] = 0x00; - ret = nqx_standby_write(nqx_dev, nci_init_cmd, - NCI_INIT_CMD_LEN); - if (ret < 0) { - dev_dbg(&client->dev, - "%s: - i2c_master_send failed for Core INIT\n", - __func__); - goto err_nfcc_hw_info; - } - - ret = is_data_available_for_read(nqx_dev); - if (ret <= 0) { - nqx_disable_irq(nqx_dev); - goto err_nfcc_hw_info; - } - - /* Read Response of INIT command */ - ret = i2c_master_recv(client, nci_init_rsp, NCI_INIT_RSP_LEN); - if (ret < 0) { - dev_dbg(&client->dev, - "%s: - i2c_master_recv get INIT rsp Error\n", - __func__); - goto err_nfcc_hw_info; - } - nfcc_hw_info = nci_init_rsp; - } else { - /* - * Chipset is NQ4xx or later. - * Retrieve NTF data from wait queue. - */ - ret = is_data_available_for_read(nqx_dev); - if (ret <= 0) { - nqx_disable_irq(nqx_dev); - goto err_nfcc_hw_info; - } - - /* Read Notification of RESET command */ - ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); - if (ret < 0) { - dev_dbg(&client->dev, - "%s: - i2c_master_recv get RESET ntf Error\n", - __func__); - goto err_nfcc_hw_info; - } - nfcc_hw_info = nci_reset_ntf; - } - - /* Save NFCC HW info */ - nfcc_hw_info_len = - NCI_HEADER_LEN + nfcc_hw_info[NCI_PAYLOAD_LENGTH_INDEX]; - if (nfcc_hw_info_len > PAYLOAD_HEADER_LENGTH) { - nqx_dev->nqx_info.info.chip_type = - nfcc_hw_info[nfcc_hw_info_len - - NFCC_HW_CHIP_ID_OFFSET]; - nqx_dev->nqx_info.info.rom_version = - nfcc_hw_info[nfcc_hw_info_len - - NFCC_HW_ROM_VER_OFFSET]; - nqx_dev->nqx_info.info.fw_major = - nfcc_hw_info[nfcc_hw_info_len - - NFCC_HW_MAJOR_NO_OFFSET]; - nqx_dev->nqx_info.info.fw_minor = - nfcc_hw_info[nfcc_hw_info_len - - NFCC_HW_MINOR_NO_OFFSET]; - } - -err_nfcc_hw_info: - - kfree(nci_reset_ntf); - kfree(nci_init_rsp); - kfree(nci_init_cmd); - - return ret; -} - /* Check for availability of NQ_ NFC controller hardware */ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) { @@ -1222,11 +1093,10 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) int gpio_retry_count = 0; int send_retry_count = 0; unsigned char reset_ntf_len = 0; - unsigned int enable_gpio = nqx_dev->en_gpio; char *nci_reset_cmd = NULL; char *nci_reset_rsp = NULL; - + char *nci_reset_ntf = NULL; char *nci_get_version_cmd = NULL; char *nci_get_version_rsp = NULL; @@ -1241,6 +1111,13 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) ret = -ENOMEM; goto done; } + + nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL); + if (!nci_reset_ntf) { + ret = -ENOMEM; + goto done; + } + nci_get_version_cmd = kzalloc(NCI_GET_VERSION_CMD_LEN + 1, GFP_DMA | GFP_KERNEL); if (!nci_get_version_cmd) { @@ -1255,6 +1132,7 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) goto done; } +reset_enable_gpio: /* making sure that the NFCC starts in a clean state. */ #ifdef NQ_READ_INT gpio_set_value(enable_gpio, 1);/* HPD : Enable*/ @@ -1350,12 +1228,14 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) } #endif - - /* Read Header of RESET command */ - ret = i2c_master_recv(client, nci_reset_rsp, NCI_HEADER_LEN); - if (ret != NCI_HEADER_LEN) { - dev_dbg(&client->dev, - "%s: - i2c_master_recv get RESET rsp header Error\n", __func__); + /* Read Response of RESET command */ + ret = i2c_master_recv(client, nci_reset_rsp, NCI_RESET_RSP_LEN); + if (ret < 0) { + dev_err(&client->dev, + "%s: - i2c_master_recv Error\n", __func__); + gpio_retry_count = gpio_retry_count + 1; + if (gpio_retry_count < MAX_RETRY_COUNT) + goto reset_enable_gpio; goto err_nfcc_hw_check; } @@ -1366,26 +1246,29 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) ret = is_data_available_for_read(nqx_dev); if (ret <= 0) { nqx_disable_irq(nqx_dev); - - ret = i2c_master_recv(client, &nci_reset_rsp[NCI_PAYLOAD_START_INDEX], - nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]); - if (ret != nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]) { - dev_dbg(&client->dev, - "%s: - i2c_master_recv get RESET rsp data Error\n", __func__); goto err_nfcc_hw_check; } #endif - /* Retrieve NFCC HW info */ - ret = get_nfcc_hw_info(client, nqx_dev, - nci_reset_rsp[NCI_PAYLOAD_LENGTH_INDEX]); + /* Read Notification of RESET command */ + ret = i2c_master_recv(client, nci_reset_ntf, NCI_RESET_NTF_LEN); if (ret < 0) { - dev_dbg(&client->dev, - "%s: - Error in getting NFCC HW info\n", __func__); + dev_err(&client->dev, + "%s: - i2c_master_recv Error\n", __func__); goto err_nfcc_hw_check; } - + reset_ntf_len = 2 + nci_reset_ntf[2]; /*payload + len*/ + if (reset_ntf_len > PAYLOAD_HEADER_LENGTH) { + nqx_dev->nqx_info.info.chip_type = + nci_reset_ntf[reset_ntf_len - 3]; + nqx_dev->nqx_info.info.rom_version = + nci_reset_ntf[reset_ntf_len - 2]; + nqx_dev->nqx_info.info.fw_major = + nci_reset_ntf[reset_ntf_len - 1]; + nqx_dev->nqx_info.info.fw_minor = + nci_reset_ntf[reset_ntf_len]; + } dev_dbg(&client->dev, "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n", __func__, nci_reset_rsp[0], @@ -1434,6 +1317,7 @@ static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev) done: kfree(nci_reset_rsp); + kfree(nci_reset_ntf); kfree(nci_reset_cmd); kfree(nci_get_version_cmd); kfree(nci_get_version_rsp); @@ -2002,3 +1886,5 @@ module_exit(nqx_dev_exit); MODULE_DESCRIPTION("NFC nqx"); MODULE_LICENSE("GPL v2"); + + diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c index b7828fb252f2..b7d5b12035c1 100644 --- a/drivers/nfc/s3fwrn5/firmware.c +++ b/drivers/nfc/s3fwrn5/firmware.c @@ -304,8 +304,10 @@ static int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info) if (ret < 0) return ret; - if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE) + if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE) { + release_firmware(fw->fw); return -EINVAL; + } memcpy(fw->date, fw->fw->data + 0x00, 12); fw->date[12] = '\0'; diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c index 4da409e77a72..6c78529a8c89 100644 --- a/drivers/nfc/s3fwrn5/i2c.c +++ b/drivers/nfc/s3fwrn5/i2c.c @@ -37,8 +37,8 @@ struct s3fwrn5_i2c_phy { struct i2c_client *i2c_dev; struct nci_dev *ndev; - unsigned int gpio_en; - unsigned int gpio_fw_wake; + int gpio_en; + int gpio_fw_wake; struct mutex mutex; diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index 863cabc35215..f0e0e3b42c91 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c @@ -359,16 +359,16 @@ static ssize_t state_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(state); -static ssize_t available_slots_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf) { - struct nvdimm_drvdata *ndd = dev_get_drvdata(dev); + struct device *dev; ssize_t rc; u32 nfree; if (!ndd) return -ENXIO; + dev = ndd->dev; nvdimm_bus_lock(dev); nfree = nd_label_nfree(ndd); if (nfree - 1 > nfree) { @@ -380,6 +380,18 @@ static ssize_t available_slots_show(struct device *dev, nvdimm_bus_unlock(dev); return rc; } + +static ssize_t available_slots_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t rc; + + device_lock(dev); + rc = __available_slots_show(dev_get_drvdata(dev), buf); + device_unlock(dev); + + return rc; +} static DEVICE_ATTR_RO(available_slots); static struct attribute *nvdimm_attributes[] = { diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index 9f1b7e3153f9..19e3469d5908 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c @@ -861,6 +861,15 @@ static int __blk_label_update(struct nd_region *nd_region, } } + /* release slots associated with any invalidated UUIDs */ + mutex_lock(&nd_mapping->lock); + list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) + if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags)) { + reap_victim(nd_mapping, label_ent); + list_move(&label_ent->list, &list); + } + mutex_unlock(&nd_mapping->lock); + /* * Find the resource associated with the first label in the set * per the v1.2 namespace specification. @@ -880,8 +889,10 @@ static int __blk_label_update(struct nd_region *nd_region, if (is_old_resource(res, old_res_list, old_num_resources)) continue; /* carry-over */ slot = nd_label_alloc_slot(ndd); - if (slot == UINT_MAX) + if (slot == UINT_MAX) { + rc = -ENXIO; goto abort; + } dev_dbg(ndd->dev, "allocated: %d\n", slot); nd_label = to_label(ndd, slot); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 3c68a5b35ec1..82d87d2e280c 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -276,9 +276,21 @@ static void nvme_dbbuf_init(struct nvme_dev *dev, nvmeq->dbbuf_cq_ei = &dev->dbbuf_eis[cq_idx(qid, dev->db_stride)]; } +static void nvme_dbbuf_free(struct nvme_queue *nvmeq) +{ + if (!nvmeq->qid) + return; + + nvmeq->dbbuf_sq_db = NULL; + nvmeq->dbbuf_cq_db = NULL; + nvmeq->dbbuf_sq_ei = NULL; + nvmeq->dbbuf_cq_ei = NULL; +} + static void nvme_dbbuf_set(struct nvme_dev *dev) { struct nvme_command c; + unsigned int i; if (!dev->dbbuf_dbs) return; @@ -292,6 +304,9 @@ static void nvme_dbbuf_set(struct nvme_dev *dev) dev_warn(dev->ctrl.device, "unable to set dbbuf\n"); /* Free memory and continue on */ nvme_dbbuf_dma_free(dev); + + for (i = 1; i <= dev->online_queues; i++) + nvme_dbbuf_free(&dev->queues[i]); } } @@ -2718,6 +2733,8 @@ static const struct pci_device_id nvme_id_table[] = { { PCI_DEVICE(0x1d1d, 0x2601), /* CNEX Granby */ .driver_data = NVME_QUIRK_LIGHTNVM, }, { PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_EXPRESS, 0xffffff) }, + { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */ + .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2001) }, { PCI_DEVICE(PCI_VENDOR_ID_APPLE, 0x2003) }, { 0, } diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 134e14e778f8..8798274dc3ba 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -644,8 +644,11 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl) return ret; ctrl->ctrl.queue_count = nr_io_queues + 1; - if (ctrl->ctrl.queue_count < 2) - return 0; + if (ctrl->ctrl.queue_count < 2) { + dev_err(ctrl->ctrl.device, + "unable to set any I/O queues\n"); + return -ENOMEM; + } dev_info(ctrl->ctrl.device, "creating %d I/O queues.\n", nr_io_queues); diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 2b492ad55f0e..1a35d73c39c3 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -770,9 +770,20 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl) { lockdep_assert_held(&ctrl->lock); - if (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES || - nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES || - nvmet_cc_mps(ctrl->cc) != 0 || + /* + * Only I/O controllers should verify iosqes,iocqes. + * Strictly speaking, the spec says a discovery controller + * should verify iosqes,iocqes are zeroed, however that + * would break backwards compatibility, so don't enforce it. + */ + if (ctrl->subsys->type != NVME_NQN_DISC && + (nvmet_cc_iosqes(ctrl->cc) != NVME_NVM_IOSQES || + nvmet_cc_iocqes(ctrl->cc) != NVME_NVM_IOCQES)) { + ctrl->csts = NVME_CSTS_CFS; + return; + } + + if (nvmet_cc_mps(ctrl->cc) != 0 || nvmet_cc_ams(ctrl->cc) != 0 || nvmet_cc_css(ctrl->cc) != 0) { ctrl->csts = NVME_CSTS_CFS; diff --git a/drivers/of/address.c b/drivers/of/address.c index c42aebba35ab..30806dd35735 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -975,11 +975,13 @@ EXPORT_SYMBOL_GPL(of_dma_get_range); */ bool of_dma_is_coherent(struct device_node *np) { - struct device_node *node = of_node_get(np); + struct device_node *node; if (IS_ENABLED(CONFIG_OF_DMA_DEFAULT_COHERENT)) return true; + node = of_node_get(np); + while (node) { if (of_property_read_bool(node, "dma-coherent")) { of_node_put(node); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 50c2e0fe4ce6..885d9aa44b74 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -1321,8 +1321,16 @@ int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size) int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool nomap) { - if (nomap) - return memblock_remove(base, size); + if (nomap) { + /* + * If the memory is already reserved (by another region), we + * should not allow it to be marked nomap. + */ + if (memblock_is_region_reserved(base, size)) + return -EBUSY; + + return memblock_mark_nomap(base, size); + } return memblock_reserve(base, size); } diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index b7b2e811d547..4513b5a08145 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -1253,7 +1253,7 @@ ccio_ioc_init(struct ioc *ioc) ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD). */ - iova_space_size = (u32) (totalram_pages / count_parisc_driver(&ccio_driver)); + iova_space_size = (u32) (totalram_pages() / count_parisc_driver(&ccio_driver)); /* limit IOVA space size to 1MB-1GB */ @@ -1292,7 +1292,7 @@ ccio_ioc_init(struct ioc *ioc) DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n", __func__, ioc->ioc_regs, - (unsigned long) totalram_pages >> (20 - PAGE_SHIFT), + (unsigned long) totalram_pages() >> (20 - PAGE_SHIFT), iova_space_size>>20, iov_order + PAGE_SHIFT); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 0f19cc75cc0c..a707a857b9e4 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1418,7 +1418,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** for DMA hints - ergo only 30 bits max. */ - iova_space_size = (u32) (totalram_pages/global_ioc_cnt); + iova_space_size = (u32) (totalram_pages()/global_ioc_cnt); /* limit IOVA space size to 1MB-1GB */ if (iova_space_size < (1 << (20 - PAGE_SHIFT))) { @@ -1443,7 +1443,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n", __func__, ioc->ioc_hpa, - (unsigned long) totalram_pages >> (20 - PAGE_SHIFT), + (unsigned long) totalram_pages() >> (20 - PAGE_SHIFT), iova_space_size>>20, iov_order + PAGE_SHIFT); diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index 1bdac298a943..33e510393976 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -108,6 +108,7 @@ struct qcom_pcie_resources_2_1_0 { struct reset_control *ahb_reset; struct reset_control *por_reset; struct reset_control *phy_reset; + struct reset_control *ext_reset; struct regulator_bulk_data supplies[QCOM_PCIE_2_1_0_MAX_SUPPLY]; }; @@ -269,6 +270,10 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) if (IS_ERR(res->por_reset)) return PTR_ERR(res->por_reset); + res->ext_reset = devm_reset_control_get_optional_exclusive(dev, "ext"); + if (IS_ERR(res->ext_reset)) + return PTR_ERR(res->ext_reset); + res->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); return PTR_ERR_OR_ZERO(res->phy_reset); } @@ -281,6 +286,7 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) reset_control_assert(res->axi_reset); reset_control_assert(res->ahb_reset); reset_control_assert(res->por_reset); + reset_control_assert(res->ext_reset); reset_control_assert(res->pci_reset); clk_disable_unprepare(res->iface_clk); clk_disable_unprepare(res->core_clk); @@ -333,6 +339,12 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) goto err_deassert_ahb; } + ret = reset_control_deassert(res->ext_reset); + if (ret) { + dev_err(dev, "cannot deassert ext reset\n"); + goto err_deassert_ahb; + } + /* enable PCIe clocks and resets */ val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); val &= ~BIT(0); @@ -359,7 +371,9 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) /* enable external reference clock */ val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); - val &= ~PHY_REFCLK_USE_PAD; + /* USE_PAD is required only for ipq806x */ + if (!of_device_is_compatible(node, "qcom,pcie-apq8064")) + val &= ~PHY_REFCLK_USE_PAD; val |= PHY_REFCLK_SSP_EN; writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); diff --git a/drivers/pci/controller/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c index f4c02da84e59..0bfa5065b440 100644 --- a/drivers/pci/controller/pci-xgene-msi.c +++ b/drivers/pci/controller/pci-xgene-msi.c @@ -384,13 +384,9 @@ static int xgene_msi_hwirq_alloc(unsigned int cpu) if (!msi_group->gic_irq) continue; - irq_set_chained_handler(msi_group->gic_irq, - xgene_msi_isr); - err = irq_set_handler_data(msi_group->gic_irq, msi_group); - if (err) { - pr_err("failed to register GIC IRQ handler\n"); - return -EINVAL; - } + irq_set_chained_handler_and_data(msi_group->gic_irq, + xgene_msi_isr, msi_group); + /* * Statically allocate MSI GIC IRQs to each CPU core. * With 8-core X-Gene v1, 2 MSI GIC IRQs are allocated diff --git a/drivers/pci/controller/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c index ec86414216f9..f2d79e0235bc 100644 --- a/drivers/pci/controller/pcie-iproc.c +++ b/drivers/pci/controller/pcie-iproc.c @@ -300,7 +300,7 @@ enum iproc_pcie_reg { }; /* iProc PCIe PAXB BCMA registers */ -static const u16 iproc_pcie_reg_paxb_bcma[] = { +static const u16 iproc_pcie_reg_paxb_bcma[IPROC_PCIE_MAX_NUM_REG] = { [IPROC_PCIE_CLK_CTRL] = 0x000, [IPROC_PCIE_CFG_IND_ADDR] = 0x120, [IPROC_PCIE_CFG_IND_DATA] = 0x124, @@ -311,7 +311,7 @@ static const u16 iproc_pcie_reg_paxb_bcma[] = { }; /* iProc PCIe PAXB registers */ -static const u16 iproc_pcie_reg_paxb[] = { +static const u16 iproc_pcie_reg_paxb[IPROC_PCIE_MAX_NUM_REG] = { [IPROC_PCIE_CLK_CTRL] = 0x000, [IPROC_PCIE_CFG_IND_ADDR] = 0x120, [IPROC_PCIE_CFG_IND_DATA] = 0x124, @@ -327,7 +327,7 @@ static const u16 iproc_pcie_reg_paxb[] = { }; /* iProc PCIe PAXB v2 registers */ -static const u16 iproc_pcie_reg_paxb_v2[] = { +static const u16 iproc_pcie_reg_paxb_v2[IPROC_PCIE_MAX_NUM_REG] = { [IPROC_PCIE_CLK_CTRL] = 0x000, [IPROC_PCIE_CFG_IND_ADDR] = 0x120, [IPROC_PCIE_CFG_IND_DATA] = 0x124, @@ -355,7 +355,7 @@ static const u16 iproc_pcie_reg_paxb_v2[] = { }; /* iProc PCIe PAXC v1 registers */ -static const u16 iproc_pcie_reg_paxc[] = { +static const u16 iproc_pcie_reg_paxc[IPROC_PCIE_MAX_NUM_REG] = { [IPROC_PCIE_CLK_CTRL] = 0x000, [IPROC_PCIE_CFG_IND_ADDR] = 0x1f0, [IPROC_PCIE_CFG_IND_DATA] = 0x1f4, @@ -364,7 +364,7 @@ static const u16 iproc_pcie_reg_paxc[] = { }; /* iProc PCIe PAXC v2 registers */ -static const u16 iproc_pcie_reg_paxc_v2[] = { +static const u16 iproc_pcie_reg_paxc_v2[IPROC_PCIE_MAX_NUM_REG] = { [IPROC_PCIE_MSI_GIC_MODE] = 0x050, [IPROC_PCIE_MSI_BASE_ADDR] = 0x074, [IPROC_PCIE_MSI_WINDOW_SIZE] = 0x078, diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index ca06d8bc01e7..066e9e00de11 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -1089,14 +1089,14 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie) err = of_pci_get_devfn(child); if (err < 0) { dev_err(dev, "failed to parse devfn: %d\n", err); - return err; + goto error_put_node; } slot = PCI_SLOT(err); err = mtk_pcie_parse_port(pcie, child, slot); if (err) - return err; + goto error_put_node; } err = mtk_pcie_subsys_powerup(pcie); @@ -1112,6 +1112,9 @@ static int mtk_pcie_setup(struct mtk_pcie *pcie) mtk_pcie_subsys_powerdown(pcie); return 0; +error_put_node: + of_node_put(child); + return err; } static int mtk_pcie_request_resources(struct mtk_pcie *pcie) diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index cdbfa5df3a51..dbfa0b55d31a 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -34,12 +34,11 @@ static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr, if (nbytes >= MAX_DRC_NAME_LEN) return 0; - memcpy(drc_name, buf, nbytes); + strscpy(drc_name, buf, nbytes + 1); end = strchr(drc_name, '\n'); - if (!end) - end = &drc_name[nbytes]; - *end = '\0'; + if (end) + *end = '\0'; rc = dlpar_add_slot(drc_name); if (rc) @@ -65,12 +64,11 @@ static ssize_t remove_slot_store(struct kobject *kobj, if (nbytes >= MAX_DRC_NAME_LEN) return 0; - memcpy(drc_name, buf, nbytes); + strscpy(drc_name, buf, nbytes + 1); end = strchr(drc_name, '\n'); - if (!end) - end = &drc_name[nbytes]; - *end = '\0'; + if (end) + *end = '\0'; rc = dlpar_remove_slot(drc_name); if (rc) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index f7218c1673ce..2c46f7dcd2f5 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -587,7 +587,7 @@ static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable) { while (bus->parent) { if (acpi_pm_device_can_wakeup(&bus->self->dev)) - return acpi_pm_set_bridge_wakeup(&bus->self->dev, enable); + return acpi_pm_set_device_wakeup(&bus->self->dev, enable); bus = bus->parent; } @@ -595,7 +595,7 @@ static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable) /* We have reached the root bus. */ if (bus->bridge) { if (acpi_pm_device_can_wakeup(bus->bridge)) - return acpi_pm_set_bridge_wakeup(bus->bridge, enable); + return acpi_pm_set_device_wakeup(bus->bridge, enable); } return 0; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 8aabd2317fc9..e5eec743cf03 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3362,7 +3362,14 @@ u32 pci_rebar_get_possible_sizes(struct pci_dev *pdev, int bar) return 0; pci_read_config_dword(pdev, pos + PCI_REBAR_CAP, &cap); - return (cap & PCI_REBAR_CAP_SIZES) >> 4; + cap &= PCI_REBAR_CAP_SIZES; + + /* Sapphire RX 5600 XT Pulse has an invalid cap dword for BAR 0 */ + if (pdev->vendor == PCI_VENDOR_ID_ATI && pdev->device == 0x731f && + bar == 0 && cap == 0x7000) + cap = 0x3f000; + + return cap >> 4; } /** @@ -3811,6 +3818,10 @@ int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr, ret = logic_pio_register_range(range); if (ret) kfree(range); + + /* Ignore duplicates due to deferred probing */ + if (ret == -EEXIST) + ret = 0; #endif return ret; @@ -5841,19 +5852,21 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev, while (*p) { count = 0; if (sscanf(p, "%d%n", &align_order, &count) == 1 && - p[count] == '@') { + p[count] == '@') { p += count + 1; + if (align_order > 63) { + pr_err("PCI: Invalid requested alignment (order %d)\n", + align_order); + align_order = PAGE_SHIFT; + } } else { - align_order = -1; + align_order = PAGE_SHIFT; } ret = pci_dev_str_match(dev, p, &p); if (ret == 1) { *resize = true; - if (align_order == -1) - align = PAGE_SIZE; - else - align = 1 << align_order; + align = 1ULL << align_order; break; } else if (ret < 0) { pr_err("PCI: Can't parse resource_alignment parameter: %s\n", diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index af2149632102..70f05595da60 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3961,6 +3961,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9183, /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c46 */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0, quirk_dma_func1_alias); +/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c135 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9215, + quirk_dma_func1_alias); /* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c127 */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9220, quirk_dma_func1_alias); diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index fb7478b6c4f9..dfbe9cbf292c 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -307,6 +307,9 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, goto err; } + INIT_LIST_HEAD(&slot->list); + list_add(&slot->list, &parent->slots); + err = kobject_init_and_add(&slot->kobj, &pci_slot_ktype, NULL, "%s", slot_name); if (err) { @@ -314,9 +317,6 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, goto err; } - INIT_LIST_HEAD(&slot->list); - list_add(&slot->list, &parent->slots); - down_read(&pci_bus_sem); list_for_each_entry(dev, &parent->devices, bus_list) if (PCI_SLOT(dev->devfn) == slot_nr) diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index d96626c614f5..a7bdd10fccf3 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -19,7 +19,7 @@ SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn, u16 word; u32 dword; long err; - long cfg_ret; + int cfg_ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -45,7 +45,7 @@ SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn, } err = -EIO; - if (cfg_ret != PCIBIOS_SUCCESSFUL) + if (cfg_ret) goto error; switch (len) { @@ -103,7 +103,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (err) break; err = pci_user_write_config_byte(dev, off, byte); - if (err != PCIBIOS_SUCCESSFUL) + if (err) err = -EIO; break; @@ -112,7 +112,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (err) break; err = pci_user_write_config_word(dev, off, word); - if (err != PCIBIOS_SUCCESSFUL) + if (err) err = -EIO; break; @@ -121,7 +121,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn, if (err) break; err = pci_user_write_config_dword(dev, off, dword); - if (err != PCIBIOS_SUCCESSFUL) + if (err) err = -EIO; break; diff --git a/drivers/phy/motorola/phy-cpcap-usb.c b/drivers/phy/motorola/phy-cpcap-usb.c index 593c77dbde2e..106f53f33324 100644 --- a/drivers/phy/motorola/phy-cpcap-usb.c +++ b/drivers/phy/motorola/phy-cpcap-usb.c @@ -623,35 +623,42 @@ static int cpcap_usb_phy_probe(struct platform_device *pdev) generic_phy = devm_phy_create(ddata->dev, NULL, &ops); if (IS_ERR(generic_phy)) { error = PTR_ERR(generic_phy); - return PTR_ERR(generic_phy); + goto out_reg_disable; } phy_set_drvdata(generic_phy, ddata); phy_provider = devm_of_phy_provider_register(ddata->dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); + if (IS_ERR(phy_provider)) { + error = PTR_ERR(phy_provider); + goto out_reg_disable; + } error = cpcap_usb_init_optional_pins(ddata); if (error) - return error; + goto out_reg_disable; cpcap_usb_init_optional_gpios(ddata); error = cpcap_usb_init_iio(ddata); if (error) - return error; + goto out_reg_disable; error = cpcap_usb_init_interrupts(pdev, ddata); if (error) - return error; + goto out_reg_disable; usb_add_phy_dev(&ddata->phy); atomic_set(&ddata->active, 1); schedule_delayed_work(&ddata->detect_work, msecs_to_jiffies(1)); return 0; + +out_reg_disable: + regulator_disable(ddata->vusb); + + return error; } static int cpcap_usb_phy_remove(struct platform_device *pdev) diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index de1b4ebe4de2..39c01ef57d83 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -899,6 +899,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev) reset: reset_control_assert(padctl->rst); remove: + platform_set_drvdata(pdev, NULL); soc->ops->remove(padctl); return err; } diff --git a/drivers/pinctrl/aspeed/pinctrl-aspeed.c b/drivers/pinctrl/aspeed/pinctrl-aspeed.c index aefe3c33dffd..8dec302dc067 100644 --- a/drivers/pinctrl/aspeed/pinctrl-aspeed.c +++ b/drivers/pinctrl/aspeed/pinctrl-aspeed.c @@ -458,13 +458,14 @@ int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function, static bool aspeed_expr_is_gpio(const struct aspeed_sig_expr *expr) { /* - * The signal type is GPIO if the signal name has "GPIO" as a prefix. + * The signal type is GPIO if the signal name has "GPI" as a prefix. * strncmp (rather than strcmp) is used to implement the prefix * requirement. * - * expr->signal might look like "GPIOT3" in the GPIO case. + * expr->signal might look like "GPIOB1" in the GPIO case. + * expr->signal might look like "GPIT0" in the GPI case. */ - return strncmp(expr->signal, "GPIO", 4) == 0; + return strncmp(expr->signal, "GPI", 3) == 0; } static bool aspeed_gpio_in_exprs(const struct aspeed_sig_expr **exprs) diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index acb02a7aa949..b3d478edbbb1 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1009,6 +1009,21 @@ static void byt_gpio_disable_free(struct pinctrl_dev *pctl_dev, pm_runtime_put(&vg->pdev->dev); } +static void byt_gpio_direct_irq_check(struct byt_gpio *vg, + unsigned int offset) +{ + void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); + + /* + * Before making any direction modifications, do a check if gpio is set + * for direct IRQ. On Bay Trail, setting GPIO to output does not make + * sense, so let's at least inform the caller before they shoot + * themselves in the foot. + */ + if (readl(conf_reg) & BYT_DIRECT_IRQ_EN) + dev_info_once(&vg->pdev->dev, "Potential Error: Setting GPIO with direct_irq_en to output"); +} + static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, struct pinctrl_gpio_range *range, unsigned int offset, @@ -1016,7 +1031,6 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, { struct byt_gpio *vg = pinctrl_dev_get_drvdata(pctl_dev); void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); - void __iomem *conf_reg = byt_gpio_reg(vg, offset, BYT_CONF0_REG); unsigned long flags; u32 value; @@ -1027,14 +1041,8 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, if (input) value |= BYT_OUTPUT_EN; else - /* - * Before making any direction modifications, do a check if gpio - * is set for direct IRQ. On baytrail, setting GPIO to output - * does not make sense, so let's at least warn the caller before - * they shoot themselves in the foot. - */ - WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, - "Potential Error: Setting GPIO with direct_irq_en to output"); + byt_gpio_direct_irq_check(vg, offset); + writel(value, val_reg); raw_spin_unlock_irqrestore(&byt_lock, flags); @@ -1250,7 +1258,6 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, break; case PIN_CONFIG_INPUT_DEBOUNCE: debounce = readl(db_reg); - debounce &= ~BYT_DEBOUNCE_PULSE_MASK; if (arg) conf |= BYT_DEBOUNCE_EN; @@ -1259,24 +1266,31 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, switch (arg) { case 375: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_375US; break; case 750: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_750US; break; case 1500: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_1500US; break; case 3000: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_3MS; break; case 6000: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_6MS; break; case 12000: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_12MS; break; case 24000: + debounce &= ~BYT_DEBOUNCE_PULSE_MASK; debounce |= BYT_DEBOUNCE_PULSE_24MS; break; default: @@ -1374,19 +1388,50 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { - return pinctrl_gpio_direction_input(chip->base + offset); + struct byt_gpio *vg = gpiochip_get_data(chip); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + unsigned long flags; + u32 reg; + + raw_spin_lock_irqsave(&byt_lock, flags); + + reg = readl(val_reg); + reg &= ~BYT_DIR_MASK; + reg |= BYT_OUTPUT_EN; + writel(reg, val_reg); + + raw_spin_unlock_irqrestore(&byt_lock, flags); + return 0; } +/* + * Note despite the temptation this MUST NOT be converted into a call to + * pinctrl_gpio_direction_output() + byt_gpio_set() that does not work this + * MUST be done as a single BYT_VAL_REG register write. + * See the commit message of the commit adding this comment for details. + */ static int byt_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { - int ret = pinctrl_gpio_direction_output(chip->base + offset); + struct byt_gpio *vg = gpiochip_get_data(chip); + void __iomem *val_reg = byt_gpio_reg(vg, offset, BYT_VAL_REG); + unsigned long flags; + u32 reg; - if (ret) - return ret; + raw_spin_lock_irqsave(&byt_lock, flags); - byt_gpio_set(chip, offset, value); + byt_gpio_direct_irq_check(vg, offset); + reg = readl(val_reg); + reg &= ~BYT_DIR_MASK; + if (value) + reg |= BYT_LEVEL; + else + reg &= ~BYT_LEVEL; + + writel(reg, val_reg); + + raw_spin_unlock_irqrestore(&byt_lock, flags); return 0; } diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 89ff2795a8b5..5e0adb00b430 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -621,6 +621,10 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin, value |= PADCFG1_TERM_UP; + /* Set default strength value in case none is given */ + if (arg == 1) + arg = 5000; + switch (arg) { case 20000: value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT; @@ -643,6 +647,10 @@ static int intel_config_set_pull(struct intel_pinctrl *pctrl, unsigned pin, case PIN_CONFIG_BIAS_PULL_DOWN: value &= ~(PADCFG1_TERM_UP | PADCFG1_TERM_MASK); + /* Set default strength value in case none is given */ + if (arg == 1) + arg = 5000; + switch (arg) { case 20000: value |= PADCFG1_TERM_20K << PADCFG1_TERM_SHIFT; diff --git a/drivers/pinctrl/intel/pinctrl-lewisburg.c b/drivers/pinctrl/intel/pinctrl-lewisburg.c index dc32c22bf19f..8388aa671b21 100644 --- a/drivers/pinctrl/intel/pinctrl-lewisburg.c +++ b/drivers/pinctrl/intel/pinctrl-lewisburg.c @@ -297,9 +297,9 @@ static const struct pinctrl_pin_desc lbg_pins[] = { static const struct intel_community lbg_communities[] = { LBG_COMMUNITY(0, 0, 71), LBG_COMMUNITY(1, 72, 132), - LBG_COMMUNITY(3, 133, 144), - LBG_COMMUNITY(4, 145, 180), - LBG_COMMUNITY(5, 181, 246), + LBG_COMMUNITY(3, 133, 143), + LBG_COMMUNITY(4, 144, 178), + LBG_COMMUNITY(5, 179, 246), }; static const struct intel_pinctrl_soc_data lbg_soc_data = { diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 4fa69f988c7b..6b2312e73f23 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -729,6 +729,10 @@ static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin, mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK; bits |= BUFCFG_PU_EN; + /* Set default strength value in case none is given */ + if (arg == 1) + arg = 20000; + switch (arg) { case 50000: bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT; @@ -749,6 +753,10 @@ static int mrfld_config_set_pin(struct mrfld_pinctrl *mp, unsigned int pin, mask |= BUFCFG_Px_EN_MASK | BUFCFG_PUPD_VAL_MASK; bits |= BUFCFG_PD_EN; + /* Set default strength value in case none is given */ + if (arg == 1) + arg = 20000; + switch (arg) { case 50000: bits |= BUFCFG_PUPD_VAL_50K << BUFCFG_PUPD_VAL_SHIFT; diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index b1ffdd3f6d07..d9b9c11c7f8f 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -157,7 +157,7 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF); pin_reg &= ~BIT(DB_TMR_LARGE_OFF); } else if (debounce < 250000) { - time = debounce / 15600; + time = debounce / 15625; pin_reg |= time & DB_TMR_OUT_MASK; pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF); pin_reg |= BIT(DB_TMR_LARGE_OFF); @@ -167,14 +167,14 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset, pin_reg |= BIT(DB_TMR_OUT_UNIT_OFF); pin_reg |= BIT(DB_TMR_LARGE_OFF); } else { - pin_reg &= ~DB_CNTRl_MASK; + pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); ret = -EINVAL; } } else { pin_reg &= ~BIT(DB_TMR_OUT_UNIT_OFF); pin_reg &= ~BIT(DB_TMR_LARGE_OFF); pin_reg &= ~DB_TMR_OUT_MASK; - pin_reg &= ~DB_CNTRl_MASK; + pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); } writel(pin_reg, gpio_dev->base + offset * 4); raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); @@ -439,7 +439,6 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin_reg &= ~BIT(LEVEL_TRIG_OFF); pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF; - pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF; irq_set_handler_locked(d, handle_edge_irq); break; @@ -447,7 +446,6 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin_reg &= ~BIT(LEVEL_TRIG_OFF); pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF; - pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF; irq_set_handler_locked(d, handle_edge_irq); break; @@ -455,7 +453,6 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin_reg &= ~BIT(LEVEL_TRIG_OFF); pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg |= BOTH_EADGE << ACTIVE_LEVEL_OFF; - pin_reg |= DB_TYPE_REMOVE_GLITCH << DB_CNTRL_OFF; irq_set_handler_locked(d, handle_edge_irq); break; @@ -463,8 +460,6 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin_reg |= LEVEL_TRIGGER << LEVEL_TRIG_OFF; pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg |= ACTIVE_HIGH << ACTIVE_LEVEL_OFF; - pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); - pin_reg |= DB_TYPE_PRESERVE_LOW_GLITCH << DB_CNTRL_OFF; irq_set_handler_locked(d, handle_level_irq); break; @@ -472,8 +467,6 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type) pin_reg |= LEVEL_TRIGGER << LEVEL_TRIG_OFF; pin_reg &= ~(ACTIVE_LEVEL_MASK << ACTIVE_LEVEL_OFF); pin_reg |= ACTIVE_LOW << ACTIVE_LEVEL_OFF; - pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF); - pin_reg |= DB_TYPE_PRESERVE_HIGH_GLITCH << DB_CNTRL_OFF; irq_set_handler_locked(d, handle_level_irq); break; diff --git a/drivers/pinctrl/pinctrl-falcon.c b/drivers/pinctrl/pinctrl-falcon.c index fb73dcbb5ef3..68dcf53aaac3 100644 --- a/drivers/pinctrl/pinctrl-falcon.c +++ b/drivers/pinctrl/pinctrl-falcon.c @@ -438,24 +438,28 @@ static int pinctrl_falcon_probe(struct platform_device *pdev) /* load and remap the pad resources of the different banks */ for_each_compatible_node(np, NULL, "lantiq,pad-falcon") { - struct platform_device *ppdev = of_find_device_by_node(np); const __be32 *bank = of_get_property(np, "lantiq,bank", NULL); struct resource res; + struct platform_device *ppdev; u32 avail; int pins; if (!of_device_is_available(np)) continue; - if (!ppdev) { - dev_err(&pdev->dev, "failed to find pad pdev\n"); - continue; - } if (!bank || *bank >= PORTS) continue; if (of_address_to_resource(np, 0, &res)) continue; + + ppdev = of_find_device_by_node(np); + if (!ppdev) { + dev_err(&pdev->dev, "failed to find pad pdev\n"); + continue; + } + falcon_info.clk[*bank] = clk_get(&ppdev->dev, NULL); + put_device(&ppdev->dev); if (IS_ERR(falcon_info.clk[*bank])) { dev_err(&ppdev->dev, "failed to get clock\n"); return PTR_ERR(falcon_info.clk[*bank]); diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 005df24f5b3f..d0d5b8bdbc10 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -2778,7 +2778,9 @@ static int rockchip_gpio_to_irq(struct gpio_chip *gc, unsigned offset) if (!bank->domain) return -ENXIO; + clk_enable(bank->clk); virq = irq_create_mapping(bank->domain, offset); + clk_disable(bank->clk); return (virq) ? : -ENXIO; } @@ -3351,12 +3353,15 @@ static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev) static int __maybe_unused rockchip_pinctrl_resume(struct device *dev) { struct rockchip_pinctrl *info = dev_get_drvdata(dev); - int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, - rk3288_grf_gpio6c_iomux | - GPIO6C6_SEL_WRITE_ENABLE); + int ret; - if (ret) - return ret; + if (info->ctrl->type == RK3288) { + ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, + rk3288_grf_gpio6c_iomux | + GPIO6C6_SEL_WRITE_ENABLE); + if (ret) + return ret; + } return pinctrl_force_default(info->pctl_dev); } diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c index 49a56aa1ee4f..c2a5b95b1182 100644 --- a/drivers/pinctrl/qcom/pinctrl-msm.c +++ b/drivers/pinctrl/qcom/pinctrl-msm.c @@ -177,14 +177,14 @@ static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev, raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->ctl_reg); + val = readl_relaxed(pctrl->regs + g->ctl_reg); val &= ~mask; val |= i << g->mux_bit; /* Check if egpio present and enable that feature */ if (val & BIT(g->egpio_present)) val |= BIT(g->egpio_enable); - writel(val, pctrl->regs + g->ctl_reg); + writel_relaxed(val, pctrl->regs + g->ctl_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); @@ -259,7 +259,7 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev, if (ret < 0) return ret; - val = readl(pctrl->regs + g->ctl_reg); + val = readl_relaxed(pctrl->regs + g->ctl_reg); arg = (val >> bit) & mask; /* Convert register value to pinconf value */ @@ -298,7 +298,7 @@ static int msm_config_group_get(struct pinctrl_dev *pctldev, if (!arg) return -EINVAL; - val = readl(pctrl->regs + g->io_reg); + val = readl_relaxed(pctrl->regs + g->io_reg); arg = !!(val & BIT(g->in_bit)); break; case PIN_CONFIG_INPUT_ENABLE: @@ -372,12 +372,12 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev, case PIN_CONFIG_OUTPUT: /* set output value */ raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->io_reg); + val = readl_relaxed(pctrl->regs + g->io_reg); if (arg) val |= BIT(g->out_bit); else val &= ~BIT(g->out_bit); - writel(val, pctrl->regs + g->io_reg); + writel_relaxed(val, pctrl->regs + g->io_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); /* enable output */ @@ -400,10 +400,10 @@ static int msm_config_group_set(struct pinctrl_dev *pctldev, } raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->ctl_reg); + val = readl_relaxed(pctrl->regs + g->ctl_reg); val &= ~(mask << bit); val |= arg << bit; - writel(val, pctrl->regs + g->ctl_reg); + writel_relaxed(val, pctrl->regs + g->ctl_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); } @@ -427,9 +427,9 @@ static int msm_gpio_direction_input(struct gpio_chip *chip, unsigned offset) raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->ctl_reg); + val = readl_relaxed(pctrl->regs + g->ctl_reg); val &= ~BIT(g->oe_bit); - writel(val, pctrl->regs + g->ctl_reg); + writel_relaxed(val, pctrl->regs + g->ctl_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); @@ -447,16 +447,16 @@ static int msm_gpio_direction_output(struct gpio_chip *chip, unsigned offset, in raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->io_reg); + val = readl_relaxed(pctrl->regs + g->io_reg); if (value) val |= BIT(g->out_bit); else val &= ~BIT(g->out_bit); - writel(val, pctrl->regs + g->io_reg); + writel_relaxed(val, pctrl->regs + g->io_reg); - val = readl(pctrl->regs + g->ctl_reg); + val = readl_relaxed(pctrl->regs + g->ctl_reg); val |= BIT(g->oe_bit); - writel(val, pctrl->regs + g->ctl_reg); + writel_relaxed(val, pctrl->regs + g->ctl_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); @@ -513,12 +513,12 @@ static void msm_gpio_set(struct gpio_chip *chip, unsigned offset, int value) raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->io_reg); + val = readl_relaxed(pctrl->regs + g->io_reg); if (value) val |= BIT(g->out_bit); else val &= ~BIT(g->out_bit); - writel(val, pctrl->regs + g->io_reg); + writel_relaxed(val, pctrl->regs + g->io_reg); raw_spin_unlock_irqrestore(&pctrl->lock, flags); } @@ -642,14 +642,14 @@ static void msm_gpio_update_dual_edge_pos(struct msm_pinctrl *pctrl, unsigned pol; do { - val = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit); + val = readl_relaxed(pctrl->regs + g->io_reg) & BIT(g->in_bit); - pol = readl(pctrl->regs + g->intr_cfg_reg); + pol = readl_relaxed(pctrl->regs + g->intr_cfg_reg); pol ^= BIT(g->intr_polarity_bit); - writel(pol, pctrl->regs + g->intr_cfg_reg); + writel_relaxed(pol, pctrl->regs + g->intr_cfg_reg); - val2 = readl(pctrl->regs + g->io_reg) & BIT(g->in_bit); - intstat = readl(pctrl->regs + g->intr_status_reg); + val2 = readl_relaxed(pctrl->regs + g->io_reg) & BIT(g->in_bit); + intstat = readl_relaxed(pctrl->regs + g->intr_status_reg); if (intstat || (val == val2)) return; } while (loop_limit-- > 0); @@ -688,7 +688,7 @@ static void _msm_gpio_irq_mask(struct irq_data *d) raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->intr_cfg_reg); + val = readl_relaxed(pctrl->regs + g->intr_cfg_reg); /* * There are two bits that control interrupt forwarding to the CPU. The * RAW_STATUS_EN bit causes the level or edge sensed on the line to be @@ -713,7 +713,7 @@ static void _msm_gpio_irq_mask(struct irq_data *d) val &= ~BIT(g->intr_raw_status_bit); val &= ~BIT(g->intr_enable_bit); - writel(val, pctrl->regs + g->intr_cfg_reg); + writel_relaxed(val, pctrl->regs + g->intr_cfg_reg); clear_bit(d->hwirq, pctrl->enabled_irqs); @@ -738,15 +738,15 @@ static void _msm_gpio_irq_unmask(struct irq_data *d, bool status_clear) * any erroneous interrupts that would have got latched * when the interrupt is not in use. */ - val = readl(pctrl->regs + g->intr_status_reg); + val = readl_relaxed(pctrl->regs + g->intr_status_reg); val &= ~BIT(g->intr_status_bit); - writel(val, pctrl->regs + g->intr_status_reg); + writel_relaxed(val, pctrl->regs + g->intr_status_reg); } - val = readl(pctrl->regs + g->intr_cfg_reg); + val = readl_relaxed(pctrl->regs + g->intr_cfg_reg); val |= BIT(g->intr_raw_status_bit); val |= BIT(g->intr_enable_bit); - writel(val, pctrl->regs + g->intr_cfg_reg); + writel_relaxed(val, pctrl->regs + g->intr_cfg_reg); set_bit(d->hwirq, pctrl->enabled_irqs); @@ -883,12 +883,12 @@ static void msm_gpio_irq_ack(struct irq_data *d) raw_spin_lock_irqsave(&pctrl->lock, flags); - val = readl(pctrl->regs + g->intr_status_reg); + val = readl_relaxed(pctrl->regs + g->intr_status_reg); if (g->intr_ack_high) val |= BIT(g->intr_status_bit); else val &= ~BIT(g->intr_status_bit); - writel(val, pctrl->regs + g->intr_status_reg); + writel_relaxed(val, pctrl->regs + g->intr_status_reg); if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) msm_gpio_update_dual_edge_pos(pctrl, g, d); @@ -1054,17 +1054,17 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) clear_bit(d->hwirq, pctrl->dual_edge_irqs); /* Route interrupts to application cpu */ - val = readl(pctrl->regs + g->intr_target_reg); + val = readl_relaxed(pctrl->regs + g->intr_target_reg); val &= ~(7 << g->intr_target_bit); val |= g->intr_target_kpss_val << g->intr_target_bit; - writel(val, pctrl->regs + g->intr_target_reg); + writel_relaxed(val, pctrl->regs + g->intr_target_reg); /* Update configuration for gpio. * RAW_STATUS_EN is left on for all gpio irqs. Due to the * internal circuitry of TLMM, toggling the RAW_STATUS * could cause the INTR_STATUS to be set for EDGE interrupts. */ - val = readl(pctrl->regs + g->intr_cfg_reg); + val = readl_relaxed(pctrl->regs + g->intr_cfg_reg); val |= BIT(g->intr_raw_status_bit); if (g->intr_detection_width == 2) { val &= ~(3 << g->intr_detection_bit); @@ -1112,7 +1112,7 @@ static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int type) } else { BUG(); } - writel(val, pctrl->regs + g->intr_cfg_reg); + writel_relaxed(val, pctrl->regs + g->intr_cfg_reg); if (test_bit(d->hwirq, pctrl->dual_edge_irqs)) msm_gpio_update_dual_edge_pos(pctrl, g, d); @@ -1187,7 +1187,7 @@ static void msm_gpio_irq_handler(struct irq_desc *desc) */ for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) { g = &pctrl->soc->groups[i]; - val = readl(pctrl->regs + g->intr_status_reg); + val = readl_relaxed(pctrl->regs + g->intr_status_reg); if (val & BIT(g->intr_status_bit)) { irq_pin = irq_find_mapping(gc->irq.domain, i); generic_handle_irq(irq_pin); diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 61aaaf58c599..ff9c2758d25e 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -1001,20 +1001,22 @@ static void sunxi_pinctrl_irq_handler(struct irq_desc *desc) if (bank == pctl->desc->irq_banks) return; + chained_irq_enter(chip, desc); + reg = sunxi_irq_status_reg_from_bank(pctl->desc, bank); val = readl(pctl->membase + reg); if (val) { int irqoffset; - chained_irq_enter(chip, desc); for_each_set_bit(irqoffset, &val, IRQ_PER_BANK) { int pin_irq = irq_find_mapping(pctl->domain, bank * IRQ_PER_BANK + irqoffset); generic_handle_irq(pin_irq); } - chained_irq_exit(chip, desc); } + + chained_irq_exit(chip, desc); } static int sunxi_pinctrl_add_function(struct sunxi_pinctrl *pctl, diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h index da435048a9f5..0b3d49e91374 100644 --- a/drivers/platform/msm/gsi/gsi.h +++ b/drivers/platform/msm/gsi/gsi.h @@ -147,7 +147,7 @@ struct gsi_chan_ctx { struct completion compl; bool allocated; atomic_t poll_mode; - union __packed gsi_channel_scratch scratch; + union gsi_channel_scratch scratch; struct gsi_chan_stats stats; bool enable_dp_stats; bool print_dp_stats; diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index 2dab4cecae31..ef74697bc288 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -2640,7 +2640,7 @@ bool ipa_has_open_aggr_frame(enum ipa_client_type client) int ipa_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, - union __packed gsi_channel_scratch ch_scratch, u8 index) + union gsi_channel_scratch ch_scratch, u8 index) { int ret; diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h index 901b4c3f27b1..101c4b48026c 100644 --- a/drivers/platform/msm/ipa/ipa_api.h +++ b/drivers/platform/msm/ipa/ipa_api.h @@ -302,7 +302,7 @@ struct ipa_api_controller { enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, - union __packed gsi_channel_scratch ch_scratch, + union gsi_channel_scratch ch_scratch, u8 index); int (*ipa_mhi_destroy_channel)(enum ipa_client_type client); diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c index b9f80e2fce53..d8afe2fd0c06 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c @@ -113,7 +113,7 @@ struct ipa_mhi_channel_ctx { u64 event_context_addr; struct ipa_mhi_ev_ctx ev_ctx_host; bool brstmode_enabled; - union __packed gsi_channel_scratch ch_scratch; + union gsi_channel_scratch ch_scratch; unsigned long cached_gsi_evt_ring_hdl; }; diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h index d2f3b32cfb90..ee574fb50281 100644 --- a/drivers/platform/msm/ipa/ipa_common_i.h +++ b/drivers/platform/msm/ipa/ipa_common_i.h @@ -391,7 +391,7 @@ int ipa_mhi_start_channel_internal(enum ipa_client_type client); bool ipa_mhi_sps_channel_empty(enum ipa_client_type client); int ipa_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, - union __packed gsi_channel_scratch ch_scratch, u8 index); + union gsi_channel_scratch ch_scratch, u8 index); int ipa_mhi_handle_ipa_config_req(struct ipa_config_req_msg_v01 *config_req); int ipa_mhi_query_ch_info(enum ipa_client_type client, struct gsi_chan_info *ch_info); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 7f03e6d17bc1..8ec06c589b55 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -746,6 +746,15 @@ static int ipa3_ioctl_add_rt_rule_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_add_rt_rule_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_add_rt_rule_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { @@ -841,6 +850,15 @@ static int ipa3_ioctl_add_rt_rule_ext_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_add_rt_rule_ext_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_add_rt_rule_ext_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { @@ -937,6 +955,15 @@ static int ipa3_ioctl_add_rt_rule_after_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_add_rt_rule_after_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_add_rt_rule_after_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { @@ -1031,6 +1058,15 @@ static int ipa3_ioctl_mdfy_rt_rule_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_mdfy_rt_rule_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_mdfy_rt_rule_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { @@ -1124,6 +1160,15 @@ static int ipa3_ioctl_add_flt_rule_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_add_flt_rule_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_add_flt_rule_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { @@ -1217,6 +1262,15 @@ static int ipa3_ioctl_add_flt_rule_after_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_add_flt_rule_after_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_add_flt_rule_after_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { @@ -1311,6 +1365,15 @@ static int ipa3_ioctl_mdfy_flt_rule_v2(unsigned long arg) retval = -EFAULT; goto free_param_kptr; } + /* add check in case user-space module compromised */ + if (unlikely(((struct ipa_ioc_mdfy_flt_rule_v2 *)param)->num_rules + != pre_entry)) { + IPAERR_RL("current %d pre %d\n", + ((struct ipa_ioc_mdfy_flt_rule_v2 *)param)-> + num_rules, pre_entry); + retval = -EFAULT; + goto free_param_kptr; + } /* alloc kernel pointer with actual payload size */ kptr = kzalloc(pyld_sz, GFP_KERNEL); if (!kptr) { diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 4d771cb56b6a..134cef084ab9 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -651,7 +651,7 @@ int ipa3_request_gsi_channel(struct ipa_request_gsi_channel_params *params, } memcpy(&ep->chan_scratch, ¶ms->chan_scratch, - sizeof(union __packed gsi_channel_scratch)); + sizeof(union gsi_channel_scratch)); /* * Update scratch for MCS smart prefetch: diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 5d6191ebd1d4..5859e7d41f40 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -4718,7 +4718,7 @@ static int ipa_gsi_setup_transfer_ring(struct ipa3_ep_context *ep, u32 ring_size, struct ipa3_sys_context *user_data, gfp_t mem_flag) { dma_addr_t dma_addr; - union __packed gsi_channel_scratch ch_scratch; + union gsi_channel_scratch ch_scratch; struct gsi_chan_props gsi_channel_props; const struct ipa_gsi_ep_config *gsi_ep_info; int result; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 29a8fbdb0e1b..830dedd1404a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -918,7 +918,7 @@ struct ipa3_ep_context { unsigned long gsi_chan_hdl; unsigned long gsi_evt_ring_hdl; struct ipa_gsi_ep_mem_info gsi_mem_info; - union __packed gsi_channel_scratch chan_scratch; + union gsi_channel_scratch chan_scratch; struct gsi_chan_xfer_notify xfer_notify; bool xfer_notify_valid; struct ipa_ep_cfg cfg; @@ -975,7 +975,7 @@ struct ipa_request_gsi_channel_params { struct gsi_evt_ring_props evt_ring_params; union __packed gsi_evt_scratch evt_scratch; struct gsi_chan_props chan_params; - union __packed gsi_channel_scratch chan_scratch; + union gsi_channel_scratch chan_scratch; }; enum ipa3_sys_pipe_policy { @@ -2773,7 +2773,7 @@ bool ipa3_has_open_aggr_frame(enum ipa_client_type client); int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, - union __packed gsi_channel_scratch ch_scratch, u8 index); + union gsi_channel_scratch ch_scratch, u8 index); int ipa3_mhi_destroy_channel(enum ipa_client_type client); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index 1c47b93dc11e..7f44347de846 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -189,7 +189,7 @@ static int ipa_mhi_start_gsi_channel(enum ipa_client_type client, struct gsi_evt_ring_props ev_props; struct ipa_mhi_msi_info *msi; struct gsi_chan_props ch_props; - union __packed gsi_channel_scratch ch_scratch; + union gsi_channel_scratch ch_scratch; struct ipa3_ep_context *ep; const struct ipa_gsi_ep_config *ep_cfg; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; @@ -613,12 +613,12 @@ int ipa3_disconnect_mhi_pipe(u32 clnt_hdl) int ipa3_mhi_resume_channels_internal(enum ipa_client_type client, bool LPTransitionRejected, bool brstmode_enabled, - union __packed gsi_channel_scratch ch_scratch, u8 index) + union gsi_channel_scratch ch_scratch, u8 index) { int res; int ipa_ep_idx; struct ipa3_ep_context *ep; - union __packed gsi_channel_scratch gsi_ch_scratch; + union gsi_channel_scratch gsi_ch_scratch; IPA_MHI_FUNC_ENTRY(); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index 7f85a9ebf9df..e0d92f83bc32 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -1170,7 +1170,7 @@ int ipa3_connect_gsi_wdi_pipe(struct ipa_wdi_in_params *in, struct ipa_ep_cfg_ctrl ep_cfg_ctrl; struct gsi_chan_props gsi_channel_props; struct gsi_evt_ring_props gsi_evt_ring_props; - union __packed gsi_channel_scratch gsi_scratch; + union gsi_channel_scratch gsi_scratch; phys_addr_t pa; unsigned long va; unsigned long wifi_rx_ri_addr = 0; @@ -2479,7 +2479,7 @@ int ipa3_resume_gsi_wdi_pipe(u32 clnt_hdl) struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; struct gsi_chan_info chan_info; - union __packed gsi_channel_scratch gsi_scratch; + union gsi_channel_scratch gsi_scratch; struct IpaHwOffloadStatsAllocCmdData_t *pcmd_t = NULL; IPADBG("ep=%d\n", clnt_hdl); @@ -2615,7 +2615,7 @@ int ipa3_suspend_gsi_wdi_pipe(u32 clnt_hdl) struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 }; int retry_cnt = 0; struct gsi_chan_info chan_info; - union __packed gsi_channel_scratch gsi_scratch; + union gsi_channel_scratch gsi_scratch; struct IpaHwOffloadStatsAllocCmdData_t *pcmd_t = NULL; ipa_ep_idx = ipa3_get_ep_mapping(ipa3_get_client_mapping(clnt_hdl)); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c index 1679d8c24948..efa2338dfa9d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c @@ -69,7 +69,7 @@ static int ipa3_setup_wdi3_gsi_channel(u8 is_smmu_enabled, { struct gsi_evt_ring_props gsi_evt_ring_props; struct gsi_chan_props gsi_channel_props; - union __packed gsi_channel_scratch ch_scratch; + union gsi_channel_scratch ch_scratch; union __packed gsi_evt_scratch evt_scratch; const struct ipa_gsi_ep_config *gsi_ep_info; int result, len; @@ -909,7 +909,7 @@ int ipa3_write_qmapid_wdi3_gsi_pipe(u32 clnt_hdl, u8 qmap_id) { int result = 0; struct ipa3_ep_context *ep; - union __packed gsi_channel_scratch ch_scratch; + union gsi_channel_scratch ch_scratch; memset(&ch_scratch, 0, sizeof(ch_scratch)); if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c b/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c index f91c2d1d8c82..649c699e4e02 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_wigig_i.c @@ -603,7 +603,7 @@ static int ipa3_wigig_config_gsi(bool Rx, { struct gsi_evt_ring_props evt_props; struct gsi_chan_props channel_props; - union __packed gsi_channel_scratch gsi_scratch; + union gsi_channel_scratch gsi_scratch; int gsi_res; struct ipa_wigig_pipe_setup_info_smmu *pipe_smmu; struct ipa_wigig_pipe_setup_info *pipe; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c index 3edca59dcf8c..0a146d4858be 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_hw_stats.c @@ -225,7 +225,7 @@ static struct ipahal_stats_init_pyld *ipahal_generate_init_pyld_flt_rt_v4_5( void *params, bool is_atomic_ctx) { struct ipahal_stats_init_pyld *pyld; - int num = (int)(params); + int num = (int)(long)params; if (num > IPA_MAX_FLT_RT_CNT_INDEX || num <= 0) { diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index e178b8ef2eeb..922f4fb3524a 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -1221,9 +1221,9 @@ static int ipa3_wwan_change_mtu(struct net_device *dev, int new_mtu) * later * -EFAULT: Error while transmitting the skb */ -static int ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) +static netdev_tx_t ipa3_wwan_xmit(struct sk_buff *skb, struct net_device *dev) { - int ret = 0; + netdev_tx_t ret = NETDEV_TX_OK; bool qmap_check; struct ipa3_wwan_private *wwan_ptr = netdev_priv(dev); unsigned long flags; diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index fcfeadd1301f..bd25c8a156d2 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -43,6 +43,7 @@ #include #include +ACPI_MODULE_NAME(KBUILD_MODNAME); MODULE_AUTHOR("Carlos Corbacho"); MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver"); MODULE_LICENSE("GPL"); @@ -93,7 +94,7 @@ MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026"); enum acer_wmi_event_ids { WMID_HOTKEY_EVENT = 0x1, - WMID_ACCEL_EVENT = 0x5, + WMID_ACCEL_OR_KBD_DOCK_EVENT = 0x5, }; static const struct key_entry acer_wmi_keymap[] __initconst = { @@ -124,6 +125,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = { {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ {KE_IGNORE, 0x81, {KEY_SLEEP} }, {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */ + {KE_IGNORE, 0x84, {KEY_KBDILLUMTOGGLE} }, /* Automatic Keyboard background light toggle */ {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} }, {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} }, {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, @@ -140,7 +142,9 @@ struct event_return_value { u8 function; u8 key_num; u16 device_state; - u32 reserved; + u16 reserved1; + u8 kbd_dock_state; + u8 reserved2; } __attribute__((packed)); /* @@ -218,14 +222,13 @@ struct hotkey_function_type_aa { /* * Interface capability flags */ -#define ACER_CAP_MAILLED (1<<0) -#define ACER_CAP_WIRELESS (1<<1) -#define ACER_CAP_BLUETOOTH (1<<2) -#define ACER_CAP_BRIGHTNESS (1<<3) -#define ACER_CAP_THREEG (1<<4) -#define ACER_CAP_ACCEL (1<<5) -#define ACER_CAP_RFBTN (1<<6) -#define ACER_CAP_ANY (0xFFFFFFFF) +#define ACER_CAP_MAILLED BIT(0) +#define ACER_CAP_WIRELESS BIT(1) +#define ACER_CAP_BLUETOOTH BIT(2) +#define ACER_CAP_BRIGHTNESS BIT(3) +#define ACER_CAP_THREEG BIT(4) +#define ACER_CAP_SET_FUNCTION_MODE BIT(5) +#define ACER_CAP_KBD_DOCK BIT(6) /* * Interface type flags @@ -248,6 +251,7 @@ static int mailled = -1; static int brightness = -1; static int threeg = -1; static int force_series; +static int force_caps = -1; static bool ec_raw_mode; static bool has_type_aa; static u16 commun_func_bitmap; @@ -257,11 +261,13 @@ module_param(mailled, int, 0444); module_param(brightness, int, 0444); module_param(threeg, int, 0444); module_param(force_series, int, 0444); +module_param(force_caps, int, 0444); module_param(ec_raw_mode, bool, 0444); MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); MODULE_PARM_DESC(force_series, "Force a different laptop series"); +MODULE_PARM_DESC(force_caps, "Force the capability bitmask to this value"); MODULE_PARM_DESC(ec_raw_mode, "Enable EC raw mode"); struct acer_data { @@ -332,6 +338,15 @@ static int __init dmi_matched(const struct dmi_system_id *dmi) return 1; } +static int __init set_force_caps(const struct dmi_system_id *dmi) +{ + if (force_caps == -1) { + force_caps = (uintptr_t)dmi->driver_data; + pr_info("Found %s, set force_caps to 0x%x\n", dmi->ident, force_caps); + } + return 1; +} + static struct quirk_entry quirk_unknown = { }; @@ -510,6 +525,33 @@ static const struct dmi_system_id acer_quirks[] __initconst = { }, .driver_data = &quirk_acer_travelmate_2490, }, + { + .callback = set_force_caps, + .ident = "Acer Aspire Switch 10E SW3-016", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW3-016"), + }, + .driver_data = (void *)ACER_CAP_KBD_DOCK, + }, + { + .callback = set_force_caps, + .ident = "Acer Aspire Switch 10 SW5-012", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire SW5-012"), + }, + .driver_data = (void *)ACER_CAP_KBD_DOCK, + }, + { + .callback = set_force_caps, + .ident = "Acer One 10 (S1003)", + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "One S1003"), + }, + .driver_data = (void *)ACER_CAP_KBD_DOCK, + }, {} }; @@ -1265,10 +1307,8 @@ static void __init type_aa_dmi_decode(const struct dmi_header *header, void *d) interface->capability |= ACER_CAP_THREEG; if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_BLUETOOTH) interface->capability |= ACER_CAP_BLUETOOTH; - if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN) { - interface->capability |= ACER_CAP_RFBTN; + if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_RFBTN) commun_func_bitmap &= ~ACER_WMID3_GDS_RFBTN; - } commun_fn_key_number = type_aa->commun_fn_key_number; } @@ -1529,7 +1569,7 @@ static int acer_gsensor_event(void) struct acpi_buffer output; union acpi_object out_obj[5]; - if (!has_cap(ACER_CAP_ACCEL)) + if (!acer_wmi_accel_dev) return -1; output.length = sizeof(out_obj); @@ -1552,6 +1592,71 @@ static int acer_gsensor_event(void) return 0; } +/* + * Switch series keyboard dock status + */ +static int acer_kbd_dock_state_to_sw_tablet_mode(u8 kbd_dock_state) +{ + switch (kbd_dock_state) { + case 0x01: /* Docked, traditional clamshell laptop mode */ + return 0; + case 0x04: /* Stand-alone tablet */ + case 0x40: /* Docked, tent mode, keyboard not usable */ + return 1; + default: + pr_warn("Unknown kbd_dock_state 0x%02x\n", kbd_dock_state); + } + + return 0; +} + +static void acer_kbd_dock_get_initial_state(void) +{ + u8 *output, input[8] = { 0x05, 0x00, }; + struct acpi_buffer input_buf = { sizeof(input), input }; + struct acpi_buffer output_buf = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + acpi_status status; + int sw_tablet_mode; + + status = wmi_evaluate_method(WMID_GUID3, 0, 0x2, &input_buf, &output_buf); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Error getting keyboard-dock initial status")); + return; + } + + obj = output_buf.pointer; + if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { + pr_err("Unexpected output format getting keyboard-dock initial status\n"); + goto out_free_obj; + } + + output = obj->buffer.pointer; + if (output[0] != 0x00 || (output[3] != 0x05 && output[3] != 0x45)) { + pr_err("Unexpected output [0]=0x%02x [3]=0x%02x getting keyboard-dock initial status\n", + output[0], output[3]); + goto out_free_obj; + } + + sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(output[4]); + input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode); + +out_free_obj: + kfree(obj); +} + +static void acer_kbd_dock_event(const struct event_return_value *event) +{ + int sw_tablet_mode; + + if (!has_cap(ACER_CAP_KBD_DOCK)) + return; + + sw_tablet_mode = acer_kbd_dock_state_to_sw_tablet_mode(event->kbd_dock_state); + input_report_switch(acer_wmi_input_dev, SW_TABLET_MODE, sw_tablet_mode); + input_sync(acer_wmi_input_dev); +} + /* * Rfkill devices */ @@ -1779,8 +1884,9 @@ static void acer_wmi_notify(u32 value, void *context) sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true); } break; - case WMID_ACCEL_EVENT: + case WMID_ACCEL_OR_KBD_DOCK_EVENT: acer_gsensor_event(); + acer_kbd_dock_event(&return_value); break; default: pr_warn("Unknown function number - %d - %d\n", @@ -1938,8 +2044,6 @@ static int __init acer_wmi_accel_setup(void) if (err) return err; - interface->capability |= ACER_CAP_ACCEL; - acer_wmi_accel_dev = input_allocate_device(); if (!acer_wmi_accel_dev) return -ENOMEM; @@ -1965,11 +2069,6 @@ static int __init acer_wmi_accel_setup(void) return err; } -static void acer_wmi_accel_destroy(void) -{ - input_unregister_device(acer_wmi_accel_dev); -} - static int __init acer_wmi_input_setup(void) { acpi_status status; @@ -1987,6 +2086,9 @@ static int __init acer_wmi_input_setup(void) if (err) goto err_free_dev; + if (has_cap(ACER_CAP_KBD_DOCK)) + input_set_capability(acer_wmi_input_dev, EV_SW, SW_TABLET_MODE); + status = wmi_install_notify_handler(ACERWMID_EVENT_GUID, acer_wmi_notify, NULL); if (ACPI_FAILURE(status)) { @@ -1994,6 +2096,9 @@ static int __init acer_wmi_input_setup(void) goto err_free_dev; } + if (has_cap(ACER_CAP_KBD_DOCK)) + acer_kbd_dock_get_initial_state(); + err = input_register_device(acer_wmi_input_dev); if (err) goto err_uninstall_notifier; @@ -2124,7 +2229,7 @@ static int acer_resume(struct device *dev) if (has_cap(ACER_CAP_BRIGHTNESS)) set_u32(data->brightness, ACER_CAP_BRIGHTNESS); - if (has_cap(ACER_CAP_ACCEL)) + if (acer_wmi_accel_dev) acer_gsensor_init(); return 0; @@ -2239,7 +2344,7 @@ static int __init acer_wmi_init(void) } /* WMID always provides brightness methods */ interface->capability |= ACER_CAP_BRIGHTNESS; - } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa) { + } else if (!wmi_has_guid(WMID_GUID2) && interface && !has_type_aa && force_caps == -1) { pr_err("No WMID device detection method found\n"); return -ENODEV; } @@ -2269,7 +2374,14 @@ static int __init acer_wmi_init(void) if (acpi_video_get_backlight_type() != acpi_backlight_vendor) interface->capability &= ~ACER_CAP_BRIGHTNESS; - if (wmi_has_guid(WMID_GUID3)) { + if (wmi_has_guid(WMID_GUID3)) + interface->capability |= ACER_CAP_SET_FUNCTION_MODE; + + if (force_caps != -1) + interface->capability = force_caps; + + if (wmi_has_guid(WMID_GUID3) && + (interface->capability & ACER_CAP_SET_FUNCTION_MODE)) { if (ACPI_FAILURE(acer_wmi_enable_rf_button())) pr_warn("Cannot enable RF Button Driver\n"); @@ -2332,8 +2444,8 @@ static int __init acer_wmi_init(void) error_platform_register: if (wmi_has_guid(ACERWMID_EVENT_GUID)) acer_wmi_input_destroy(); - if (has_cap(ACER_CAP_ACCEL)) - acer_wmi_accel_destroy(); + if (acer_wmi_accel_dev) + input_unregister_device(acer_wmi_accel_dev); return err; } @@ -2343,8 +2455,8 @@ static void __exit acer_wmi_exit(void) if (wmi_has_guid(ACERWMID_EVENT_GUID)) acer_wmi_input_destroy(); - if (has_cap(ACER_CAP_ACCEL)) - acer_wmi_accel_destroy(); + if (acer_wmi_accel_dev) + input_unregister_device(acer_wmi_accel_dev); remove_debugfs(); platform_device_unregister(acer_platform_device); diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c index 0537d44d45a6..9e9fc5155789 100644 --- a/drivers/platform/x86/dell-smbios-base.c +++ b/drivers/platform/x86/dell-smbios-base.c @@ -597,6 +597,7 @@ static int __init dell_smbios_init(void) if (wmi && smm) { pr_err("No SMBIOS backends available (wmi: %d, smm: %d)\n", wmi, smm); + ret = -ENODEV; goto fail_create_group; } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 952544ca0d84..93fadd4abf14 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -45,6 +45,10 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C"); MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4"); +static int enable_tablet_mode_sw = -1; +module_param(enable_tablet_mode_sw, int, 0444); +MODULE_PARM_DESC(enable_tablet_mode_sw, "Enable SW_TABLET_MODE reporting (-1=auto, 0=no, 1=yes)"); + #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4" @@ -656,10 +660,12 @@ static int __init hp_wmi_input_setup(void) } /* Tablet mode */ - val = hp_wmi_hw_state(HPWMI_TABLET_MASK); - if (!(val < 0)) { - __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); - input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); + if (enable_tablet_mode_sw > 0) { + val = hp_wmi_hw_state(HPWMI_TABLET_MASK); + if (val >= 0) { + __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); + input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); + } } err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index d7d69eadb9bb..fa3cda69cec9 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -94,6 +94,13 @@ static const struct dmi_system_id button_array_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Spectre x2 Detachable"), }, }, + { + .ident = "Lenovo ThinkPad X1 Tablet Gen 2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), + DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Tablet Gen 2"), + }, + }, { } }; diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index 1e6b4661c764..772f9ae3d7e9 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -46,8 +46,16 @@ static const struct key_entry intel_vbtn_keymap[] = { }; static const struct key_entry intel_vbtn_switchmap[] = { - { KE_SW, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */ - { KE_SW, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */ + /* + * SW_DOCK should only be reported for docking stations, but DSDTs using the + * intel-vbtn code, always seem to use this for 2-in-1s / convertibles and set + * SW_DOCK=1 when in laptop-mode (in tandem with setting SW_TABLET_MODE=0). + * This causes userspace to think the laptop is docked to a port-replicator + * and to disable suspend-on-lid-close, which is undesirable. + * Map the dock events to KEY_IGNORE to avoid this broken SW_DOCK reporting. + */ + { KE_IGNORE, 0xCA, { .sw = { SW_DOCK, 1 } } }, /* Docked */ + { KE_IGNORE, 0xCB, { .sw = { SW_DOCK, 0 } } }, /* Undocked */ { KE_SW, 0xCC, { .sw = { SW_TABLET_MODE, 1 } } }, /* Tablet */ { KE_SW, 0xCD, { .sw = { SW_TABLET_MODE, 0 } } }, /* Laptop */ }; @@ -194,7 +202,19 @@ static const struct dmi_system_id dmi_switches_allow_list[] = { { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Stream x360 Convertible PC 11"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion 13 x360 PC"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Switch SA5-271"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7352"), }, }, {} /* Array terminator */ diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c index 0c72de95b5cc..b2a196a2b6c7 100644 --- a/drivers/platform/x86/mlx-platform.c +++ b/drivers/platform/x86/mlx-platform.c @@ -212,15 +212,6 @@ static struct i2c_mux_reg_platform_data mlxplat_mux_data[] = { }; /* Platform hotplug devices */ -static struct i2c_board_info mlxplat_mlxcpld_psu[] = { - { - I2C_BOARD_INFO("24c02", 0x51), - }, - { - I2C_BOARD_INFO("24c02", 0x50), - }, -}; - static struct i2c_board_info mlxplat_mlxcpld_pwr[] = { { I2C_BOARD_INFO("dps460", 0x59), @@ -251,15 +242,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_default_psu_items_data[] = { .label = "psu1", .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, }, { .label = "psu2", .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_DEFAULT_NR, + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, }, }; @@ -326,7 +315,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { .aggr_mask = MLXPLAT_CPLD_AGGR_PSU_MASK_DEF, .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, .mask = MLXPLAT_CPLD_PSU_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_psu), + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_psu_items_data), .inversed = 1, .health = false, }, @@ -335,7 +324,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { .aggr_mask = MLXPLAT_CPLD_AGGR_PWR_MASK_DEF, .reg = MLXPLAT_CPLD_LPC_REG_PWR_OFFSET, .mask = MLXPLAT_CPLD_PWR_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_pwr), + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_pwr_items_data), .inversed = 0, .health = false, }, @@ -344,7 +333,7 @@ static struct mlxreg_core_item mlxplat_mlxcpld_default_items[] = { .aggr_mask = MLXPLAT_CPLD_AGGR_FAN_MASK_DEF, .reg = MLXPLAT_CPLD_LPC_REG_FAN_OFFSET, .mask = MLXPLAT_CPLD_FAN_MASK, - .count = ARRAY_SIZE(mlxplat_mlxcpld_fan), + .count = ARRAY_SIZE(mlxplat_mlxcpld_default_fan_items_data), .inversed = 1, .health = false, }, @@ -422,15 +411,13 @@ static struct mlxreg_core_data mlxplat_mlxcpld_msn274x_psu_items_data[] = { .label = "psu1", .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, .mask = BIT(0), - .hpdev.brdinfo = &mlxplat_mlxcpld_psu[0], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, }, { .label = "psu2", .reg = MLXPLAT_CPLD_LPC_REG_PSU_OFFSET, .mask = BIT(1), - .hpdev.brdinfo = &mlxplat_mlxcpld_psu[1], - .hpdev.nr = MLXPLAT_CPLD_PSU_MSNXXXX_NR, + .hpdev.nr = MLXPLAT_CPLD_NR_NONE, }, }; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 98bd8213b037..559698640fe2 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3242,7 +3242,14 @@ static int hotkey_init_tablet_mode(void) in_tablet_mode = hotkey_gmms_get_tablet_mode(res, &has_tablet_mode); - if (has_tablet_mode) + /* + * The Yoga 11e series has 2 accelerometers described by a + * BOSC0200 ACPI node. This setup relies on a Windows service + * which calls special ACPI methods on this node to report + * the laptop/tent/tablet mode to the EC. The bmc150 iio driver + * does not support this, so skip the hotkey on these models. + */ + if (has_tablet_mode && !acpi_dev_present("BOSC0200", "1", -1)) tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS; type = "GMMS"; } else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) { @@ -4095,13 +4102,19 @@ static bool hotkey_notify_6xxx(const u32 hkey, case TP_HKEY_EV_KEY_NUMLOCK: case TP_HKEY_EV_KEY_FN: - case TP_HKEY_EV_KEY_FN_ESC: /* key press events, we just ignore them as long as the EC * is still reporting them in the normal keyboard stream */ *send_acpi_ev = false; *ignore_acpi_ev = true; return true; + case TP_HKEY_EV_KEY_FN_ESC: + /* Get the media key status to foce the status LED to update */ + acpi_evalf(hkey_handle, NULL, "GMKS", "v"); + *send_acpi_ev = false; + *ignore_acpi_ev = true; + return true; + case TP_HKEY_EV_TABLET_CHANGED: tpacpi_input_send_tabletsw(); hotkey_tablet_mode_notify_change(); @@ -4251,6 +4264,7 @@ static void hotkey_resume(void) pr_err("error while attempting to reset the event firmware interface\n"); tpacpi_send_radiosw_update(); + tpacpi_input_send_tabletsw(); hotkey_tablet_mode_notify_change(); hotkey_wakeup_reason_notify_change(); hotkey_wakeup_hotunplug_complete_notify_change(); @@ -9689,6 +9703,7 @@ static const struct tpacpi_quirk battery_quirk_table[] __initconst = { TPACPI_Q_LNV3('R', '0', 'B', true), /* Thinkpad 11e gen 3 */ TPACPI_Q_LNV3('R', '0', 'C', true), /* Thinkpad 13 */ TPACPI_Q_LNV3('R', '0', 'J', true), /* Thinkpad 13 gen 2 */ + TPACPI_Q_LNV3('R', '0', 'K', true), /* Thinkpad 11e gen 4 celeron BIOS */ }; static int __init tpacpi_battery_init(struct ibm_init_struct *ibm) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index e366977bda41..8c3e9bac4754 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -1497,7 +1497,7 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, struct toshiba_acpi_dev *dev = PDE_DATA(file_inode(file)); char *buffer; char *cmd; - int lcd_out, crt_out, tv_out; + int lcd_out = -1, crt_out = -1, tv_out = -1; int remain = count; int value; int ret; @@ -1529,7 +1529,6 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf, kfree(cmd); - lcd_out = crt_out = tv_out = -1; ret = get_video_status(dev, &video_out); if (!ret) { unsigned int new_video_out = video_out; diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index cb204f973491..f122a0263a1b 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -163,6 +163,16 @@ static const struct ts_dmi_data digma_citi_e200_data = { .properties = digma_citi_e200_props, }; +static const struct property_entry estar_beauty_hd_props[] = { + PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"), + { } +}; + +static const struct ts_dmi_data estar_beauty_hd_data = { + .acpi_name = "GDIX1001:00", + .properties = estar_beauty_hd_props, +}; + static const struct property_entry gp_electronic_t701_props[] = { PROPERTY_ENTRY_U32("touchscreen-size-x", 960), PROPERTY_ENTRY_U32("touchscreen-size-y", 640), @@ -501,6 +511,14 @@ static const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"), }, }, + { + /* Estar Beauty HD (MID 7316R) */ + .driver_data = (void *)&estar_beauty_hd_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Estar"), + DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"), + }, + }, { /* GP-electronic T701 */ .driver_data = (void *)&gp_electronic_t701_data, diff --git a/drivers/power/reset/at91-sama5d2_shdwc.c b/drivers/power/reset/at91-sama5d2_shdwc.c index d9493e893d64..7cf59e764ef2 100644 --- a/drivers/power/reset/at91-sama5d2_shdwc.c +++ b/drivers/power/reset/at91-sama5d2_shdwc.c @@ -36,7 +36,7 @@ #define AT91_SHDW_MR 0x04 /* Shut Down Mode Register */ #define AT91_SHDW_WKUPDBC_SHIFT 24 -#define AT91_SHDW_WKUPDBC_MASK GENMASK(31, 16) +#define AT91_SHDW_WKUPDBC_MASK GENMASK(26, 24) #define AT91_SHDW_WKUPDBC(x) (((x) << AT91_SHDW_WKUPDBC_SHIFT) \ & AT91_SHDW_WKUPDBC_MASK) diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c index 46eb7716c35c..84106a9836c8 100644 --- a/drivers/power/supply/axp288_charger.c +++ b/drivers/power/supply/axp288_charger.c @@ -555,14 +555,15 @@ static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev) /* * The HP Pavilion x2 10 series comes in a number of variants: - * Bay Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "815D" - * Cherry Trail SoC + AXP288 PMIC, DMI_BOARD_NAME: "813E" - * Cherry Trail SoC + TI PMIC, DMI_BOARD_NAME: "827C" or "82F4" + * Bay Trail SoC + AXP288 PMIC, Micro-USB, DMI_BOARD_NAME: "8021" + * Bay Trail SoC + AXP288 PMIC, Type-C, DMI_BOARD_NAME: "815D" + * Cherry Trail SoC + AXP288 PMIC, Type-C, DMI_BOARD_NAME: "813E" + * Cherry Trail SoC + TI PMIC, Type-C, DMI_BOARD_NAME: "827C" or "82F4" * - * The variants with the AXP288 PMIC are all kinds of special: + * The variants with the AXP288 + Type-C connector are all kinds of special: * - * 1. All variants use a Type-C connector which the AXP288 does not support, so - * when using a Type-C charger it is not recognized. Unlike most AXP288 devices, + * 1. They use a Type-C connector which the AXP288 does not support, so when + * using a Type-C charger it is not recognized. Unlike most AXP288 devices, * this model actually has mostly working ACPI AC / Battery code, the ACPI code * "solves" this by simply setting the input_current_limit to 3A. * There are still some issues with the ACPI code, so we use this native driver, @@ -585,12 +586,17 @@ static irqreturn_t axp288_charger_irq_thread_handler(int irq, void *dev) */ static const struct dmi_system_id axp288_hp_x2_dmi_ids[] = { { - /* - * Bay Trail model has "Hewlett-Packard" as sys_vendor, Cherry - * Trail model has "HP", so we only match on product_name. - */ .matches = { - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "815D"), + }, + }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "813E"), }, }, {} /* Terminating entry */ diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index b58df04d03b3..863208928cf0 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -446,8 +446,10 @@ static ssize_t bq24190_sysfs_show(struct device *dev, return -EINVAL; ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } ret = bq24190_read_mask(bdi, info->reg, info->mask, info->shift, &v); if (ret) @@ -1092,8 +1094,10 @@ static int bq24190_charger_get_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_CHARGE_TYPE: @@ -1164,8 +1168,10 @@ static int bq24190_charger_set_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_ONLINE: @@ -1425,8 +1431,10 @@ static int bq24190_battery_get_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_STATUS: @@ -1471,8 +1479,10 @@ static int bq24190_battery_set_property(struct power_supply *psy, dev_dbg(bdi->dev, "prop: %d\n", psp); ret = pm_runtime_get_sync(bdi->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_noidle(bdi->dev); return ret; + } switch (psp) { case POWER_SUPPLY_PROP_ONLINE: diff --git a/drivers/power/supply/cas_qcom/bq25790_charger.c b/drivers/power/supply/cas_qcom/bq25790_charger.c index 7d0b7700c2d8..a590050f3b12 100644 --- a/drivers/power/supply/cas_qcom/bq25790_charger.c +++ b/drivers/power/supply/cas_qcom/bq25790_charger.c @@ -49,7 +49,7 @@ enum print_reason { PR_DEBUG = BIT(3), }; -static int debug_mask = PR_OEM; +static int debug_mask = 0; module_param_named(debug_mask, debug_mask, int, 0600); #define bq_dbg(reason, fmt, ...) \ diff --git a/drivers/power/supply/cas_qcom/max28200.c b/drivers/power/supply/cas_qcom/max28200.c index bc4ecccf4994..a72661293837 100644 --- a/drivers/power/supply/cas_qcom/max28200.c +++ b/drivers/power/supply/cas_qcom/max28200.c @@ -22,7 +22,7 @@ enum print_reason { PR_FW = BIT(4), }; -static int debug_mask = PR_OEM | PR_FW; +static int debug_mask = 0; module_param_named(debug_mask, debug_mask, int, 0600); diff --git a/drivers/power/supply/cas_qcom/max77932.c b/drivers/power/supply/cas_qcom/max77932.c index 6ce9d9d26c59..f02dc2980bbd 100644 --- a/drivers/power/supply/cas_qcom/max77932.c +++ b/drivers/power/supply/cas_qcom/max77932.c @@ -38,7 +38,7 @@ enum print_reason { PR_DEBUG = BIT(3), }; -static int debug_mask = PR_OEM; +static int debug_mask = 0; module_param_named( debug_mask, debug_mask, int, 0600 diff --git a/drivers/power/supply/maxim/ds28e16.c b/drivers/power/supply/maxim/ds28e16.c index 8304cc8cd9d4..1c851004eb69 100644 --- a/drivers/power/supply/maxim/ds28e16.c +++ b/drivers/power/supply/maxim/ds28e16.c @@ -158,7 +158,7 @@ short Read_RomID(unsigned char *RomID) ds_dbg("Ready to write 0x33 to maxim IC!\n"); write_byte(CMD_READ_ROM); - Delay_us(10); + udelay(10); for (i = 0; i < 8; i++) RomID[i] = read_byte(); @@ -341,7 +341,7 @@ unsigned char *read_buf, int *read_len, int write_len) // check for strong pull-up if (delay_ms > 0) { write_byte(CMD_RELEASE_BYTE); - Delay_us(1000*delay_ms); + mdelay(delay_ms); } read_byte(); @@ -1295,7 +1295,7 @@ struct device_attribute *attr, char *buf) ds_dbg("RomID = %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n", RomID[0], RomID[1], RomID[2], RomID[3], RomID[4], RomID[5], RomID[6], RomID[7]); - Delay_us(1000); + udelay(1000); } ds_log("test done\nsuccess time : %d\n", count); return scnprintf(buf, PAGE_SIZE, @@ -1348,7 +1348,7 @@ struct device_attribute *attr, char *buf) pagedata[4], pagedata[5], pagedata[6], pagedata[7], pagedata[8], pagedata[9], pagedata[10], pagedata[11], pagedata[12], pagedata[13], pagedata[14], pagedata[15]); - Delay_us(1000); + udelay(1000); } ds_log("test done\nsuccess time : %d\n", count); return scnprintf(buf, PAGE_SIZE, @@ -1569,7 +1569,7 @@ struct device_attribute *attr, char *buf) status[4], status[5], status[6], status[7], status[8], status[9], status[10], status[11], status[12], status[13], status[14], status[15]); - Delay_us(1000); + udelay(1000); } ds_log("test done\nsuccess time : %d\n", count); return scnprintf(buf, PAGE_SIZE, diff --git a/drivers/power/supply/maxim/onewire_gpio.c b/drivers/power/supply/maxim/onewire_gpio.c index 9e70aeca91ba..52303a042f0f 100644 --- a/drivers/power/supply/maxim/onewire_gpio.c +++ b/drivers/power/supply/maxim/onewire_gpio.c @@ -73,18 +73,6 @@ static int onewire_major; static int onewire_gpio_detected; static struct onewire_gpio_data *g_onewire_data; -void Delay_us(unsigned int T) -{ - udelay(T); -} -EXPORT_SYMBOL(Delay_us); - -void Delay_ns(unsigned int T) -{ - ndelay(T); -} -EXPORT_SYMBOL(Delay_ns); - unsigned char ow_reset(void) { unsigned char presence = 0xFF; @@ -94,12 +82,12 @@ unsigned char ow_reset(void) ONE_WIRE_CONFIG_OUT; ONE_WIRE_OUT_LOW; - Delay_us(50);// 48 + udelay(50);// 48 ONE_WIRE_OUT_HIGH; ONE_WIRE_CONFIG_IN; - Delay_us(7); + udelay(7); presence = (unsigned char)readl_relaxed(g_onewire_data->gpio_in_out_reg) & 0x01; // Read - Delay_us(50); + udelay(50); raw_spin_unlock_irqrestore(&g_onewire_data->lock, flags); return presence; @@ -112,26 +100,26 @@ unsigned char read_bit(void) ONE_WIRE_CONFIG_OUT; ONE_WIRE_OUT_LOW; - Delay_us(1);//// + udelay(1);//// ONE_WIRE_CONFIG_IN; - Delay_ns(500);// + ndelay(500);// vamm = readl_relaxed(g_onewire_data->gpio_in_out_reg); // Read - Delay_us(5); + udelay(5); ONE_WIRE_OUT_HIGH; ONE_WIRE_CONFIG_OUT; - Delay_us(6); + udelay(6); return((unsigned char)vamm & 0x01); } void write_bit(char bitval) { ONE_WIRE_OUT_LOW; - Delay_us(1);// + udelay(1);// if (bitval != 0) ONE_WIRE_OUT_HIGH; - Delay_us(10); + udelay(10); ONE_WIRE_OUT_HIGH; - Delay_us(6); + udelay(6); } unsigned char read_byte(void) @@ -330,49 +318,49 @@ const char *buf, size_t count) ONE_WIRE_OUT_HIGH; ONE_WIRE_OUT_LOW; - Delay_us(1000); + udelay(1000); ONE_WIRE_OUT_HIGH; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_LOW; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_HIGH; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_LOW; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_HIGH; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_LOW; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_HIGH; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_LOW; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_HIGH; - Delay_us(1); + udelay(1); ONE_WIRE_OUT_LOW; - Delay_us(1); + udelay(1); - Delay_us(1000); + udelay(1000); ONE_WIRE_OUT_HIGH; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_LOW; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_HIGH; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_LOW; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_HIGH; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_LOW; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_HIGH; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_LOW; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_HIGH; - Delay_us(5); + udelay(5); ONE_WIRE_OUT_LOW; - Delay_us(5); + udelay(5); } return count; diff --git a/drivers/power/supply/maxim/onewire_gpio.h b/drivers/power/supply/maxim/onewire_gpio.h index f62e4a73fb76..ccffe90edca2 100644 --- a/drivers/power/supply/maxim/onewire_gpio.h +++ b/drivers/power/supply/maxim/onewire_gpio.h @@ -1,8 +1,6 @@ #ifndef __ONEWIRE_GPIO_H__ #define __ONEWIRE_GPIO_H__ -void Delay_us(unsigned int T); -void Delay_ns(unsigned int T); unsigned char ow_reset(void); unsigned char read_byte(void); void write_byte(char val); diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 633e006b3984..5c1d98657339 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -355,7 +355,8 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data) unsigned int *count = data; (*count)++; - if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY) + if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY && + psy->desc->type != POWER_SUPPLY_TYPE_BMS) if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret)) return ret.intval; diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index 83cec78bb57c..b9f5bf6bc3cb 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -727,29 +727,12 @@ void power_supply_init_attrs(struct device_type *dev_type) __power_supply_attrs[i] = &power_supply_attrs[i].attr; } -static char *kstruprdup(const char *str, gfp_t gfp) -{ - char *ret, *ustr; - - ustr = ret = kmalloc(strlen(str) + 1, gfp); - - if (!ret) - return NULL; - - while (*str) - *ustr++ = toupper(*str++); - - *ustr = 0; - - return ret; -} - int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) { struct power_supply *psy = dev_get_drvdata(dev); int ret = 0, j; char *prop_buf; - char *attrname; + char attrname[64]; if (!psy || !psy->desc) { dev_dbg(dev, "No power supply yet\n"); @@ -766,7 +749,8 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) for (j = 0; j < psy->desc->num_properties; j++) { struct device_attribute *attr; - char *line; + const char *str; + char *line, *ustr; attr = &power_supply_attrs[psy->desc->properties[j]]; @@ -785,14 +769,14 @@ int power_supply_uevent(struct device *dev, struct kobj_uevent_env *env) if (line) *line = 0; - attrname = kstruprdup(attr->attr.name, GFP_KERNEL); - if (!attrname) { - ret = -ENOMEM; - goto out; - } + str = attr->attr.name; + ustr = attrname; + while (*str) + *ustr++ = toupper(*str++); + + *ustr = 0; ret = add_uevent_var(env, "POWER_SUPPLY_%s=%s", attrname, prop_buf); - kfree(attrname); if (ret) goto out; } diff --git a/drivers/power/supply/qcom/bq25790_charger.c b/drivers/power/supply/qcom/bq25790_charger.c index 518b69ce98a0..98c31ba3a946 100644 --- a/drivers/power/supply/qcom/bq25790_charger.c +++ b/drivers/power/supply/qcom/bq25790_charger.c @@ -43,6 +43,8 @@ #include "bq25790_reg.h" #include "bq25790.h" +static int debug_mask = 0; + #define bq_info pr_err #define bq_dbg pr_debug #define bq_err pr_err diff --git a/drivers/power/supply/qcom/bq27z561_fg.c b/drivers/power/supply/qcom/bq27z561_fg.c index be6bc0c2f95c..67d70e9c72b3 100644 --- a/drivers/power/supply/qcom/bq27z561_fg.c +++ b/drivers/power/supply/qcom/bq27z561_fg.c @@ -40,7 +40,7 @@ enum print_reason { PR_DEBUG = BIT(3), }; -static int debug_mask = PR_OEM; +static int debug_mask = 0; module_param_named( debug_mask, debug_mask, int, 0600 ); diff --git a/drivers/power/supply/qcom/max28200.c b/drivers/power/supply/qcom/max28200.c index d39f0be9be7f..86a78d52ea40 100644 --- a/drivers/power/supply/qcom/max28200.c +++ b/drivers/power/supply/qcom/max28200.c @@ -40,7 +40,7 @@ enum print_reason { PR_DEBUG = BIT(3), }; -static int debug_mask = PR_OEM; +static int debug_mask = 0; module_param_named( debug_mask, debug_mask, int, 0600 diff --git a/drivers/power/supply/qcom/max77932.c b/drivers/power/supply/qcom/max77932.c index 33d0252947c1..c8c4d6ed0ad3 100644 --- a/drivers/power/supply/qcom/max77932.c +++ b/drivers/power/supply/qcom/max77932.c @@ -38,7 +38,7 @@ enum print_reason { PR_DEBUG = BIT(3), }; -static int debug_mask = PR_OEM; +static int debug_mask = 0; module_param_named( debug_mask, debug_mask, int, 0600 diff --git a/drivers/power/supply/qcom/qpnp-fg-gen4.c b/drivers/power/supply/qcom/qpnp-fg-gen4.c index accd371bd6c4..e62de63884c7 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen4.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen4.c @@ -355,7 +355,7 @@ struct bias_config { int bias_kohms; }; -static int fg_gen4_debug_mask = FG_STATUS | FG_FVSS | FG_POWER_SUPPLY; +static int fg_gen4_debug_mask = 0; static bool is_batt_vendor_gyb; static bool is_batt_vendor_nvt; @@ -7735,3 +7735,4 @@ module_platform_driver(fg_gen4_driver); MODULE_DESCRIPTION("QPNP Fuel gauge GEN4 driver"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" FG_GEN4_DEV_NAME); + diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c index 381a059f1db9..050b886fb4dc 100644 --- a/drivers/power/supply/qcom/qpnp-smb5.c +++ b/drivers/power/supply/qcom/qpnp-smb5.c @@ -232,7 +232,7 @@ struct smb5 { static struct smb_charger *__smbchg; -static int __debug_mask = PR_MISC | PR_WLS | PR_OEM | PR_PARALLEL; +static int __debug_mask = 0; static ssize_t pd_disabled_show(struct device *dev, struct device_attribute *attr, char *buf) diff --git a/drivers/power/supply/qcom/smb1390-charger-psy.c b/drivers/power/supply/qcom/smb1390-charger-psy.c index 7a4127e5a187..3346dcba6297 100644 --- a/drivers/power/supply/qcom/smb1390-charger-psy.c +++ b/drivers/power/supply/qcom/smb1390-charger-psy.c @@ -2101,7 +2101,7 @@ static int smb1390_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, chip); - chip->cp_role = (int)of_device_get_match_data(chip->dev); + chip->cp_role = (int)(long)of_device_get_match_data(chip->dev); switch (chip->cp_role) { case CP_MASTER: rc = smb1390_master_probe(chip); diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c index ef5100d1c07c..41ca902f5239 100644 --- a/drivers/power/supply/qcom/smb5-lib.c +++ b/drivers/power/supply/qcom/smb5-lib.c @@ -11389,7 +11389,6 @@ static void smblib_chg_termination_work(struct work_struct *work) rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_CAPACITY_RAW, &pval); pval.intval = pval.intval / 100; - capacity_raw = pval.intval; } else { rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_REAL_CAPACITY, &pval); @@ -11508,11 +11507,7 @@ static void smblib_chg_termination_work(struct work_struct *work) * vbat is indeed rising above vfloat. */ if (chg->ext_fg) { - if (capacity_raw < 100) { - vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, false, 0); - vote(chg->dc_suspend_votable, CHG_TERMINATION_VOTER, false, 0); - delay = CHG_TERM_WA_ENTRY_DELAY_MS; - } else if (((vbat_now_uv > chg->term_vbat_uv) && (vbat_now_uv > max_fv_uv))) { + if (((vbat_now_uv > chg->term_vbat_uv) && (vbat_now_uv > max_fv_uv))) { if (input_present & INPUT_PRESENT_USB) vote(chg->usb_icl_votable, CHG_TERMINATION_VOTER, true, 0); diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c index 925fb4fd66ec..2f8921d2adea 100644 --- a/drivers/power/supply/qcom/step-chg-jeita.c +++ b/drivers/power/supply/qcom/step-chg-jeita.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2019, 2021 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "QCOM-STEPCHG: %s: " fmt, __func__ @@ -17,7 +17,6 @@ #define STEP_CHG_VOTER "STEP_CHG_VOTER" #define STEP_BMS_CHG_VOTER "STEP_BMS_CHG_VOTER" #define JEITA_VOTER "JEITA_VOTER" -#define JEITA_FCC_SCALE_VOTER "JEITA_FCC_SCALE_VOTER" #define is_between(left, right, value) \ (((left) >= (right) && (left) >= (value) \ @@ -64,7 +63,6 @@ struct step_chg_info { bool use_bq_gauge; bool taper_fcc; bool six_pin_battery; - bool jeita_fcc_scaling; int jeita_fcc_index; int jeita_fv_index; int jeita_cold_fcc_index; @@ -74,10 +72,6 @@ struct step_chg_info { int jeita_cold_th; int jeita_cool_th; int jeita_warm_th; - int jeita_last_update_temp; - int jeita_fcc_scaling_temp_threshold[2]; - long jeita_max_fcc_ua; - long jeita_fcc_step_size; struct step_chg_cfg *step_chg_config; struct jeita_fcc_cfg *jeita_fcc_config; @@ -269,8 +263,7 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip) u32 max_fv_uv, max_fcc_ma; const char *batt_type_str; const __be32 *handle; - int batt_id_ohms, rc, hysteresis[2] = {0}; - u32 jeita_scaling_min_fcc_ua = 0; + int batt_id_ohms, rc; union power_supply_propval prop = {0, }; handle = of_get_property(chip->dev->of_node, @@ -329,7 +322,6 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip) pr_err("max-fastchg-current-ma reading failed, rc=%d\n", rc); return rc; } - chip->jeita_max_fcc_ua = max_fcc_ma * 1000; chip->taper_fcc = of_property_read_bool(profile_node, "qcom,taper-fcc"); @@ -448,47 +440,6 @@ static int get_step_chg_jeita_setting_from_profile(struct step_chg_info *chip) chip->six_pin_battery = of_property_read_bool(profile_node, "mi,six-pin-battery"); - if (of_property_read_bool(profile_node, "qcom,jeita-fcc-scaling")) { - - rc = of_property_read_u32_array(profile_node, - "qcom,jeita-fcc-scaling-temp-threshold", - chip->jeita_fcc_scaling_temp_threshold, 2); - if (rc < 0) - pr_debug("Read jeita-fcc-scaling-temp-threshold from battery profile, rc=%d\n", - rc); - - rc = of_property_read_u32(profile_node, - "qcom,jeita-scaling-min-fcc-ua", - &jeita_scaling_min_fcc_ua); - if (rc < 0) - pr_debug("Read jeita-scaling-min-fcc-ua from battery profile, rc=%d\n", - rc); - - if ((jeita_scaling_min_fcc_ua && - (jeita_scaling_min_fcc_ua < chip->jeita_max_fcc_ua)) && - (chip->jeita_fcc_scaling_temp_threshold[0] < - chip->jeita_fcc_scaling_temp_threshold[1])) { - /* - * Calculate jeita-fcc-step-size = - * (difference-in-fcc) / ( difference-in-temp) - */ - chip->jeita_fcc_step_size = div_s64( - (chip->jeita_max_fcc_ua - jeita_scaling_min_fcc_ua), - (chip->jeita_fcc_scaling_temp_threshold[1] - - chip->jeita_fcc_scaling_temp_threshold[0])); - - if (chip->jeita_fcc_step_size > 0) - chip->jeita_fcc_scaling = true; - } - - pr_debug("jeita-fcc-scaling: enabled = %d, jeita-fcc-scaling-temp-threshold = [%d, %d], jeita-scaling-min-fcc-ua = %ld, jeita-scaling-max_fcc_ua = %ld,jeita-fcc-step-size = %ld\n", - chip->jeita_fcc_scaling, - chip->jeita_fcc_scaling_temp_threshold[0], - chip->jeita_fcc_scaling_temp_threshold[1], - jeita_scaling_min_fcc_ua, chip->jeita_max_fcc_ua, - chip->jeita_fcc_step_size - ); - } return rc; } @@ -843,79 +794,6 @@ static int handle_fast_charge(struct step_chg_info *chip, int temp) #define JEITA_HYSTERESIS_TEMP_THRED 150 #define JEITA_SIX_PIN_BATT_HYST_UV 100000 #define WARM_VFLOAT_UV 4100000 - -static void handle_jeita_fcc_scaling(struct step_chg_info *chip) -{ - union power_supply_propval pval = {0, }; - int fcc_ua = 0, temp_diff = 0, rc; - bool first_time_entry; - - if (chip->jeita_fcc_config->param.use_bms) - rc = power_supply_get_property(chip->bms_psy, - chip->jeita_fcc_config->param.psy_prop, &pval); - else - rc = power_supply_get_property(chip->batt_psy, - chip->jeita_fcc_config->param.psy_prop, &pval); - - if (rc < 0) { - pr_err("Couldn't read %s property rc=%d\n", - chip->jeita_fcc_config->param.prop_name, rc); - return; - } - - /* Skip mitigation if temp is not within min-max thresholds */ - if (!is_between(chip->jeita_fcc_scaling_temp_threshold[0], - chip->jeita_fcc_scaling_temp_threshold[1], pval.intval)) { - pr_debug("jeita-fcc-scaling : Skip jeita scaling, temp out of range temp = %d\n", - pval.intval); - chip->jeita_last_update_temp = pval.intval; - vote(chip->fcc_votable, JEITA_FCC_SCALE_VOTER, false, 0); - return; - } - - /* - * We determine this is the first time entry to jeita-fcc-scaling if - * jeita_last_update_temp is not within entry/exist thresholds. - */ - first_time_entry = !is_between(chip->jeita_fcc_scaling_temp_threshold[0] - , chip->jeita_fcc_scaling_temp_threshold[1], - chip->jeita_last_update_temp); - - /* - * VOTE on FCC only when temp is within hys or if this the very first - * time we crossed the entry threshold. - */ - if (first_time_entry || - ((pval.intval > (chip->jeita_last_update_temp + - chip->jeita_fcc_config->param.rise_hys)) || - (pval.intval < (chip->jeita_last_update_temp - - chip->jeita_fcc_config->param.fall_hys)))) { - - /* - * New FCC step is calculated as : - * fcc_ua = (max-fcc - ((current_temp - min-temp) * - * jeita-step-size)) - */ - temp_diff = pval.intval - - chip->jeita_fcc_scaling_temp_threshold[0]; - fcc_ua = div_s64((chip->jeita_max_fcc_ua - - (chip->jeita_fcc_step_size * temp_diff)), 100) * 100; - - vote(chip->fcc_votable, JEITA_FCC_SCALE_VOTER, true, fcc_ua); - pr_debug("jeita-fcc-scaling: first_time_entry = %d, max_fcc_ua = %ld, voted_fcc_ua = %d, temp_diff = %d, prev_temp = %d, current_temp = %d\n", - first_time_entry, chip->jeita_max_fcc_ua, fcc_ua, - temp_diff, chip->jeita_last_update_temp, pval.intval); - - chip->jeita_last_update_temp = pval.intval; - } else { - pr_debug("jeita-fcc-scaling: Skip jeita mitigation temp within first_time_entry = %d, hys temp = %d, last_updated_temp = %d\n", - first_time_entry, pval.intval, - chip->jeita_last_update_temp); - } -} - -#define JEITA_SUSPEND_HYST_UV 50000 - static int handle_jeita(struct step_chg_info *chip) { union power_supply_propval pval = {0, }; @@ -931,10 +809,6 @@ static int handle_jeita(struct step_chg_info *chip) else chip->sw_jeita_enable = pval.intval; - /* Handle jeita-fcc-scaling if enabled */ - if (chip->jeita_fcc_scaling) - handle_jeita_fcc_scaling(chip); - if (!chip->sw_jeita_enable || !chip->sw_jeita_cfg_valid) { if (chip->fcc_votable) vote(chip->fcc_votable, JEITA_VOTER, false, 0); @@ -1360,3 +1234,4 @@ void qcom_step_chg_deinit(void) wakeup_source_unregister(chip->step_chg_ws); the_chip = NULL; } + diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c index 8c3f5adf1bc6..2d7618375662 100644 --- a/drivers/ps3/ps3stor_lib.c +++ b/drivers/ps3/ps3stor_lib.c @@ -201,7 +201,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler) dev->bounce_lpar = ps3_mm_phys_to_lpar(__pa(dev->bounce_buf)); dev->bounce_dma = dma_map_single(&dev->sbd.core, dev->bounce_buf, dev->bounce_size, DMA_BIDIRECTIONAL); - if (!dev->bounce_dma) { + if (dma_mapping_error(&dev->sbd.core, dev->bounce_dma)) { dev_err(&dev->sbd.core, "%s:%u: map DMA region failed\n", __func__, __LINE__); error = -ENODEV; diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c index 15b40a8bc4fb..5055ba2c6c94 100644 --- a/drivers/pwm/pwm-lp3943.c +++ b/drivers/pwm/pwm-lp3943.c @@ -278,6 +278,7 @@ static int lp3943_pwm_probe(struct platform_device *pdev) lp3943_pwm->chip.dev = &pdev->dev; lp3943_pwm->chip.ops = &lp3943_pwm_ops; lp3943_pwm->chip.npwm = LP3943_NUM_PWMS; + lp3943_pwm->chip.base = -1; platform_set_drvdata(pdev, lp3943_pwm); diff --git a/drivers/pwm/pwm-rockchip.c b/drivers/pwm/pwm-rockchip.c index 4d99d468df09..48bcc853d57a 100644 --- a/drivers/pwm/pwm-rockchip.c +++ b/drivers/pwm/pwm-rockchip.c @@ -370,7 +370,6 @@ static int rockchip_pwm_probe(struct platform_device *pdev) ret = pwmchip_add(&pc->chip); if (ret < 0) { - clk_unprepare(pc->clk); dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); goto err_pclk; } diff --git a/drivers/pwm/pwm-zx.c b/drivers/pwm/pwm-zx.c index 5d27c16edfb1..0d4112410b69 100644 --- a/drivers/pwm/pwm-zx.c +++ b/drivers/pwm/pwm-zx.c @@ -241,6 +241,7 @@ static int zx_pwm_probe(struct platform_device *pdev) ret = pwmchip_add(&zpc->chip); if (ret < 0) { dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); + clk_disable_unprepare(zpc->pclk); return ret; } diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 91b8ff8bac15..c9e3677ac734 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -558,7 +558,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) static int axp20x_regulator_parse_dt(struct platform_device *pdev) { struct device_node *np, *regulators; - int ret; + int ret = 0; u32 dcdcfreq = 0; np = of_node_get(pdev->dev.parent->of_node); @@ -573,13 +573,12 @@ static int axp20x_regulator_parse_dt(struct platform_device *pdev) ret = axp20x_set_dcdc_freq(pdev, dcdcfreq); if (ret < 0) { dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret); - return ret; } - of_node_put(regulators); } - return 0; + of_node_put(np); + return ret; } static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index 274c5ed7cd73..713730757b14 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -132,7 +132,7 @@ static struct regulator_ops vid_ops = { static struct regulator_desc regulators[] = { BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f, - 0x80, 600000, 10000, 0x3c), + 0x6f, 600000, 10000, 0x3c), BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf, 16, 1625000, 25000, 0), BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf, @@ -141,7 +141,7 @@ static struct regulator_desc regulators[] = { 11, 2800000, 100000, 0), BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops, BD9571MWV_DVFS_MONIVDAC, 0x7f, - 0x80, 600000, 10000, 0x3c), + 0x6f, 600000, 10000, 0x3c), }; #ifdef CONFIG_PM_SLEEP diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 4fb3d05c474e..682f82f46154 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1154,7 +1154,6 @@ static int _regulator_do_enable(struct regulator_dev *rdev); /** * set_machine_constraints - sets regulator constraints * @rdev: regulator source - * @constraints: constraints to apply * * Allows platform initialisation code to define and constrain * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: @@ -1162,21 +1161,11 @@ static int _regulator_do_enable(struct regulator_dev *rdev); * regulator operations to proceed i.e. set_voltage, set_current_limit, * set_mode. */ -static int set_machine_constraints(struct regulator_dev *rdev, - const struct regulation_constraints *constraints) +static int set_machine_constraints(struct regulator_dev *rdev) { int ret = 0; const struct regulator_ops *ops = rdev->desc->ops; - if (constraints) - rdev->constraints = kmemdup(constraints, sizeof(*constraints), - GFP_KERNEL); - else - rdev->constraints = kzalloc(sizeof(*constraints), - GFP_KERNEL); - if (!rdev->constraints) - return -ENOMEM; - ret = machine_constraints_voltage(rdev, rdev->constraints); if (ret != 0) return ret; @@ -1216,17 +1205,6 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } - /* If the constraints say the regulator should be on at this point - * and we have control then make sure it is enabled. - */ - if (rdev->constraints->always_on || rdev->constraints->boot_on) { - ret = _regulator_do_enable(rdev); - if (ret < 0 && ret != -EINVAL) { - rdev_err(rdev, "failed to enable\n"); - return ret; - } - } - if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) && ops->set_ramp_delay) { ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); @@ -1272,6 +1250,17 @@ static int set_machine_constraints(struct regulator_dev *rdev, } } + /* If the constraints say the regulator should be on at this point + * and we have control then make sure it is enabled. + */ + if (rdev->constraints->always_on || rdev->constraints->boot_on) { + ret = _regulator_do_enable(rdev); + if (ret < 0 && ret != -EINVAL) { + rdev_err(rdev, "failed to enable\n"); + return ret; + } + } + print_constraints(rdev); return 0; } @@ -1669,6 +1658,15 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) } } + if (r == rdev) { + dev_err(dev, "Supply for %s (%s) resolved to itself\n", + rdev->desc->name, rdev->supply_name); + if (!have_full_constraints()) + return -EINVAL; + r = dummy_regulator_rdev; + get_device(&r->dev); + } + /* * If the supply's parent device is not the same as the * regulator's parent device, then ensure the parent device @@ -4677,7 +4675,6 @@ struct regulator_dev * regulator_register(const struct regulator_desc *regulator_desc, const struct regulator_config *cfg) { - const struct regulation_constraints *constraints = NULL; const struct regulator_init_data *init_data; struct regulator_config *config = NULL; static atomic_t regulator_no = ATOMIC_INIT(-1); @@ -4778,14 +4775,23 @@ regulator_register(const struct regulator_desc *regulator_desc, /* set regulator constraints */ if (init_data) - constraints = &init_data->constraints; + rdev->constraints = kmemdup(&init_data->constraints, + sizeof(*rdev->constraints), + GFP_KERNEL); + else + rdev->constraints = kzalloc(sizeof(*rdev->constraints), + GFP_KERNEL); + if (!rdev->constraints) { + ret = -ENOMEM; + goto wash; + } if (init_data && init_data->supply_regulator) rdev->supply_name = init_data->supply_regulator; else if (regulator_desc->supply_name) rdev->supply_name = regulator_desc->supply_name; - ret = set_machine_constraints(rdev, constraints); + ret = set_machine_constraints(rdev); if (ret == -EPROBE_DEFER) { /* Regulator might be in bypass mode and so needs its supply * to set the constraints */ @@ -4794,7 +4800,7 @@ regulator_register(const struct regulator_desc *regulator_desc, * that is just being created */ ret = regulator_resolve_supply(rdev); if (!ret) - ret = set_machine_constraints(rdev, constraints); + ret = set_machine_constraints(rdev); else rdev_dbg(rdev, "unable to resolve supply early: %pe\n", ERR_PTR(ret)); diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index 30e92a9cc97e..4b8306594c3f 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -755,11 +755,14 @@ static int pfuze100_regulator_probe(struct i2c_client *client, * the switched regulator till yet. */ if (pfuze_chip->flags & PFUZE_FLAG_DISABLE_SW) { - if (pfuze_chip->regulator_descs[i].sw_reg) { - desc->ops = &pfuze100_sw_disable_regulator_ops; - desc->enable_val = 0x8; - desc->disable_val = 0x0; - desc->enable_time = 500; + if (pfuze_chip->chip_id == PFUZE100 || + pfuze_chip->chip_id == PFUZE200) { + if (pfuze_chip->regulator_descs[i].sw_reg) { + desc->ops = &pfuze100_sw_disable_regulator_ops; + desc->enable_val = 0x8; + desc->disable_val = 0x0; + desc->enable_time = 500; + } } } diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 667d16dc83ce..7ff94695eee7 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -548,14 +548,18 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, rdata = devm_kcalloc(&pdev->dev, pdata->num_regulators, sizeof(*rdata), GFP_KERNEL); - if (!rdata) + if (!rdata) { + of_node_put(regulators_np); return -ENOMEM; + } rmode = devm_kcalloc(&pdev->dev, pdata->num_regulators, sizeof(*rmode), GFP_KERNEL); - if (!rmode) + if (!rmode) { + of_node_put(regulators_np); return -ENOMEM; + } pdata->regulators = rdata; pdata->opmode = rmode; diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c index 89b9314d64c9..016330f909c0 100644 --- a/drivers/regulator/ti-abb-regulator.c +++ b/drivers/regulator/ti-abb-regulator.c @@ -342,8 +342,17 @@ static int ti_abb_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) return ret; } - /* If data is exactly the same, then just update index, no change */ info = &abb->info[sel]; + /* + * When Linux kernel is starting up, we are'nt sure of the + * Bias configuration that bootloader has configured. + * So, we get to know the actual setting the first time + * we are asked to transition. + */ + if (abb->current_info_idx == -EINVAL) + goto just_set_abb; + + /* If data is exactly the same, then just update index, no change */ oinfo = &abb->info[abb->current_info_idx]; if (!memcmp(info, oinfo, sizeof(*info))) { dev_dbg(dev, "%s: Same data new idx=%d, old idx=%d\n", __func__, @@ -351,6 +360,7 @@ static int ti_abb_set_voltage_sel(struct regulator_dev *rdev, unsigned sel) goto out; } +just_set_abb: ret = ti_abb_set_opp(rdev, abb, info); out: diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c index cc475dcbf27f..604828c04ddf 100644 --- a/drivers/remoteproc/qcom_q6v5_pil.c +++ b/drivers/remoteproc/qcom_q6v5_pil.c @@ -340,6 +340,12 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw) { struct q6v5 *qproc = rproc->priv; + /* MBA is restricted to a maximum size of 1M */ + if (fw->size > qproc->mba_size || fw->size > SZ_1M) { + dev_err(qproc->dev, "MBA firmware load failed\n"); + return -EINVAL; + } + memcpy(qproc->mba_region, fw->data, fw->size); return 0; @@ -739,14 +745,13 @@ static int q6v5_mpss_load(struct q6v5 *qproc) if (phdr->p_filesz) { snprintf(seg_name, sizeof(seg_name), "modem.b%02d", i); - ret = request_firmware(&seg_fw, seg_name, qproc->dev); + ret = request_firmware_into_buf(&seg_fw, seg_name, qproc->dev, + ptr, phdr->p_filesz); if (ret) { dev_err(qproc->dev, "failed to load %s\n", seg_name); goto release_firmware; } - memcpy(ptr, seg_fw->data, seg_fw->size); - release_firmware(seg_fw); } diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 26844dae39e5..85164174ee00 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -2076,7 +2076,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, irq = of_irq_get(dev->of_node, 0); ret = devm_request_irq(dev, irq, qcom_glink_native_intr, - IRQF_NO_SUSPEND | IRQF_SHARED, + IRQF_SHARED, glink->irqname, glink); if (ret) { dev_err(dev, "failed to request IRQ\n"); @@ -2084,6 +2084,9 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev, } glink->irq = irq; + ret = enable_irq_wake(glink->irq); + if (ret) + dev_err(dev, "failed to set irq wake\n"); size = of_property_count_u32_elems(dev->of_node, "cpu-affinity"); if (size > 0) { diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 28a4505a1bc8..b5845f16a3a2 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -639,6 +639,7 @@ config RTC_DRV_S5M tristate "Samsung S2M/S5M series" depends on MFD_SEC_CORE || COMPILE_TEST select REGMAP_IRQ + select REGMAP_I2C help If you say yes here you will get support for the RTC of Samsung S2MPS14 and S5M PMIC series. diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 2cd5a7b1a2e3..e85abe805606 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -232,7 +232,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) 300000000); if (IS_ERR(rtc->int_osc)) { pr_crit("Couldn't register the internal oscillator\n"); - return; + goto err; } parents[0] = clk_hw_get_name(rtc->int_osc); @@ -248,7 +248,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) rtc->losc = clk_register(NULL, &rtc->hw); if (IS_ERR(rtc->losc)) { pr_crit("Couldn't register the LOSC clock\n"); - return; + goto err_register; } of_property_read_string_index(node, "clock-output-names", 1, @@ -259,7 +259,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) &rtc->lock); if (IS_ERR(rtc->ext_losc)) { pr_crit("Couldn't register the LOSC external gate\n"); - return; + goto err_register; } clk_data->num = 2; @@ -268,6 +268,8 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); return; +err_register: + clk_hw_unregister_fixed_rate(rtc->int_osc); err: kfree(clk_data); } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index a23e7d394a0a..7beda20cf122 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2833,6 +2833,12 @@ static int _dasd_requeue_request(struct dasd_ccw_req *cqr) if (!block) return -EINVAL; + /* + * If the request is an ERP request there is nothing to requeue. + * This will be done with the remaining original request. + */ + if (cqr->refers) + return 0; spin_lock_irq(&cqr->dq->lock); req = (struct request *) cqr->callback_data; blk_mq_requeue_request(req, false); @@ -2934,7 +2940,8 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx, basedev = block->base; spin_lock_irq(&dq->lock); - if (basedev->state < DASD_STATE_READY) { + if (basedev->state < DASD_STATE_READY || + test_bit(DASD_FLAG_OFFLINE, &basedev->flags)) { DBF_DEV_EVENT(DBF_ERR, basedev, "device not ready for request %p", req); rc = BLK_STS_IOERR; @@ -3420,8 +3427,6 @@ void dasd_generic_remove(struct ccw_device *cdev) struct dasd_device *device; struct dasd_block *block; - cdev->handler = NULL; - device = dasd_device_from_cdev(cdev); if (IS_ERR(device)) { dasd_remove_sysfs_files(cdev); @@ -3440,6 +3445,7 @@ void dasd_generic_remove(struct ccw_device *cdev) * no quite down yet. */ dasd_set_target_state(device, DASD_STATE_NEW); + cdev->handler = NULL; /* dasd_delete_device destroys the device reference. */ block = device->block; dasd_delete_device(device); diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 99f86612f775..dc78a523a69f 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -256,7 +256,6 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) return; device->discipline->get_uid(device, &uid); spin_lock_irqsave(&lcu->lock, flags); - list_del_init(&device->alias_list); /* make sure that the workers don't use this device */ if (device == lcu->suc_data.device) { spin_unlock_irqrestore(&lcu->lock, flags); @@ -283,6 +282,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) spin_lock_irqsave(&aliastree.lock, flags); spin_lock(&lcu->lock); + list_del_init(&device->alias_list); if (list_empty(&lcu->grouplist) && list_empty(&lcu->active_devices) && list_empty(&lcu->inactive_devices)) { @@ -462,11 +462,19 @@ static int read_unit_address_configuration(struct dasd_device *device, spin_unlock_irqrestore(&lcu->lock, flags); rc = dasd_sleep_on(cqr); - if (rc && !suborder_not_supported(cqr)) { + if (!rc) + goto out; + + if (suborder_not_supported(cqr)) { + /* suborder not supported or device unusable for IO */ + rc = -EOPNOTSUPP; + } else { + /* IO failed but should be retried */ spin_lock_irqsave(&lcu->lock, flags); lcu->flags |= NEED_UAC_UPDATE; spin_unlock_irqrestore(&lcu->lock, flags); } +out: dasd_sfree_request(cqr, cqr->memdev); return rc; } @@ -503,6 +511,14 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) return rc; spin_lock_irqsave(&lcu->lock, flags); + /* + * there is another update needed skip the remaining handling + * the data might already be outdated + * but especially do not add the device to an LCU with pending + * update + */ + if (lcu->flags & NEED_UAC_UPDATE) + goto out; lcu->pav = NO_PAV; for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { switch (lcu->uac->unit[i].ua_type) { @@ -521,6 +537,7 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) alias_list) { _add_device_to_lcu(lcu, device, refdev); } +out: spin_unlock_irqrestore(&lcu->lock, flags); return 0; } @@ -625,6 +642,7 @@ int dasd_alias_add_device(struct dasd_device *device) } if (lcu->flags & UPDATE_PENDING) { list_move(&device->alias_list, &lcu->active_devices); + private->pavgroup = NULL; _schedule_lcu_update(lcu, device); } spin_unlock_irqrestore(&lcu->lock, flags); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index dc5ff47de3fe..6873ab5fe57a 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -341,7 +341,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, if (ret) return ret; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; } case VFIO_DEVICE_GET_REGION_INFO: { @@ -362,7 +362,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, if (ret) return ret; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; } case VFIO_DEVICE_GET_IRQ_INFO: { @@ -383,7 +383,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, if (info.count == -1) return -EINVAL; - return copy_to_user((void __user *)arg, &info, minsz); + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; } case VFIO_DEVICE_SET_IRQS: { diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 5f59e2dfc7db..d0aaef937b0f 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -470,12 +470,6 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, } } - if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) == - QETH_QDIO_BUF_HANDLED_DELAYED)) { - /* for recovery situations */ - qeth_init_qdio_out_buf(q, bidx); - QETH_CARD_TEXT(q->card, 2, "clprecov"); - } } diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 67efdf25657f..0447ae2781ba 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -103,7 +103,7 @@ struct virtio_rev_info { }; /* the highest virtio-ccw revision we support */ -#define VIRTIO_CCW_REV_MAX 1 +#define VIRTIO_CCW_REV_MAX 2 struct virtio_ccw_vq_info { struct virtqueue *vq; @@ -911,7 +911,7 @@ static u8 virtio_ccw_get_status(struct virtio_device *vdev) u8 old_status = *vcdev->status; struct ccw1 *ccw; - if (vcdev->revision < 1) + if (vcdev->revision < 2) return *vcdev->status; ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 6221a8372cee..3660059784f7 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -3039,7 +3039,6 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, goto create_eq_error; } - mem->dma = paddr; mem->va = eq_vaddress; ret = be_fill_queue(eq, phba->params.num_eq_entries, sizeof(struct be_eq_entry), eq_vaddress); @@ -3049,6 +3048,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba, goto create_eq_error; } + mem->dma = paddr; ret = beiscsi_cmd_eq_create(&phba->ctrl, eq, BEISCSI_EQ_DELAY_DEF); if (ret) { @@ -3105,7 +3105,6 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, goto create_cq_error; } - mem->dma = paddr; ret = be_fill_queue(cq, phba->params.num_cq_entries, sizeof(struct sol_cqe), cq_vaddress); if (ret) { @@ -3115,6 +3114,7 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba, goto create_cq_error; } + mem->dma = paddr; ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0); if (ret) { diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig index d401a096dfc7..2eb2476852b1 100644 --- a/drivers/scsi/bnx2fc/Kconfig +++ b/drivers/scsi/bnx2fc/Kconfig @@ -4,6 +4,7 @@ config SCSI_BNX2X_FCOE depends on (IPV6 || IPV6=n) depends on LIBFC depends on LIBFCOE + depends on MMU select NETDEVICES select ETHERNET select NET_VENDOR_BROADCOM diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index ba30ff86d581..b27a3738d940 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -3,6 +3,7 @@ config SCSI_BNX2_ISCSI depends on NET depends on PCI depends on (IPV6 || IPV6=n) + depends on MMU select SCSI_ISCSI_ATTRS select NETDEVICES select ETHERNET diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index c95c782b93a5..60c48dc5d945 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -672,8 +672,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) rcu_read_lock(); list_for_each_entry_rcu(h, &tmp_pg->dh_list, node) { - /* h->sdev should always be valid */ - BUG_ON(!h->sdev); + if (!h->sdev) + continue; h->sdev->access_state = desc[0]; } rcu_read_unlock(); @@ -719,7 +719,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) pg->expiry = 0; rcu_read_lock(); list_for_each_entry_rcu(h, &pg->dh_list, node) { - BUG_ON(!h->sdev); + if (!h->sdev) + continue; h->sdev->access_state = (pg->state & SCSI_ACCESS_STATE_MASK); if (pg->pref) @@ -1160,7 +1161,6 @@ static void alua_bus_detach(struct scsi_device *sdev) spin_lock(&h->pg_lock); pg = rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock)); rcu_assign_pointer(h->pg, NULL); - h->sdev = NULL; spin_unlock(&h->pg_lock); if (pg) { spin_lock_irq(&pg->lock); @@ -1169,6 +1169,7 @@ static void alua_bus_detach(struct scsi_device *sdev) kref_put(&pg->kref, release_port_group); } sdev->handler_data = NULL; + synchronize_rcu(); kfree(h); } diff --git a/drivers/scsi/fnic/fnic_main.c b/drivers/scsi/fnic/fnic_main.c index e52599f44170..bc5dbe3bae5c 100644 --- a/drivers/scsi/fnic/fnic_main.c +++ b/drivers/scsi/fnic/fnic_main.c @@ -746,6 +746,7 @@ static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) for (i = 0; i < FNIC_IO_LOCKS; i++) spin_lock_init(&fnic->io_req_lock[i]); + err = -ENOMEM; fnic->io_req_pool = mempool_create_slab_pool(2, fnic_io_req_cache); if (!fnic->io_req_pool) goto err_out_free_resources; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 11de2198bb87..0fe21cbdf0ca 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8781,7 +8781,7 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* hook into SCSI subsystem */ rc = hpsa_scsi_add_host(h); if (rc) - goto clean7; /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ + goto clean8; /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */ /* Monitor the controller for firmware lockups */ h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; @@ -8796,6 +8796,8 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) HPSA_EVENT_MONITOR_INTERVAL); return 0; +clean8: /* lastlogicals, perf, sg, cmd, irq, shost, pci, lu, aer/h */ + kfree(h->lastlogicals); clean7: /* perf, sg, cmd, irq, shost, pci, lu, aer/h */ hpsa_free_performant_mode(h); h->access.set_intr_mask(h, HPSA_INTR_OFF); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 090ab377f65e..50078a199fea 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2890,8 +2890,10 @@ static int ibmvfc_slave_configure(struct scsi_device *sdev) unsigned long flags = 0; spin_lock_irqsave(shost->host_lock, flags); - if (sdev->type == TYPE_DISK) + if (sdev->type == TYPE_DISK) { sdev->allow_restart = 1; + blk_queue_rq_timeout(sdev->request_queue, 120 * HZ); + } spin_unlock_irqrestore(shost->host_lock, flags); return 0; } diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 6ba257cbc6d9..384458d1f73c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1631,8 +1631,13 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) rc = fc_exch_done_locked(ep); WARN_ON(fc_seq_exch(sp) != ep); spin_unlock_bh(&ep->ex_lock); - if (!rc) + if (!rc) { fc_exch_delete(ep); + } else { + FC_EXCH_DBG(ep, "ep is completed already," + "hence skip calling the resp\n"); + goto skip_resp; + } } /* @@ -1651,6 +1656,7 @@ static void fc_exch_recv_seq_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if (!fc_invoke_resp(ep, sp, fp)) fc_frame_free(fp); +skip_resp: fc_exch_release(ep); return; rel: @@ -1907,10 +1913,16 @@ static void fc_exch_reset(struct fc_exch *ep) fc_exch_hold(ep); - if (!rc) + if (!rc) { fc_exch_delete(ep); + } else { + FC_EXCH_DBG(ep, "ep is completed already," + "hence skip calling the resp\n"); + goto skip_resp; + } fc_invoke_resp(ep, sp, ERR_PTR(-FC_EX_CLOSED)); +skip_resp: fc_seq_set_resp(sp, NULL, ep->arg); fc_exch_release(ep); } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 7a05c7271766..81471c304991 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -571,8 +571,8 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) if (conn->task == task) conn->task = NULL; - if (conn->ping_task == task) - conn->ping_task = NULL; + if (READ_ONCE(conn->ping_task) == task) + WRITE_ONCE(conn->ping_task, NULL); /* release get from queueing */ __iscsi_put_task(task); @@ -781,6 +781,9 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, task->conn->session->age); } + if (unlikely(READ_ONCE(conn->ping_task) == INVALID_SCSI_TASK)) + WRITE_ONCE(conn->ping_task, task); + if (!ihost->workq) { if (iscsi_prep_mgmt_task(conn, task)) goto free_task; @@ -988,8 +991,11 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) struct iscsi_nopout hdr; struct iscsi_task *task; - if (!rhdr && conn->ping_task) - return -EINVAL; + if (!rhdr) { + if (READ_ONCE(conn->ping_task)) + return -EINVAL; + WRITE_ONCE(conn->ping_task, INVALID_SCSI_TASK); + } memset(&hdr, 0, sizeof(struct iscsi_nopout)); hdr.opcode = ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE; @@ -1004,11 +1010,12 @@ static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); if (!task) { + if (!rhdr) + WRITE_ONCE(conn->ping_task, NULL); iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); return -EIO; } else if (!rhdr) { /* only track our nops */ - conn->ping_task = task; conn->last_ping = jiffies; } @@ -1021,7 +1028,7 @@ static int iscsi_nop_out_rsp(struct iscsi_task *task, struct iscsi_conn *conn = task->conn; int rc = 0; - if (conn->ping_task != task) { + if (READ_ONCE(conn->ping_task) != task) { /* * If this is not in response to one of our * nops then it must be from userspace. @@ -1562,14 +1569,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) } rc = iscsi_prep_scsi_cmd_pdu(conn->task); if (rc) { - if (rc == -ENOMEM || rc == -EACCES) { - spin_lock_bh(&conn->taskqueuelock); - list_add_tail(&conn->task->running, - &conn->cmdqueue); - conn->task = NULL; - spin_unlock_bh(&conn->taskqueuelock); - goto done; - } else + if (rc == -ENOMEM || rc == -EACCES) + fail_scsi_task(conn->task, DID_IMM_RETRY); + else fail_scsi_task(conn->task, DID_ABORT); spin_lock_bh(&conn->taskqueuelock); continue; @@ -1961,7 +1963,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn) */ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) { - if (conn->ping_task && + if (READ_ONCE(conn->ping_task) && time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + (conn->ping_timeout * HZ), jiffies)) return 1; @@ -2096,7 +2098,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) * Checking the transport already or nop from a cmd timeout still * running */ - if (conn->ping_task) { + if (READ_ONCE(conn->ping_task)) { task->have_checked_conn = true; rc = BLK_EH_RESET_TIMER; goto done; @@ -3361,125 +3363,125 @@ int iscsi_session_get_param(struct iscsi_cls_session *cls_session, switch(param) { case ISCSI_PARAM_FAST_ABORT: - len = sprintf(buf, "%d\n", session->fast_abort); + len = sysfs_emit(buf, "%d\n", session->fast_abort); break; case ISCSI_PARAM_ABORT_TMO: - len = sprintf(buf, "%d\n", session->abort_timeout); + len = sysfs_emit(buf, "%d\n", session->abort_timeout); break; case ISCSI_PARAM_LU_RESET_TMO: - len = sprintf(buf, "%d\n", session->lu_reset_timeout); + len = sysfs_emit(buf, "%d\n", session->lu_reset_timeout); break; case ISCSI_PARAM_TGT_RESET_TMO: - len = sprintf(buf, "%d\n", session->tgt_reset_timeout); + len = sysfs_emit(buf, "%d\n", session->tgt_reset_timeout); break; case ISCSI_PARAM_INITIAL_R2T_EN: - len = sprintf(buf, "%d\n", session->initial_r2t_en); + len = sysfs_emit(buf, "%d\n", session->initial_r2t_en); break; case ISCSI_PARAM_MAX_R2T: - len = sprintf(buf, "%hu\n", session->max_r2t); + len = sysfs_emit(buf, "%hu\n", session->max_r2t); break; case ISCSI_PARAM_IMM_DATA_EN: - len = sprintf(buf, "%d\n", session->imm_data_en); + len = sysfs_emit(buf, "%d\n", session->imm_data_en); break; case ISCSI_PARAM_FIRST_BURST: - len = sprintf(buf, "%u\n", session->first_burst); + len = sysfs_emit(buf, "%u\n", session->first_burst); break; case ISCSI_PARAM_MAX_BURST: - len = sprintf(buf, "%u\n", session->max_burst); + len = sysfs_emit(buf, "%u\n", session->max_burst); break; case ISCSI_PARAM_PDU_INORDER_EN: - len = sprintf(buf, "%d\n", session->pdu_inorder_en); + len = sysfs_emit(buf, "%d\n", session->pdu_inorder_en); break; case ISCSI_PARAM_DATASEQ_INORDER_EN: - len = sprintf(buf, "%d\n", session->dataseq_inorder_en); + len = sysfs_emit(buf, "%d\n", session->dataseq_inorder_en); break; case ISCSI_PARAM_DEF_TASKMGMT_TMO: - len = sprintf(buf, "%d\n", session->def_taskmgmt_tmo); + len = sysfs_emit(buf, "%d\n", session->def_taskmgmt_tmo); break; case ISCSI_PARAM_ERL: - len = sprintf(buf, "%d\n", session->erl); + len = sysfs_emit(buf, "%d\n", session->erl); break; case ISCSI_PARAM_TARGET_NAME: - len = sprintf(buf, "%s\n", session->targetname); + len = sysfs_emit(buf, "%s\n", session->targetname); break; case ISCSI_PARAM_TARGET_ALIAS: - len = sprintf(buf, "%s\n", session->targetalias); + len = sysfs_emit(buf, "%s\n", session->targetalias); break; case ISCSI_PARAM_TPGT: - len = sprintf(buf, "%d\n", session->tpgt); + len = sysfs_emit(buf, "%d\n", session->tpgt); break; case ISCSI_PARAM_USERNAME: - len = sprintf(buf, "%s\n", session->username); + len = sysfs_emit(buf, "%s\n", session->username); break; case ISCSI_PARAM_USERNAME_IN: - len = sprintf(buf, "%s\n", session->username_in); + len = sysfs_emit(buf, "%s\n", session->username_in); break; case ISCSI_PARAM_PASSWORD: - len = sprintf(buf, "%s\n", session->password); + len = sysfs_emit(buf, "%s\n", session->password); break; case ISCSI_PARAM_PASSWORD_IN: - len = sprintf(buf, "%s\n", session->password_in); + len = sysfs_emit(buf, "%s\n", session->password_in); break; case ISCSI_PARAM_IFACE_NAME: - len = sprintf(buf, "%s\n", session->ifacename); + len = sysfs_emit(buf, "%s\n", session->ifacename); break; case ISCSI_PARAM_INITIATOR_NAME: - len = sprintf(buf, "%s\n", session->initiatorname); + len = sysfs_emit(buf, "%s\n", session->initiatorname); break; case ISCSI_PARAM_BOOT_ROOT: - len = sprintf(buf, "%s\n", session->boot_root); + len = sysfs_emit(buf, "%s\n", session->boot_root); break; case ISCSI_PARAM_BOOT_NIC: - len = sprintf(buf, "%s\n", session->boot_nic); + len = sysfs_emit(buf, "%s\n", session->boot_nic); break; case ISCSI_PARAM_BOOT_TARGET: - len = sprintf(buf, "%s\n", session->boot_target); + len = sysfs_emit(buf, "%s\n", session->boot_target); break; case ISCSI_PARAM_AUTO_SND_TGT_DISABLE: - len = sprintf(buf, "%u\n", session->auto_snd_tgt_disable); + len = sysfs_emit(buf, "%u\n", session->auto_snd_tgt_disable); break; case ISCSI_PARAM_DISCOVERY_SESS: - len = sprintf(buf, "%u\n", session->discovery_sess); + len = sysfs_emit(buf, "%u\n", session->discovery_sess); break; case ISCSI_PARAM_PORTAL_TYPE: - len = sprintf(buf, "%s\n", session->portal_type); + len = sysfs_emit(buf, "%s\n", session->portal_type); break; case ISCSI_PARAM_CHAP_AUTH_EN: - len = sprintf(buf, "%u\n", session->chap_auth_en); + len = sysfs_emit(buf, "%u\n", session->chap_auth_en); break; case ISCSI_PARAM_DISCOVERY_LOGOUT_EN: - len = sprintf(buf, "%u\n", session->discovery_logout_en); + len = sysfs_emit(buf, "%u\n", session->discovery_logout_en); break; case ISCSI_PARAM_BIDI_CHAP_EN: - len = sprintf(buf, "%u\n", session->bidi_chap_en); + len = sysfs_emit(buf, "%u\n", session->bidi_chap_en); break; case ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL: - len = sprintf(buf, "%u\n", session->discovery_auth_optional); + len = sysfs_emit(buf, "%u\n", session->discovery_auth_optional); break; case ISCSI_PARAM_DEF_TIME2WAIT: - len = sprintf(buf, "%d\n", session->time2wait); + len = sysfs_emit(buf, "%d\n", session->time2wait); break; case ISCSI_PARAM_DEF_TIME2RETAIN: - len = sprintf(buf, "%d\n", session->time2retain); + len = sysfs_emit(buf, "%d\n", session->time2retain); break; case ISCSI_PARAM_TSID: - len = sprintf(buf, "%u\n", session->tsid); + len = sysfs_emit(buf, "%u\n", session->tsid); break; case ISCSI_PARAM_ISID: - len = sprintf(buf, "%02x%02x%02x%02x%02x%02x\n", + len = sysfs_emit(buf, "%02x%02x%02x%02x%02x%02x\n", session->isid[0], session->isid[1], session->isid[2], session->isid[3], session->isid[4], session->isid[5]); break; case ISCSI_PARAM_DISCOVERY_PARENT_IDX: - len = sprintf(buf, "%u\n", session->discovery_parent_idx); + len = sysfs_emit(buf, "%u\n", session->discovery_parent_idx); break; case ISCSI_PARAM_DISCOVERY_PARENT_TYPE: if (session->discovery_parent_type) - len = sprintf(buf, "%s\n", + len = sysfs_emit(buf, "%s\n", session->discovery_parent_type); else - len = sprintf(buf, "\n"); + len = sysfs_emit(buf, "\n"); break; default: return -ENOSYS; @@ -3511,16 +3513,16 @@ int iscsi_conn_get_addr_param(struct sockaddr_storage *addr, case ISCSI_PARAM_CONN_ADDRESS: case ISCSI_HOST_PARAM_IPADDRESS: if (sin) - len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr); + len = sysfs_emit(buf, "%pI4\n", &sin->sin_addr.s_addr); else - len = sprintf(buf, "%pI6\n", &sin6->sin6_addr); + len = sysfs_emit(buf, "%pI6\n", &sin6->sin6_addr); break; case ISCSI_PARAM_CONN_PORT: case ISCSI_PARAM_LOCAL_PORT: if (sin) - len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port)); + len = sysfs_emit(buf, "%hu\n", be16_to_cpu(sin->sin_port)); else - len = sprintf(buf, "%hu\n", + len = sysfs_emit(buf, "%hu\n", be16_to_cpu(sin6->sin6_port)); break; default: @@ -3539,88 +3541,88 @@ int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, switch(param) { case ISCSI_PARAM_PING_TMO: - len = sprintf(buf, "%u\n", conn->ping_timeout); + len = sysfs_emit(buf, "%u\n", conn->ping_timeout); break; case ISCSI_PARAM_RECV_TMO: - len = sprintf(buf, "%u\n", conn->recv_timeout); + len = sysfs_emit(buf, "%u\n", conn->recv_timeout); break; case ISCSI_PARAM_MAX_RECV_DLENGTH: - len = sprintf(buf, "%u\n", conn->max_recv_dlength); + len = sysfs_emit(buf, "%u\n", conn->max_recv_dlength); break; case ISCSI_PARAM_MAX_XMIT_DLENGTH: - len = sprintf(buf, "%u\n", conn->max_xmit_dlength); + len = sysfs_emit(buf, "%u\n", conn->max_xmit_dlength); break; case ISCSI_PARAM_HDRDGST_EN: - len = sprintf(buf, "%d\n", conn->hdrdgst_en); + len = sysfs_emit(buf, "%d\n", conn->hdrdgst_en); break; case ISCSI_PARAM_DATADGST_EN: - len = sprintf(buf, "%d\n", conn->datadgst_en); + len = sysfs_emit(buf, "%d\n", conn->datadgst_en); break; case ISCSI_PARAM_IFMARKER_EN: - len = sprintf(buf, "%d\n", conn->ifmarker_en); + len = sysfs_emit(buf, "%d\n", conn->ifmarker_en); break; case ISCSI_PARAM_OFMARKER_EN: - len = sprintf(buf, "%d\n", conn->ofmarker_en); + len = sysfs_emit(buf, "%d\n", conn->ofmarker_en); break; case ISCSI_PARAM_EXP_STATSN: - len = sprintf(buf, "%u\n", conn->exp_statsn); + len = sysfs_emit(buf, "%u\n", conn->exp_statsn); break; case ISCSI_PARAM_PERSISTENT_PORT: - len = sprintf(buf, "%d\n", conn->persistent_port); + len = sysfs_emit(buf, "%d\n", conn->persistent_port); break; case ISCSI_PARAM_PERSISTENT_ADDRESS: - len = sprintf(buf, "%s\n", conn->persistent_address); + len = sysfs_emit(buf, "%s\n", conn->persistent_address); break; case ISCSI_PARAM_STATSN: - len = sprintf(buf, "%u\n", conn->statsn); + len = sysfs_emit(buf, "%u\n", conn->statsn); break; case ISCSI_PARAM_MAX_SEGMENT_SIZE: - len = sprintf(buf, "%u\n", conn->max_segment_size); + len = sysfs_emit(buf, "%u\n", conn->max_segment_size); break; case ISCSI_PARAM_KEEPALIVE_TMO: - len = sprintf(buf, "%u\n", conn->keepalive_tmo); + len = sysfs_emit(buf, "%u\n", conn->keepalive_tmo); break; case ISCSI_PARAM_LOCAL_PORT: - len = sprintf(buf, "%u\n", conn->local_port); + len = sysfs_emit(buf, "%u\n", conn->local_port); break; case ISCSI_PARAM_TCP_TIMESTAMP_STAT: - len = sprintf(buf, "%u\n", conn->tcp_timestamp_stat); + len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_stat); break; case ISCSI_PARAM_TCP_NAGLE_DISABLE: - len = sprintf(buf, "%u\n", conn->tcp_nagle_disable); + len = sysfs_emit(buf, "%u\n", conn->tcp_nagle_disable); break; case ISCSI_PARAM_TCP_WSF_DISABLE: - len = sprintf(buf, "%u\n", conn->tcp_wsf_disable); + len = sysfs_emit(buf, "%u\n", conn->tcp_wsf_disable); break; case ISCSI_PARAM_TCP_TIMER_SCALE: - len = sprintf(buf, "%u\n", conn->tcp_timer_scale); + len = sysfs_emit(buf, "%u\n", conn->tcp_timer_scale); break; case ISCSI_PARAM_TCP_TIMESTAMP_EN: - len = sprintf(buf, "%u\n", conn->tcp_timestamp_en); + len = sysfs_emit(buf, "%u\n", conn->tcp_timestamp_en); break; case ISCSI_PARAM_IP_FRAGMENT_DISABLE: - len = sprintf(buf, "%u\n", conn->fragment_disable); + len = sysfs_emit(buf, "%u\n", conn->fragment_disable); break; case ISCSI_PARAM_IPV4_TOS: - len = sprintf(buf, "%u\n", conn->ipv4_tos); + len = sysfs_emit(buf, "%u\n", conn->ipv4_tos); break; case ISCSI_PARAM_IPV6_TC: - len = sprintf(buf, "%u\n", conn->ipv6_traffic_class); + len = sysfs_emit(buf, "%u\n", conn->ipv6_traffic_class); break; case ISCSI_PARAM_IPV6_FLOW_LABEL: - len = sprintf(buf, "%u\n", conn->ipv6_flow_label); + len = sysfs_emit(buf, "%u\n", conn->ipv6_flow_label); break; case ISCSI_PARAM_IS_FW_ASSIGNED_IPV6: - len = sprintf(buf, "%u\n", conn->is_fw_assigned_ipv6); + len = sysfs_emit(buf, "%u\n", conn->is_fw_assigned_ipv6); break; case ISCSI_PARAM_TCP_XMIT_WSF: - len = sprintf(buf, "%u\n", conn->tcp_xmit_wsf); + len = sysfs_emit(buf, "%u\n", conn->tcp_xmit_wsf); break; case ISCSI_PARAM_TCP_RECV_WSF: - len = sprintf(buf, "%u\n", conn->tcp_recv_wsf); + len = sysfs_emit(buf, "%u\n", conn->tcp_recv_wsf); break; case ISCSI_PARAM_LOCAL_IPADDR: - len = sprintf(buf, "%s\n", conn->local_ipaddr); + len = sysfs_emit(buf, "%s\n", conn->local_ipaddr); break; default: return -ENOSYS; @@ -3638,13 +3640,13 @@ int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, switch (param) { case ISCSI_HOST_PARAM_NETDEV_NAME: - len = sprintf(buf, "%s\n", ihost->netdev); + len = sysfs_emit(buf, "%s\n", ihost->netdev); break; case ISCSI_HOST_PARAM_HWADDRESS: - len = sprintf(buf, "%s\n", ihost->hwaddress); + len = sysfs_emit(buf, "%s\n", ihost->hwaddress); break; case ISCSI_HOST_PARAM_INITIATOR_NAME: - len = sprintf(buf, "%s\n", ihost->initiatorname); + len = sysfs_emit(buf, "%s\n", ihost->initiatorname); break; default: return -ENOSYS; diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index d82698b7dfe6..e032af654733 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -215,18 +215,17 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); task->total_xfer_len = qc->nbytes; task->num_scatter = qc->n_elem; + task->data_dir = qc->dma_dir; + } else if (qc->tf.protocol == ATA_PROT_NODATA) { + task->data_dir = DMA_NONE; } else { for_each_sg(qc->sg, sg, qc->n_elem, si) xfer += sg_dma_len(sg); task->total_xfer_len = xfer; task->num_scatter = si; - } - - if (qc->tf.protocol == ATA_PROT_NODATA) - task->data_dir = DMA_NONE; - else task->data_dir = qc->dma_dir; + } task->scatter = qc->sg; task->ata_task.retry_count = 1; task->task_state_flags = SAS_TASK_STATE_PENDING; diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index f1951c432766..2c70e311943a 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -1843,7 +1843,7 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf, memset(dstbuf, 0, 33); size = (nbytes < 32) ? nbytes : 32; if (copy_from_user(dstbuf, buf, size)) - return 0; + return -EFAULT; if (dent == phba->debug_InjErrLBA) { if ((buf[0] == 'o') && (buf[1] == 'f') && (buf[2] == 'f')) @@ -1851,7 +1851,7 @@ lpfc_debugfs_dif_err_write(struct file *file, const char __user *buf, } if ((tmp == 0) && (kstrtoull(dstbuf, 0, &tmp))) - return 0; + return -EINVAL; if (dent == phba->debug_writeGuard) phba->lpfc_injerr_wgrd_cnt = (uint32_t)tmp; diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c index 9c22a2c93462..fa758f9b82e0 100644 --- a/drivers/scsi/lpfc/lpfc_mem.c +++ b/drivers/scsi/lpfc/lpfc_mem.c @@ -560,8 +560,6 @@ lpfc_els_hbq_free(struct lpfc_hba *phba, struct hbq_dmabuf *hbqbp) * Description: Allocates a DMA-mapped receive buffer from the lpfc_hrb_pool PCI * pool along a non-DMA-mapped container for it. * - * Notes: Not interrupt-safe. Must be called with no locks held. - * * Returns: * pointer to HBQ on success * NULL on failure @@ -631,7 +629,7 @@ lpfc_sli4_nvmet_alloc(struct lpfc_hba *phba) { struct rqb_dmabuf *dma_buf; - dma_buf = kzalloc(sizeof(struct rqb_dmabuf), GFP_KERNEL); + dma_buf = kzalloc(sizeof(*dma_buf), GFP_KERNEL); if (!dma_buf) return NULL; @@ -754,7 +752,6 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) drqe.address_hi = putPaddrHigh(rqb_entry->dbuf.phys); rc = lpfc_sli4_rq_put(rqb_entry->hrq, rqb_entry->drq, &hrqe, &drqe); if (rc < 0) { - (rqbp->rqb_free_buffer)(phba, rqb_entry); lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "6409 Cannot post to HRQ %d: %x %x %x " "DRQ %x %x\n", @@ -764,6 +761,7 @@ lpfc_rq_buf_free(struct lpfc_hba *phba, struct lpfc_dmabuf *mp) rqb_entry->hrq->entry_count, rqb_entry->drq->host_index, rqb_entry->drq->hba_index); + (rqbp->rqb_free_buffer)(phba, rqb_entry); } else { list_add_tail(&rqb_entry->hbuf.list, &rqbp->rqb_buffer_list); rqbp->buffer_count++; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 2ab351260e81..a7b14875af5f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -6755,12 +6755,16 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, struct rqb_dmabuf *rqb_buffer; LIST_HEAD(rqb_buf_list); - spin_lock_irqsave(&phba->hbalock, flags); rqbp = hrq->rqbp; for (i = 0; i < count; i++) { + spin_lock_irqsave(&phba->hbalock, flags); /* IF RQ is already full, don't bother */ - if (rqbp->buffer_count + i >= rqbp->entry_count - 1) + if (rqbp->buffer_count + i >= rqbp->entry_count - 1) { + spin_unlock_irqrestore(&phba->hbalock, flags); break; + } + spin_unlock_irqrestore(&phba->hbalock, flags); + rqb_buffer = rqbp->rqb_alloc_buffer(phba); if (!rqb_buffer) break; @@ -6769,6 +6773,8 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq, rqb_buffer->idx = idx; list_add_tail(&rqb_buffer->hbuf.list, &rqb_buf_list); } + + spin_lock_irqsave(&phba->hbalock, flags); while (!list_empty(&rqb_buf_list)) { list_remove_head(&rqb_buf_list, rqb_buffer, struct rqb_dmabuf, hbuf.list); diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 21f971447dd8..8877a21102f1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -7192,7 +7192,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, int error = 0, i; void *sense = NULL; dma_addr_t sense_handle; - unsigned long *sense_ptr; + void *sense_ptr; u32 opcode = 0; memset(kbuff_arr, 0, sizeof(kbuff_arr)); @@ -7309,6 +7309,13 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, } if (ioc->sense_len) { + /* make sure the pointer is part of the frame */ + if (ioc->sense_off > + (sizeof(union megasas_frame) - sizeof(__le64))) { + error = -EINVAL; + goto out; + } + sense = dma_alloc_coherent(&instance->pdev->dev, ioc->sense_len, &sense_handle, GFP_KERNEL); if (!sense) { @@ -7316,12 +7323,9 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, goto out; } - sense_ptr = - (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); - if (instance->consistent_mask_64bit) - *sense_ptr = cpu_to_le64(sense_handle); - else - *sense_ptr = cpu_to_le32(sense_handle); + /* always store 64 bits regardless of addressing */ + sense_ptr = (void *)cmd->frame + ioc->sense_off; + put_unaligned_le64(sense_handle, sense_ptr); } /* diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 9fbe20e38ad0..447ac667f4b2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -5771,7 +5771,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc) r = _base_handshake_req_reply_wait(ioc, sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, - sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10); + sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 30); if (r != 0) { pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", @@ -6629,14 +6629,18 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ioc->pend_os_device_add_sz++; ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz, GFP_KERNEL); - if (!ioc->pend_os_device_add) + if (!ioc->pend_os_device_add) { + r = -ENOMEM; goto out_free_resources; + } ioc->device_remove_in_progress_sz = ioc->pend_os_device_add_sz; ioc->device_remove_in_progress = kzalloc(ioc->device_remove_in_progress_sz, GFP_KERNEL); - if (!ioc->device_remove_in_progress) + if (!ioc->device_remove_in_progress) { + r = -ENOMEM; goto out_free_resources; + } ioc->fwfault_debug = mpt3sas_fwfault_debug; diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 07345016fd9c..8cfb4f12c68c 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -654,7 +654,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, struct _pcie_device *pcie_device = NULL; u32 ioc_state; u16 smid; - u8 timeout; + unsigned long timeout; u8 issue_reset; u32 sz, sz_arg; void *psge; diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 7a697ca68501..1d59d7447a1c 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -1059,7 +1059,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev, pm8001_init_sas_add(pm8001_ha); /* phy setting support for motherboard controller */ - if (pm8001_configure_phy_settings(pm8001_ha)) + rc = pm8001_configure_phy_settings(pm8001_ha); + if (rc) goto err_out_shost; pm8001_post_sas_ha_init(shost, chip); diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 763c7628356b..fe26144d390a 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -1559,6 +1559,7 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi) if (!qedi->global_queues[i]) { QEDI_ERR(&qedi->dbg_ctx, "Unable to allocation global queue %d.\n", i); + status = -ENOMEM; goto mem_alloc_failure; } @@ -2129,7 +2130,7 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type, chap_name); break; case ISCSI_BOOT_TGT_CHAP_SECRET: - rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN, + rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN, chap_secret); break; case ISCSI_BOOT_TGT_REV_CHAP_NAME: @@ -2137,7 +2138,7 @@ qedi_show_boot_tgt_info(struct qedi_ctx *qedi, int type, mchap_name); break; case ISCSI_BOOT_TGT_REV_CHAP_SECRET: - rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_NAME_MAX_LEN, + rc = sprintf(buf, "%.*s\n", NVM_ISCSI_CFG_CHAP_PWD_MAX_LEN, mchap_secret); break; case ISCSI_BOOT_TGT_FLAGS: @@ -2580,7 +2581,7 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) QEDI_ERR(&qedi->dbg_ctx, "Unable to start offload thread!\n"); rc = -ENODEV; - goto free_cid_que; + goto free_tmf_thread; } /* F/w needs 1st task context memory entry for performance */ @@ -2600,6 +2601,8 @@ static int __qedi_probe(struct pci_dev *pdev, int mode) return 0; +free_tmf_thread: + destroy_workqueue(qedi->tmf_thread); free_cid_que: qedi_release_cid_que(qedi); free_uio: diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 199d3ba1916d..67a74720c02c 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -124,7 +124,6 @@ (min(1270, ((ql) > 0) ? (QLA_TGT_DATASEGS_PER_CMD_24XX + \ QLA_TGT_DATASEGS_PER_CONT_24XX*((ql) - 1)) : 0)) #endif -#endif #define GET_TARGET_ID(ha, iocb) ((HAS_EXTENDED_IDS(ha)) \ ? le16_to_cpu((iocb)->u.isp2x.target.extended) \ @@ -257,6 +256,7 @@ struct ctio_to_2xxx { #ifndef CTIO_RET_TYPE #define CTIO_RET_TYPE 0x17 /* CTIO return entry */ #define ATIO_TYPE7 0x06 /* Accept target I/O entry for 24xx */ +#endif struct fcp_hdr { uint8_t r_ctl; diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index 0ccd06f11f12..de3136294097 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c @@ -940,7 +940,8 @@ qla27xx_template_checksum(void *p, ulong size) static inline int qla27xx_verify_template_checksum(struct qla27xx_fwdt_template *tmp) { - return qla27xx_template_checksum(tmp, tmp->template_size) == 0; + return qla27xx_template_checksum(tmp, + le32_to_cpu(tmp->template_size)) == 0; } static inline int @@ -956,7 +957,7 @@ qla27xx_execute_fwdt_template(struct scsi_qla_host *vha) ulong len; if (qla27xx_fwdt_template_valid(tmp)) { - len = tmp->template_size; + len = le32_to_cpu(tmp->template_size); tmp = memcpy(vha->hw->fw_dump, tmp, len); ql27xx_edit_template(vha, tmp); qla27xx_walk_template(vha, tmp, tmp, &len); @@ -972,7 +973,7 @@ qla27xx_fwdt_calculate_dump_size(struct scsi_qla_host *vha) ulong len = 0; if (qla27xx_fwdt_template_valid(tmp)) { - len = tmp->template_size; + len = le32_to_cpu(tmp->template_size); qla27xx_walk_template(vha, tmp, NULL, &len); } @@ -984,7 +985,7 @@ qla27xx_fwdt_template_size(void *p) { struct qla27xx_fwdt_template *tmp = p; - return tmp->template_size; + return le32_to_cpu(tmp->template_size); } ulong diff --git a/drivers/scsi/qla2xxx/qla_tmpl.h b/drivers/scsi/qla2xxx/qla_tmpl.h index 141c1c5e73f4..2d3e1a8349b3 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.h +++ b/drivers/scsi/qla2xxx/qla_tmpl.h @@ -13,7 +13,7 @@ struct __packed qla27xx_fwdt_template { uint32_t template_type; uint32_t entry_offset; - uint32_t template_size; + __le32 template_size; uint32_t reserved_1; uint32_t entry_count; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 54e74ca30606..c4de94f83f55 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -3477,6 +3477,78 @@ void sdev_enable_disk_events(struct scsi_device *sdev) } EXPORT_SYMBOL(sdev_enable_disk_events); +static unsigned char designator_prio(const unsigned char *d) +{ + if (d[1] & 0x30) + /* not associated with LUN */ + return 0; + + if (d[3] == 0) + /* invalid length */ + return 0; + + /* + * Order of preference for lun descriptor: + * - SCSI name string + * - NAA IEEE Registered Extended + * - EUI-64 based 16-byte + * - EUI-64 based 12-byte + * - NAA IEEE Registered + * - NAA IEEE Extended + * - EUI-64 based 8-byte + * - SCSI name string (truncated) + * - T10 Vendor ID + * as longer descriptors reduce the likelyhood + * of identification clashes. + */ + + switch (d[1] & 0xf) { + case 8: + /* SCSI name string, variable-length UTF-8 */ + return 9; + case 3: + switch (d[4] >> 4) { + case 6: + /* NAA registered extended */ + return 8; + case 5: + /* NAA registered */ + return 5; + case 4: + /* NAA extended */ + return 4; + case 3: + /* NAA locally assigned */ + return 1; + default: + break; + } + break; + case 2: + switch (d[3]) { + case 16: + /* EUI64-based, 16 byte */ + return 7; + case 12: + /* EUI64-based, 12 byte */ + return 6; + case 8: + /* EUI64-based, 8 byte */ + return 3; + default: + break; + } + break; + case 1: + /* T10 vendor ID */ + return 1; + default: + break; + } + + return 0; +} + /** * scsi_vpd_lun_id - return a unique device identification * @sdev: SCSI device @@ -3493,7 +3565,7 @@ EXPORT_SYMBOL(sdev_enable_disk_events); */ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) { - u8 cur_id_type = 0xff; + u8 cur_id_prio = 0; u8 cur_id_size = 0; const unsigned char *d, *cur_id_str; const struct scsi_vpd *vpd_pg83; @@ -3506,20 +3578,6 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) return -ENXIO; } - /* - * Look for the correct descriptor. - * Order of preference for lun descriptor: - * - SCSI name string - * - NAA IEEE Registered Extended - * - EUI-64 based 16-byte - * - EUI-64 based 12-byte - * - NAA IEEE Registered - * - NAA IEEE Extended - * - T10 Vendor ID - * as longer descriptors reduce the likelyhood - * of identification clashes. - */ - /* The id string must be at least 20 bytes + terminating NULL byte */ if (id_len < 21) { rcu_read_unlock(); @@ -3529,8 +3587,9 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) memset(id, 0, id_len); d = vpd_pg83->data + 4; while (d < vpd_pg83->data + vpd_pg83->len) { - /* Skip designators not referring to the LUN */ - if ((d[1] & 0x30) != 0x00) + u8 prio = designator_prio(d); + + if (prio == 0 || cur_id_prio > prio) goto next_desig; switch (d[1] & 0xf) { @@ -3538,28 +3597,19 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) /* T10 Vendor ID */ if (cur_id_size > d[3]) break; - /* Prefer anything */ - if (cur_id_type > 0x01 && cur_id_type != 0xff) - break; + cur_id_prio = prio; cur_id_size = d[3]; if (cur_id_size + 4 > id_len) cur_id_size = id_len - 4; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; id_size = snprintf(id, id_len, "t10.%*pE", cur_id_size, cur_id_str); break; case 0x2: /* EUI-64 */ - if (cur_id_size > d[3]) - break; - /* Prefer NAA IEEE Registered Extended */ - if (cur_id_type == 0x3 && - cur_id_size == d[3]) - break; + cur_id_prio = prio; cur_id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; switch (cur_id_size) { case 8: id_size = snprintf(id, id_len, @@ -3577,17 +3627,14 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) cur_id_str); break; default: - cur_id_size = 0; break; } break; case 0x3: /* NAA */ - if (cur_id_size > d[3]) - break; + cur_id_prio = prio; cur_id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; switch (cur_id_size) { case 8: id_size = snprintf(id, id_len, @@ -3600,26 +3647,25 @@ int scsi_vpd_lun_id(struct scsi_device *sdev, char *id, size_t id_len) cur_id_str); break; default: - cur_id_size = 0; break; } break; case 0x8: /* SCSI name string */ - if (cur_id_size + 4 > d[3]) + if (cur_id_size > d[3]) break; /* Prefer others for truncated descriptor */ - if (cur_id_size && d[3] > id_len) - break; + if (d[3] > id_len) { + prio = 2; + if (cur_id_prio > prio) + break; + } + cur_id_prio = prio; cur_id_size = id_size = d[3]; cur_id_str = d + 4; - cur_id_type = d[1] & 0xf; if (cur_id_size >= id_len) cur_id_size = id_len - 1; memcpy(id, cur_id_str, cur_id_size); - /* Decrease priority for truncated descriptor */ - if (cur_id_size != id_size) - cur_id_size = 6; break; default: break; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 698347301198..e340b05278b6 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -119,7 +119,11 @@ show_transport_handle(struct device *dev, struct device_attribute *attr, char *buf) { struct iscsi_internal *priv = dev_to_iscsi_internal(dev); - return sprintf(buf, "%llu\n", (unsigned long long)iscsi_handle(priv->iscsi_transport)); + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return sysfs_emit(buf, "%llu\n", + (unsigned long long)iscsi_handle(priv->iscsi_transport)); } static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL); @@ -129,7 +133,7 @@ show_transport_##name(struct device *dev, \ struct device_attribute *attr,char *buf) \ { \ struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \ - return sprintf(buf, format"\n", priv->iscsi_transport->name); \ + return sysfs_emit(buf, format"\n", priv->iscsi_transport->name);\ } \ static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL); @@ -170,7 +174,7 @@ static ssize_t show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf) { struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); - return sprintf(buf, "%llu\n", (unsigned long long) ep->id); + return sysfs_emit(buf, "%llu\n", (unsigned long long) ep->id); } static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL); @@ -2763,6 +2767,9 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) struct iscsi_cls_session *session; int err = 0, value = 0; + if (ev->u.set_param.len > PAGE_SIZE) + return -EINVAL; + session = iscsi_session_lookup(ev->u.set_param.sid); conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid); if (!conn || !session) @@ -2910,6 +2917,9 @@ iscsi_set_host_param(struct iscsi_transport *transport, if (!transport->set_host_param) return -ENOSYS; + if (ev->u.set_host_param.len > PAGE_SIZE) + return -EINVAL; + shost = scsi_host_lookup(ev->u.set_host_param.host_no); if (!shost) { printk(KERN_ERR "set_host_param could not find host no %u\n", @@ -3497,6 +3507,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) { int err = 0; u32 portid; + u32 pdu_len; struct iscsi_uevent *ev = nlmsg_data(nlh); struct iscsi_transport *transport = NULL; struct iscsi_internal *priv; @@ -3504,6 +3515,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) struct iscsi_cls_conn *conn; struct iscsi_endpoint *ep = NULL; + if (!netlink_capable(skb, CAP_SYS_ADMIN)) + return -EPERM; + if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE) *group = ISCSI_NL_GRP_UIP; else @@ -3611,6 +3625,14 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) err = -EINVAL; break; case ISCSI_UEVENT_SEND_PDU: + pdu_len = nlh->nlmsg_len - sizeof(*nlh) - sizeof(*ev); + + if ((ev->u.send_pdu.hdr_size > pdu_len) || + (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) { + err = -EINVAL; + break; + } + conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid); if (conn) ev->r.retcode = transport->send_pdu(conn, @@ -4017,7 +4039,7 @@ show_priv_session_state(struct device *dev, struct device_attribute *attr, char *buf) { struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); - return sprintf(buf, "%s\n", iscsi_session_state_name(session->state)); + return sysfs_emit(buf, "%s\n", iscsi_session_state_name(session->state)); } static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state, NULL); @@ -4026,7 +4048,7 @@ show_priv_session_creator(struct device *dev, struct device_attribute *attr, char *buf) { struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); - return sprintf(buf, "%d\n", session->creator); + return sysfs_emit(buf, "%d\n", session->creator); } static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator, NULL); @@ -4035,7 +4057,7 @@ show_priv_session_target_id(struct device *dev, struct device_attribute *attr, char *buf) { struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent); - return sprintf(buf, "%d\n", session->target_id); + return sysfs_emit(buf, "%d\n", session->target_id); } static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO, show_priv_session_target_id, NULL); @@ -4048,8 +4070,8 @@ show_priv_session_##field(struct device *dev, \ struct iscsi_cls_session *session = \ iscsi_dev_to_session(dev->parent); \ if (session->field == -1) \ - return sprintf(buf, "off\n"); \ - return sprintf(buf, format"\n", session->field); \ + return sysfs_emit(buf, "off\n"); \ + return sysfs_emit(buf, format"\n", session->field); \ } #define iscsi_priv_session_attr_store(field) \ diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 69213842e63e..efb9c3d90213 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -130,12 +130,16 @@ static int spi_execute(struct scsi_device *sdev, const void *cmd, sshdr = &sshdr_tmp; for(i = 0; i < DV_RETRIES; i++) { + /* + * The purpose of the RQF_PM flag below is to bypass the + * SDEV_QUIESCE state. + */ result = scsi_execute(sdev, cmd, dir, buffer, bufflen, sense, sshdr, DV_TIMEOUT, /* retries */ 1, REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER, - 0, NULL); + RQF_PM, NULL); if (driver_byte(result) != DRIVER_SENSE || sshdr->sense_key != UNIT_ATTENTION) break; @@ -1018,23 +1022,26 @@ spi_dv_device(struct scsi_device *sdev) */ lock_system_sleep(); + if (scsi_autopm_get_device(sdev)) + goto unlock_system_sleep; + if (unlikely(spi_dv_in_progress(starget))) - goto unlock; + goto put_autopm; if (unlikely(scsi_device_get(sdev))) - goto unlock; + goto put_autopm; spi_dv_in_progress(starget) = 1; buffer = kzalloc(len, GFP_KERNEL); if (unlikely(!buffer)) - goto out_put; + goto put_sdev; /* We need to verify that the actual device will quiesce; the * later target quiesce is just a nice to have */ if (unlikely(scsi_device_quiesce(sdev))) - goto out_free; + goto free_buffer; scsi_target_quiesce(starget); @@ -1054,12 +1061,16 @@ spi_dv_device(struct scsi_device *sdev) spi_initial_dv(starget) = 1; - out_free: +free_buffer: kfree(buffer); - out_put: + +put_sdev: spi_dv_in_progress(starget) = 0; scsi_device_put(sdev); -unlock: +put_autopm: + scsi_autopm_put_device(sdev); + +unlock_system_sleep: unlock_system_sleep(); } EXPORT_SYMBOL(spi_dv_device); diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 4e46fdb2d7c9..9ac89462a8e0 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -555,7 +555,14 @@ int srp_reconnect_rport(struct srp_rport *rport) res = mutex_lock_interruptible(&rport->mutex); if (res) goto out; - scsi_target_block(&shost->shost_gendev); + if (rport->state != SRP_RPORT_FAIL_FAST && rport->state != SRP_RPORT_LOST) + /* + * sdev state must be SDEV_TRANSPORT_OFFLINE, transition + * to SDEV_BLOCK is illegal. Calling scsi_target_unblock() + * later is ok though, scsi_internal_device_unblock_nowait() + * treats SDEV_TRANSPORT_OFFLINE like SDEV_BLOCK. + */ + scsi_target_block(&shost->shost_gendev); res = rport->state != SRP_RPORT_LOST ? i->f->reconnect(rport) : -ENODEV; pr_debug("%s (state %d): transport.reconnect() returned %d\n", dev_name(&shost->shost_gendev), rport->state, res); diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 307df2fa39a3..5078db7743cd 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1265,8 +1265,8 @@ static int st_open(struct inode *inode, struct file *filp) spin_lock(&st_use_lock); if (STp->in_use) { spin_unlock(&st_use_lock); - scsi_tape_put(STp); DEBC_printk(STp, "Device already in use.\n"); + scsi_tape_put(STp); return (-EBUSY); } diff --git a/drivers/scsi/ufs/ufs-qcom-debugfs.c b/drivers/scsi/ufs/ufs-qcom-debugfs.c index 957a8f2825b6..4ed71bbb7011 100644 --- a/drivers/scsi/ufs/ufs-qcom-debugfs.c +++ b/drivers/scsi/ufs/ufs-qcom-debugfs.c @@ -244,39 +244,6 @@ static const struct file_operations ufs_qcom_dbg_dbg_regs_desc = { .read = seq_read, }; -static int ufs_qcom_dbg_pm_qos_show(struct seq_file *file, void *data) -{ - struct ufs_qcom_host *host = (struct ufs_qcom_host *)file->private; - unsigned long flags; - int i; - - spin_lock_irqsave(host->hba->host->host_lock, flags); - - seq_printf(file, "enabled: %d\n", host->pm_qos.is_enabled); - for (i = 0; i < host->pm_qos.num_groups && host->pm_qos.groups; i++) - seq_printf(file, - "CPU Group #%d(mask=0x%lx): active_reqs=%d, state=%d, latency=%d\n", - i, host->pm_qos.groups[i].mask.bits[0], - host->pm_qos.groups[i].active_reqs, - host->pm_qos.groups[i].state, - host->pm_qos.groups[i].latency_us); - - spin_unlock_irqrestore(host->hba->host->host_lock, flags); - - return 0; -} - -static int ufs_qcom_dbg_pm_qos_open(struct inode *inode, - struct file *file) -{ - return single_open(file, ufs_qcom_dbg_pm_qos_show, inode->i_private); -} - -static const struct file_operations ufs_qcom_dbg_pm_qos_desc = { - .open = ufs_qcom_dbg_pm_qos_open, - .read = seq_read, -}; - void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root) { struct ufs_qcom_host *host; @@ -365,17 +332,6 @@ void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root) goto err; } - host->debugfs_files.pm_qos = - debugfs_create_file("pm_qos", 0400, - host->debugfs_files.debugfs_root, host, - &ufs_qcom_dbg_pm_qos_desc); - if (!host->debugfs_files.dbg_regs) { - dev_err(host->hba->dev, - "%s: failed create dbg_regs debugfs entry\n", - __func__); - goto err; - } - return; err: diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 5bba72c8ae13..45b3a6a1fa62 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -19,6 +19,7 @@ #include #include #include +#include #ifdef CONFIG_QCOM_BUS_SCALING #include @@ -36,8 +37,6 @@ #define MAX_PROP_SIZE 32 #define VDDP_REF_CLK_MIN_UV 1200000 #define VDDP_REF_CLK_MAX_UV 1200000 -/* TODO: further tuning for this parameter may be required */ -#define UFS_QCOM_PM_QOS_UNVOTE_TIMEOUT_US (10000) /* microseconds */ #define UFS_QCOM_DEFAULT_DBG_PRINT_EN \ (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_TEST_BUS_EN) @@ -65,7 +64,6 @@ static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host); static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, u32 clk_1us_cycles, u32 clk_40ns_cycles); -static void ufs_qcom_pm_qos_suspend(struct ufs_qcom_host *host); static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len, char *prefix) @@ -864,8 +862,6 @@ static int ufs_qcom_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) goto out; } } - /* Unvote PM QoS */ - ufs_qcom_pm_qos_suspend(host); out: return ret; @@ -1532,7 +1528,6 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba) if (!host->disable_lpm) { hba->caps |= UFSHCD_CAP_CLK_GATING; hba->caps |= UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; - hba->caps |= UFSHCD_CAP_CLK_SCALING; } hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; @@ -1638,398 +1633,6 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on, return err; } -#ifdef CONFIG_SMP /* CONFIG_SMP */ -static int ufs_qcom_cpu_to_group(struct ufs_qcom_host *host, int cpu) -{ - int i; - - if (cpu >= 0 && cpu < num_possible_cpus()) - for (i = 0; i < host->pm_qos.num_groups; i++) - if (cpumask_test_cpu(cpu, &host->pm_qos.groups[i].mask)) - return i; - - return host->pm_qos.default_cpu; -} - -static void ufs_qcom_pm_qos_req_start(struct ufs_hba *hba, struct request *req) -{ - unsigned long flags; - struct ufs_qcom_host *host; - struct ufs_qcom_pm_qos_cpu_group *group; - - if (!hba || !req) - return; - - host = ufshcd_get_variant(hba); - if (!host->pm_qos.groups) - return; - - group = &host->pm_qos.groups[ufs_qcom_cpu_to_group(host, req->cpu)]; - - ufs_spin_lock_irqsave(hba->host->host_lock, flags); - if (!host->pm_qos.is_enabled) - goto out; - - group->active_reqs++; - if (group->state != PM_QOS_REQ_VOTE && - group->state != PM_QOS_VOTED) { - group->state = PM_QOS_REQ_VOTE; - queue_work(host->pm_qos.workq, &group->vote_work); - } -out: - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); -} - -/* hba->host->host_lock is assumed to be held by caller */ -static void __ufs_qcom_pm_qos_req_end(struct ufs_qcom_host *host, int req_cpu) -{ - struct ufs_qcom_pm_qos_cpu_group *group; - - if (!host->pm_qos.groups || !host->pm_qos.is_enabled) - return; - - group = &host->pm_qos.groups[ufs_qcom_cpu_to_group(host, req_cpu)]; - - if (group->active_reqs <= 0) - pr_err_ratelimited("ufshcd-qcom: active req coount is negative: %d\n", - group->active_reqs); - if (--group->active_reqs) - return; - group->state = PM_QOS_REQ_UNVOTE; - queue_work(host->pm_qos.workq, &group->unvote_work); -} - -static void ufs_qcom_pm_qos_req_end(struct ufs_hba *hba, struct request *req, - bool should_lock) -{ - unsigned long flags = 0; - - if (!hba || !req) - return; - - if (should_lock) - ufs_spin_lock_irqsave(hba->host->host_lock, flags); - __ufs_qcom_pm_qos_req_end(ufshcd_get_variant(hba), req->cpu); - if (should_lock) - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); -} - -static void ufs_qcom_pm_qos_vote_work(struct work_struct *work) -{ - struct ufs_qcom_pm_qos_cpu_group *group = - container_of(work, struct ufs_qcom_pm_qos_cpu_group, vote_work); - struct ufs_qcom_host *host = group->host; - unsigned long flags; - - ufs_spin_lock_irqsave(host->hba->host->host_lock, flags); - - if (!host->pm_qos.is_enabled || !group->active_reqs) { - ufs_spin_unlock_irqrestore(host->hba->host->host_lock, flags); - return; - } - - group->state = PM_QOS_VOTED; - ufs_spin_unlock_irqrestore(host->hba->host->host_lock, flags); - - pm_qos_update_request(&group->req, group->latency_us); -} - -static void ufs_qcom_pm_qos_unvote_work(struct work_struct *work) -{ - struct ufs_qcom_pm_qos_cpu_group *group = container_of(work, - struct ufs_qcom_pm_qos_cpu_group, unvote_work); - struct ufs_qcom_host *host = group->host; - unsigned long flags; - - /* - * Check if new requests were submitted in the meantime and do not - * unvote if so. - */ - ufs_spin_lock_irqsave(host->hba->host->host_lock, flags); - - if (!host->pm_qos.is_enabled || group->active_reqs) { - ufs_spin_unlock_irqrestore(host->hba->host->host_lock, flags); - return; - } - - group->state = PM_QOS_UNVOTED; - ufs_spin_unlock_irqrestore(host->hba->host->host_lock, flags); - - pm_qos_update_request_timeout(&group->req, - group->latency_us, UFS_QCOM_PM_QOS_UNVOTE_TIMEOUT_US); -} - -static ssize_t ufs_qcom_pm_qos_enable_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev->parent); - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - - return snprintf(buf, PAGE_SIZE, "%d\n", host->pm_qos.is_enabled); -} - -static ssize_t ufs_qcom_pm_qos_enable_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct ufs_hba *hba = dev_get_drvdata(dev->parent); - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - unsigned long value; - unsigned long flags; - bool enable; - int i; - - if (kstrtoul(buf, 0, &value)) - return -EINVAL; - - enable = !!value; - - /* - * Must take the spinlock and save irqs before changing the enabled - * flag in order to keep correctness of PM QoS release. - */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); - if (enable == host->pm_qos.is_enabled) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); - return count; - } - host->pm_qos.is_enabled = enable; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); - - if (!enable) - for (i = 0; i < host->pm_qos.num_groups; i++) { - cancel_work_sync(&host->pm_qos.groups[i].vote_work); - cancel_work_sync(&host->pm_qos.groups[i].unvote_work); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); - host->pm_qos.groups[i].state = PM_QOS_UNVOTED; - host->pm_qos.groups[i].active_reqs = 0; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); - pm_qos_update_request(&host->pm_qos.groups[i].req, - PM_QOS_DEFAULT_VALUE); - } - - return count; -} - -static ssize_t ufs_qcom_pm_qos_latency_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ufs_hba *hba = dev_get_drvdata(dev->parent); - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - int ret; - int i; - int offset = 0; - - for (i = 0; i < host->pm_qos.num_groups; i++) { - ret = snprintf(&buf[offset], PAGE_SIZE, - "cpu group #%d(mask=0x%lx): %d\n", i, - host->pm_qos.groups[i].mask.bits[0], - host->pm_qos.groups[i].latency_us); - if (ret > 0) - offset += ret; - else - break; - } - - return offset; -} - -static ssize_t ufs_qcom_pm_qos_latency_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct ufs_hba *hba = dev_get_drvdata(dev->parent); - struct ufs_qcom_host *host = ufshcd_get_variant(hba); - unsigned long value; - unsigned long flags; - char *strbuf; - char *strbuf_copy; - char *token; - int i; - int ret; - - /* reserve one byte for null termination */ - strbuf = kmalloc(count + 1, GFP_KERNEL); - if (!strbuf) - return -ENOMEM; - strbuf_copy = strbuf; - strlcpy(strbuf, buf, count + 1); - - for (i = 0; i < host->pm_qos.num_groups; i++) { - token = strsep(&strbuf, ","); - if (!token) - break; - - ret = kstrtoul(token, 0, &value); - if (ret) - break; - - ufs_spin_lock_irqsave(hba->host->host_lock, flags); - host->pm_qos.groups[i].latency_us = value; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); - } - - kfree(strbuf_copy); - return count; -} - -static int ufs_qcom_pm_qos_init(struct ufs_qcom_host *host) -{ - struct device_node *node = host->hba->dev->of_node; - struct device_attribute *attr; - int ret = 0; - int num_groups; - int num_values; - char wq_name[sizeof("ufs_pm_qos_00")]; - int i; - - num_groups = of_property_count_u32_elems(node, - "qcom,pm-qos-cpu-groups"); - if (num_groups <= 0) - goto no_pm_qos; - - num_values = of_property_count_u32_elems(node, - "qcom,pm-qos-cpu-group-latency-us"); - if (num_values <= 0) - goto no_pm_qos; - - if (num_values != num_groups || num_groups > num_possible_cpus()) { - dev_err(host->hba->dev, "%s: invalid count: num_groups=%d, num_values=%d, num_possible_cpus=%d\n", - __func__, num_groups, num_values, num_possible_cpus()); - goto no_pm_qos; - } - - host->pm_qos.num_groups = num_groups; - host->pm_qos.groups = kcalloc(host->pm_qos.num_groups, - sizeof(struct ufs_qcom_pm_qos_cpu_group), GFP_KERNEL); - if (!host->pm_qos.groups) - return -ENOMEM; - - for (i = 0; i < host->pm_qos.num_groups; i++) { - u32 mask; - - ret = of_property_read_u32_index(node, "qcom,pm-qos-cpu-groups", - i, &mask); - if (ret) - goto free_groups; - host->pm_qos.groups[i].mask.bits[0] = mask; - if (!cpumask_subset(&host->pm_qos.groups[i].mask, - cpu_possible_mask)) { - dev_err(host->hba->dev, "%s: invalid mask 0x%x for cpu group\n", - __func__, mask); - goto free_groups; - } - - ret = of_property_read_u32_index(node, - "qcom,pm-qos-cpu-group-latency-us", i, - &host->pm_qos.groups[i].latency_us); - if (ret) - goto free_groups; - - host->pm_qos.groups[i].req.type = PM_QOS_REQ_AFFINE_CORES; - host->pm_qos.groups[i].req.cpus_affine = - host->pm_qos.groups[i].mask; - host->pm_qos.groups[i].state = PM_QOS_UNVOTED; - host->pm_qos.groups[i].active_reqs = 0; - host->pm_qos.groups[i].host = host; - - INIT_WORK(&host->pm_qos.groups[i].vote_work, - ufs_qcom_pm_qos_vote_work); - INIT_WORK(&host->pm_qos.groups[i].unvote_work, - ufs_qcom_pm_qos_unvote_work); - } - - ret = of_property_read_u32(node, "qcom,pm-qos-default-cpu", - &host->pm_qos.default_cpu); - if (ret || host->pm_qos.default_cpu > num_possible_cpus()) - host->pm_qos.default_cpu = 0; - - /* - * Use a single-threaded workqueue to assure work submitted to the queue - * is performed in order. Consider the following 2 possible cases: - * - * 1. A new request arrives and voting work is scheduled for it. Before - * the voting work is performed the request is finished and unvote - * work is also scheduled. - * 2. A request is finished and unvote work is scheduled. Before the - * work is performed a new request arrives and voting work is also - * scheduled. - * - * In both cases a vote work and unvote work wait to be performed. - * If ordering is not guaranteed, then the end state might be the - * opposite of the desired state. - */ - snprintf(wq_name, ARRAY_SIZE(wq_name), "%s_%d", "ufs_pm_qos", - host->hba->host->host_no); - host->pm_qos.workq = create_singlethread_workqueue(wq_name); - if (!host->pm_qos.workq) { - dev_err(host->hba->dev, "%s: failed to create the workqueue\n", - __func__); - ret = -ENOMEM; - goto free_groups; - } - - /* Initialization was ok, add all PM QoS requests */ - for (i = 0; i < host->pm_qos.num_groups; i++) - pm_qos_add_request(&host->pm_qos.groups[i].req, - PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); - - /* PM QoS latency sys-fs attribute */ - attr = &host->pm_qos.latency_attr; - attr->show = ufs_qcom_pm_qos_latency_show; - attr->store = ufs_qcom_pm_qos_latency_store; - sysfs_attr_init(&attr->attr); - attr->attr.name = "pm_qos_latency_us"; - attr->attr.mode = 0644; - if (device_create_file(host->hba->var->dev, attr)) - dev_dbg(host->hba->dev, "Failed to create sysfs for pm_qos_latency_us\n"); - - /* PM QoS enable sys-fs attribute */ - attr = &host->pm_qos.enable_attr; - attr->show = ufs_qcom_pm_qos_enable_show; - attr->store = ufs_qcom_pm_qos_enable_store; - sysfs_attr_init(&attr->attr); - attr->attr.name = "pm_qos_enable"; - attr->attr.mode = 0644; - if (device_create_file(host->hba->var->dev, attr)) - dev_dbg(host->hba->dev, "Failed to create sysfs for pm_qos enable\n"); - - host->pm_qos.is_enabled = true; - - return 0; - -free_groups: - kfree(host->pm_qos.groups); -no_pm_qos: - host->pm_qos.groups = NULL; - return ret ? ret : -ENOTSUPP; -} - -static void ufs_qcom_pm_qos_suspend(struct ufs_qcom_host *host) -{ - int i; - - if (!host->pm_qos.groups) - return; - - for (i = 0; i < host->pm_qos.num_groups; i++) - flush_work(&host->pm_qos.groups[i].unvote_work); -} - -static void ufs_qcom_pm_qos_remove(struct ufs_qcom_host *host) -{ - int i; - - if (!host->pm_qos.groups) - return; - - for (i = 0; i < host->pm_qos.num_groups; i++) - pm_qos_remove_request(&host->pm_qos.groups[i].req); - destroy_workqueue(host->pm_qos.workq); - - kfree(host->pm_qos.groups); - host->pm_qos.groups = NULL; -} -#endif /* CONFIG_SMP */ - #define ANDROID_BOOT_DEV_MAX 30 static char android_boot_dev[ANDROID_BOOT_DEV_MAX]; @@ -2194,10 +1797,6 @@ static int ufs_qcom_init(struct ufs_hba *hba) goto out_variant_clear; } - err = ufs_qcom_pm_qos_init(host); - if (err) - dev_info(dev, "%s: PM QoS will be disabled\n", __func__); - /* restore the secure configuration */ ufs_qcom_update_sec_cfg(hba, true); @@ -2321,7 +1920,6 @@ static void ufs_qcom_exit(struct ufs_hba *hba) host->is_phy_pwr_on = false; } phy_exit(host->generic_phy); - ufs_qcom_pm_qos_remove(host); } static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba, @@ -2600,7 +2198,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) if (!host) return -EINVAL; hba = host->hba; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); switch (host->testbus.select_major) { case TSTBUS_UAWM: reg = UFS_TEST_BUS_CTRL_0; @@ -2661,12 +2259,12 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) if (offset < 0) { dev_err(hba->dev, "%s: Bad offset: %d\n", __func__, offset); ret = -EINVAL; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); goto out; } mask <<= offset; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (reg) { ufshcd_rmwl(host->hba, TEST_BUS_SEL, (u32)host->testbus.select_major << testbus_sel_offset, @@ -2794,15 +2392,9 @@ static struct ufs_hba_variant_ops ufs_hba_qcom_vops = { .get_user_cap_mode = ufs_qcom_get_user_cap_mode, }; -static struct ufs_hba_pm_qos_variant_ops ufs_hba_pm_qos_variant_ops = { - .req_start = ufs_qcom_pm_qos_req_start, - .req_end = ufs_qcom_pm_qos_req_end, -}; - static struct ufs_hba_variant ufs_hba_qcom_variant = { .name = "qcom", .vops = &ufs_hba_qcom_vops, - .pm_qos_vops = &ufs_hba_pm_qos_variant_ops, }; /** diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 6538637b1c43..409211b091c3 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -16,7 +16,6 @@ #define UFS_QCOM_H_ #include -#include #include "ufshcd.h" #define MAX_UFS_QCOM_HOSTS 2 @@ -247,62 +246,9 @@ struct qcom_debugfs_files { struct dentry *testbus_cfg; struct dentry *testbus_bus; struct dentry *dbg_regs; - struct dentry *pm_qos; }; #endif -/* PM QoS voting state */ -enum ufs_qcom_pm_qos_state { - PM_QOS_UNVOTED, - PM_QOS_VOTED, - PM_QOS_REQ_VOTE, - PM_QOS_REQ_UNVOTE, -}; - -/** - * struct ufs_qcom_pm_qos_cpu_group - data related to cluster PM QoS voting - * logic - * @req: request object for PM QoS - * @vote_work: work object for voting procedure - * @unvote_work: work object for un-voting procedure - * @host: back pointer to the main structure - * @state: voting state machine current state - * @latency_us: requested latency value used for cluster voting, in - * microseconds - * @mask: cpu mask defined for this cluster - * @active_reqs: number of active requests on this cluster - */ -struct ufs_qcom_pm_qos_cpu_group { - struct pm_qos_request req; - struct work_struct vote_work; - struct work_struct unvote_work; - struct ufs_qcom_host *host; - enum ufs_qcom_pm_qos_state state; - s32 latency_us; - cpumask_t mask; - int active_reqs; -}; - -/** - * struct ufs_qcom_pm_qos - data related to PM QoS voting logic - * @groups: PM QoS cpu group state array - * @enable_attr: sysfs attribute to enable/disable PM QoS voting logic - * @latency_attr: sysfs attribute to set latency value - * @workq: single threaded workqueue to run PM QoS voting/unvoting - * @num_clusters: number of clusters defined - * @default_cpu: cpu to use for voting for request not specifying a cpu - * @is_enabled: flag specifying whether voting logic is enabled - */ -struct ufs_qcom_pm_qos { - struct ufs_qcom_pm_qos_cpu_group *groups; - struct device_attribute enable_attr; - struct device_attribute latency_attr; - struct workqueue_struct *workq; - int num_groups; - int default_cpu; - bool is_enabled; -}; - struct ufs_qcom_host { /* * Set this capability if host controller supports the QUniPro mode @@ -340,9 +286,6 @@ struct ufs_qcom_host { struct clk *rx_l1_sync_clk; struct clk *tx_l1_sync_clk; - /* PM Quality-of-Service (QoS) data */ - struct ufs_qcom_pm_qos pm_qos; - bool disable_lpm; bool is_lane_clks_enabled; bool sec_cfg_updated; diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index ffe6f82182ba..68f4f67c5ff8 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -96,6 +96,30 @@ static int ufshcd_pci_resume(struct device *dev) { return ufshcd_system_resume(dev_get_drvdata(dev)); } + +/** + * ufshcd_pci_poweroff - suspend-to-disk poweroff function + * @dev: pointer to PCI device handle + * + * Returns 0 if successful + * Returns non-zero otherwise + */ +static int ufshcd_pci_poweroff(struct device *dev) +{ + struct ufs_hba *hba = dev_get_drvdata(dev); + int spm_lvl = hba->spm_lvl; + int ret; + + /* + * For poweroff we need to set the UFS device to PowerDown mode. + * Force spm_lvl to ensure that. + */ + hba->spm_lvl = 5; + ret = ufshcd_system_suspend(hba); + hba->spm_lvl = spm_lvl; + return ret; +} + #endif /* !CONFIG_PM_SLEEP */ #ifdef CONFIG_PM @@ -190,8 +214,14 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) } static const struct dev_pm_ops ufshcd_pci_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(ufshcd_pci_suspend, - ufshcd_pci_resume) +#ifdef CONFIG_PM_SLEEP + .suspend = ufshcd_pci_suspend, + .resume = ufshcd_pci_resume, + .freeze = ufshcd_pci_suspend, + .thaw = ufshcd_pci_resume, + .poweroff = ufshcd_pci_poweroff, + .restore = ufshcd_pci_resume, +#endif SET_RUNTIME_PM_OPS(ufshcd_pci_runtime_suspend, ufshcd_pci_runtime_resume, ufshcd_pci_runtime_idle) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 5100049889b6..64b9519b44c3 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1624,7 +1624,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, ktime_t start; ufshcd_hold_all(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); /* * Wait for all the outstanding tasks/transfer requests. * Verify by checking the doorbell registers are clear. @@ -1645,7 +1645,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, break; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); schedule(); if (ktime_to_us(ktime_sub(ktime_get(), start)) > wait_timeout_us) { @@ -1657,7 +1657,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, */ do_last_check = true; } - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); } while (tm_doorbell || tr_doorbell); if (timeout) { @@ -1667,7 +1667,7 @@ int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, ret = -EBUSY; } out: - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_release_all(hba); return ret; } @@ -1875,13 +1875,13 @@ static void ufshcd_clk_scaling_suspend_work(struct work_struct *work) clk_scaling.suspend_work); unsigned long irq_flags; - ufs_spin_lock_irqsave(hba->host->host_lock, irq_flags); + spin_lock_irqsave(hba->host->host_lock, irq_flags); if (hba->clk_scaling.active_reqs || hba->clk_scaling.is_suspended) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); return; } hba->clk_scaling.is_suspended = true; - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); __ufshcd_suspend_clkscaling(hba); } @@ -1892,13 +1892,13 @@ static void ufshcd_clk_scaling_resume_work(struct work_struct *work) clk_scaling.resume_work); unsigned long irq_flags; - ufs_spin_lock_irqsave(hba->host->host_lock, irq_flags); + spin_lock_irqsave(hba->host->host_lock, irq_flags); if (!hba->clk_scaling.is_suspended) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); return; } hba->clk_scaling.is_suspended = false; - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); devfreq_resume_device(hba->devfreq); } @@ -1917,9 +1917,9 @@ static int ufshcd_devfreq_target(struct device *dev, if (!ufshcd_is_clkscaling_supported(hba)) return -EINVAL; - ufs_spin_lock_irqsave(hba->host->host_lock, irq_flags); + spin_lock_irqsave(hba->host->host_lock, irq_flags); if (ufshcd_eh_in_progress(hba)) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); return 0; } @@ -1927,18 +1927,18 @@ static int ufshcd_devfreq_target(struct device *dev, sched_clk_scaling_suspend_work = true; if (list_empty(clk_list)) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); goto out; } clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list); scale_up = (*freq == clki->max_freq) ? true : false; if (!ufshcd_is_devfreq_scaling_required(hba, scale_up)) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); ret = 0; goto out; /* no state change required */ } - ufs_spin_unlock_irqrestore(hba->host->host_lock, irq_flags); + spin_unlock_irqrestore(hba->host->host_lock, irq_flags); start = ktime_get(); ret = ufshcd_devfreq_scale(hba, scale_up); @@ -1967,7 +1967,7 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, memset(stat, 0, sizeof(*stat)); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (!scaling->window_start_t) goto start_window; @@ -1989,7 +1989,7 @@ static int ufshcd_devfreq_get_dev_status(struct device *dev, scaling->busy_start_t = 0; scaling->is_busy_started = false; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return 0; } @@ -2052,9 +2052,9 @@ static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba) unsigned long flags; devfreq_suspend_device(hba->devfreq); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_scaling.window_start_t = 0; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } static void ufshcd_suspend_clkscaling(struct ufs_hba *hba) @@ -2065,12 +2065,12 @@ static void ufshcd_suspend_clkscaling(struct ufs_hba *hba) if (!ufshcd_is_clkscaling_supported(hba)) return; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (!hba->clk_scaling.is_suspended) { suspend = true; hba->clk_scaling.is_suspended = true; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (suspend) __ufshcd_suspend_clkscaling(hba); @@ -2084,17 +2084,37 @@ static void ufshcd_resume_clkscaling(struct ufs_hba *hba) if (!ufshcd_is_clkscaling_supported(hba)) return; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_scaling.is_suspended) { resume = true; hba->clk_scaling.is_suspended = false; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (resume) devfreq_resume_device(hba->devfreq); } +static int bogus_clkscale_enable = 1; +static ssize_t ufshcd_bogus_clkscale_enable_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", bogus_clkscale_enable); +} + +static ssize_t ufshcd_bogus_clkscale_enable_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + u32 value; + + if (kstrtou32(buf, 0, &value)) + return -EINVAL; + + bogus_clkscale_enable = !!value; + + return count; +} + static ssize_t ufshcd_clkscale_enable_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -2141,10 +2161,15 @@ static ssize_t ufshcd_clkscale_enable_store(struct device *dev, return count; } -static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba) +static void ufshcd_clkscaling_init_sysfs(struct ufs_hba *hba, bool bogus) { - hba->clk_scaling.enable_attr.show = ufshcd_clkscale_enable_show; - hba->clk_scaling.enable_attr.store = ufshcd_clkscale_enable_store; + if (bogus) { + hba->clk_scaling.enable_attr.show = ufshcd_bogus_clkscale_enable_show; + hba->clk_scaling.enable_attr.store = ufshcd_bogus_clkscale_enable_store; + } else { + hba->clk_scaling.enable_attr.show = ufshcd_clkscale_enable_show; + hba->clk_scaling.enable_attr.store = ufshcd_clkscale_enable_store; + } sysfs_attr_init(&hba->clk_scaling.enable_attr.attr); hba->clk_scaling.enable_attr.attr.name = "clkscale_enable"; hba->clk_scaling.enable_attr.attr.mode = 0644; @@ -2161,15 +2186,17 @@ static void ufshcd_ungate_work(struct work_struct *work) ufshcd_cancel_gate_work(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_gating.state == CLKS_ON) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); goto unblock_reqs; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_hba_vreg_set_hpm(hba); ufshcd_enable_clocks(hba); + + ufshcd_enable_irq(hba); /* Exit from hibern8 */ if (ufshcd_can_hibern8_during_gating(hba)) { @@ -2197,13 +2224,13 @@ static void ufshcd_panic_ungate_work(struct ufs_hba *hba) if (!oops_in_progress) ufshcd_cancel_gate_work(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_gating.state == CLKS_ON) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); goto unblock_reqs; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_hba_vreg_set_hpm(hba); ufshcd_enable_clocks(hba); @@ -2239,11 +2266,11 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) if (!ufshcd_is_clkgating_allowed(hba)) goto out; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.active_reqs++; if (ufshcd_eh_in_progress(hba)) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return 0; } @@ -2315,21 +2342,21 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) break; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (!oops_in_progress) flush_work(&hba->clk_gating.ungate_work); else ufshcd_panic_ungate_work(hba); /* Make sure state is CLKS_ON before returning */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); goto start; default: dev_err(hba->dev, "%s: clk gating is in invalid state %d\n", __func__, hba->clk_gating.state); break; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); out: hba->ufs_stats.clk_hold.ts = ktime_get(); return rc; @@ -2367,7 +2394,7 @@ static void ufshcd_gate_work(struct work_struct *work) || hba->active_uic_cmd || hba->uic_async_done) goto rel_lock; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (ufshcd_is_hibern8_on_idle_allowed(hba) && hba->hibern8_on_idle.is_enabled) @@ -2387,6 +2414,8 @@ static void ufshcd_gate_work(struct work_struct *work) } ufshcd_set_link_hibern8(hba); } + + ufshcd_disable_irq(hba); /* * If auto hibern8 is enabled then the link will already @@ -2411,14 +2440,14 @@ static void ufshcd_gate_work(struct work_struct *work) * prevent from doing cancel work multiple times when there are * new requests arriving before the current cancel work is done. */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_gating.state == REQ_CLKS_OFF) { hba->clk_gating.state = CLKS_OFF; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); } rel_lock: - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); out: hba->clk_gating.gate_wk_in_process = false; return; @@ -2452,9 +2481,9 @@ void ufshcd_release(struct ufs_hba *hba, bool no_sched) { unsigned long flags; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); __ufshcd_release(hba, no_sched); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } EXPORT_SYMBOL_GPL(ufshcd_release); @@ -2475,9 +2504,9 @@ static ssize_t ufshcd_clkgate_delay_store(struct device *dev, if (kstrtoul(buf, 0, &value)) return -EINVAL; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.delay_ms = value; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } @@ -2499,14 +2528,14 @@ static ssize_t ufshcd_clkgate_delay_pwr_save_store(struct device *dev, if (kstrtoul(buf, 0, &value)) return -EINVAL; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.delay_ms_pwr_save = value; if (ufshcd_is_clkscaling_supported(hba) && !hba->clk_scaling.is_scaled_up) hba->clk_gating.delay_ms = hba->clk_gating.delay_ms_pwr_save; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } @@ -2527,14 +2556,14 @@ static ssize_t ufshcd_clkgate_delay_perf_store(struct device *dev, if (kstrtoul(buf, 0, &value)) return -EINVAL; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.delay_ms_perf = value; if (ufshcd_is_clkscaling_supported(hba) && hba->clk_scaling.is_scaled_up) hba->clk_gating.delay_ms = hba->clk_gating.delay_ms_perf; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } @@ -2563,9 +2592,9 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev, if (value) { ufshcd_release(hba, false); } else { - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.active_reqs++; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } hba->clk_gating.is_enabled = value; @@ -2589,8 +2618,10 @@ static void ufshcd_init_clk_scaling(struct ufs_hba *hba) { char wq_name[sizeof("ufs_clkscaling_00")]; - if (!ufshcd_is_clkscaling_supported(hba)) + if (!ufshcd_is_clkscaling_supported(hba)) { + ufshcd_clkscaling_init_sysfs(hba, true); return; + } INIT_WORK(&hba->clk_scaling.suspend_work, ufshcd_clk_scaling_suspend_work); @@ -2601,7 +2632,7 @@ static void ufshcd_init_clk_scaling(struct ufs_hba *hba) hba->host->host_no); hba->clk_scaling.workq = create_singlethread_workqueue(wq_name); - ufshcd_clkscaling_init_sysfs(hba); + ufshcd_clkscaling_init_sysfs(hba, false); } static void ufshcd_exit_clk_scaling(struct ufs_hba *hba) @@ -2726,11 +2757,11 @@ static int ufshcd_hibern8_hold(struct ufs_hba *hba, bool async) if (!ufshcd_is_hibern8_on_idle_allowed(hba)) goto out; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->hibern8_on_idle.active_reqs++; if (ufshcd_eh_in_progress(hba)) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return 0; } @@ -2780,11 +2811,11 @@ static int ufshcd_hibern8_hold(struct ufs_hba *hba, bool async) hba->hibern8_on_idle.active_reqs--; break; } else { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (!oops_in_progress) flush_work(&hba->hibern8_on_idle.exit_work); /* Make sure state is HIBERN8_EXITED before returning */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); goto start; } default: @@ -2792,7 +2823,7 @@ static int ufshcd_hibern8_hold(struct ufs_hba *hba, bool async) __func__, hba->hibern8_on_idle.state); break; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); out: return rc; } @@ -2839,9 +2870,9 @@ static void ufshcd_hibern8_release(struct ufs_hba *hba, bool no_sched) { unsigned long flags; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); __ufshcd_hibern8_release(hba, no_sched); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } static void ufshcd_hibern8_enter_work(struct work_struct *work) @@ -2850,7 +2881,7 @@ static void ufshcd_hibern8_enter_work(struct work_struct *work) hibern8_on_idle.enter_work.work); unsigned long flags; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->hibern8_on_idle.is_suspended) { hba->hibern8_on_idle.state = HIBERN8_EXITED; trace_ufshcd_hibern8_on_idle(dev_name(hba->dev), @@ -2864,7 +2895,7 @@ static void ufshcd_hibern8_enter_work(struct work_struct *work) || hba->active_uic_cmd || hba->uic_async_done) goto rel_lock; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (ufshcd_is_link_active(hba) && ufshcd_uic_hibern8_enter(hba)) { /* Enter failed */ @@ -2884,14 +2915,14 @@ static void ufshcd_hibern8_enter_work(struct work_struct *work) * prevent from doing cancel work multiple times when there are * new requests arriving before the current cancel work is done. */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->hibern8_on_idle.state == REQ_HIBERN8_ENTER) { hba->hibern8_on_idle.state = HIBERN8_ENTERED; trace_ufshcd_hibern8_on_idle(dev_name(hba->dev), hba->hibern8_on_idle.state); } rel_lock: - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); out: return; } @@ -2905,14 +2936,14 @@ static void ufshcd_hibern8_exit_work(struct work_struct *work) cancel_delayed_work_sync(&hba->hibern8_on_idle.enter_work); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if ((hba->hibern8_on_idle.state == HIBERN8_EXITED) || ufshcd_is_link_active(hba)) { hba->hibern8_on_idle.state = HIBERN8_EXITED; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); goto unblock_reqs; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /* Exit from hibern8 */ if (ufshcd_is_link_hibern8(hba)) { @@ -2922,12 +2953,12 @@ static void ufshcd_hibern8_exit_work(struct work_struct *work) hba->ufs_stats.clk_rel.ctx = H8_EXIT_WORK; ufshcd_release(hba, false); if (!ret) { - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_set_link_active(hba); hba->hibern8_on_idle.state = HIBERN8_EXITED; trace_ufshcd_hibern8_on_idle(dev_name(hba->dev), hba->hibern8_on_idle.state); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } } unblock_reqs: @@ -2952,7 +2983,7 @@ static ssize_t ufshcd_hibern8_on_idle_delay_store(struct device *dev, if (kstrtoul(buf, 0, &value)) return -EINVAL; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->hibern8_on_idle.delay_ms == value) change = false; @@ -2961,12 +2992,12 @@ static ssize_t ufshcd_hibern8_on_idle_delay_store(struct device *dev, dev_err(hba->dev, "hibern8_on_idle_delay (%lu) can not be >= to clkgate_delay_ms_pwr_save (%lu) and clkgate_delay_ms_perf (%lu)\n", value, hba->clk_gating.delay_ms_pwr_save, hba->clk_gating.delay_ms_perf); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return -EINVAL; } hba->hibern8_on_idle.delay_ms = value; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return count; } @@ -3002,9 +3033,9 @@ static ssize_t ufshcd_hibern8_on_idle_enable_store(struct device *dev, ufshcd_hold(hba, false); ufshcd_release_all(hba); } else { - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->hibern8_on_idle.active_reqs++; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } hba->hibern8_on_idle.is_enabled = value; @@ -3133,6 +3164,20 @@ static void ufshcd_clk_scaling_update_busy(struct ufs_hba *hba) static inline int ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag) { + if (hba->lrb[task_tag].cmd) { + u8 opcode = (u8)(*hba->lrb[task_tag].cmd->cmnd); + + if (opcode == SECURITY_PROTOCOL_OUT && hba->security_in) { + hba->security_in--; + } else if (opcode == SECURITY_PROTOCOL_IN) { + if (hba->security_in) { + WARN_ON(1); + return -EINVAL; + } + hba->security_in++; + } + } + hba->lrb[task_tag].issue_time_stamp = ktime_get(); hba->lrb[task_tag].compl_time_stamp = ktime_set(0, 0); ufshcd_cond_add_cmd_trace(hba, task_tag, @@ -3297,9 +3342,9 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) ufshcd_dme_cmd_log(hba, "dme_cmpl_1", hba->active_uic_cmd->command); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->active_uic_cmd = NULL; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return ret; } @@ -3350,9 +3395,9 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) mutex_lock(&hba->uic_cmd_mutex); ufshcd_add_delay_before_dme_cmd(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ret = __ufshcd_send_uic_cmd(hba, uic_cmd, true); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (!ret) ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd); @@ -3736,6 +3781,48 @@ static inline void ufshcd_put_read_lock(struct ufs_hba *hba) up_read(&hba->lock); } +static void ufshcd_pm_qos_get_worker(struct work_struct *work) +{ + struct ufs_hba *hba = container_of(work, typeof(*hba), pm_qos.get_work); + + if (!atomic_read(&hba->pm_qos.count)) + return; + + mutex_lock(&hba->pm_qos.lock); + if (atomic_read(&hba->pm_qos.count) && !hba->pm_qos.active) { + pm_qos_update_request(&hba->pm_qos.req, 100); + hba->pm_qos.active = true; + } + mutex_unlock(&hba->pm_qos.lock); +} + +static void ufshcd_pm_qos_put_worker(struct work_struct *work) +{ + struct ufs_hba *hba = container_of(work, typeof(*hba), pm_qos.put_work); + + if (atomic_read(&hba->pm_qos.count)) + return; + + mutex_lock(&hba->pm_qos.lock); + if (!atomic_read(&hba->pm_qos.count) && hba->pm_qos.active) { + pm_qos_update_request(&hba->pm_qos.req, PM_QOS_DEFAULT_VALUE); + hba->pm_qos.active = false; + } + mutex_unlock(&hba->pm_qos.lock); +} + +static void ufshcd_pm_qos_get(struct ufs_hba *hba) +{ + if (atomic_inc_return(&hba->pm_qos.count) == 1) + queue_work(system_unbound_wq, &hba->pm_qos.get_work); +} + +static void ufshcd_pm_qos_put(struct ufs_hba *hba) +{ + if (atomic_dec_return(&hba->pm_qos.count) == 0) + queue_work(system_unbound_wq, &hba->pm_qos.put_work); +} + /** * ufshcd_queuecommand - main entry point for SCSI requests * @host: SCSI host pointer @@ -3751,12 +3838,16 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) int tag; int err = 0; bool has_read_lock = false; + bool cmd_sent = false; hba = shost_priv(host); if (!cmd || !cmd->request || !hba) return -EINVAL; + /* Wake the CPU managing the IRQ as soon as possible */ + ufshcd_pm_qos_get(hba); + tag = cmd->request->tag; if (!ufshcd_valid_tag(hba, tag)) { dev_err(hba->dev, @@ -3770,12 +3861,12 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) if (err == -EPERM) { set_host_byte(cmd, DID_ERROR); cmd->scsi_done(cmd); - return 0; + err = 0; + goto out_pm_qos; } if (err == -EAGAIN) { - hba->ufs_stats.scsi_blk_reqs.ts = ktime_get(); - hba->ufs_stats.scsi_blk_reqs.busy_ctx = SCALING_BUSY; - return SCSI_MLQUEUE_HOST_BUSY; + err = SCSI_MLQUEUE_HOST_BUSY; + goto out_pm_qos; } } else if (err == 1) { has_read_lock = true; @@ -3787,7 +3878,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) */ err = 0; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); /* if error handling is in progress, return host busy */ if (ufshcd_eh_in_progress(hba)) { @@ -3818,7 +3909,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) cmd->scsi_done(cmd); goto out_unlock; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); hba->req_abort_count = 0; @@ -3863,9 +3954,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) if (ufshcd_is_hibern8_on_idle_allowed(hba)) WARN_ON(hba->hibern8_on_idle.state != HIBERN8_EXITED); - /* Vote PM QoS for the request */ - ufshcd_vops_pm_qos_req_start(hba, cmd->request); - WARN_ON(hba->clk_gating.state != CLKS_ON); lrbp = &hba->lrb[tag]; @@ -3898,7 +3986,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) lrbp->cmd = NULL; clear_bit_unlock(tag, &hba->lrb_in_use); ufshcd_release_all(hba); - ufshcd_vops_pm_qos_req_end(hba, cmd->request, true); goto out; } @@ -3907,7 +3994,6 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) lrbp->cmd = NULL; clear_bit_unlock(tag, &hba->lrb_in_use); ufshcd_release_all(hba); - ufshcd_vops_pm_qos_req_end(hba, cmd->request, true); goto out; } @@ -3915,29 +4001,39 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) wmb(); /* issue command to the controller */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); err = ufshcd_send_command(hba, tag); if (err) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); scsi_dma_unmap(lrbp->cmd); lrbp->cmd = NULL; clear_bit_unlock(tag, &hba->lrb_in_use); ufshcd_release_all(hba); - ufshcd_vops_pm_qos_req_end(hba, cmd->request, true); - dev_err(hba->dev, "%s: failed sending command, %d\n", __func__, err); - err = DID_ERROR; + if (err == -EINVAL) { + set_host_byte(cmd, DID_ERROR); + if (has_read_lock) + ufshcd_put_read_lock(hba); + cmd->scsi_done(cmd); + err = 0; + goto out_pm_qos; + } goto out; } + cmd_sent = true; + out_unlock: - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); out: if (has_read_lock) ufshcd_put_read_lock(hba); +out_pm_qos: + if (!cmd_sent) + ufshcd_pm_qos_put(hba); return err; } @@ -3966,9 +4062,9 @@ ufshcd_clear_cmd(struct ufs_hba *hba, int tag) u32 mask = 1 << tag; /* clear outstanding transaction before retry */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_utrl_clear(hba, tag); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /* * wait for for h/w to clear corresponding bit in door-bell. @@ -4047,14 +4143,14 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba, /* Make sure descriptors are ready before ringing the doorbell */ wmb(); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->dev_cmd.complete = NULL; if (likely(time_left)) { err = ufshcd_get_tr_ocs(lrbp); if (!err) err = ufshcd_dev_cmd_completion(hba, lrbp); } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (!time_left) { err = -ETIMEDOUT; @@ -4164,10 +4260,10 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba, ufshcd_add_query_upiu_trace(hba, tag, "query_send"); /* Make sure descriptors are ready before ringing the doorbell */ wmb(); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_vops_setup_xfer_req(hba, tag, (lrbp->cmd ? true : false)); err = ufshcd_send_command(hba, tag); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (err) { dev_err(hba->dev, "%s: failed sending command, %d\n", __func__, err); @@ -5027,7 +5123,7 @@ static int ufshcd_dme_enable(struct ufs_hba *hba) ret = ufshcd_send_uic_cmd(hba, &uic_cmd); if (ret) dev_err(hba->dev, - "dme-reset: error code %d\n", ret); + "dme-enable: error code %d\n", ret); return ret; } @@ -5228,7 +5324,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) init_completion(&uic_async_done); ufshcd_add_delay_before_dme_cmd(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->uic_async_done = &uic_async_done; if (ufshcd_readl(hba, REG_INTERRUPT_ENABLE) & UIC_COMMAND_COMPL) { @@ -5241,7 +5337,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) reenable_intr = true; } ret = __ufshcd_send_uic_cmd(hba, cmd, false); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (ret) { dev_err(hba->dev, "pwr ctrl cmd 0x%x with mode 0x%x uic error %d\n", @@ -5328,12 +5424,12 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) } ufshcd_save_tstamp_of_last_dme_cmd(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->active_uic_cmd = NULL; hba->uic_async_done = NULL; if (reenable_intr) ufshcd_enable_intr(hba, UIC_COMMAND_COMPL); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); mutex_unlock(&hba->uic_cmd_mutex); return ret; } @@ -5385,11 +5481,11 @@ static int ufshcd_link_recovery(struct ufs_hba *hba) * anything out of it. We are just avoiding race here. */ do { - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (!(work_pending(&hba->eh_work) || hba->ufshcd_state == UFSHCD_STATE_RESET)) break; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); dev_dbg(hba->dev, "%s: reset in progress\n", __func__); flush_work(&hba->eh_work); } while (1); @@ -5409,16 +5505,16 @@ static int ufshcd_link_recovery(struct ufs_hba *hba) if (!(work_pending(&hba->eh_work) || hba->ufshcd_state == UFSHCD_STATE_RESET)) break; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); dev_dbg(hba->dev, "%s: reset in progress\n", __func__); flush_work(&hba->eh_work); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); } while (1); if (!((hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) && ufshcd_is_link_active(hba))) ret = -ENOLINK; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return ret; } @@ -5534,11 +5630,11 @@ static void ufshcd_set_auto_hibern8_timer(struct ufs_hba *hba) if (!ufshcd_is_auto_hibern8_supported(hba)) return; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_writel(hba, hba->ahit, REG_AUTO_HIBERNATE_IDLE_TIMER); /* Make sure the timer gets applied before further operations */ mb(); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } /** @@ -6327,9 +6423,9 @@ static void ufshcd_slave_destroy(struct scsi_device *sdev) if (ufshcd_scsi_to_upiu_lun(sdev->lun) == UFS_UPIU_UFS_DEVICE_WLUN) { unsigned long flags; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->sdev_ufs_device = NULL; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } ufshcd_crypto_destroy_rq_keyslot_manager(hba, q); @@ -6351,7 +6447,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp) int ocs_value; int task_result; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); /* Clear completed tasks from outstanding_tasks */ __clear_bit(index, &hba->outstanding_tasks); @@ -6370,7 +6466,7 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp) dev_err(hba->dev, "%s: failed, ocs = 0x%x\n", __func__, ocs_value); } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return ocs_value; } @@ -6610,15 +6706,8 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba, /* Mark completed command as NULL in LRB */ lrbp->cmd = NULL; hba->ufs_stats.clk_rel.ctx = XFR_REQ_COMPL; - if (cmd->request) { - /* - * As we are accessing the "request" structure, - * this must be called before calling - * ->scsi_done() callback. - */ - ufshcd_vops_pm_qos_req_end(hba, cmd->request, - false); - } + if (cmd->request) + ufshcd_pm_qos_put(hba); clear_bit_unlock(index, &hba->lrb_in_use); /* @@ -6687,15 +6776,8 @@ void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, int result) update_req_stats(hba, lrbp); /* Mark completed command as NULL in LRB */ lrbp->cmd = NULL; - if (cmd->request) { - /* - * As we are accessing the "request" structure, - * this must be called before calling - * ->scsi_done() callback. - */ - ufshcd_vops_pm_qos_req_end(hba, cmd->request, - true); - } + if (cmd->request) + ufshcd_pm_qos_put(hba); clear_bit_unlock(index, &hba->lrb_in_use); /* @@ -7245,7 +7327,7 @@ static bool ufshcd_quirk_dl_nac_errors(struct ufs_hba *hba) unsigned long flags; bool err_handling = true; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); /* * UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS only workaround the * device fatal error and/or DL NAC & REPLAY timeout errors. @@ -7270,9 +7352,9 @@ static bool ufshcd_quirk_dl_nac_errors(struct ufs_hba *hba) /* * wait for 50ms to see if we can get any other errors or not. */ - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); msleep(50); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); /* * now check if we have got any other severe errors other than @@ -7297,9 +7379,9 @@ static bool ufshcd_quirk_dl_nac_errors(struct ufs_hba *hba) /* silence the error logs from NOP command */ hba->silence_err_logs = true; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); err = ufshcd_verify_dev_init(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->silence_err_logs = false; if (err) { @@ -7323,7 +7405,7 @@ static bool ufshcd_quirk_dl_nac_errors(struct ufs_hba *hba) hba->silence_err_logs = true; } out: - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return err_handling; } @@ -7359,10 +7441,10 @@ static void ufshcd_err_handler(struct work_struct *work) */ if (unlikely((hba->clk_gating.state != CLKS_ON) && ufshcd_is_auto_hibern8_enabled(hba))) { - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); hba->ufs_stats.clk_hold.ctx = ERR_HNDLR_WORK; ufshcd_hold(hba, false); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); clks_enabled = true; } @@ -7376,10 +7458,10 @@ static void ufshcd_err_handler(struct work_struct *work) UFS_DEVICE_QUIRK_RECOVERY_FROM_DL_NAC_ERRORS) { bool ret; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /* release the lock as ufshcd_quirk_dl_nac_errors() may sleep */ ret = ufshcd_quirk_dl_nac_errors(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (!ret) goto skip_err_handling; } @@ -7394,13 +7476,13 @@ static void ufshcd_err_handler(struct work_struct *work) __func__, hba->saved_err, hba->saved_uic_err); if (!hba->silence_err_logs) { /* release lock as print host regs sleeps */ - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); ufshcd_print_host_regs(hba); ufshcd_print_host_state(hba); ufshcd_print_pwr_info(hba); ufshcd_print_tmrs(hba, hba->outstanding_tasks); ufshcd_print_cmd_log(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); } hba->auto_h8_err = false; } @@ -7422,7 +7504,7 @@ static void ufshcd_err_handler(struct work_struct *work) goto skip_pending_xfer_clear; /* release lock as clear command might sleep */ - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /* Clear pending transfer requests */ for_each_set_bit(tag, &hba->outstanding_reqs, hba->nutrs) { if (ufshcd_clear_cmd(hba, tag)) { @@ -7440,7 +7522,7 @@ static void ufshcd_err_handler(struct work_struct *work) } lock_skip_pending_xfer_clear: - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); /* Complete the requests that are cleared by s/w */ ufshcd_complete_requests(hba); @@ -7478,9 +7560,9 @@ static void ufshcd_err_handler(struct work_struct *work) __ufshcd_transfer_req_compl(hba, (1UL << (hba->nutrs - 1))); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); err = ufshcd_reset_and_restore(hba); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (err) { dev_err(hba->dev, "%s: reset and restore failed\n", __func__); @@ -7513,7 +7595,7 @@ static void ufshcd_err_handler(struct work_struct *work) } out: ufshcd_clear_eh_in_progress(hba); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); } static void ufshcd_update_uic_reg_hist(struct ufs_uic_err_reg_hist *reg_hist, @@ -7804,7 +7886,7 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) struct ufs_hba *hba = __hba; int retries = hba->nutrs; - ufs_spin_lock(hba->host->host_lock); + spin_lock(hba->host->host_lock); intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS); hba->ufs_stats.last_intr_status = intr_status; hba->ufs_stats.last_intr_ts = ktime_get(); @@ -7835,7 +7917,7 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba) UFSHCI_REG_SPACE_SIZE); } - ufs_spin_unlock(hba->host->host_lock); + spin_unlock(hba->host->host_lock); return retval; } @@ -7848,9 +7930,9 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag) if (!test_bit(tag, &hba->outstanding_tasks)) goto out; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_utmrl_clear(hba, tag); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /* poll for max. 1 sec to clear door bell register by h/w */ err = ufshcd_wait_for_register(hba, @@ -7892,7 +7974,7 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, hba->ufs_stats.clk_hold.ctx = TM_CMD_SEND; ufshcd_hold_all(hba); - ufs_spin_lock_irqsave(host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); task_req_descp = hba->utmrdl_base_addr; task_req_descp += free_slot; @@ -7929,7 +8011,7 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id, /* Make sure that doorbell is committed immediately */ wmb(); - ufs_spin_unlock_irqrestore(host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); ufshcd_add_tm_upiu_trace(hba, task_tag, "tm_send"); @@ -7973,19 +8055,16 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) { struct Scsi_Host *host; struct ufs_hba *hba; - unsigned int tag; u32 pos; int err; - u8 resp = 0xF; - struct ufshcd_lrb *lrbp; + u8 resp = 0xF, lun; unsigned long flags; host = cmd->device->host; hba = shost_priv(host); - tag = cmd->request->tag; - lrbp = &hba->lrb[tag]; - err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp); + lun = ufshcd_scsi_to_upiu_lun(cmd->device->lun); + err = ufshcd_issue_tm_cmd(hba, lun, 0, UFS_LOGICAL_RESET, &resp); if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) { if (!err) err = resp; @@ -7994,15 +8073,15 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd) /* clear the commands that were pending for corresponding LUN */ for_each_set_bit(pos, &hba->outstanding_reqs, hba->nutrs) { - if (hba->lrb[pos].lun == lrbp->lun) { + if (hba->lrb[pos].lun == lun) { err = ufshcd_clear_cmd(hba, pos); if (err) break; } } - ufs_spin_lock_irqsave(host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); ufshcd_transfer_req_compl(hba); - ufs_spin_unlock_irqrestore(host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); out: hba->req_abort_count = 0; @@ -8188,10 +8267,10 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) cleanup: scsi_dma_unmap(cmd); - ufs_spin_lock_irqsave(host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); ufshcd_outstanding_req_clear(hba, tag); hba->lrb[tag].cmd = NULL; - ufs_spin_unlock_irqrestore(host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); clear_bit_unlock(tag, &hba->lrb_in_use); wake_up(&hba->dev_cmd.tag_wq); @@ -8329,12 +8408,12 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) * anything out of it. We are just avoiding race here. */ do { - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (!(work_pending(&hba->eh_work) || hba->ufshcd_state == UFSHCD_STATE_RESET || hba->ufshcd_state == UFSHCD_STATE_EH_SCHEDULED)) break; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); dev_err(hba->dev, "%s: reset in progress - 1\n", __func__); flush_work(&hba->eh_work); } while (1); @@ -8352,10 +8431,10 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) if (!(work_pending(&hba->eh_work) || hba->ufshcd_state == UFSHCD_STATE_RESET)) break; - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); dev_err(hba->dev, "%s: reset in progress - 2\n", __func__); flush_work(&hba->eh_work); - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); } while (1); if (!((hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) && @@ -8364,7 +8443,7 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) hba->ufshcd_state = UFSHCD_STATE_ERROR; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); return err; } @@ -8647,9 +8726,6 @@ static int ufs_get_device_desc(struct ufs_hba *hba, hba->dev_info.b_wb_buffer_type = desc_buf[DEVICE_DESC_PARAM_WB_TYPE]; - if (hba->dev_info.b_wb_buffer_type) - goto skip_unit_desc; - hba->dev_info.wb_config_lun = false; for (lun = 0; lun < UFS_UPIU_MAX_GENERAL_LUN; lun++) { d_lu_wb_buf_alloc = 0; @@ -9176,9 +9252,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) __func__, err); /* Reset the host controller */ - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); ufshcd_hba_stop(hba, false); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); err = ufshcd_hba_enable(hba); if (err) @@ -9365,7 +9441,7 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) if (!hba) return BLK_EH_DONE; - ufs_spin_lock_irqsave(host->host_lock, flags); + spin_lock_irqsave(host->host_lock, flags); for_each_set_bit(index, &hba->outstanding_reqs, hba->nutrs) { if (hba->lrb[index].cmd == scmd) { @@ -9374,7 +9450,7 @@ static enum blk_eh_timer_return ufshcd_eh_timed_out(struct scsi_cmnd *scmd) } } - ufs_spin_unlock_irqrestore(host->host_lock, flags); + spin_unlock_irqrestore(host->host_lock, flags); /* * Bypass SCSI error handling and reset the block layer timer if this @@ -10004,11 +10080,11 @@ static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on, clk_disable_unprepare(clki->clk); } } else if (!ret && on) { - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); hba->clk_gating.state = CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /* restore the secure configuration as clocks are enabled */ ufshcd_vops_update_sec_cfg(hba, true); } @@ -10216,7 +10292,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, unsigned long flags; int ret; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); sdp = hba->sdev_ufs_device; if (sdp) { ret = scsi_device_get(sdp); @@ -10227,7 +10303,7 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba, } else { ret = -ENODEV; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); if (ret) return ret; @@ -10940,12 +11016,12 @@ static void __ufshcd_shutdown_clkscaling(struct ufs_hba *hba) bool suspend = false; unsigned long flags; - ufs_spin_lock_irqsave(hba->host->host_lock, flags); + spin_lock_irqsave(hba->host->host_lock, flags); if (hba->clk_scaling.is_allowed) { hba->clk_scaling.is_allowed = false; suspend = true; } - ufs_spin_unlock_irqrestore(hba->host->host_lock, flags); + spin_unlock_irqrestore(hba->host->host_lock, flags); /** * Scaling may be scheduled before, hence make sure it @@ -11029,6 +11105,9 @@ void ufshcd_remove(struct ufs_hba *hba) /* disable interrupts */ ufshcd_disable_intr(hba, hba->intr_mask); ufshcd_hba_stop(hba, true); + cancel_work_sync(&hba->pm_qos.put_work); + cancel_work_sync(&hba->pm_qos.get_work); + pm_qos_remove_request(&hba->pm_qos.req); ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); @@ -11245,6 +11324,14 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) */ mb(); + mutex_init(&hba->pm_qos.lock); + INIT_WORK(&hba->pm_qos.get_work, ufshcd_pm_qos_get_worker); + INIT_WORK(&hba->pm_qos.put_work, ufshcd_pm_qos_put_worker); + hba->pm_qos.req.type = PM_QOS_REQ_AFFINE_IRQ; + hba->pm_qos.req.irq = irq; + pm_qos_add_request(&hba->pm_qos.req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); + /* IRQ registration */ err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, dev_name(dev), hba); @@ -11323,11 +11410,14 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) ufs_sysfs_add_nodes(hba->dev); + device_enable_async_suspend(dev); + return 0; out_remove_scsi_host: scsi_remove_host(hba->host); exit_gating: + pm_qos_remove_request(&hba->pm_qos.req); ufshcd_exit_clk_scaling(hba); ufshcd_exit_clk_gating(hba); out_disable: diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 595bb1dafe8d..27f2c01515f5 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -60,6 +60,7 @@ #include #include #include +#include #include "unipro.h" #include @@ -90,29 +91,6 @@ enum dev_cmd_type { DEV_CMD_TYPE_QUERY = 0x1, }; -#define ufs_spin_lock_irqsave(lock, flags) \ -do { \ - if (!oops_in_progress)\ - spin_lock_irqsave(lock, flags); \ -} while (0) - -#define ufs_spin_unlock_irqrestore(lock, flags) \ -do { \ - if (!oops_in_progress)\ - spin_unlock_irqrestore(lock, flags); \ -} while (0) - -#define ufs_spin_lock(lock) \ -do { \ - if (!oops_in_progress)\ - spin_lock(lock); \ -} while (0) - -#define ufs_spin_unlock(lock) \ -do { \ - if (!oops_in_progress)\ - spin_unlock(lock); \ -} while (0) /** * struct uic_command - UIC command structure * @command: UIC command @@ -412,15 +390,6 @@ struct ufs_hba_variant_ops { ANDROID_KABI_RESERVE(4); }; -/** - * struct ufs_hba_pm_qos_variant_ops - variant specific PM QoS callbacks - */ -struct ufs_hba_pm_qos_variant_ops { - void (*req_start)(struct ufs_hba *hba, struct request *req); - void (*req_end)(struct ufs_hba *hba, struct request *req, - bool should_lock); -}; - /** * struct ufs_hba_variant - variant specific parameters * @name: variant name @@ -429,7 +398,6 @@ struct ufs_hba_variant { struct device *dev; const char *name; struct ufs_hba_variant_ops *vops; - struct ufs_hba_pm_qos_variant_ops *pm_qos_vops; }; struct keyslot_mgmt_ll_ops; @@ -1053,6 +1021,8 @@ struct ufs_hba { /* Number of requests aborts */ int req_abort_count; + u32 security_in; + /* Number of lanes available (1 or 2) for Rx/Tx */ u32 lanes_per_direction; @@ -1151,6 +1121,15 @@ struct ufs_hba { ANDROID_KABI_RESERVE(2); ANDROID_KABI_RESERVE(3); ANDROID_KABI_RESERVE(4); + + struct { + struct pm_qos_request req; + struct work_struct get_work; + struct work_struct put_work; + struct mutex lock; + atomic_t count; + bool active; + } pm_qos; }; static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba) @@ -1615,21 +1594,6 @@ static inline void ufshcd_vops_remove_debugfs(struct ufs_hba *hba) } #endif -static inline void ufshcd_vops_pm_qos_req_start(struct ufs_hba *hba, - struct request *req) -{ - if (hba->var && hba->var->pm_qos_vops && - hba->var->pm_qos_vops->req_start) - hba->var->pm_qos_vops->req_start(hba, req); -} - -static inline void ufshcd_vops_pm_qos_req_end(struct ufs_hba *hba, - struct request *req, bool lock) -{ - if (hba->var && hba->var->pm_qos_vops && hba->var->pm_qos_vops->req_end) - hba->var->pm_qos_vops->req_end(hba, req, lock); -} - extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; /* diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c index 4dd03b099c89..76117405d841 100644 --- a/drivers/soc/atmel/soc.c +++ b/drivers/soc/atmel/soc.c @@ -254,8 +254,21 @@ struct soc_device * __init at91_soc_init(const struct at91_soc *socs) return soc_dev; } +static const struct of_device_id at91_soc_allowed_list[] __initconst = { + { .compatible = "atmel,at91rm9200", }, + { .compatible = "atmel,at91sam9", }, + { .compatible = "atmel,sama5", }, + { .compatible = "atmel,samv7", }, + { } +}; + static int __init atmel_soc_device_init(void) { + struct device_node *np = of_find_node_by_path("/"); + + if (!of_match_node(at91_soc_allowed_list, np)) + return 0; + at91_soc_init(socs); return 0; diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index b60b77bfaffa..ea6f8904c01b 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -53,7 +53,6 @@ static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) struct dpio_priv *priv; int error; struct fsl_mc_device_irq *irq; - cpumask_t mask; priv = dev_get_drvdata(&dpio_dev->dev); @@ -72,9 +71,7 @@ static int register_dpio_irq_handlers(struct fsl_mc_device *dpio_dev, int cpu) } /* set the affinity hint */ - cpumask_clear(&mask); - cpumask_set_cpu(cpu, &mask); - if (irq_set_affinity_hint(irq->msi_desc->irq, &mask)) + if (irq_set_affinity_hint(irq->msi_desc->irq, cpumask_of(cpu))) dev_err(&dpio_dev->dev, "irq_set_affinity failed irq %d cpu %d\n", irq->msi_desc->irq, cpu); diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index a4ac6073c555..d7bf456fd10e 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -184,7 +184,7 @@ struct qm_eqcr_entry { __be32 tag; struct qm_fd fd; u8 __reserved3[32]; -} __packed; +} __packed __aligned(8); #define QM_EQCR_VERB_VBIT 0x80 #define QM_EQCR_VERB_CMD_MASK 0x61 /* but only one value; */ #define QM_EQCR_VERB_CMD_ENQUEUE 0x01 diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index 5b24bb4bfbf6..ef54f1638d20 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c @@ -454,6 +454,7 @@ static void mtk_register_power_domains(struct platform_device *pdev, for (i = 0; i < num; i++) { struct scp_domain *scpd = &scp->domains[i]; struct generic_pm_domain *genpd = &scpd->genpd; + bool on; /* * Initially turn on all domains to make the domains usable @@ -461,9 +462,9 @@ static void mtk_register_power_domains(struct platform_device *pdev, * software. The unused domains will be switched off during * late_init time. */ - genpd->power_on(genpd); + on = !WARN_ON(genpd->power_on(genpd) < 0); - pm_genpd_init(genpd, NULL, false); + pm_genpd_init(genpd, NULL, !on); } /* diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index b6067f7f227b..69ad22d828e5 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -407,7 +407,7 @@ config MSM_REMOTEQDSS /sys/class/remoteqdss. config MSM_TZ_SMMU - depends on ARCH_MSM8953 || ARCH_QCS405 || ARCH_MSM8917 + depends on ARCH_MSM8953 || ARCH_QCS405 || ARCH_MSM8917 || ARCH_MSM8937 bool "Helper functions for SMMU configuration through TZ" help Say 'Y' here for targets that need to call into TZ to configure diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c index 439df9208385..d5df086a32db 100644 --- a/drivers/soc/qcom/icnss.c +++ b/drivers/soc/qcom/icnss.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "icnss: " fmt @@ -1081,26 +1081,26 @@ static int icnss_driver_event_server_arrive(void *data) goto qmi_registered; } ignore_assert = true; - goto clear_server; + goto fail; } if (!penv->msa_va) { icnss_pr_err("Invalid MSA address\n"); ret = -EINVAL; - goto clear_server; + goto fail; } ret = wlfw_msa_mem_info_send_sync_msg(penv); if (ret < 0) { ignore_assert = true; - goto clear_server; + goto fail; } if (!test_bit(ICNSS_MSA0_ASSIGNED, &penv->state)) { ret = icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_WLAN_HW_RW); if (ret < 0) - goto clear_server; + goto fail; set_bit(ICNSS_MSA0_ASSIGNED, &penv->state); } @@ -1140,8 +1140,6 @@ static int icnss_driver_event_server_arrive(void *data) err_setup_msa: icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL); clear_bit(ICNSS_MSA0_ASSIGNED, &penv->state); -clear_server: - icnss_clear_server(penv); fail: ICNSS_ASSERT(ignore_assert); qmi_registered: @@ -4069,6 +4067,7 @@ static struct platform_driver icnss_driver = { .name = "icnss", .pm = &icnss_pm_ops, .of_match_table = icnss_dt_match, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index ca0703b26949..618f6d83b84d 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -566,7 +566,7 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, ret = icnss_hw_power_on(priv); if (ret) - goto clear_server; + goto fail; ret = wlfw_ind_register_send_sync_msg(priv); if (ret < 0) { @@ -654,8 +654,6 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, err_power_on: icnss_hw_power_off(priv); -clear_server: - icnss_clear_server(priv); fail: ICNSS_ASSERT(ignore_assert); qmi_registered: diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c index 524fb0c7f20e..4592bc8b8acf 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_adhoc.c @@ -18,6 +18,8 @@ #define NUM_LNODES 3 #define MAX_STR_CL 50 +#define DEBUG_REC_TRANSACTION 0 + struct bus_search_type { struct list_head link; struct list_head node_list; @@ -1241,7 +1243,8 @@ static int update_bw_adhoc(struct msm_bus_client_handle *cl, u64 ab, u64 ib) if (!strcmp(test_cl, cl->name)) log_transaction = true; - msm_bus_dbg_rec_transaction(cl, ab, ib); + if (DEBUG_REC_TRANSACTION) + msm_bus_dbg_rec_transaction(cl, ab, ib); if ((cl->cur_act_ib == ib) && (cl->cur_act_ab == ab)) { MSM_BUS_DBG("%s:no change in request", cl->name); @@ -1302,7 +1305,9 @@ static int update_bw_context(struct msm_bus_client_handle *cl, u64 act_ab, if (!slp_ab && !slp_ib) cl->active_only = true; - msm_bus_dbg_rec_transaction(cl, cl->cur_act_ab, cl->cur_dual_ib); + if (DEBUG_REC_TRANSACTION) + msm_bus_dbg_rec_transaction(cl, cl->cur_act_ab, + cl->cur_dual_ib); ret = update_path(cl->mas_dev, cl->slv, act_ib, act_ab, slp_ib, slp_ab, cl->cur_act_ab, cl->cur_act_ab, cl->first_hop, cl->active_only); diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c index e8797b5386ac..a25dbeb06b13 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c @@ -1323,8 +1323,7 @@ static uint32_t register_client_adhoc(struct msm_bus_scale_pdata *pdata) return handle; } -static int update_client_paths(struct msm_bus_client *client, bool log_trns, - unsigned int idx) +static int update_client_paths(struct msm_bus_client *client, unsigned int idx) { int lnode, src, dest, cur_idx; uint64_t req_clk, req_bw, curr_clk, curr_bw, slp_clk, slp_bw; @@ -1385,16 +1384,13 @@ static int update_client_paths(struct msm_bus_client *client, bool log_trns, goto exit_update_client_paths; } - if (log_trns) - getpath_debug(src, lnode, pdata->active_only); } commit_data(); exit_update_client_paths: return ret; } -static int update_client_alc(struct msm_bus_client *client, bool log_trns, - unsigned int idx) +static int update_client_alc(struct msm_bus_client *client, unsigned int idx) { int lnode, cur_idx; uint64_t req_idle_time, req_fal, dual_idle_time, dual_fal, @@ -1573,7 +1569,7 @@ static int update_context(uint32_t cl, bool active_only, pdata->active_only = active_only; msm_bus_dbg_client_data(client->pdata, ctx_idx, cl); - ret = update_client_paths(client, false, ctx_idx); + ret = update_client_paths(client, ctx_idx); if (ret) { pr_err("%s: Err updating path\n", __func__); goto exit_update_context; @@ -1591,8 +1587,6 @@ static int update_request_adhoc(uint32_t cl, unsigned int index) int ret = 0; struct msm_bus_scale_pdata *pdata; struct msm_bus_client *client; - const char *test_cl = "Null"; - bool log_transaction = false; mbus_rpmh_rt_mutex_lock(&msm_bus_adhoc_lock); @@ -1630,18 +1624,15 @@ static int update_request_adhoc(uint32_t cl, unsigned int index) goto exit_update_request; } - if (!strcmp(test_cl, pdata->name)) - log_transaction = true; - MSM_BUS_DBG("%s: cl: %u index: %d curr: %d num_paths: %d\n", __func__, cl, index, client->curr, client->pdata->usecase->num_paths); if (pdata->alc) - ret = update_client_alc(client, log_transaction, index); + ret = update_client_alc(client, index); else { if (!oops_in_progress) msm_bus_dbg_client_data(client->pdata, index, cl); - ret = update_client_paths(client, log_transaction, index); + ret = update_client_paths(client, index); } if (ret) { pr_err("%s: Err updating path\n", __func__); diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c index 3a48c03a8be7..1ae0c2df5c6d 100644 --- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c @@ -967,7 +967,7 @@ static int msm_bus_dev_init_qos(struct device *dev, void *data) goto exit_init_qos; } - if (node_dev->ap_owned) { + if (node_dev->ap_owned && node_dev->num_node_qos_clks) { struct msm_bus_node_device_type *bus_node_info; bus_node_info = diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index ee89ffb6dde8..7369b061929b 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -275,6 +275,7 @@ static void geni_se_select_fifo_mode(struct geni_se *se) static void geni_se_select_dma_mode(struct geni_se *se) { + u32 proto = geni_se_read_proto(se); u32 val; writel_relaxed(0, se->base + SE_GSI_EVENT_EN); @@ -284,6 +285,18 @@ static void geni_se_select_dma_mode(struct geni_se *se) writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR); writel_relaxed(0xffffffff, se->base + SE_IRQ_EN); + val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); + if (proto != GENI_SE_UART) { + val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN); + val &= ~(M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); + } + writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN); + + val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN); + if (proto != GENI_SE_UART) + val &= ~S_CMD_DONE_EN; + writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN); + val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); val |= GENI_DMA_MODE_EN; writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN); @@ -633,7 +646,7 @@ int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len, writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L); writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H); writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR); - writel_relaxed(len, se->base + SE_DMA_TX_LEN); + writel(len, se->base + SE_DMA_TX_LEN); return 0; } EXPORT_SYMBOL(geni_se_tx_dma_prep); @@ -667,7 +680,7 @@ int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len, writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H); /* RX does not have EOT buffer type bit. So just reset RX_ATTR */ writel_relaxed(0, se->base + SE_DMA_RX_ATTR); - writel_relaxed(len, se->base + SE_DMA_RX_LEN); + writel(len, se->base + SE_DMA_RX_LEN); return 0; } EXPORT_SYMBOL(geni_se_rx_dma_prep); diff --git a/drivers/soc/qcom/qmi_rmnet.c b/drivers/soc/qcom/qmi_rmnet.c index adef8129abcb..dc8d44ed63a8 100644 --- a/drivers/soc/qcom/qmi_rmnet.c +++ b/drivers/soc/qcom/qmi_rmnet.c @@ -14,7 +14,6 @@ #include #include #include -#include #define NLMSG_FLOW_ACTIVATE 1 #define NLMSG_FLOW_DEACTIVATE 2 @@ -45,7 +44,6 @@ unsigned int rmnet_wq_frequency __read_mostly = 1000; #define PS_INTERVAL (((!rmnet_wq_frequency) ? \ 1 : rmnet_wq_frequency/10) * (HZ/100)) #define NO_DELAY (0x0000 * HZ) -#define PS_INTERVAL_KT (ms_to_ktime(1000)) #define WATCHDOG_EXPIRE_JF (msecs_to_jiffies(50)) #ifdef CONFIG_QCOM_QMI_DFC @@ -1052,7 +1050,6 @@ static LIST_HEAD(ps_list); struct rmnet_powersave_work { struct delayed_work work; - struct alarm atimer; void *port; u64 old_rx_pkts; u64 old_tx_pkts; @@ -1137,16 +1134,6 @@ static void qmi_rmnet_work_restart(void *port) rcu_read_unlock(); } -static enum alarmtimer_restart qmi_rmnet_work_alarm(struct alarm *atimer, - ktime_t now) -{ - struct rmnet_powersave_work *real_work; - - real_work = container_of(atimer, struct rmnet_powersave_work, atimer); - qmi_rmnet_work_restart(real_work->port); - return ALARMTIMER_NORESTART; -} - static void qmi_rmnet_check_stats(struct work_struct *work) { struct rmnet_powersave_work *real_work; @@ -1154,7 +1141,6 @@ static void qmi_rmnet_check_stats(struct work_struct *work) u64 rxd, txd; u64 rx, tx; bool dl_msg_active; - bool use_alarm_timer = true; real_work = container_of(to_delayed_work(work), struct rmnet_powersave_work, work); @@ -1200,10 +1186,8 @@ static void qmi_rmnet_check_stats(struct work_struct *work) * (likely in RLF), no need to enter powersave */ if (!dl_msg_active && - !rmnet_all_flows_enabled(real_work->port)) { - use_alarm_timer = false; + !rmnet_all_flows_enabled(real_work->port)) goto end; - } /* Deregister to suppress QMI DFC and DL marker */ if (qmi_rmnet_set_powersave_mode(real_work->port, 1) < 0) @@ -1227,14 +1211,8 @@ static void qmi_rmnet_check_stats(struct work_struct *work) } end: rcu_read_lock(); - if (!rmnet_work_quit) { - if (use_alarm_timer) - alarm_start_relative(&real_work->atimer, - PS_INTERVAL_KT); - else - queue_delayed_work(rmnet_ps_wq, &real_work->work, - PS_INTERVAL); - } + if (!rmnet_work_quit) + queue_delayed_work(rmnet_ps_wq, &real_work->work, PS_INTERVAL); rcu_read_unlock(); } @@ -1257,8 +1235,7 @@ void qmi_rmnet_work_init(void *port) if (rmnet_ps_wq) return; - rmnet_ps_wq = alloc_workqueue("rmnet_powersave_work", - WQ_CPU_INTENSIVE, 1); + rmnet_ps_wq = create_freezable_workqueue("rmnet_powersave_work"); if (!rmnet_ps_wq) return; @@ -1270,7 +1247,6 @@ void qmi_rmnet_work_init(void *port) return; } INIT_DEFERRABLE_WORK(&rmnet_work->work, qmi_rmnet_check_stats); - alarm_init(&rmnet_work->atimer, ALARM_BOOTTIME, qmi_rmnet_work_alarm); rmnet_work->port = port; rmnet_get_packets(rmnet_work->port, &rmnet_work->old_rx_pkts, &rmnet_work->old_tx_pkts); @@ -1304,7 +1280,6 @@ void qmi_rmnet_work_exit(void *port) synchronize_rcu(); rmnet_work_inited = false; - alarm_cancel(&rmnet_work->atimer); cancel_delayed_work_sync(&rmnet_work->work); destroy_workqueue(rmnet_ps_wq); qmi_rmnet_work_set_active(port, 0); diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 724614151b39..0c5b4e83d345 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -477,13 +477,10 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) do { ret = tcs_write(drv, msg); if (ret == -EBUSY) { - pr_info_ratelimited("DRV:%s TCS Busy, retrying RPMH message send: addr=%#x\n", - drv->name, msg->cmds[0].addr); udelay(10); count++; } if ((count == 50000) && (in_long_press)) { - printk(KERN_ERR "Long Press :TCS Busy but log saved!"); break; } @@ -699,11 +696,11 @@ static void print_tcs_info(struct rsc_drv *drv, int tcs_id, unsigned long *accl) data = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, 0); irq_sts = read_tcs_reg(drv, RSC_DRV_IRQ_STATUS, 0, 0); - pr_warn("Request: tcs-in-use:%s active_tcs=%s(%d) state=%d wait_for_compl=%u]\n", + pr_debug("Request: tcs-in-use:%s active_tcs=%s(%d) state=%d wait_for_compl=%u]\n", (in_use ? "YES" : "NO"), ((tcs_grp->type == ACTIVE_TCS) ? "YES" : "NO"), tcs_grp->type, req->state, req->wait_for_compl); - pr_warn("TCS=%d [ctrlr-sts:%s amc-mode:0x%x irq-sts:%s]\n", + pr_debug("TCS=%d [ctrlr-sts:%s amc-mode:0x%x irq-sts:%s]\n", tcs_id, sts ? "IDLE" : "BUSY", data, (irq_sts & BIT(tcs_id)) ? "COMPLETED" : "PENDING"); @@ -712,7 +709,7 @@ static void print_tcs_info(struct rsc_drv *drv, int tcs_id, unsigned long *accl) data = read_tcs_reg(drv, RSC_DRV_CMD_DATA, tcs_id, i); msgid = read_tcs_reg(drv, RSC_DRV_CMD_MSGID, tcs_id, i); sts = read_tcs_reg(drv, RSC_DRV_CMD_STATUS, tcs_id, i); - pr_warn("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x enabled=1]\n", + pr_debug("\tCMD=%d [addr=0x%x data=0x%x hdr=0x%x sts=0x%x enabled=1]\n", i, addr, data, msgid, sts); if (!(sts & CMD_STATUS_ISSUED)) continue; @@ -730,7 +727,7 @@ void rpmh_rsc_debug(struct rsc_drv *drv, struct completion *compl) unsigned long accl = 0; char str[20] = ""; - pr_warn("RSC:%s\n", drv->name); + pr_debug("RSC:%s\n", drv->name); for (i = 0; i < drv->num_tcs; i++) { if (!test_bit(i, drv->tcs_in_use)) @@ -745,9 +742,9 @@ void rpmh_rsc_debug(struct rsc_drv *drv, struct completion *compl) } irq_get_irqchip_state(drv->irq, IRQCHIP_STATE_PENDING, &irq_sts); - pr_warn("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq, + pr_debug("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq, irq_sts ? "PENDING" : "NOT PENDING"); - pr_warn("Completion is %s to finish\n", + pr_debug("Completion is %s to finish\n", completion_done(compl) ? "PENDING" : "NOT PENDING"); for_each_set_bit(i, &accl, ARRAY_SIZE(accl_str)) { @@ -756,10 +753,10 @@ void rpmh_rsc_debug(struct rsc_drv *drv, struct completion *compl) } if (busy && !irq_sts) - pr_warn("ERROR:Accelerator(s) { %s } at AOSS did not respond\n", + pr_debug("ERROR:Accelerator(s) { %s } at AOSS did not respond\n", str); else if (irq_sts) - pr_warn("ERROR:Possible lockup in Linux\n"); + pr_debug("ERROR:Possible lockup in Linux\n"); /* * The TCS(s) are busy waiting, we have no way to recover from this. diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c index bff6cdc9431d..35f9dab99386 100644 --- a/drivers/soc/qcom/scm.c +++ b/drivers/soc/qcom/scm.c @@ -28,6 +28,7 @@ #define SCM_INTERRUPTED 1 #define SCM_V2_EBUSY -12 +static atomic_t scm_call_count = ATOMIC_INIT(0); static DEFINE_MUTEX(scm_lock); /* @@ -94,7 +95,7 @@ static int scm_remap_error(int err) #ifdef CONFIG_ARM64 -static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, +static int ___scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, u64 *ret1, u64 *ret2, u64 *ret3) { register u64 r0 asm("x0") = x0; @@ -143,7 +144,19 @@ static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, return r0; } -static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, +static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, + u64 *ret1, u64 *ret2, u64 *ret3) +{ + int ret; + + atomic_inc(&scm_call_count); + ret = ___scm_call_armv8_64(x0, x1, x2, x3, x4, x5, ret1, ret2, ret3); + atomic_dec(&scm_call_count); + + return ret; +} + +static int ___scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, u64 *ret1, u64 *ret2, u64 *ret3) { register u32 r0 asm("w0") = w0; @@ -193,6 +206,18 @@ static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, return r0; } +static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, + u64 *ret1, u64 *ret2, u64 *ret3) +{ + int ret; + + atomic_inc(&scm_call_count); + ret = ___scm_call_armv8_32(w0, w1, w2, w3, w4, w5, ret1, ret2, ret3); + atomic_dec(&scm_call_count); + + return ret; +} + #else static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, @@ -243,6 +268,18 @@ static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, return r0; } +static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, + u64 *ret1, u64 *ret2, u64 *ret3) +{ + int ret; + + atomic_inc(&scm_call_count); + ret = ___scm_call_armv8_32(w0, w1, w2, w3, w4, w5, ret1, ret2, ret3); + atomic_dec(&scm_call_count); + + return ret; +} + static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, u64 *ret1, u64 *ret2, u64 *ret3) { @@ -700,3 +737,8 @@ early_initcall(scm_mem_protection_init); #endif #endif + +bool under_scm_call(void) +{ + return atomic_read(&scm_call_count); +} diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index 19c47078881a..949396b05eab 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -668,7 +668,7 @@ static int qcom_smp2p_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, smp2p->irq, qcom_smp2p_isr, qcom_smp2p_intr, - IRQF_NO_SUSPEND | IRQF_ONESHOT, + IRQF_ONESHOT, "smp2p", (void *)smp2p); if (ret) { dev_err(&pdev->dev, "failed to request interrupt\n"); diff --git a/drivers/soc/qcom/smp2p_sleepstate.c b/drivers/soc/qcom/smp2p_sleepstate.c index eeae932ab91e..314d5641015c 100644 --- a/drivers/soc/qcom/smp2p_sleepstate.c +++ b/drivers/soc/qcom/smp2p_sleepstate.c @@ -1,6 +1,15 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. */ #include #include @@ -11,6 +20,7 @@ #include #include #include +#include #define PROC_AWAKE_ID 12 /* 12th bit */ #define AWAKE_BIT BIT(PROC_AWAKE_ID) @@ -32,6 +42,7 @@ static int sleepstate_pm_notifier(struct notifier_block *nb, switch (event) { case PM_SUSPEND_PREPARE: qcom_smem_state_update_bits(state, AWAKE_BIT, 0); + usleep_range(10000, 10500); /* Tuned based on SMP2P latencies */ break; case PM_POST_SUSPEND: diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c index 5373f4c16b54..4403b89561fd 100644 --- a/drivers/soc/tegra/fuse/speedo-tegra210.c +++ b/drivers/soc/tegra/fuse/speedo-tegra210.c @@ -105,7 +105,7 @@ static int get_process_id(int value, const u32 *speedos, unsigned int num) unsigned int i; for (i = 0; i < num; i++) - if (value < speedos[num]) + if (value < speedos[i]) return i; return -EINVAL; diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index 224d7ddeeb76..eb2e87229c1d 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -759,8 +759,9 @@ static int knav_dma_probe(struct platform_device *pdev) pm_runtime_enable(kdev->dev); ret = pm_runtime_get_sync(kdev->dev); if (ret < 0) { + pm_runtime_put_noidle(kdev->dev); dev_err(kdev->dev, "unable to enable pktdma, err %d\n", ret); - return ret; + goto err_pm_disable; } /* Initialise all packet dmas */ @@ -774,7 +775,8 @@ static int knav_dma_probe(struct platform_device *pdev) if (list_empty(&kdev->list)) { dev_err(dev, "no valid dma instance\n"); - return -ENODEV; + ret = -ENODEV; + goto err_put_sync; } debugfs_create_file("knav_dma", S_IFREG | S_IRUGO, NULL, NULL, @@ -782,6 +784,13 @@ static int knav_dma_probe(struct platform_device *pdev) device_ready = true; return ret; + +err_put_sync: + pm_runtime_put_sync(kdev->dev); +err_pm_disable: + pm_runtime_disable(kdev->dev); + + return ret; } static int knav_dma_remove(struct platform_device *pdev) diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index ef36acc0e708..9f5ce52e6c16 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -1799,6 +1799,7 @@ static int knav_queue_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); dev_err(dev, "Failed to enable QMSS\n"); return ret; } @@ -1866,9 +1867,10 @@ static int knav_queue_probe(struct platform_device *pdev) if (ret) goto err; - regions = of_get_child_by_name(node, "descriptor-regions"); + regions = of_get_child_by_name(node, "descriptor-regions"); if (!regions) { dev_err(dev, "descriptor-regions not specified\n"); + ret = -ENODEV; goto err; } ret = knav_queue_setup_regions(kdev, regions); diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 5a9d7e252a77..2254e36c7f46 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1605,7 +1605,7 @@ static int atmel_spi_probe(struct platform_device *pdev) if (ret == 0) { as->use_dma = true; } else if (ret == -EPROBE_DEFER) { - return ret; + goto out_unmap_regs; } } else if (as->caps.has_pdc_support) { as->use_pdc = true; diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 2145a70dac69..4ee92f7ca20b 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1223,7 +1223,7 @@ int bcm_qspi_probe(struct platform_device *pdev, if (!of_match_node(bcm_qspi_of_match, dev->of_node)) return -ENODEV; - master = spi_alloc_master(dev, sizeof(struct bcm_qspi)); + master = devm_spi_alloc_master(dev, sizeof(struct bcm_qspi)); if (!master) { dev_err(dev, "error allocating spi_master\n"); return -ENOMEM; @@ -1257,21 +1257,17 @@ int bcm_qspi_probe(struct platform_device *pdev, if (res) { qspi->base[MSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[MSPI])) { - ret = PTR_ERR(qspi->base[MSPI]); - goto qspi_resource_err; - } + if (IS_ERR(qspi->base[MSPI])) + return PTR_ERR(qspi->base[MSPI]); } else { - goto qspi_resource_err; + return 0; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); if (res) { qspi->base[BSPI] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[BSPI])) { - ret = PTR_ERR(qspi->base[BSPI]); - goto qspi_resource_err; - } + if (IS_ERR(qspi->base[BSPI])) + return PTR_ERR(qspi->base[BSPI]); qspi->bspi_mode = true; } else { qspi->bspi_mode = false; @@ -1282,18 +1278,14 @@ int bcm_qspi_probe(struct platform_device *pdev, res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cs_reg"); if (res) { qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); - if (IS_ERR(qspi->base[CHIP_SELECT])) { - ret = PTR_ERR(qspi->base[CHIP_SELECT]); - goto qspi_resource_err; - } + if (IS_ERR(qspi->base[CHIP_SELECT])) + return PTR_ERR(qspi->base[CHIP_SELECT]); } qspi->dev_ids = kcalloc(num_irqs, sizeof(struct bcm_qspi_dev_id), GFP_KERNEL); - if (!qspi->dev_ids) { - ret = -ENOMEM; - goto qspi_resource_err; - } + if (!qspi->dev_ids) + return -ENOMEM; for (val = 0; val < num_irqs; val++) { irq = -1; @@ -1369,7 +1361,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->xfer_mode.addrlen = -1; qspi->xfer_mode.hp = -1; - ret = devm_spi_register_master(&pdev->dev, master); + ret = spi_register_master(master); if (ret < 0) { dev_err(dev, "can't register master\n"); goto qspi_reg_err; @@ -1382,8 +1374,6 @@ int bcm_qspi_probe(struct platform_device *pdev, clk_disable_unprepare(qspi->clk); qspi_probe_err: kfree(qspi->dev_ids); -qspi_resource_err: - spi_master_put(master); return ret; } /* probe function to be called by SoC specific platform driver probe */ @@ -1393,10 +1383,10 @@ int bcm_qspi_remove(struct platform_device *pdev) { struct bcm_qspi *qspi = platform_get_drvdata(pdev); + spi_unregister_master(qspi->master); bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); kfree(qspi->dev_ids); - spi_unregister_master(qspi->master); return 0; } diff --git a/drivers/spi/spi-bcm2835.c b/drivers/spi/spi-bcm2835.c index df6abc75bc16..6824beae18e4 100644 --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -737,7 +737,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev) struct resource *res; int err; - master = spi_alloc_master(&pdev->dev, sizeof(*bs)); + master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs)); if (!master) { dev_err(&pdev->dev, "spi_alloc_master() failed\n"); return -ENOMEM; @@ -759,23 +759,20 @@ static int bcm2835_spi_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); bs->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(bs->regs)) { - err = PTR_ERR(bs->regs); - goto out_master_put; - } + if (IS_ERR(bs->regs)) + return PTR_ERR(bs->regs); bs->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(bs->clk)) { err = PTR_ERR(bs->clk); dev_err(&pdev->dev, "could not get clk: %d\n", err); - goto out_master_put; + return err; } bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); - err = bs->irq ? bs->irq : -ENODEV; - goto out_master_put; + return bs->irq ? bs->irq : -ENODEV; } clk_prepare_enable(bs->clk); @@ -790,21 +787,20 @@ static int bcm2835_spi_probe(struct platform_device *pdev) dev_name(&pdev->dev), master); if (err) { dev_err(&pdev->dev, "could not request IRQ: %d\n", err); - goto out_clk_disable; + goto out_dma_release; } err = spi_register_master(master); if (err) { dev_err(&pdev->dev, "could not register SPI master: %d\n", err); - goto out_clk_disable; + goto out_dma_release; } return 0; -out_clk_disable: +out_dma_release: + bcm2835_dma_release(master); clk_disable_unprepare(bs->clk); -out_master_put: - spi_master_put(master); return err; } diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 11895c98aae3..8ea7e31b8c2f 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -407,7 +407,7 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) unsigned long clk_hz; int err; - master = spi_alloc_master(&pdev->dev, sizeof(*bs)); + master = devm_spi_alloc_master(&pdev->dev, sizeof(*bs)); if (!master) { dev_err(&pdev->dev, "spi_alloc_master() failed\n"); return -ENOMEM; @@ -439,30 +439,27 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) /* the main area */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); bs->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(bs->regs)) { - err = PTR_ERR(bs->regs); - goto out_master_put; - } + if (IS_ERR(bs->regs)) + return PTR_ERR(bs->regs); bs->clk = devm_clk_get(&pdev->dev, NULL); if ((!bs->clk) || (IS_ERR(bs->clk))) { err = PTR_ERR(bs->clk); dev_err(&pdev->dev, "could not get clk: %d\n", err); - goto out_master_put; + return err; } bs->irq = platform_get_irq(pdev, 0); if (bs->irq <= 0) { dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq); - err = bs->irq ? bs->irq : -ENODEV; - goto out_master_put; + return bs->irq ? bs->irq : -ENODEV; } /* this also enables the HW block */ err = clk_prepare_enable(bs->clk); if (err) { dev_err(&pdev->dev, "could not prepare clock: %d\n", err); - goto out_master_put; + return err; } /* just checking if the clock returns a sane value */ @@ -495,8 +492,6 @@ static int bcm2835aux_spi_probe(struct platform_device *pdev) out_clk_disable: clk_disable_unprepare(bs->clk); -out_master_put: - spi_master_put(master); return err; } diff --git a/drivers/spi/spi-bcm63xx-hsspi.c b/drivers/spi/spi-bcm63xx-hsspi.c index 1669c554ea34..2ad7b3f3666b 100644 --- a/drivers/spi/spi-bcm63xx-hsspi.c +++ b/drivers/spi/spi-bcm63xx-hsspi.c @@ -487,8 +487,10 @@ static int bcm63xx_hsspi_resume(struct device *dev) if (bs->pll_clk) { ret = clk_prepare_enable(bs->pll_clk); - if (ret) + if (ret) { + clk_disable_unprepare(bs->clk); return ret; + } } spi_master_resume(master); diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 94cc0a152449..f5055ceb7529 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -119,6 +119,7 @@ struct cdns_spi { void __iomem *regs; struct clk *ref_clk; struct clk *pclk; + unsigned int clk_rate; u32 speed_hz; const u8 *txbuf; u8 *rxbuf; @@ -258,7 +259,7 @@ static void cdns_spi_config_clock_freq(struct spi_device *spi, u32 ctrl_reg, baud_rate_val; unsigned long frequency; - frequency = clk_get_rate(xspi->ref_clk); + frequency = xspi->clk_rate; ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR); @@ -628,8 +629,9 @@ static int cdns_spi_probe(struct platform_device *pdev) master->auto_runtime_pm = true; master->mode_bits = SPI_CPOL | SPI_CPHA; + xspi->clk_rate = clk_get_rate(xspi->ref_clk); /* Set to default valid value */ - master->max_speed_hz = clk_get_rate(xspi->ref_clk) / 4; + master->max_speed_hz = xspi->clk_rate / 4; xspi->speed_hz = master->max_speed_hz; master->bits_per_word_mask = SPI_BPW_MASK(8); diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index a02099c90c5c..b56038945f41 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -1086,13 +1086,13 @@ static int davinci_spi_remove(struct platform_device *pdev) spi_bitbang_stop(&dspi->bitbang); clk_disable_unprepare(dspi->clk); - spi_master_put(master); if (dspi->dma_rx) { dma_release_channel(dspi->dma_rx); dma_release_channel(dspi->dma_tx); } + spi_master_put(master); return 0; } diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index 3a3e325da975..6af2c50f1473 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -195,6 +195,13 @@ static inline void spi_geni_clk_conf(struct spi_geni_master *mas, mb(); } +int geni_spi_get_master_irq(struct spi_device *spi_slv) +{ + struct spi_geni_master *mas = spi_master_get_devdata(spi_slv->master); + + return mas->irq; +} + static int get_spi_clk_cfg(u32 speed_hz, struct spi_geni_master *mas, int *clk_idx, int *clk_div) { diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index e4b31d6e6e33..25a545c985d4 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -774,8 +774,10 @@ static int img_spfi_resume(struct device *dev) int ret; ret = pm_runtime_get_sync(dev); - if (ret) + if (ret) { + pm_runtime_put_noidle(dev); return ret; + } spfi_reset(spfi); pm_runtime_put(dev); diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 6ac95a2a21ce..4a7375ecb65e 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -605,6 +605,7 @@ static int mxs_spi_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(ssp->dev); if (ret < 0) { + pm_runtime_put_noidle(ssp->dev); dev_err(ssp->dev, "runtime_get_sync failed\n"); goto out_pm_runtime_disable; } diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 288002f6c613..661a40c653e9 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -839,6 +839,7 @@ static int pic32_spi_probe(struct platform_device *pdev) return 0; err_bailout: + pic32_spi_dma_unprep(pic32s); clk_disable_unprepare(pic32s->clk); err_master: spi_master_put(master); diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c index 869f188b02eb..1736a48bbcce 100644 --- a/drivers/spi/spi-pxa2xx-pci.c +++ b/drivers/spi/spi-pxa2xx-pci.c @@ -21,7 +21,8 @@ enum { PORT_BSW1, PORT_BSW2, PORT_CE4100, - PORT_LPT, + PORT_LPT0, + PORT_LPT1, }; struct pxa_spi_info { @@ -55,8 +56,10 @@ static struct dw_dma_slave bsw1_rx_param = { .src_id = 7 }; static struct dw_dma_slave bsw2_tx_param = { .dst_id = 8 }; static struct dw_dma_slave bsw2_rx_param = { .src_id = 9 }; -static struct dw_dma_slave lpt_tx_param = { .dst_id = 0 }; -static struct dw_dma_slave lpt_rx_param = { .src_id = 1 }; +static struct dw_dma_slave lpt1_tx_param = { .dst_id = 0 }; +static struct dw_dma_slave lpt1_rx_param = { .src_id = 1 }; +static struct dw_dma_slave lpt0_tx_param = { .dst_id = 2 }; +static struct dw_dma_slave lpt0_rx_param = { .src_id = 3 }; static bool lpss_dma_filter(struct dma_chan *chan, void *param) { @@ -182,12 +185,19 @@ static struct pxa_spi_info spi_info_configs[] = { .num_chipselect = 1, .max_clk_rate = 50000000, }, - [PORT_LPT] = { + [PORT_LPT0] = { .type = LPSS_LPT_SSP, .port_id = 0, .setup = lpss_spi_setup, - .tx_param = &lpt_tx_param, - .rx_param = &lpt_rx_param, + .tx_param = &lpt0_tx_param, + .rx_param = &lpt0_rx_param, + }, + [PORT_LPT1] = { + .type = LPSS_LPT_SSP, + .port_id = 1, + .setup = lpss_spi_setup, + .tx_param = &lpt1_tx_param, + .rx_param = &lpt1_rx_param, }, }; @@ -281,8 +291,9 @@ static const struct pci_device_id pxa2xx_spi_pci_devices[] = { { PCI_VDEVICE(INTEL, 0x2290), PORT_BSW1 }, { PCI_VDEVICE(INTEL, 0x22ac), PORT_BSW2 }, { PCI_VDEVICE(INTEL, 0x2e6a), PORT_CE4100 }, - { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT }, - { }, + { PCI_VDEVICE(INTEL, 0x9ce5), PORT_LPT0 }, + { PCI_VDEVICE(INTEL, 0x9ce6), PORT_LPT1 }, + { } }; MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index eafd0c2135a1..a889505e978b 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -1572,7 +1572,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) return -ENODEV; } - master = spi_alloc_master(dev, sizeof(struct driver_data)); + master = devm_spi_alloc_master(dev, sizeof(*drv_data)); if (!master) { dev_err(&pdev->dev, "cannot alloc spi_master\n"); pxa_ssp_free(ssp); @@ -1759,7 +1759,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) free_irq(ssp->irq, drv_data); out_error_master_alloc: - spi_controller_put(master); pxa_ssp_free(ssp); return status; } diff --git a/drivers/spi/spi-rb4xx.c b/drivers/spi/spi-rb4xx.c index 3641d0e20135..1d7fd6dbaf87 100644 --- a/drivers/spi/spi-rb4xx.c +++ b/drivers/spi/spi-rb4xx.c @@ -148,7 +148,7 @@ static int rb4xx_spi_probe(struct platform_device *pdev) if (IS_ERR(spi_base)) return PTR_ERR(spi_base); - master = spi_alloc_master(&pdev->dev, sizeof(*rbspi)); + master = devm_spi_alloc_master(&pdev->dev, sizeof(*rbspi)); if (!master) return -ENOMEM; diff --git a/drivers/spi/spi-s3c24xx-fiq.S b/drivers/spi/spi-s3c24xx-fiq.S index 059f2dc1fda2..1565c792da07 100644 --- a/drivers/spi/spi-s3c24xx-fiq.S +++ b/drivers/spi/spi-s3c24xx-fiq.S @@ -36,7 +36,6 @@ @ and an offset to the irq acknowledgment word ENTRY(s3c24xx_spi_fiq_rx) -s3c24xx_spi_fix_rx: .word fiq_rx_end - fiq_rx_start .word fiq_rx_irq_ack - fiq_rx_start fiq_rx_start: @@ -50,7 +49,7 @@ fiq_rx_start: strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ] subs fiq_rcount, fiq_rcount, #1 - subnes pc, lr, #4 @@ return, still have work to do + subsne pc, lr, #4 @@ return, still have work to do @@ set IRQ controller so that next op will trigger IRQ mov fiq_rtmp, #0 @@ -62,7 +61,6 @@ fiq_rx_irq_ack: fiq_rx_end: ENTRY(s3c24xx_spi_fiq_txrx) -s3c24xx_spi_fiq_txrx: .word fiq_txrx_end - fiq_txrx_start .word fiq_txrx_irq_ack - fiq_txrx_start fiq_txrx_start: @@ -77,7 +75,7 @@ fiq_txrx_start: strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ] subs fiq_rcount, fiq_rcount, #1 - subnes pc, lr, #4 @@ return, still have work to do + subsne pc, lr, #4 @@ return, still have work to do mov fiq_rtmp, #0 str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ] @@ -89,7 +87,6 @@ fiq_txrx_irq_ack: fiq_txrx_end: ENTRY(s3c24xx_spi_fiq_tx) -s3c24xx_spi_fix_tx: .word fiq_tx_end - fiq_tx_start .word fiq_tx_irq_ack - fiq_tx_start fiq_tx_start: @@ -102,7 +99,7 @@ fiq_tx_start: strb fiq_rtmp, [ fiq_rspi, # S3C2410_SPTDAT ] subs fiq_rcount, fiq_rcount, #1 - subnes pc, lr, #4 @@ return, still have work to do + subsne pc, lr, #4 @@ return, still have work to do mov fiq_rtmp, #0 str fiq_rtmp, [ fiq_rirq, # S3C2410_INTMOD - S3C24XX_VA_IRQ ] diff --git a/drivers/spi/spi-sc18is602.c b/drivers/spi/spi-sc18is602.c index 52cf0e9189c2..64cf1f572b6d 100644 --- a/drivers/spi/spi-sc18is602.c +++ b/drivers/spi/spi-sc18is602.c @@ -248,13 +248,12 @@ static int sc18is602_probe(struct i2c_client *client, struct sc18is602_platform_data *pdata = dev_get_platdata(dev); struct sc18is602 *hw; struct spi_master *master; - int error; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) return -EINVAL; - master = spi_alloc_master(dev, sizeof(struct sc18is602)); + master = devm_spi_alloc_master(dev, sizeof(struct sc18is602)); if (!master) return -ENOMEM; @@ -308,15 +307,7 @@ static int sc18is602_probe(struct i2c_client *client, master->min_speed_hz = hw->freq / 128; master->max_speed_hz = hw->freq / 4; - error = devm_spi_register_master(dev, master); - if (error) - goto error_reg; - - return 0; - -error_reg: - spi_master_put(master); - return error; + return devm_spi_register_master(dev, master); } static const struct i2c_device_id sc18is602_id[] = { diff --git a/drivers/spi/spi-sh.c b/drivers/spi/spi-sh.c index 50e0ea9acf8b..cba49a65ed2b 100644 --- a/drivers/spi/spi-sh.c +++ b/drivers/spi/spi-sh.c @@ -450,7 +450,7 @@ static int spi_sh_probe(struct platform_device *pdev) return irq; } - master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); + master = devm_spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data)); if (master == NULL) { dev_err(&pdev->dev, "spi_alloc_master error.\n"); return -ENOMEM; @@ -468,16 +468,14 @@ static int spi_sh_probe(struct platform_device *pdev) break; default: dev_err(&pdev->dev, "No support width\n"); - ret = -ENODEV; - goto error1; + return -ENODEV; } ss->irq = irq; ss->master = master; ss->addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (ss->addr == NULL) { dev_err(&pdev->dev, "ioremap error.\n"); - ret = -ENOMEM; - goto error1; + return -ENOMEM; } INIT_LIST_HEAD(&ss->queue); spin_lock_init(&ss->lock); @@ -487,7 +485,7 @@ static int spi_sh_probe(struct platform_device *pdev) ret = request_irq(irq, spi_sh_irq, 0, "spi_sh", ss); if (ret < 0) { dev_err(&pdev->dev, "request_irq error\n"); - goto error1; + return ret; } master->num_chipselect = 2; @@ -506,9 +504,6 @@ static int spi_sh_probe(struct platform_device *pdev) error3: free_irq(irq, ss); - error1: - spi_master_put(master); - return ret; } diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index 5df01ffdef46..b46502db7f12 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -379,13 +379,14 @@ static int spi_st_probe(struct platform_device *pdev) ret = devm_spi_register_master(&pdev->dev, master); if (ret) { dev_err(&pdev->dev, "Failed to register master\n"); - goto clk_disable; + goto rpm_disable; } return 0; -clk_disable: +rpm_disable: pm_runtime_disable(&pdev->dev); +clk_disable: clk_disable_unprepare(spi_st->clk); put_master: spi_master_put(master); diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 391a20b3d2fd..8d692f16d90a 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -299,9 +299,9 @@ static u32 stm32_spi_prepare_fthlv(struct stm32_spi *spi) /* align packet size with data registers access */ if (spi->cur_bpw > 8) - fthlv -= (fthlv % 2); /* multiple of 2 */ + fthlv += (fthlv % 2) ? 1 : 0; else - fthlv -= (fthlv % 4); /* multiple of 4 */ + fthlv += (fthlv % 4) ? (4 - (fthlv % 4)) : 0; return fthlv; } @@ -992,6 +992,10 @@ static int stm32_spi_transfer_one(struct spi_master *master, struct stm32_spi *spi = spi_master_get_devdata(master); int ret; + /* Don't do anything on 0 bytes transfers */ + if (transfer->len == 0) + return 0; + spi->tx_buf = transfer->tx_buf; spi->rx_buf = transfer->rx_buf; spi->tx_len = spi->tx_buf ? transfer->len : 0; diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 09cfae3abce2..c510b53e5e3f 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -827,6 +827,7 @@ static int tegra_spi_setup(struct spi_device *spi) ret = pm_runtime_get_sync(tspi->dev); if (ret < 0) { + pm_runtime_put_noidle(tspi->dev); dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret); return ret; } @@ -1252,6 +1253,7 @@ static int tegra_spi_resume(struct device *dev) ret = pm_runtime_get_sync(dev); if (ret < 0) { + pm_runtime_put_noidle(dev); dev_err(dev, "pm runtime failed, e = %d\n", ret); return ret; } diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index 22893a7e0aa0..749288310c36 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -564,6 +564,7 @@ static int tegra_sflash_resume(struct device *dev) ret = pm_runtime_get_sync(dev); if (ret < 0) { + pm_runtime_put_noidle(dev); dev_err(dev, "pm runtime failed, e = %d\n", ret); return ret; } diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index d1187317bb5d..c6b80a60951b 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c @@ -761,6 +761,7 @@ static int tegra_slink_setup(struct spi_device *spi) ret = pm_runtime_get_sync(tspi->dev); if (ret < 0) { + pm_runtime_put_noidle(tspi->dev); dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret); return ret; } @@ -1197,6 +1198,7 @@ static int tegra_slink_resume(struct device *dev) ret = pm_runtime_get_sync(dev); if (ret < 0) { + pm_runtime_put_noidle(dev); dev_err(dev, "pm runtime failed, e = %d\n", ret); return ret; } diff --git a/drivers/spi/spi-ti-qspi.c b/drivers/spi/spi-ti-qspi.c index 95c28abaa027..73a08724034b 100644 --- a/drivers/spi/spi-ti-qspi.c +++ b/drivers/spi/spi-ti-qspi.c @@ -183,6 +183,7 @@ static int ti_qspi_setup(struct spi_device *spi) ret = pm_runtime_get_sync(qspi->dev); if (ret < 0) { + pm_runtime_put_noidle(qspi->dev); dev_err(qspi->dev, "pm_runtime_get_sync() failed\n"); return ret; } diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 1fd529a2d2f6..7dabbc82b646 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -362,9 +362,11 @@ static int spi_drv_probe(struct device *dev) if (ret) return ret; - ret = sdrv->probe(spi); - if (ret) - dev_pm_domain_detach(dev, true); + if (sdrv->probe) { + ret = sdrv->probe(spi); + if (ret) + dev_pm_domain_detach(dev, true); + } return ret; } @@ -372,9 +374,10 @@ static int spi_drv_probe(struct device *dev) static int spi_drv_remove(struct device *dev) { const struct spi_driver *sdrv = to_spi_driver(dev->driver); - int ret; + int ret = 0; - ret = sdrv->remove(to_spi_device(dev)); + if (sdrv->remove) + ret = sdrv->remove(to_spi_device(dev)); dev_pm_domain_detach(dev, true); return ret; @@ -399,10 +402,8 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) { sdrv->driver.owner = owner; sdrv->driver.bus = &spi_bus_type; - if (sdrv->probe) - sdrv->driver.probe = spi_drv_probe; - if (sdrv->remove) - sdrv->driver.remove = spi_drv_remove; + sdrv->driver.probe = spi_drv_probe; + sdrv->driver.remove = spi_drv_remove; if (sdrv->shutdown) sdrv->driver.shutdown = spi_drv_shutdown; return driver_register(&sdrv->driver); @@ -2050,6 +2051,49 @@ struct spi_controller *__spi_alloc_controller(struct device *dev, } EXPORT_SYMBOL_GPL(__spi_alloc_controller); +static void devm_spi_release_controller(struct device *dev, void *ctlr) +{ + spi_controller_put(*(struct spi_controller **)ctlr); +} + +/** + * __devm_spi_alloc_controller - resource-managed __spi_alloc_controller() + * @dev: physical device of SPI controller + * @size: how much zeroed driver-private data to allocate + * @slave: whether to allocate an SPI master (false) or SPI slave (true) + * Context: can sleep + * + * Allocate an SPI controller and automatically release a reference on it + * when @dev is unbound from its driver. Drivers are thus relieved from + * having to call spi_controller_put(). + * + * The arguments to this function are identical to __spi_alloc_controller(). + * + * Return: the SPI controller structure on success, else NULL. + */ +struct spi_controller *__devm_spi_alloc_controller(struct device *dev, + unsigned int size, + bool slave) +{ + struct spi_controller **ptr, *ctlr; + + ptr = devres_alloc(devm_spi_release_controller, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return NULL; + + ctlr = __spi_alloc_controller(dev, size, slave); + if (ctlr) { + *ptr = ctlr; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return ctlr; +} +EXPORT_SYMBOL_GPL(__devm_spi_alloc_controller); + #ifdef CONFIG_OF static int of_spi_register_master(struct spi_controller *ctlr) { @@ -2300,6 +2344,11 @@ int devm_spi_register_controller(struct device *dev, } EXPORT_SYMBOL_GPL(devm_spi_register_controller); +static int devm_spi_match_controller(struct device *dev, void *res, void *ctlr) +{ + return *(struct spi_controller **)res == ctlr; +} + static int __unregister(struct device *dev, void *null) { spi_unregister_device(to_spi_device(dev)); @@ -2341,7 +2390,15 @@ void spi_unregister_controller(struct spi_controller *ctlr) list_del(&ctlr->list); mutex_unlock(&board_lock); - device_unregister(&ctlr->dev); + device_del(&ctlr->dev); + + /* Release the last reference on the controller if its driver + * has not yet been converted to devm_spi_alloc_master/slave(). + */ + if (!devres_find(ctlr->dev.parent, devm_spi_release_controller, + devm_spi_match_controller, ctlr)) + put_device(&ctlr->dev); + /* free bus id */ mutex_lock(&board_lock); if (found == ctlr) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 9b01420c25d1..2aa7ef0b0318 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -114,8 +114,6 @@ source "drivers/staging/mt7621-spi/Kconfig" source "drivers/staging/mt7621-dma/Kconfig" -source "drivers/staging/mt7621-mmc/Kconfig" - source "drivers/staging/mt7621-eth/Kconfig" source "drivers/staging/mt7621-dts/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 829e5ec6576b..4a63d6132b01 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -47,7 +47,6 @@ obj-$(CONFIG_SOC_MT7621) += mt7621-pci/ obj-$(CONFIG_SOC_MT7621) += mt7621-pinctrl/ obj-$(CONFIG_SOC_MT7621) += mt7621-spi/ obj-$(CONFIG_SOC_MT7621) += mt7621-dma/ -obj-$(CONFIG_SOC_MT7621) += mt7621-mmc/ obj-$(CONFIG_SOC_MT7621) += mt7621-eth/ obj-$(CONFIG_SOC_MT7621) += mt7621-dts/ obj-$(CONFIG_STAGING_GASKET_FRAMEWORK) += gasket/ diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index a97bbd89fae2..693bc1e7af7f 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -1,241 +1,40 @@ // SPDX-License-Identifier: GPL-2.0 -/* mm/ashmem.c - * - * Anonymous Shared Memory Subsystem, ashmem - * +/* * Copyright (C) 2008 Google, Inc. - * * Robert Love + * Copyright (C) 2021 Sultan Alsawaf . */ #define pr_fmt(fmt) "ashmem: " fmt -#include -#include -#include -#include -#include #include -#include -#include #include -#include -#include -#include -#include #include #include "ashmem.h" -#define ASHMEM_NAME_PREFIX "dev/ashmem/" -#define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1) -#define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN) - /** * struct ashmem_area - The anonymous shared memory area - * @name: The optional name in /proc/pid/maps - * @unpinned_list: The list of all ashmem areas + * @mmap_lock: The mmap mutex lock * @file: The shmem-based backing file * @size: The size of the mapping, in bytes * @prot_mask: The allowed protection bits, as vm_flags * * The lifecycle of this structure is from our parent file's open() until - * its release(). It is also protected by 'ashmem_mutex' + * its release(). * * Warning: Mappings do NOT pin this structure; It dies on close() */ struct ashmem_area { - char name[ASHMEM_FULL_NAME_LEN]; - struct list_head unpinned_list; + struct mutex mmap_lock; struct file *file; size_t size; unsigned long prot_mask; }; -/** - * struct ashmem_range - A range of unpinned/evictable pages - * @lru: The entry in the LRU list - * @unpinned: The entry in its area's unpinned list - * @asma: The associated anonymous shared memory area. - * @pgstart: The starting page (inclusive) - * @pgend: The ending page (inclusive) - * @purged: The purge status (ASHMEM_NOT or ASHMEM_WAS_PURGED) - * - * The lifecycle of this structure is from unpin to pin. - * It is protected by 'ashmem_mutex' - */ -struct ashmem_range { - struct list_head lru; - struct list_head unpinned; - struct ashmem_area *asma; - size_t pgstart; - size_t pgend; - unsigned int purged; -}; - -/* LRU list of unpinned pages, protected by ashmem_mutex */ -static LIST_HEAD(ashmem_lru_list); - -static atomic_t ashmem_shrink_inflight = ATOMIC_INIT(0); -static DECLARE_WAIT_QUEUE_HEAD(ashmem_shrink_wait); - -/* - * long lru_count - The count of pages on our LRU list. - * - * This is protected by ashmem_mutex. - */ -static unsigned long lru_count; - -/* - * ashmem_mutex - protects the list of and each individual ashmem_area - * - * Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem - */ -static DEFINE_MUTEX(ashmem_mutex); - static struct kmem_cache *ashmem_area_cachep __read_mostly; -static struct kmem_cache *ashmem_range_cachep __read_mostly; - -/* - * A separate lockdep class for the backing shmem inodes to resolve the lockdep - * warning about the race between kswapd taking fs_reclaim before inode_lock - * and write syscall taking inode_lock and then fs_reclaim. - * Note that such race is impossible because ashmem does not support write - * syscalls operating on the backing shmem. - */ -static struct lock_class_key backing_shmem_inode_class; - -static inline unsigned long range_size(struct ashmem_range *range) -{ - return range->pgend - range->pgstart + 1; -} - -static inline bool range_on_lru(struct ashmem_range *range) -{ - return range->purged == ASHMEM_NOT_PURGED; -} - -static inline bool page_range_subsumes_range(struct ashmem_range *range, - size_t start, size_t end) -{ - return (range->pgstart >= start) && (range->pgend <= end); -} - -static inline bool page_range_subsumed_by_range(struct ashmem_range *range, - size_t start, size_t end) -{ - return (range->pgstart <= start) && (range->pgend >= end); -} - -static inline bool page_in_range(struct ashmem_range *range, size_t page) -{ - return (range->pgstart <= page) && (range->pgend >= page); -} - -static inline bool page_range_in_range(struct ashmem_range *range, - size_t start, size_t end) -{ - return page_in_range(range, start) || page_in_range(range, end) || - page_range_subsumes_range(range, start, end); -} - -static inline bool range_before_page(struct ashmem_range *range, size_t page) -{ - return range->pgend < page; -} #define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE) -/** - * lru_add() - Adds a range of memory to the LRU list - * @range: The memory range being added. - * - * The range is first added to the end (tail) of the LRU list. - * After this, the size of the range is added to @lru_count - */ -static inline void lru_add(struct ashmem_range *range) -{ - list_add_tail(&range->lru, &ashmem_lru_list); - lru_count += range_size(range); -} - -/** - * lru_del() - Removes a range of memory from the LRU list - * @range: The memory range being removed - * - * The range is first deleted from the LRU list. - * After this, the size of the range is removed from @lru_count - */ -static inline void lru_del(struct ashmem_range *range) -{ - list_del(&range->lru); - lru_count -= range_size(range); -} - -/** - * range_alloc() - Allocates and initializes a new ashmem_range structure - * @asma: The associated ashmem_area - * @prev_range: The previous ashmem_range in the sorted asma->unpinned list - * @purged: Initial purge status (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED) - * @start: The starting page (inclusive) - * @end: The ending page (inclusive) - * - * This function is protected by ashmem_mutex. - */ -static void range_alloc(struct ashmem_area *asma, - struct ashmem_range *prev_range, unsigned int purged, - size_t start, size_t end, - struct ashmem_range **new_range) -{ - struct ashmem_range *range = *new_range; - - *new_range = NULL; - range->asma = asma; - range->pgstart = start; - range->pgend = end; - range->purged = purged; - - list_add_tail(&range->unpinned, &prev_range->unpinned); - - if (range_on_lru(range)) - lru_add(range); -} - -/** - * range_del() - Deletes and dealloctes an ashmem_range structure - * @range: The associated ashmem_range that has previously been allocated - */ -static void range_del(struct ashmem_range *range) -{ - list_del(&range->unpinned); - if (range_on_lru(range)) - lru_del(range); - kmem_cache_free(ashmem_range_cachep, range); -} - -/** - * range_shrink() - Shrinks an ashmem_range - * @range: The associated ashmem_range being shrunk - * @start: The starting byte of the new range - * @end: The ending byte of the new range - * - * This does not modify the data inside the existing range in any way - It - * simply shrinks the boundaries of the range. - * - * Theoretically, with a little tweaking, this could eventually be changed - * to range_resize, and expand the lru_count if the new range is larger. - */ -static inline void range_shrink(struct ashmem_range *range, - size_t start, size_t end) -{ - size_t pre = range_size(range); - - range->pgstart = start; - range->pgend = end; - - if (range_on_lru(range)) - lru_count -= pre - range_size(range); -} - /** * ashmem_open() - Opens an Anonymous Shared Memory structure * @inode: The backing file's index node(?) @@ -252,16 +51,18 @@ static int ashmem_open(struct inode *inode, struct file *file) int ret; ret = generic_file_open(inode, file); - if (ret) + if (unlikely(ret)) return ret; - asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL); - if (!asma) + asma = kmem_cache_alloc(ashmem_area_cachep, GFP_KERNEL); + if (unlikely(!asma)) return -ENOMEM; - INIT_LIST_HEAD(&asma->unpinned_list); - memcpy(asma->name, ASHMEM_NAME_PREFIX, ASHMEM_NAME_PREFIX_LEN); - asma->prot_mask = PROT_MASK; + *asma = (typeof(*asma)){ + .mmap_lock = __MUTEX_INITIALIZER(asma->mmap_lock), + .prot_mask = PROT_MASK + }; + file->private_data = asma; return 0; @@ -278,12 +79,6 @@ static int ashmem_open(struct inode *inode, struct file *file) static int ashmem_release(struct inode *ignored, struct file *file) { struct ashmem_area *asma = file->private_data; - struct ashmem_range *range, *next; - - mutex_lock(&ashmem_mutex); - list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) - range_del(range); - mutex_unlock(&ashmem_mutex); if (asma->file) fput(asma->file); @@ -295,18 +90,16 @@ static int ashmem_release(struct inode *ignored, struct file *file) static ssize_t ashmem_read_iter(struct kiocb *iocb, struct iov_iter *iter) { struct ashmem_area *asma = iocb->ki_filp->private_data; - int ret = 0; - - mutex_lock(&ashmem_mutex); + struct file *vmfile; + ssize_t ret; /* If size is not set, or set to 0, always return EOF. */ - if (asma->size == 0) - goto out_unlock; + if (!READ_ONCE(asma->size)) + return 0; - if (!asma->file) { - ret = -EBADF; - goto out_unlock; - } + vmfile = READ_ONCE(asma->file); + if (!vmfile) + return -EBADF; /* * asma and asma->file are used outside the lock here. We assume @@ -314,41 +107,31 @@ static ssize_t ashmem_read_iter(struct kiocb *iocb, struct iov_iter *iter) * be destroyed until all references to the file are dropped and * ashmem_release is called. */ - mutex_unlock(&ashmem_mutex); - ret = vfs_iter_read(asma->file, iter, &iocb->ki_pos, 0); - mutex_lock(&ashmem_mutex); + ret = vfs_iter_read(vmfile, iter, &iocb->ki_pos, 0); if (ret > 0) - asma->file->f_pos = iocb->ki_pos; -out_unlock: - mutex_unlock(&ashmem_mutex); + vmfile->f_pos = iocb->ki_pos; return ret; } static loff_t ashmem_llseek(struct file *file, loff_t offset, int origin) { struct ashmem_area *asma = file->private_data; + struct file *vmfile; loff_t ret; - mutex_lock(&ashmem_mutex); - - if (asma->size == 0) { - mutex_unlock(&ashmem_mutex); + if (!READ_ONCE(asma->size)) return -EINVAL; - } - if (!asma->file) { - mutex_unlock(&ashmem_mutex); + vmfile = READ_ONCE(asma->file); + if (!vmfile) return -EBADF; - } - mutex_unlock(&ashmem_mutex); - - ret = vfs_llseek(asma->file, offset, origin); + ret = vfs_llseek(vmfile, offset, origin); if (ret < 0) return ret; /** Copy f_pos from backing file, since f_ops->llseek() sets it */ - file->f_pos = asma->file->f_pos; + file->f_pos = vmfile->f_pos; return ret; } @@ -373,77 +156,81 @@ ashmem_vmfile_get_unmapped_area(struct file *file, unsigned long addr, return current->mm->get_unmapped_area(file, addr, len, pgoff, flags); } -static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) +static int ashmem_file_setup(struct ashmem_area *asma, size_t size, + struct vm_area_struct *vma) { static struct file_operations vmfile_fops; + static DEFINE_SPINLOCK(vmfile_fops_lock); + struct file *vmfile; + + vmfile = shmem_file_setup(ASHMEM_NAME_DEF, size, vma->vm_flags); + if (IS_ERR(vmfile)) + return PTR_ERR(vmfile); + + /* + * override mmap operation of the vmfile so that it can't be + * remapped which would lead to creation of a new vma with no + * asma permission checks. Have to override get_unmapped_area + * as well to prevent VM_BUG_ON check for f_ops modification. + */ + if (!READ_ONCE(vmfile_fops.mmap)) { + spin_lock(&vmfile_fops_lock); + if (!vmfile_fops.mmap) { + vmfile_fops = *vmfile->f_op; + vmfile_fops.get_unmapped_area = + ashmem_vmfile_get_unmapped_area; + WRITE_ONCE(vmfile_fops.mmap, ashmem_vmfile_mmap); + } + spin_unlock(&vmfile_fops_lock); + } + vmfile->f_op = &vmfile_fops; + vmfile->f_mode |= FMODE_LSEEK; + + WRITE_ONCE(asma->file, vmfile); + return 0; +} + +static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) +{ struct ashmem_area *asma = file->private_data; + unsigned long prot_mask; + size_t size; int ret = 0; - mutex_lock(&ashmem_mutex); - /* user needs to SET_SIZE before mapping */ - if (!asma->size) { - ret = -EINVAL; - goto out; - } + size = READ_ONCE(asma->size); + if (unlikely(!size)) + return -EINVAL; /* requested mapping size larger than object size */ - if (vma->vm_end - vma->vm_start > PAGE_ALIGN(asma->size)) { - ret = -EINVAL; - goto out; - } + if (vma->vm_end - vma->vm_start > PAGE_ALIGN(size)) + return -EINVAL; /* requested protection bits must match our allowed protection mask */ - if ((vma->vm_flags & ~calc_vm_prot_bits(asma->prot_mask, 0)) & - calc_vm_prot_bits(PROT_MASK, 0)) { - ret = -EPERM; - goto out; - } - vma->vm_flags &= ~calc_vm_may_flags(~asma->prot_mask); + prot_mask = READ_ONCE(asma->prot_mask); + if (unlikely((vma->vm_flags & ~calc_vm_prot_bits(prot_mask, 0)) & + calc_vm_prot_bits(PROT_MASK, 0))) + return -EPERM; - if (!asma->file) { - char *name = ASHMEM_NAME_DEF; - struct file *vmfile; - struct inode *inode; + vma->vm_flags &= ~calc_vm_may_flags(~prot_mask); - if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') - name = asma->name; + if (!READ_ONCE(asma->file)) { + mutex_lock(&asma->mmap_lock); + if (!asma->file) + ret = ashmem_file_setup(asma, size, vma); + mutex_unlock(&asma->mmap_lock); - /* ... and allocate the backing shmem file */ - vmfile = shmem_file_setup(name, asma->size, vma->vm_flags); - if (IS_ERR(vmfile)) { - ret = PTR_ERR(vmfile); - goto out; - } - vmfile->f_mode |= FMODE_LSEEK; - inode = file_inode(vmfile); - lockdep_set_class(&inode->i_rwsem, &backing_shmem_inode_class); - asma->file = vmfile; - /* - * override mmap operation of the vmfile so that it can't be - * remapped which would lead to creation of a new vma with no - * asma permission checks. Have to override get_unmapped_area - * as well to prevent VM_BUG_ON check for f_ops modification. - */ - if (!vmfile_fops.mmap) { - vmfile_fops = *vmfile->f_op; - vmfile_fops.mmap = ashmem_vmfile_mmap; - vmfile_fops.get_unmapped_area = - ashmem_vmfile_get_unmapped_area; - } - vmfile->f_op = &vmfile_fops; + if (ret) + return ret; } + get_file(asma->file); - /* - * XXX - Reworked to use shmem_zero_setup() instead of - * shmem_set_file while we're in staging. -jstultz - */ if (vma->vm_flags & VM_SHARED) { ret = shmem_zero_setup(vma); if (ret) { fput(asma->file); - goto out; + return ret; } } else { vma_set_anonymous(vma); @@ -453,414 +240,55 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) fput(vma->vm_file); vma->vm_file = asma->file; -out: - mutex_unlock(&ashmem_mutex); - return ret; -} - -/* - * ashmem_shrink - our cache shrinker, called from mm/vmscan.c - * - * 'nr_to_scan' is the number of objects to scan for freeing. - * - * 'gfp_mask' is the mask of the allocation that got us into this mess. - * - * Return value is the number of objects freed or -1 if we cannot - * proceed without risk of deadlock (due to gfp_mask). - * - * We approximate LRU via least-recently-unpinned, jettisoning unpinned partial - * chunks of ashmem regions LRU-wise one-at-a-time until we hit 'nr_to_scan' - * pages freed. - */ -static unsigned long -ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) -{ - unsigned long freed = 0; - - /* We might recurse into filesystem code, so bail out if necessary */ - if (!(sc->gfp_mask & __GFP_FS)) - return SHRINK_STOP; - - if (!mutex_trylock(&ashmem_mutex)) - return -1; - - while (!list_empty(&ashmem_lru_list)) { - struct ashmem_range *range = - list_first_entry(&ashmem_lru_list, typeof(*range), lru); - loff_t start = range->pgstart * PAGE_SIZE; - loff_t end = (range->pgend + 1) * PAGE_SIZE; - struct file *f = range->asma->file; - - get_file(f); - atomic_inc(&ashmem_shrink_inflight); - range->purged = ASHMEM_WAS_PURGED; - lru_del(range); - - freed += range_size(range); - mutex_unlock(&ashmem_mutex); - f->f_op->fallocate(f, - FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, - start, end - start); - fput(f); - if (atomic_dec_and_test(&ashmem_shrink_inflight)) - wake_up_all(&ashmem_shrink_wait); - if (!mutex_trylock(&ashmem_mutex)) - goto out; - if (--sc->nr_to_scan <= 0) - break; - } - mutex_unlock(&ashmem_mutex); -out: - return freed; -} - -static unsigned long -ashmem_shrink_count(struct shrinker *shrink, struct shrink_control *sc) -{ - /* - * note that lru_count is count of pages on the lru, not a count of - * objects on the list. This means the scan function needs to return the - * number of pages freed, not the number of objects scanned. - */ - return lru_count; + return 0; } -static struct shrinker ashmem_shrinker = { - .count_objects = ashmem_shrink_count, - .scan_objects = ashmem_shrink_scan, - /* - * XXX (dchinner): I wish people would comment on why they need on - * significant changes to the default value here - */ - .seeks = DEFAULT_SEEKS * 4, -}; - static int set_prot_mask(struct ashmem_area *asma, unsigned long prot) { - int ret = 0; - - mutex_lock(&ashmem_mutex); - /* the user can only remove, not add, protection bits */ - if ((asma->prot_mask & prot) != prot) { - ret = -EINVAL; - goto out; - } + if (unlikely((READ_ONCE(asma->prot_mask) & prot) != prot)) + return -EINVAL; /* does the application expect PROT_READ to imply PROT_EXEC? */ if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC)) prot |= PROT_EXEC; - asma->prot_mask = prot; - -out: - mutex_unlock(&ashmem_mutex); - return ret; -} - -static int set_name(struct ashmem_area *asma, void __user *name) -{ - int len; - int ret = 0; - char local_name[ASHMEM_NAME_LEN]; - - /* - * Holding the ashmem_mutex while doing a copy_from_user might cause - * an data abort which would try to access mmap_sem. If another - * thread has invoked ashmem_mmap then it will be holding the - * semaphore and will be waiting for ashmem_mutex, there by leading to - * deadlock. We'll release the mutex and take the name to a local - * variable that does not need protection and later copy the local - * variable to the structure member with lock held. - */ - len = strncpy_from_user(local_name, name, ASHMEM_NAME_LEN); - if (len < 0) - return len; - if (len == ASHMEM_NAME_LEN) - local_name[ASHMEM_NAME_LEN - 1] = '\0'; - mutex_lock(&ashmem_mutex); - /* cannot change an existing mapping's name */ - if (asma->file) - ret = -EINVAL; - else - strcpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name); - - mutex_unlock(&ashmem_mutex); - return ret; -} - -static int get_name(struct ashmem_area *asma, void __user *name) -{ - int ret = 0; - size_t len; - /* - * Have a local variable to which we'll copy the content - * from asma with the lock held. Later we can copy this to the user - * space safely without holding any locks. So even if we proceed to - * wait for mmap_sem, it won't lead to deadlock. - */ - char local_name[ASHMEM_NAME_LEN]; - - mutex_lock(&ashmem_mutex); - if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') { - /* - * Copying only `len', instead of ASHMEM_NAME_LEN, bytes - * prevents us from revealing one user's stack to another. - */ - len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + 1; - memcpy(local_name, asma->name + ASHMEM_NAME_PREFIX_LEN, len); - } else { - len = sizeof(ASHMEM_NAME_DEF); - memcpy(local_name, ASHMEM_NAME_DEF, len); - } - mutex_unlock(&ashmem_mutex); - - /* - * Now we are just copying from the stack variable to userland - * No lock held - */ - if (copy_to_user(name, local_name, len)) - ret = -EFAULT; - return ret; -} - -/* - * ashmem_pin - pin the given ashmem region, returning whether it was - * previously purged (ASHMEM_WAS_PURGED) or not (ASHMEM_NOT_PURGED). - * - * Caller must hold ashmem_mutex. - */ -static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend, - struct ashmem_range **new_range) -{ - struct ashmem_range *range, *next; - int ret = ASHMEM_NOT_PURGED; - - list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) { - /* moved past last applicable page; we can short circuit */ - if (range_before_page(range, pgstart)) - break; - - /* - * The user can ask us to pin pages that span multiple ranges, - * or to pin pages that aren't even unpinned, so this is messy. - * - * Four cases: - * 1. The requested range subsumes an existing range, so we - * just remove the entire matching range. - * 2. The requested range overlaps the start of an existing - * range, so we just update that range. - * 3. The requested range overlaps the end of an existing - * range, so we just update that range. - * 4. The requested range punches a hole in an existing range, - * so we have to update one side of the range and then - * create a new range for the other side. - */ - if (page_range_in_range(range, pgstart, pgend)) { - ret |= range->purged; - - /* Case #1: Easy. Just nuke the whole thing. */ - if (page_range_subsumes_range(range, pgstart, pgend)) { - range_del(range); - continue; - } - - /* Case #2: We overlap from the start, so adjust it */ - if (range->pgstart >= pgstart) { - range_shrink(range, pgend + 1, range->pgend); - continue; - } - - /* Case #3: We overlap from the rear, so adjust it */ - if (range->pgend <= pgend) { - range_shrink(range, range->pgstart, - pgstart - 1); - continue; - } - - /* - * Case #4: We eat a chunk out of the middle. A bit - * more complicated, we allocate a new range for the - * second half and adjust the first chunk's endpoint. - */ - range_alloc(asma, range, range->purged, - pgend + 1, range->pgend, new_range); - range_shrink(range, range->pgstart, pgstart - 1); - break; - } - } - - return ret; -} - -/* - * ashmem_unpin - unpin the given range of pages. Returns zero on success. - * - * Caller must hold ashmem_mutex. - */ -static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend, - struct ashmem_range **new_range) -{ - struct ashmem_range *range, *next; - unsigned int purged = ASHMEM_NOT_PURGED; - -restart: - list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) { - /* short circuit: this is our insertion point */ - if (range_before_page(range, pgstart)) - break; - - /* - * The user can ask us to unpin pages that are already entirely - * or partially pinned. We handle those two cases here. - */ - if (page_range_subsumed_by_range(range, pgstart, pgend)) - return 0; - if (page_range_in_range(range, pgstart, pgend)) { - pgstart = min(range->pgstart, pgstart); - pgend = max(range->pgend, pgend); - purged |= range->purged; - range_del(range); - goto restart; - } - } - - range_alloc(asma, range, purged, pgstart, pgend, new_range); + WRITE_ONCE(asma->prot_mask, prot); return 0; } -/* - * ashmem_get_pin_status - Returns ASHMEM_IS_UNPINNED if _any_ pages in the - * given interval are unpinned and ASHMEM_IS_PINNED otherwise. - * - * Caller must hold ashmem_mutex. - */ -static int ashmem_get_pin_status(struct ashmem_area *asma, size_t pgstart, - size_t pgend) -{ - struct ashmem_range *range; - int ret = ASHMEM_IS_PINNED; - - list_for_each_entry(range, &asma->unpinned_list, unpinned) { - if (range_before_page(range, pgstart)) - break; - if (page_range_in_range(range, pgstart, pgend)) { - ret = ASHMEM_IS_UNPINNED; - break; - } - } - - return ret; -} - -static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd, - void __user *p) -{ - struct ashmem_pin pin; - size_t pgstart, pgend; - int ret = -EINVAL; - struct ashmem_range *range = NULL; - - if (copy_from_user(&pin, p, sizeof(pin))) - return -EFAULT; - - if (cmd == ASHMEM_PIN || cmd == ASHMEM_UNPIN) { - range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL); - if (!range) - return -ENOMEM; - } - - mutex_lock(&ashmem_mutex); - wait_event(ashmem_shrink_wait, !atomic_read(&ashmem_shrink_inflight)); - - if (!asma->file) - goto out_unlock; - - /* per custom, you can pass zero for len to mean "everything onward" */ - if (!pin.len) - pin.len = PAGE_ALIGN(asma->size) - pin.offset; - - if ((pin.offset | pin.len) & ~PAGE_MASK) - goto out_unlock; - - if (((__u32)-1) - pin.offset < pin.len) - goto out_unlock; - - if (PAGE_ALIGN(asma->size) < pin.offset + pin.len) - goto out_unlock; - - pgstart = pin.offset / PAGE_SIZE; - pgend = pgstart + (pin.len / PAGE_SIZE) - 1; - - switch (cmd) { - case ASHMEM_PIN: - ret = ashmem_pin(asma, pgstart, pgend, &range); - break; - case ASHMEM_UNPIN: - ret = ashmem_unpin(asma, pgstart, pgend, &range); - break; - case ASHMEM_GET_PIN_STATUS: - ret = ashmem_get_pin_status(asma, pgstart, pgend); - break; - } - -out_unlock: - mutex_unlock(&ashmem_mutex); - if (range) - kmem_cache_free(ashmem_range_cachep, range); - - return ret; -} - static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ashmem_area *asma = file->private_data; - long ret = -ENOTTY; switch (cmd) { case ASHMEM_SET_NAME: - ret = set_name(asma, (void __user *)arg); - break; + return 0; case ASHMEM_GET_NAME: - ret = get_name(asma, (void __user *)arg); - break; + return 0; case ASHMEM_SET_SIZE: - ret = -EINVAL; - mutex_lock(&ashmem_mutex); - if (!asma->file) { - ret = 0; - asma->size = (size_t)arg; - } - mutex_unlock(&ashmem_mutex); - break; + if (READ_ONCE(asma->file)) + return -EINVAL; + + WRITE_ONCE(asma->size, (size_t)arg); + return 0; case ASHMEM_GET_SIZE: - ret = asma->size; - break; + return READ_ONCE(asma->size); case ASHMEM_SET_PROT_MASK: - ret = set_prot_mask(asma, arg); - break; + return set_prot_mask(asma, arg); case ASHMEM_GET_PROT_MASK: - ret = asma->prot_mask; - break; + return READ_ONCE(asma->prot_mask); case ASHMEM_PIN: + return 0; case ASHMEM_UNPIN: + return 0; case ASHMEM_GET_PIN_STATUS: - ret = ashmem_pin_unpin(asma, cmd, (void __user *)arg); - break; + return ASHMEM_IS_PINNED; case ASHMEM_PURGE_ALL_CACHES: - ret = -EPERM; - if (capable(CAP_SYS_ADMIN)) { - struct shrink_control sc = { - .gfp_mask = GFP_KERNEL, - .nr_to_scan = LONG_MAX, - }; - ret = ashmem_shrink_count(&ashmem_shrinker, &sc); - ashmem_shrink_scan(&ashmem_shrinker, &sc); - } - break; + return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; } - return ret; + return -ENOTTY; } /* support of 32bit userspace on 64bit platforms */ @@ -879,23 +307,7 @@ static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, return ashmem_ioctl(file, cmd, arg); } #endif -#ifdef CONFIG_PROC_FS -static void ashmem_show_fdinfo(struct seq_file *m, struct file *file) -{ - struct ashmem_area *asma = file->private_data; - - mutex_lock(&ashmem_mutex); - - if (asma->file) - seq_printf(m, "inode:\t%ld\n", file_inode(asma->file)->i_ino); - if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') - seq_printf(m, "name:\t%s\n", - asma->name + ASHMEM_NAME_PREFIX_LEN); - - mutex_unlock(&ashmem_mutex); -} -#endif static const struct file_operations ashmem_fops = { .owner = THIS_MODULE, .open = ashmem_open, @@ -907,9 +319,6 @@ static const struct file_operations ashmem_fops = { #ifdef CONFIG_COMPAT .compat_ioctl = compat_ashmem_ioctl, #endif -#ifdef CONFIG_PROC_FS - .show_fdinfo = ashmem_show_fdinfo, -#endif }; static struct miscdevice ashmem_misc = { @@ -920,44 +329,27 @@ static struct miscdevice ashmem_misc = { static int __init ashmem_init(void) { - int ret = -ENOMEM; + int ret; ashmem_area_cachep = kmem_cache_create("ashmem_area_cache", sizeof(struct ashmem_area), 0, 0, NULL); - if (!ashmem_area_cachep) { + if (unlikely(!ashmem_area_cachep)) { pr_err("failed to create slab cache\n"); + ret = -ENOMEM; goto out; } - ashmem_range_cachep = kmem_cache_create("ashmem_range_cache", - sizeof(struct ashmem_range), - 0, 0, NULL); - if (!ashmem_range_cachep) { - pr_err("failed to create slab cache\n"); - goto out_free1; - } - ret = misc_register(&ashmem_misc); - if (ret) { + if (unlikely(ret)) { pr_err("failed to register misc device!\n"); - goto out_free2; - } - - ret = register_shrinker(&ashmem_shrinker); - if (ret) { - pr_err("failed to register shrinker!\n"); - goto out_demisc; + goto out_free1; } pr_info("initialized\n"); return 0; -out_demisc: - misc_deregister(&ashmem_misc); -out_free2: - kmem_cache_destroy(ashmem_range_cachep); out_free1: kmem_cache_destroy(ashmem_area_cachep); out: diff --git a/drivers/staging/android/ion/ion_camera_heap.c b/drivers/staging/android/ion/ion_camera_heap.c index 97ec92948900..1eb5d5cebeb4 100644 --- a/drivers/staging/android/ion/ion_camera_heap.c +++ b/drivers/staging/android/ion/ion_camera_heap.c @@ -265,7 +265,7 @@ static int ion_camera_heap_allocate(struct ion_heap *heap, unsigned int sz; int vmid = get_secure_vmid(buffer->flags); - if (size / PAGE_SIZE > totalram_pages / 2) + if (size / PAGE_SIZE > totalram_pages() / 2) return -ENOMEM; if (ion_heap_is_camera_heap_type(buffer->heap->type) && diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 6754d1367359..0a4b470ac7ff 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -287,7 +287,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, struct list_head pages; struct list_head pages_from_pool; struct page_info *info, *tmp_info; - int i = 0; + int i = 0, j; unsigned int nents_sync = 0; unsigned long size_remaining = PAGE_ALIGN(size); unsigned int max_order = orders[0]; @@ -295,7 +295,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, unsigned int sz; int vmid = get_secure_vmid(buffer->flags); - if (size / PAGE_SIZE > totalram_pages / 2) + if (size / PAGE_SIZE > totalram_pages() / 2) return -ENOMEM; if (ion_heap_is_system_heap_type(buffer->heap->type) && @@ -373,7 +373,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, * together while preserving the ordering of the pages (higher order * first). */ - do { + for_each_sg(table->sgl, sg, table->nents, j) { info = list_first_entry_or_null(&pages, struct page_info, list); tmp_info = list_first_entry_or_null(&pages_from_pool, struct page_info, list); @@ -390,9 +390,7 @@ static int ion_system_heap_allocate(struct ion_heap *heap, } else if (tmp_info) { i = process_info(tmp_info, sg, 0, 0, i); } - sg = sg_next(sg); - - } while (sg); + } if (nents_sync) { if (vmid > 0) { diff --git a/drivers/staging/android/ion/msm/msm_ion_of.c b/drivers/staging/android/ion/msm/msm_ion_of.c index 3826887ceca4..2057264de471 100644 --- a/drivers/staging/android/ion/msm/msm_ion_of.c +++ b/drivers/staging/android/ion/msm/msm_ion_of.c @@ -372,6 +372,7 @@ static struct platform_driver msm_ion_driver = { .driver = { .name = "ion-msm", .of_match_table = msm_ion_match_table, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; diff --git a/drivers/staging/comedi/drivers/addi_apci_1032.c b/drivers/staging/comedi/drivers/addi_apci_1032.c index e035c9f757a1..2176d3289eff 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1032.c +++ b/drivers/staging/comedi/drivers/addi_apci_1032.c @@ -260,6 +260,7 @@ static irqreturn_t apci1032_interrupt(int irq, void *d) struct apci1032_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int ctrl; + unsigned short val; /* check interrupt is from this device */ if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) & @@ -275,7 +276,8 @@ static irqreturn_t apci1032_interrupt(int irq, void *d) outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG); s->state = inl(dev->iobase + APCI1032_STATUS_REG) & 0xffff; - comedi_buf_write_samples(s, &s->state, 1); + val = s->state; + comedi_buf_write_samples(s, &val, 1); comedi_handle_events(dev, s); /* enable the interrupt */ diff --git a/drivers/staging/comedi/drivers/addi_apci_1500.c b/drivers/staging/comedi/drivers/addi_apci_1500.c index 816dd25b9d0e..8c3eff7cf465 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1500.c +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c @@ -208,7 +208,7 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) struct comedi_device *dev = d; struct apci1500_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; - unsigned int status = 0; + unsigned short status = 0; unsigned int val; val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); @@ -238,14 +238,14 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) * * Mask Meaning * ---------- ------------------------------------------ - * 0x00000001 Event 1 has occurred - * 0x00000010 Event 2 has occurred - * 0x00000100 Counter/timer 1 has run down (not implemented) - * 0x00001000 Counter/timer 2 has run down (not implemented) - * 0x00010000 Counter 3 has run down (not implemented) - * 0x00100000 Watchdog has run down (not implemented) - * 0x01000000 Voltage error - * 0x10000000 Short-circuit error + * 0b00000001 Event 1 has occurred + * 0b00000010 Event 2 has occurred + * 0b00000100 Counter/timer 1 has run down (not implemented) + * 0b00001000 Counter/timer 2 has run down (not implemented) + * 0b00010000 Counter 3 has run down (not implemented) + * 0b00100000 Watchdog has run down (not implemented) + * 0b01000000 Voltage error + * 0b10000000 Short-circuit error */ comedi_buf_write_samples(s, &status, 1); comedi_handle_events(dev, s); diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c index c1c3b18793d5..8cdee455e8a5 100644 --- a/drivers/staging/comedi/drivers/adv_pci1710.c +++ b/drivers/staging/comedi/drivers/adv_pci1710.c @@ -300,11 +300,11 @@ static int pci1710_ai_eoc(struct comedi_device *dev, static int pci1710_ai_read_sample(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int cur_chan, - unsigned int *val) + unsigned short *val) { const struct boardtype *board = dev->board_ptr; struct pci1710_private *devpriv = dev->private; - unsigned int sample; + unsigned short sample; unsigned int chan; sample = inw(dev->iobase + PCI171X_AD_DATA_REG); @@ -345,7 +345,7 @@ static int pci1710_ai_insn_read(struct comedi_device *dev, pci1710_ai_setup_chanlist(dev, s, &insn->chanspec, 1, 1); for (i = 0; i < insn->n; i++) { - unsigned int val; + unsigned short val; /* start conversion */ outw(0, dev->iobase + PCI171X_SOFTTRG_REG); @@ -395,7 +395,7 @@ static void pci1710_handle_every_sample(struct comedi_device *dev, { struct comedi_cmd *cmd = &s->async->cmd; unsigned int status; - unsigned int val; + unsigned short val; int ret; status = inw(dev->iobase + PCI171X_STATUS_REG); @@ -455,7 +455,7 @@ static void pci1710_handle_fifo(struct comedi_device *dev, } for (i = 0; i < devpriv->max_samples; i++) { - unsigned int val; + unsigned short val; int ret; ret = pci1710_ai_read_sample(dev, s, s->async->cur_chan, &val); diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 9b716c696477..86cae5d0e983 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -1281,7 +1281,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, devpriv->amcc + AMCC_OP_REG_INTCSR); ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED, - dev->board_name, dev); + "cb_pcidas", dev); if (ret) { dev_dbg(dev->class_dev, "unable to allocate irq %d\n", pcidev->irq); diff --git a/drivers/staging/comedi/drivers/cb_pcidas64.c b/drivers/staging/comedi/drivers/cb_pcidas64.c index 631a703b345d..91403cc1bbf9 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas64.c +++ b/drivers/staging/comedi/drivers/cb_pcidas64.c @@ -4021,7 +4021,7 @@ static int auto_attach(struct comedi_device *dev, init_stc_registers(dev); retval = request_irq(pcidev->irq, handle_interrupt, IRQF_SHARED, - dev->board_name, dev); + "cb_pcidas64", dev); if (retval) { dev_dbg(dev->class_dev, "unable to allocate irq %u\n", pcidev->irq); diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c index f99211ec46de..0034005bdf8f 100644 --- a/drivers/staging/comedi/drivers/das6402.c +++ b/drivers/staging/comedi/drivers/das6402.c @@ -186,7 +186,7 @@ static irqreturn_t das6402_interrupt(int irq, void *d) if (status & DAS6402_STATUS_FFULL) { async->events |= COMEDI_CB_OVERFLOW; } else if (status & DAS6402_STATUS_FFNE) { - unsigned int val; + unsigned short val; val = das6402_ai_read_sample(dev, s); comedi_buf_write_samples(s, &val, 1); diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c index 8cf09ef3012f..4bd8fd5218c8 100644 --- a/drivers/staging/comedi/drivers/das800.c +++ b/drivers/staging/comedi/drivers/das800.c @@ -427,7 +427,7 @@ static irqreturn_t das800_interrupt(int irq, void *d) struct comedi_cmd *cmd; unsigned long irq_flags; unsigned int status; - unsigned int val; + unsigned short val; bool fifo_empty; bool fifo_overflow; int i; diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c index 75693cdde313..c180d18ce517 100644 --- a/drivers/staging/comedi/drivers/dmm32at.c +++ b/drivers/staging/comedi/drivers/dmm32at.c @@ -404,7 +404,7 @@ static irqreturn_t dmm32at_isr(int irq, void *d) { struct comedi_device *dev = d; unsigned char intstat; - unsigned int val; + unsigned short val; int i; if (!dev->attached) { diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c index ee53571a8969..ead8000b5929 100644 --- a/drivers/staging/comedi/drivers/me4000.c +++ b/drivers/staging/comedi/drivers/me4000.c @@ -924,7 +924,7 @@ static irqreturn_t me4000_ai_isr(int irq, void *dev_id) struct comedi_subdevice *s = dev->read_subdev; int i; int c = 0; - unsigned int lval; + unsigned short lval; if (!dev->attached) return IRQ_NONE; diff --git a/drivers/staging/comedi/drivers/mf6x4.c b/drivers/staging/comedi/drivers/mf6x4.c index ea430237efa7..9da8dd748078 100644 --- a/drivers/staging/comedi/drivers/mf6x4.c +++ b/drivers/staging/comedi/drivers/mf6x4.c @@ -112,8 +112,9 @@ static int mf6x4_ai_eoc(struct comedi_device *dev, struct mf6x4_private *devpriv = dev->private; unsigned int status; + /* EOLC goes low at end of conversion. */ status = ioread32(devpriv->gpioc_reg); - if (status & MF6X4_GPIOC_EOLC) + if ((status & MF6X4_GPIOC_EOLC) == 0) return 0; return -EBUSY; } diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c index a5937206bf1c..e9abae418062 100644 --- a/drivers/staging/comedi/drivers/pcl711.c +++ b/drivers/staging/comedi/drivers/pcl711.c @@ -184,7 +184,7 @@ static irqreturn_t pcl711_interrupt(int irq, void *d) struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; struct comedi_cmd *cmd = &s->async->cmd; - unsigned int data; + unsigned short data; if (!dev->attached) { dev_err(dev->class_dev, "spurious interrupt\n"); diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c index 0af5315d4357..fc8afffc1815 100644 --- a/drivers/staging/comedi/drivers/pcl818.c +++ b/drivers/staging/comedi/drivers/pcl818.c @@ -423,7 +423,7 @@ static int pcl818_ai_eoc(struct comedi_device *dev, static bool pcl818_ai_write_sample(struct comedi_device *dev, struct comedi_subdevice *s, - unsigned int chan, unsigned int val) + unsigned int chan, unsigned short val) { struct pcl818_private *devpriv = dev->private; struct comedi_cmd *cmd = &s->async->cmd; diff --git a/drivers/staging/erofs/inode.c b/drivers/staging/erofs/inode.c index 7448744cc515..12a5be95457f 100644 --- a/drivers/staging/erofs/inode.c +++ b/drivers/staging/erofs/inode.c @@ -53,11 +53,9 @@ static int read_inode(struct inode *inode, void *data) i_gid_write(inode, le32_to_cpu(v2->i_gid)); set_nlink(inode, le32_to_cpu(v2->i_nlink)); - /* ns timestamp */ - inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = - le64_to_cpu(v2->i_ctime); - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = - le32_to_cpu(v2->i_ctime_nsec); + /* extended inode has its own timestamp */ + inode->i_ctime.tv_sec = le64_to_cpu(v2->i_ctime); + inode->i_ctime.tv_nsec = le32_to_cpu(v2->i_ctime_nsec); inode->i_size = le64_to_cpu(v2->i_size); } else if (__inode_version(advise) == EROFS_INODE_LAYOUT_V1) { @@ -83,11 +81,9 @@ static int read_inode(struct inode *inode, void *data) i_gid_write(inode, le16_to_cpu(v1->i_gid)); set_nlink(inode, le16_to_cpu(v1->i_nlink)); - /* use build time to derive all file time */ - inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = - sbi->build_time; - inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = - sbi->build_time_nsec; + /* use build time for compact inodes */ + inode->i_ctime.tv_sec = sbi->build_time; + inode->i_ctime.tv_nsec = sbi->build_time_nsec; inode->i_size = le32_to_cpu(v1->i_size); } else { @@ -97,6 +93,11 @@ static int read_inode(struct inode *inode, void *data) return -EIO; } + inode->i_mtime.tv_sec = inode->i_ctime.tv_sec; + inode->i_atime.tv_sec = inode->i_ctime.tv_sec; + inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec; + inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec; + /* measure inode.i_blocks as the generic filesystem */ inode->i_blocks = ((inode->i_size - 1) >> 9) + 1; return 0; diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index fa0dd425b454..cd062628a46b 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c @@ -2219,6 +2219,7 @@ static int fwserial_create(struct fw_unit *unit) err = fw_core_add_address_handler(&port->rx_handler, &fw_high_memory_region); if (err) { + tty_port_destroy(&port->port); kfree(port); goto free_ports; } @@ -2301,6 +2302,7 @@ static int fwserial_create(struct fw_unit *unit) free_ports: for (--i; i >= 0; --i) { + fw_core_remove_address_handler(&serial->ports[i]->rx_handler); tty_port_destroy(&serial->ports[i]->port); kfree(serial->ports[i]); } diff --git a/drivers/staging/gasket/gasket_interrupt.c b/drivers/staging/gasket/gasket_interrupt.c index 1cfbc120f228..225460c535d6 100644 --- a/drivers/staging/gasket/gasket_interrupt.c +++ b/drivers/staging/gasket/gasket_interrupt.c @@ -527,14 +527,16 @@ int gasket_interrupt_system_status(struct gasket_dev *gasket_dev) int gasket_interrupt_set_eventfd(struct gasket_interrupt_data *interrupt_data, int interrupt, int event_fd) { - struct eventfd_ctx *ctx = eventfd_ctx_fdget(event_fd); - - if (IS_ERR(ctx)) - return PTR_ERR(ctx); + struct eventfd_ctx *ctx; if (interrupt < 0 || interrupt >= interrupt_data->num_interrupts) return -EINVAL; + ctx = eventfd_ctx_fdget(event_fd); + + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + interrupt_data->eventfd_ctxs[interrupt] = ctx; return 0; } @@ -545,6 +547,9 @@ int gasket_interrupt_clear_eventfd(struct gasket_interrupt_data *interrupt_data, if (interrupt < 0 || interrupt >= interrupt_data->num_interrupts) return -EINVAL; - interrupt_data->eventfd_ctxs[interrupt] = NULL; + if (interrupt_data->eventfd_ctxs[interrupt]) { + eventfd_ctx_put(interrupt_data->eventfd_ctxs[interrupt]); + interrupt_data->eventfd_ctxs[interrupt] = NULL; + } return 0; } diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c index dc4da66c3695..54bdb64f52e8 100644 --- a/drivers/staging/gdm724x/gdm_usb.c +++ b/drivers/staging/gdm724x/gdm_usb.c @@ -56,20 +56,24 @@ static int gdm_usb_recv(void *priv_dev, static int request_mac_address(struct lte_udev *udev) { - u8 buf[16] = {0,}; - struct hci_packet *hci = (struct hci_packet *)buf; + struct hci_packet *hci; struct usb_device *usbdev = udev->usbdev; int actual; int ret = -1; + hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL); + if (!hci) + return -ENOMEM; + hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION); hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1); hci->data[0] = MAC_ADDRESS; - ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), buf, 5, + ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5, &actual, 1000); udev->request_mac_addr = 1; + kfree(hci); return ret; } diff --git a/drivers/staging/greybus/audio_codec.c b/drivers/staging/greybus/audio_codec.c index 35acd55ca5ab..6cbf69a57dfd 100644 --- a/drivers/staging/greybus/audio_codec.c +++ b/drivers/staging/greybus/audio_codec.c @@ -489,6 +489,7 @@ static int gbcodec_hw_params(struct snd_pcm_substream *substream, if (ret) { dev_err_ratelimited(dai->dev, "%d: Error during set_config\n", ret); + gb_pm_runtime_put_noidle(bundle); mutex_unlock(&codec->lock); return ret; } @@ -565,6 +566,7 @@ static int gbcodec_prepare(struct snd_pcm_substream *substream, break; } if (ret) { + gb_pm_runtime_put_noidle(bundle); mutex_unlock(&codec->lock); dev_err_ratelimited(dai->dev, "set_data_size failed:%d\n", ret); diff --git a/drivers/staging/ks7010/ks_wlan_net.c b/drivers/staging/ks7010/ks_wlan_net.c index dc5459ae0b51..f624d0d53a8f 100644 --- a/drivers/staging/ks7010/ks_wlan_net.c +++ b/drivers/staging/ks7010/ks_wlan_net.c @@ -1120,6 +1120,7 @@ static int ks_wlan_set_scan(struct net_device *dev, { struct ks_wlan_private *priv = netdev_priv(dev); struct iw_scan_req *req = NULL; + int len; if (priv->sleep_mode == SLP_SLEEP) return -EPERM; @@ -1129,8 +1130,9 @@ static int ks_wlan_set_scan(struct net_device *dev, if (wrqu->data.length == sizeof(struct iw_scan_req) && wrqu->data.flags & IW_SCAN_THIS_ESSID) { req = (struct iw_scan_req *)extra; - priv->scan_ssid_len = req->essid_len; - memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); + len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE); + priv->scan_ssid_len = len; + memcpy(priv->scan_ssid, req->essid, len); } else { priv->scan_ssid_len = 0; } diff --git a/drivers/staging/most/sound/sound.c b/drivers/staging/most/sound/sound.c index 89b02fc305b8..fd9245d7eeb9 100644 --- a/drivers/staging/most/sound/sound.c +++ b/drivers/staging/most/sound/sound.c @@ -86,6 +86,8 @@ static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes) { unsigned int i = 0; + if (bytes < 2) + return; while (i < bytes - 2) { dest[i] = source[i + 2]; dest[i + 1] = source[i + 1]; diff --git a/drivers/staging/mt7621-dma/Makefile b/drivers/staging/mt7621-dma/Makefile index d3152d45cf45..e3ab560ed35a 100644 --- a/drivers/staging/mt7621-dma/Makefile +++ b/drivers/staging/mt7621-dma/Makefile @@ -1,4 +1,4 @@ obj-$(CONFIG_DMA_RALINK) += ralink-gdma.o -obj-$(CONFIG_MTK_HSDMA) += mtk-hsdma.o +obj-$(CONFIG_MTK_HSDMA) += hsdma-mt7621.o ccflags-y += -I$(srctree)/drivers/dma diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/hsdma-mt7621.c similarity index 99% rename from drivers/staging/mt7621-dma/mtk-hsdma.c rename to drivers/staging/mt7621-dma/hsdma-mt7621.c index 5831f816c17b..f487cbc91dee 100644 --- a/drivers/staging/mt7621-dma/mtk-hsdma.c +++ b/drivers/staging/mt7621-dma/hsdma-mt7621.c @@ -723,7 +723,7 @@ static int mtk_hsdma_probe(struct platform_device *pdev) ret = dma_async_device_register(dd); if (ret) { dev_err(&pdev->dev, "failed to register dma device\n"); - return ret; + goto err_uninit_hsdma; } ret = of_dma_controller_register(pdev->dev.of_node, @@ -739,6 +739,8 @@ static int mtk_hsdma_probe(struct platform_device *pdev) err_unregister: dma_async_device_unregister(dd); +err_uninit_hsdma: + mtk_hsdma_uninit(hsdma); return ret; } @@ -758,7 +760,7 @@ static struct platform_driver mtk_hsdma_driver = { .probe = mtk_hsdma_probe, .remove = mtk_hsdma_remove, .driver = { - .name = "hsdma-mt7621", + .name = KBUILD_MODNAME, .of_match_table = mtk_hsdma_of_match, }, }; diff --git a/drivers/staging/mt7621-mmc/Kconfig b/drivers/staging/mt7621-mmc/Kconfig deleted file mode 100644 index c6dfe8c637dc..000000000000 --- a/drivers/staging/mt7621-mmc/Kconfig +++ /dev/null @@ -1,16 +0,0 @@ -config MTK_MMC - tristate "MTK SD/MMC" - depends on !MTD_NAND_RALINK && MMC - -config MTK_AEE_KDUMP - bool "MTK AEE KDUMP" - depends on MTK_MMC - -config MTK_MMC_CD_POLL - bool "Card Detect with Polling" - depends on MTK_MMC - -config MTK_MMC_EMMC_8BIT - bool "eMMC 8-bit support" - depends on MTK_MMC && RALINK_MT7628 - diff --git a/drivers/staging/mt7621-mmc/Makefile b/drivers/staging/mt7621-mmc/Makefile deleted file mode 100644 index caead0b54703..000000000000 --- a/drivers/staging/mt7621-mmc/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright Statement: -# -# This software/firmware and related documentation ("MediaTek Software") are -# protected under relevant copyright laws. The information contained herein -# is confidential and proprietary to MediaTek Inc. and/or its licensors. -# Without the prior written permission of MediaTek inc. and/or its licensors, -# any reproduction, modification, use or disclosure of MediaTek Software, -# and information contained herein, in whole or in part, shall be strictly prohibited. -# -# MediaTek Inc. (C) 2010. All rights reserved. -# -# BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES -# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") -# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON -# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. -# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE -# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR -# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH -# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES -# THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES -# CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK -# SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR -# STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND -# CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, -# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, -# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO -# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. -# -# The following software/firmware and/or related documentation ("MediaTek Software") -# have been modified by MediaTek Inc. All revisions are subject to any receiver's -# applicable license agreements with MediaTek Inc. - -obj-$(CONFIG_MTK_MMC) += mtk_sd.o -mtk_sd-objs := sd.o dbg.o -ifeq ($(CONFIG_MTK_AEE_KDUMP),y) -EXTRA_CFLAGS += -DMT6575_SD_DEBUG -endif - -clean: - @rm -f *.o modules.order .*.cmd diff --git a/drivers/staging/mt7621-mmc/TODO b/drivers/staging/mt7621-mmc/TODO deleted file mode 100644 index febb32d37e07..000000000000 --- a/drivers/staging/mt7621-mmc/TODO +++ /dev/null @@ -1,8 +0,0 @@ - -- general code review and clean up -- ensure device-tree requirements are documented -- should probably be merged with drivers/mmc/host/mtk-sd.c -- possibly fix to work with highmem pages so a bounce buffer isn't - needed. - -Cc: NeilBrown diff --git a/drivers/staging/mt7621-mmc/board.h b/drivers/staging/mt7621-mmc/board.h deleted file mode 100644 index 983791ee308d..000000000000 --- a/drivers/staging/mt7621-mmc/board.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - */ -/* MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - -#ifndef __ARCH_ARM_MACH_BOARD_H -#define __ARCH_ARM_MACH_BOARD_H - -#define MSDC_CD_PIN_EN BIT(0) /* card detection pin is wired */ -#define MSDC_WP_PIN_EN BIT(1) /* write protection pin is wired */ -#define MSDC_RST_PIN_EN BIT(2) /* emmc reset pin is wired */ -#define MSDC_REMOVABLE BIT(5) /* removable slot */ - -#define MSDC_SMPL_RISING (0) -#define MSDC_SMPL_FALLING (1) - -#define MSDC_CMD_PIN (0) -#define MSDC_DAT_PIN (1) -#define MSDC_CD_PIN (2) -#define MSDC_WP_PIN (3) -#define MSDC_RST_PIN (4) - -struct msdc_hw { - unsigned char clk_src; /* host clock source */ - unsigned long flags; /* hardware capability flags */ - - /* config gpio pull mode */ - void (*config_gpio_pin)(int type, int pull); -}; - -extern struct msdc_hw msdc0_hw; - -#endif /* __ARCH_ARM_MACH_BOARD_H */ diff --git a/drivers/staging/mt7621-mmc/dbg.c b/drivers/staging/mt7621-mmc/dbg.c deleted file mode 100644 index 6e518dce9029..000000000000 --- a/drivers/staging/mt7621-mmc/dbg.c +++ /dev/null @@ -1,307 +0,0 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - * - * MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -// #include /* --- by chhung */ -#include "dbg.h" -#include "mt6575_sd.h" -#include - -static char cmd_buf[256]; - -/* for debug zone */ -unsigned int sd_debug_zone[4] = { - 0, - 0, - 0, - 0 -}; - -#if defined(MT6575_SD_DEBUG) -/* for driver profile */ -#define TICKS_ONE_MS (13000) -u32 gpt_enable; -u32 sdio_pro_enable; /* make sure gpt is enabled */ -u32 sdio_pro_time; /* no more than 30s */ -struct sdio_profile sdio_perfomance = {0}; - -#if 0 /* --- chhung */ -void msdc_init_gpt(void) -{ - GPT_CONFIG config; - - config.num = GPT6; - config.mode = GPT_FREE_RUN; - config.clkSrc = GPT_CLK_SRC_SYS; - config.clkDiv = GPT_CLK_DIV_1; /* 13MHz GPT6 */ - - if (GPT_Config(config) == FALSE) - return; - - GPT_Start(GPT6); -} -#endif /* end of --- */ - -u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32) -{ - u32 ret = 0; - - if (new_H32 == old_H32) { - ret = new_L32 - old_L32; - } else if (new_H32 == (old_H32 + 1)) { - if (new_L32 > old_L32) - pr_debug("msdc old_L<0x%x> new_L<0x%x>\n", old_L32, new_L32); - ret = (0xffffffff - old_L32); - ret += new_L32; - } else { - pr_debug("msdc old_H<0x%x> new_H<0x%x>\n", old_H32, new_H32); - } - - return ret; -} - -void msdc_sdio_profile(struct sdio_profile *result) -{ - struct cmd_profile *cmd; - u32 i; - - pr_debug("sdio === performance dump ===\n"); - pr_debug("sdio === total execute tick<%d> time<%dms> Tx<%dB> Rx<%dB>\n", - result->total_tc, result->total_tc / TICKS_ONE_MS, - result->total_tx_bytes, result->total_rx_bytes); - - /* CMD52 Dump */ - cmd = &result->cmd52_rx; - pr_debug("sdio === CMD52 Rx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, - cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count); - cmd = &result->cmd52_tx; - pr_debug("sdio === CMD52 Tx <%d>times tick<%d> Max<%d> Min<%d> Aver<%d>\n", cmd->count, cmd->tot_tc, - cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count); - - /* CMD53 Rx bytes + block mode */ - for (i = 0; i < 512; i++) { - cmd = &result->cmd53_rx_byte[i]; - if (cmd->count) { - pr_debug("sdio<%6d><%3dB>_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, - cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count, - cmd->tot_bytes, (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); - } - } - for (i = 0; i < 100; i++) { - cmd = &result->cmd53_rx_blk[i]; - if (cmd->count) { - pr_debug("sdio<%6d><%3d>B_Rx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, - cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count, - cmd->tot_bytes, (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); - } - } - - /* CMD53 Tx bytes + block mode */ - for (i = 0; i < 512; i++) { - cmd = &result->cmd53_tx_byte[i]; - if (cmd->count) { - pr_debug("sdio<%6d><%3dB>_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, - cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count, - cmd->tot_bytes, (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); - } - } - for (i = 0; i < 100; i++) { - cmd = &result->cmd53_tx_blk[i]; - if (cmd->count) { - pr_debug("sdio<%6d><%3d>B_Tx_<%9d><%9d><%6d><%6d>_<%9dB><%2dM>\n", cmd->count, i, cmd->tot_tc, - cmd->max_tc, cmd->min_tc, cmd->tot_tc / cmd->count, - cmd->tot_bytes, (cmd->tot_bytes / 10) * 13 / (cmd->tot_tc / 10)); - } - } - - pr_debug("sdio === performance dump done ===\n"); -} - -//========= sdio command table =========== -void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks) -{ - struct sdio_profile *result = &sdio_perfomance; - struct cmd_profile *cmd; - u32 block; - - if (sdio_pro_enable == 0) - return; - - if (opcode == 52) { - cmd = bRx ? &result->cmd52_rx : &result->cmd52_tx; - } else if (opcode == 53) { - if (sizes < 512) { - cmd = bRx ? &result->cmd53_rx_byte[sizes] : &result->cmd53_tx_byte[sizes]; - } else { - block = sizes / 512; - if (block >= 99) { - pr_err("cmd53 error blocks\n"); - while (1) - ; - } - cmd = bRx ? &result->cmd53_rx_blk[block] : &result->cmd53_tx_blk[block]; - } - } else { - return; - } - - /* update the members */ - if (ticks > cmd->max_tc) - cmd->max_tc = ticks; - if (cmd->min_tc == 0 || ticks < cmd->min_tc) - cmd->min_tc = ticks; - cmd->tot_tc += ticks; - cmd->tot_bytes += sizes; - cmd->count++; - - if (bRx) - result->total_rx_bytes += sizes; - else - result->total_tx_bytes += sizes; - result->total_tc += ticks; - - /* dump when total_tc > 30s */ - if (result->total_tc >= sdio_pro_time * TICKS_ONE_MS * 1000) { - msdc_sdio_profile(result); - memset(result, 0, sizeof(struct sdio_profile)); - } -} - -//========== driver proc interface =========== -static int msdc_debug_proc_read(struct seq_file *s, void *p) -{ - seq_puts(s, "\n=========================================\n"); - seq_puts(s, "Index<0> + Id + Zone\n"); - seq_puts(s, "-> PWR<9> WRN<8> | FIO<7> OPS<6> FUN<5> CFG<4> | INT<3> RSP<2> CMD<1> DMA<0>\n"); - seq_puts(s, "-> echo 0 3 0x3ff >msdc_bebug -> host[3] debug zone set to 0x3ff\n"); - seq_printf(s, "-> MSDC[0] Zone: 0x%.8x\n", sd_debug_zone[0]); - seq_printf(s, "-> MSDC[1] Zone: 0x%.8x\n", sd_debug_zone[1]); - seq_printf(s, "-> MSDC[2] Zone: 0x%.8x\n", sd_debug_zone[2]); - seq_printf(s, "-> MSDC[3] Zone: 0x%.8x\n", sd_debug_zone[3]); - - seq_puts(s, "Index<3> + SDIO_PROFILE + TIME\n"); - seq_puts(s, "-> echo 3 1 0x1E >msdc_bebug -> enable sdio_profile, 30s\n"); - seq_printf(s, "-> SDIO_PROFILE<%d> TIME<%ds>\n", sdio_pro_enable, sdio_pro_time); - seq_puts(s, "=========================================\n\n"); - - return 0; -} - -static ssize_t msdc_debug_proc_write(struct file *file, - const char __user *buf, - size_t count, loff_t *data) -{ - int ret; - - int cmd, p1, p2; - int id, zone; - int mode, size; - - if (count == 0) - return -1; - if (count > 255) - count = 255; - - if (copy_from_user(cmd_buf, buf, count)) - return -EFAULT; - - cmd_buf[count] = '\0'; - pr_debug("msdc Write %s\n", cmd_buf); - - sscanf(cmd_buf, "%x %x %x", &cmd, &p1, &p2); - - if (cmd == SD_TOOL_ZONE) { - id = p1; - zone = p2; - zone &= 0x3ff; - pr_debug("msdc host_id<%d> zone<0x%.8x>\n", id, zone); - if (id >= 0 && id <= 3) { - sd_debug_zone[id] = zone; - } else if (id == 4) { - sd_debug_zone[0] = sd_debug_zone[1] = zone; - sd_debug_zone[2] = sd_debug_zone[3] = zone; - } else { - pr_err("msdc host_id error when set debug zone\n"); - } - } else if (cmd == SD_TOOL_SDIO_PROFILE) { - if (p1 == 1) { /* enable profile */ - if (gpt_enable == 0) { - // msdc_init_gpt(); /* --- by chhung */ - gpt_enable = 1; - } - sdio_pro_enable = 1; - if (p2 == 0) - p2 = 1; - if (p2 >= 30) - p2 = 30; - sdio_pro_time = p2; - } else if (p1 == 0) { - /* todo */ - sdio_pro_enable = 0; - } - } - - return count; -} - -static int msdc_debug_show(struct inode *inode, struct file *file) -{ - return single_open(file, msdc_debug_proc_read, NULL); -} - -static const struct file_operations msdc_debug_fops = { - .owner = THIS_MODULE, - .open = msdc_debug_show, - .read = seq_read, - .write = msdc_debug_proc_write, - .llseek = seq_lseek, - .release = single_release, -}; - -void msdc_debug_proc_init(void) -{ - proc_create("msdc_debug", 0660, NULL, &msdc_debug_fops); -} -EXPORT_SYMBOL_GPL(msdc_debug_proc_init); -#endif diff --git a/drivers/staging/mt7621-mmc/dbg.h b/drivers/staging/mt7621-mmc/dbg.h deleted file mode 100644 index 2f2c56b73987..000000000000 --- a/drivers/staging/mt7621-mmc/dbg.h +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - * - * MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ -#ifndef __MT_MSDC_DEUBG__ -#define __MT_MSDC_DEUBG__ - -//========================== -extern u32 sdio_pro_enable; -/* for a type command, e.g. CMD53, 2 blocks */ -struct cmd_profile { - u32 max_tc; /* Max tick count */ - u32 min_tc; - u32 tot_tc; /* total tick count */ - u32 tot_bytes; - u32 count; /* the counts of the command */ -}; - -/* dump when total_tc and total_bytes */ -struct sdio_profile { - u32 total_tc; /* total tick count of CMD52 and CMD53 */ - u32 total_tx_bytes; /* total bytes of CMD53 Tx */ - u32 total_rx_bytes; /* total bytes of CMD53 Rx */ - - /*CMD52*/ - struct cmd_profile cmd52_tx; - struct cmd_profile cmd52_rx; - - /*CMD53 in byte unit */ - struct cmd_profile cmd53_tx_byte[512]; - struct cmd_profile cmd53_rx_byte[512]; - - /*CMD53 in block unit */ - struct cmd_profile cmd53_tx_blk[100]; - struct cmd_profile cmd53_rx_blk[100]; -}; - -//========================== -enum msdc_dbg { - SD_TOOL_ZONE = 0, - SD_TOOL_DMA_SIZE = 1, - SD_TOOL_PM_ENABLE = 2, - SD_TOOL_SDIO_PROFILE = 3, -}; - -/* Debug message event */ -#define DBG_EVT_NONE (0) /* No event */ -#define DBG_EVT_DMA (1 << 0) /* DMA related event */ -#define DBG_EVT_CMD (1 << 1) /* MSDC CMD related event */ -#define DBG_EVT_RSP (1 << 2) /* MSDC CMD RSP related event */ -#define DBG_EVT_INT (1 << 3) /* MSDC INT event */ -#define DBG_EVT_CFG (1 << 4) /* MSDC CFG event */ -#define DBG_EVT_FUC (1 << 5) /* Function event */ -#define DBG_EVT_OPS (1 << 6) /* Read/Write operation event */ -#define DBG_EVT_FIO (1 << 7) /* FIFO operation event */ -#define DBG_EVT_WRN (1 << 8) /* Warning event */ -#define DBG_EVT_PWR (1 << 9) /* Power event */ -#define DBG_EVT_ALL (0xffffffff) - -#define DBG_EVT_MASK (DBG_EVT_ALL) - -extern unsigned int sd_debug_zone[4]; -#define TAG "msdc" -#if 0 /* +++ chhung */ -#define BUG_ON(x) \ -do { \ - if (x) { \ - printk("[BUG] %s LINE:%d FILE:%s\n", #x, __LINE__, __FILE__); \ - while (1) \ - ; \ - } \ -} while (0) -#endif /* end of +++ */ - -#define N_MSG(evt, fmt, args...) -/* -do { \ - if ((DBG_EVT_##evt) & sd_debug_zone[host->id]) { \ - printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ - host->id, ##args , __FUNCTION__, __LINE__, current->comm, current->pid); \ - } \ -} while(0) -*/ - -#define ERR_MSG(fmt, args...) \ -do { \ - printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ - host->id, ##args, __FUNCTION__, __LINE__, current->comm, current->pid); \ -} while (0); - -#if 1 -//defined CONFIG_MTK_MMC_CD_POLL -#define INIT_MSG(fmt, args...) -#define IRQ_MSG(fmt, args...) -#else -#define INIT_MSG(fmt, args...) \ -do { \ - printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d> PID<%s><0x%x>\n", \ - host->id, ##args, __FUNCTION__, __LINE__, current->comm, current->pid); \ -} while (0); - -/* PID in ISR in not corrent */ -#define IRQ_MSG(fmt, args...) \ -do { \ - printk(KERN_ERR TAG"%d -> "fmt" <- %s() : L<%d>\n", \ - host->id, ##args, __FUNCTION__, __LINE__); \ -} while (0); -#endif - -void msdc_debug_proc_init(void); - -#if 0 /* --- chhung */ -void msdc_init_gpt(void); -extern void GPT_GetCounter64(UINT32 *cntL32, UINT32 *cntH32); -#endif /* end of --- */ -u32 msdc_time_calc(u32 old_L32, u32 old_H32, u32 new_L32, u32 new_H32); -void msdc_performance(u32 opcode, u32 sizes, u32 bRx, u32 ticks); - -#endif diff --git a/drivers/staging/mt7621-mmc/mt6575_sd.h b/drivers/staging/mt7621-mmc/mt6575_sd.h deleted file mode 100644 index 4e287c140acb..000000000000 --- a/drivers/staging/mt7621-mmc/mt6575_sd.h +++ /dev/null @@ -1,488 +0,0 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - */ -/* MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - -#ifndef MT6575_SD_H -#define MT6575_SD_H - -#include -#include - -// #include /* --- by chhung */ - -/*--------------------------------------------------------------------------*/ -/* Common Definition */ -/*--------------------------------------------------------------------------*/ -#define MSDC_FIFO_SZ (128) -#define MSDC_FIFO_THD (64) // (128) -#define MSDC_NUM (4) - -#define MSDC_MS (0) -#define MSDC_SDMMC (1) - -#define MSDC_BUS_1BITS (0) -#define MSDC_BUS_4BITS (1) -#define MSDC_BUS_8BITS (2) - -#define MSDC_BRUST_8B (3) -#define MSDC_BRUST_16B (4) -#define MSDC_BRUST_32B (5) -#define MSDC_BRUST_64B (6) - -#define MSDC_PIN_PULL_NONE (0) -#define MSDC_PIN_PULL_DOWN (1) -#define MSDC_PIN_PULL_UP (2) -#define MSDC_PIN_KEEP (3) - -#define MSDC_MAX_SCLK (48000000) /* +/- by chhung */ -#define MSDC_MIN_SCLK (260000) - -#define MSDC_AUTOCMD12 (0x0001) -#define MSDC_AUTOCMD23 (0x0002) -#define MSDC_AUTOCMD19 (0x0003) - -#define MSDC_EMMC_BOOTMODE0 (0) /* Pull low CMD mode */ -#define MSDC_EMMC_BOOTMODE1 (1) /* Reset CMD mode */ - -enum { - RESP_NONE = 0, - RESP_R1, - RESP_R2, - RESP_R3, - RESP_R4, - RESP_R5, - RESP_R6, - RESP_R7, - RESP_R1B -}; - -/*--------------------------------------------------------------------------*/ -/* Register Offset */ -/*--------------------------------------------------------------------------*/ -#define MSDC_CFG (0x0) -#define MSDC_IOCON (0x04) -#define MSDC_PS (0x08) -#define MSDC_INT (0x0c) -#define MSDC_INTEN (0x10) -#define MSDC_FIFOCS (0x14) -#define MSDC_TXDATA (0x18) -#define MSDC_RXDATA (0x1c) -#define SDC_CFG (0x30) -#define SDC_CMD (0x34) -#define SDC_ARG (0x38) -#define SDC_STS (0x3c) -#define SDC_RESP0 (0x40) -#define SDC_RESP1 (0x44) -#define SDC_RESP2 (0x48) -#define SDC_RESP3 (0x4c) -#define SDC_BLK_NUM (0x50) -#define SDC_CSTS (0x58) -#define SDC_CSTS_EN (0x5c) -#define SDC_DCRC_STS (0x60) -#define EMMC_CFG0 (0x70) -#define EMMC_CFG1 (0x74) -#define EMMC_STS (0x78) -#define EMMC_IOCON (0x7c) -#define SDC_ACMD_RESP (0x80) -#define SDC_ACMD19_TRG (0x84) -#define SDC_ACMD19_STS (0x88) -#define MSDC_DMA_SA (0x90) -#define MSDC_DMA_CA (0x94) -#define MSDC_DMA_CTRL (0x98) -#define MSDC_DMA_CFG (0x9c) -#define MSDC_DBG_SEL (0xa0) -#define MSDC_DBG_OUT (0xa4) -#define MSDC_PATCH_BIT (0xb0) -#define MSDC_PATCH_BIT0 MSDC_PATCH_BIT -#define MSDC_PATCH_BIT1 (0xb4) -#define MSDC_PAD_CTL0 (0xe0) -#define MSDC_PAD_CTL1 (0xe4) -#define MSDC_PAD_CTL2 (0xe8) -#define MSDC_PAD_TUNE (0xec) -#define MSDC_DAT_RDDLY0 (0xf0) -#define MSDC_DAT_RDDLY1 (0xf4) -#define MSDC_HW_DBG (0xf8) -#define MSDC_VERSION (0x100) -#define MSDC_ECO_VER (0x104) - -/*--------------------------------------------------------------------------*/ -/* Register Mask */ -/*--------------------------------------------------------------------------*/ - -/* MSDC_CFG mask */ -#define MSDC_CFG_MODE (0x1 << 0) /* RW */ -#define MSDC_CFG_CKPDN (0x1 << 1) /* RW */ -#define MSDC_CFG_RST (0x1 << 2) /* RW */ -#define MSDC_CFG_PIO (0x1 << 3) /* RW */ -#define MSDC_CFG_CKDRVEN (0x1 << 4) /* RW */ -#define MSDC_CFG_BV18SDT (0x1 << 5) /* RW */ -#define MSDC_CFG_BV18PSS (0x1 << 6) /* R */ -#define MSDC_CFG_CKSTB (0x1 << 7) /* R */ -#define MSDC_CFG_CKDIV (0xff << 8) /* RW */ -#define MSDC_CFG_CKMOD (0x3 << 16) /* RW */ - -/* MSDC_IOCON mask */ -#define MSDC_IOCON_SDR104CKS (0x1 << 0) /* RW */ -#define MSDC_IOCON_RSPL (0x1 << 1) /* RW */ -#define MSDC_IOCON_DSPL (0x1 << 2) /* RW */ -#define MSDC_IOCON_DDLSEL (0x1 << 3) /* RW */ -#define MSDC_IOCON_DDR50CKD (0x1 << 4) /* RW */ -#define MSDC_IOCON_DSPLSEL (0x1 << 5) /* RW */ -#define MSDC_IOCON_D0SPL (0x1 << 16) /* RW */ -#define MSDC_IOCON_D1SPL (0x1 << 17) /* RW */ -#define MSDC_IOCON_D2SPL (0x1 << 18) /* RW */ -#define MSDC_IOCON_D3SPL (0x1 << 19) /* RW */ -#define MSDC_IOCON_D4SPL (0x1 << 20) /* RW */ -#define MSDC_IOCON_D5SPL (0x1 << 21) /* RW */ -#define MSDC_IOCON_D6SPL (0x1 << 22) /* RW */ -#define MSDC_IOCON_D7SPL (0x1 << 23) /* RW */ -#define MSDC_IOCON_RISCSZ (0x3 << 24) /* RW */ - -/* MSDC_PS mask */ -#define MSDC_PS_CDEN (0x1 << 0) /* RW */ -#define MSDC_PS_CDSTS (0x1 << 1) /* R */ -#define MSDC_PS_CDDEBOUNCE (0xf << 12) /* RW */ -#define MSDC_PS_DAT (0xff << 16) /* R */ -#define MSDC_PS_CMD (0x1 << 24) /* R */ -#define MSDC_PS_WP (0x1UL << 31) /* R */ - -/* MSDC_INT mask */ -#define MSDC_INT_MMCIRQ (0x1 << 0) /* W1C */ -#define MSDC_INT_CDSC (0x1 << 1) /* W1C */ -#define MSDC_INT_ACMDRDY (0x1 << 3) /* W1C */ -#define MSDC_INT_ACMDTMO (0x1 << 4) /* W1C */ -#define MSDC_INT_ACMDCRCERR (0x1 << 5) /* W1C */ -#define MSDC_INT_DMAQ_EMPTY (0x1 << 6) /* W1C */ -#define MSDC_INT_SDIOIRQ (0x1 << 7) /* W1C */ -#define MSDC_INT_CMDRDY (0x1 << 8) /* W1C */ -#define MSDC_INT_CMDTMO (0x1 << 9) /* W1C */ -#define MSDC_INT_RSPCRCERR (0x1 << 10) /* W1C */ -#define MSDC_INT_CSTA (0x1 << 11) /* R */ -#define MSDC_INT_XFER_COMPL (0x1 << 12) /* W1C */ -#define MSDC_INT_DXFER_DONE (0x1 << 13) /* W1C */ -#define MSDC_INT_DATTMO (0x1 << 14) /* W1C */ -#define MSDC_INT_DATCRCERR (0x1 << 15) /* W1C */ -#define MSDC_INT_ACMD19_DONE (0x1 << 16) /* W1C */ - -/* MSDC_INTEN mask */ -#define MSDC_INTEN_MMCIRQ (0x1 << 0) /* RW */ -#define MSDC_INTEN_CDSC (0x1 << 1) /* RW */ -#define MSDC_INTEN_ACMDRDY (0x1 << 3) /* RW */ -#define MSDC_INTEN_ACMDTMO (0x1 << 4) /* RW */ -#define MSDC_INTEN_ACMDCRCERR (0x1 << 5) /* RW */ -#define MSDC_INTEN_DMAQ_EMPTY (0x1 << 6) /* RW */ -#define MSDC_INTEN_SDIOIRQ (0x1 << 7) /* RW */ -#define MSDC_INTEN_CMDRDY (0x1 << 8) /* RW */ -#define MSDC_INTEN_CMDTMO (0x1 << 9) /* RW */ -#define MSDC_INTEN_RSPCRCERR (0x1 << 10) /* RW */ -#define MSDC_INTEN_CSTA (0x1 << 11) /* RW */ -#define MSDC_INTEN_XFER_COMPL (0x1 << 12) /* RW */ -#define MSDC_INTEN_DXFER_DONE (0x1 << 13) /* RW */ -#define MSDC_INTEN_DATTMO (0x1 << 14) /* RW */ -#define MSDC_INTEN_DATCRCERR (0x1 << 15) /* RW */ -#define MSDC_INTEN_ACMD19_DONE (0x1 << 16) /* RW */ - -/* MSDC_FIFOCS mask */ -#define MSDC_FIFOCS_RXCNT (0xff << 0) /* R */ -#define MSDC_FIFOCS_TXCNT (0xff << 16) /* R */ -#define MSDC_FIFOCS_CLR (0x1UL << 31) /* RW */ - -/* SDC_CFG mask */ -#define SDC_CFG_SDIOINTWKUP (0x1 << 0) /* RW */ -#define SDC_CFG_INSWKUP (0x1 << 1) /* RW */ -#define SDC_CFG_BUSWIDTH (0x3 << 16) /* RW */ -#define SDC_CFG_SDIO (0x1 << 19) /* RW */ -#define SDC_CFG_SDIOIDE (0x1 << 20) /* RW */ -#define SDC_CFG_INTATGAP (0x1 << 21) /* RW */ -#define SDC_CFG_DTOC (0xffUL << 24) /* RW */ - -/* SDC_CMD mask */ -#define SDC_CMD_OPC (0x3f << 0) /* RW */ -#define SDC_CMD_BRK (0x1 << 6) /* RW */ -#define SDC_CMD_RSPTYP (0x7 << 7) /* RW */ -#define SDC_CMD_DTYP (0x3 << 11) /* RW */ -#define SDC_CMD_DTYP (0x3 << 11) /* RW */ -#define SDC_CMD_RW (0x1 << 13) /* RW */ -#define SDC_CMD_STOP (0x1 << 14) /* RW */ -#define SDC_CMD_GOIRQ (0x1 << 15) /* RW */ -#define SDC_CMD_BLKLEN (0xfff << 16) /* RW */ -#define SDC_CMD_AUTOCMD (0x3 << 28) /* RW */ -#define SDC_CMD_VOLSWTH (0x1 << 30) /* RW */ - -/* SDC_STS mask */ -#define SDC_STS_SDCBUSY (0x1 << 0) /* RW */ -#define SDC_STS_CMDBUSY (0x1 << 1) /* RW */ -#define SDC_STS_SWR_COMPL (0x1 << 31) /* RW */ - -/* SDC_DCRC_STS mask */ -#define SDC_DCRC_STS_NEG (0xf << 8) /* RO */ -#define SDC_DCRC_STS_POS (0xff << 0) /* RO */ - -/* EMMC_CFG0 mask */ -#define EMMC_CFG0_BOOTSTART (0x1 << 0) /* W */ -#define EMMC_CFG0_BOOTSTOP (0x1 << 1) /* W */ -#define EMMC_CFG0_BOOTMODE (0x1 << 2) /* RW */ -#define EMMC_CFG0_BOOTACKDIS (0x1 << 3) /* RW */ -#define EMMC_CFG0_BOOTWDLY (0x7 << 12) /* RW */ -#define EMMC_CFG0_BOOTSUPP (0x1 << 15) /* RW */ - -/* EMMC_CFG1 mask */ -#define EMMC_CFG1_BOOTDATTMC (0xfffff << 0) /* RW */ -#define EMMC_CFG1_BOOTACKTMC (0xfffUL << 20) /* RW */ - -/* EMMC_STS mask */ -#define EMMC_STS_BOOTCRCERR (0x1 << 0) /* W1C */ -#define EMMC_STS_BOOTACKERR (0x1 << 1) /* W1C */ -#define EMMC_STS_BOOTDATTMO (0x1 << 2) /* W1C */ -#define EMMC_STS_BOOTACKTMO (0x1 << 3) /* W1C */ -#define EMMC_STS_BOOTUPSTATE (0x1 << 4) /* R */ -#define EMMC_STS_BOOTACKRCV (0x1 << 5) /* W1C */ -#define EMMC_STS_BOOTDATRCV (0x1 << 6) /* R */ - -/* EMMC_IOCON mask */ -#define EMMC_IOCON_BOOTRST (0x1 << 0) /* RW */ - -/* SDC_ACMD19_TRG mask */ -#define SDC_ACMD19_TRG_TUNESEL (0xf << 0) /* RW */ - -/* MSDC_DMA_CTRL mask */ -#define MSDC_DMA_CTRL_START (0x1 << 0) /* W */ -#define MSDC_DMA_CTRL_STOP (0x1 << 1) /* W */ -#define MSDC_DMA_CTRL_RESUME (0x1 << 2) /* W */ -#define MSDC_DMA_CTRL_MODE (0x1 << 8) /* RW */ -#define MSDC_DMA_CTRL_LASTBUF (0x1 << 10) /* RW */ -#define MSDC_DMA_CTRL_BRUSTSZ (0x7 << 12) /* RW */ -#define MSDC_DMA_CTRL_XFERSZ (0xffffUL << 16)/* RW */ - -/* MSDC_DMA_CFG mask */ -#define MSDC_DMA_CFG_STS (0x1 << 0) /* R */ -#define MSDC_DMA_CFG_DECSEN (0x1 << 1) /* RW */ -#define MSDC_DMA_CFG_BDCSERR (0x1 << 4) /* R */ -#define MSDC_DMA_CFG_GPDCSERR (0x1 << 5) /* R */ - -/* MSDC_PATCH_BIT mask */ -#define MSDC_PATCH_BIT_WFLSMODE (0x1 << 0) /* RW */ -#define MSDC_PATCH_BIT_ODDSUPP (0x1 << 1) /* RW */ -#define MSDC_PATCH_BIT_CKGEN_CK (0x1 << 6) /* E2: Fixed to 1 */ -#define MSDC_PATCH_BIT_IODSSEL (0x1 << 16) /* RW */ -#define MSDC_PATCH_BIT_IOINTSEL (0x1 << 17) /* RW */ -#define MSDC_PATCH_BIT_BUSYDLY (0xf << 18) /* RW */ -#define MSDC_PATCH_BIT_WDOD (0xf << 22) /* RW */ -#define MSDC_PATCH_BIT_IDRTSEL (0x1 << 26) /* RW */ -#define MSDC_PATCH_BIT_CMDFSEL (0x1 << 27) /* RW */ -#define MSDC_PATCH_BIT_INTDLSEL (0x1 << 28) /* RW */ -#define MSDC_PATCH_BIT_SPCPUSH (0x1 << 29) /* RW */ -#define MSDC_PATCH_BIT_DECRCTMO (0x1 << 30) /* RW */ - -/* MSDC_PATCH_BIT1 mask */ -#define MSDC_PATCH_BIT1_WRDAT_CRCS (0x7 << 3) -#define MSDC_PATCH_BIT1_CMD_RSP (0x7 << 0) - -/* MSDC_PAD_CTL0 mask */ -#define MSDC_PAD_CTL0_CLKDRVN (0x7 << 0) /* RW */ -#define MSDC_PAD_CTL0_CLKDRVP (0x7 << 4) /* RW */ -#define MSDC_PAD_CTL0_CLKSR (0x1 << 8) /* RW */ -#define MSDC_PAD_CTL0_CLKPD (0x1 << 16) /* RW */ -#define MSDC_PAD_CTL0_CLKPU (0x1 << 17) /* RW */ -#define MSDC_PAD_CTL0_CLKSMT (0x1 << 18) /* RW */ -#define MSDC_PAD_CTL0_CLKIES (0x1 << 19) /* RW */ -#define MSDC_PAD_CTL0_CLKTDSEL (0xf << 20) /* RW */ -#define MSDC_PAD_CTL0_CLKRDSEL (0xffUL << 24) /* RW */ - -/* MSDC_PAD_CTL1 mask */ -#define MSDC_PAD_CTL1_CMDDRVN (0x7 << 0) /* RW */ -#define MSDC_PAD_CTL1_CMDDRVP (0x7 << 4) /* RW */ -#define MSDC_PAD_CTL1_CMDSR (0x1 << 8) /* RW */ -#define MSDC_PAD_CTL1_CMDPD (0x1 << 16) /* RW */ -#define MSDC_PAD_CTL1_CMDPU (0x1 << 17) /* RW */ -#define MSDC_PAD_CTL1_CMDSMT (0x1 << 18) /* RW */ -#define MSDC_PAD_CTL1_CMDIES (0x1 << 19) /* RW */ -#define MSDC_PAD_CTL1_CMDTDSEL (0xf << 20) /* RW */ -#define MSDC_PAD_CTL1_CMDRDSEL (0xffUL << 24) /* RW */ - -/* MSDC_PAD_CTL2 mask */ -#define MSDC_PAD_CTL2_DATDRVN (0x7 << 0) /* RW */ -#define MSDC_PAD_CTL2_DATDRVP (0x7 << 4) /* RW */ -#define MSDC_PAD_CTL2_DATSR (0x1 << 8) /* RW */ -#define MSDC_PAD_CTL2_DATPD (0x1 << 16) /* RW */ -#define MSDC_PAD_CTL2_DATPU (0x1 << 17) /* RW */ -#define MSDC_PAD_CTL2_DATIES (0x1 << 19) /* RW */ -#define MSDC_PAD_CTL2_DATSMT (0x1 << 18) /* RW */ -#define MSDC_PAD_CTL2_DATTDSEL (0xf << 20) /* RW */ -#define MSDC_PAD_CTL2_DATRDSEL (0xffUL << 24) /* RW */ - -/* MSDC_PAD_TUNE mask */ -#define MSDC_PAD_TUNE_DATWRDLY (0x1F << 0) /* RW */ -#define MSDC_PAD_TUNE_DATRRDLY (0x1F << 8) /* RW */ -#define MSDC_PAD_TUNE_CMDRDLY (0x1F << 16) /* RW */ -#define MSDC_PAD_TUNE_CMDRRDLY (0x1FUL << 22) /* RW */ -#define MSDC_PAD_TUNE_CLKTXDLY (0x1FUL << 27) /* RW */ - -/* MSDC_DAT_RDDLY0/1 mask */ -#define MSDC_DAT_RDDLY0_D0 (0x1F << 0) /* RW */ -#define MSDC_DAT_RDDLY0_D1 (0x1F << 8) /* RW */ -#define MSDC_DAT_RDDLY0_D2 (0x1F << 16) /* RW */ -#define MSDC_DAT_RDDLY0_D3 (0x1F << 24) /* RW */ - -#define MSDC_DAT_RDDLY1_D4 (0x1F << 0) /* RW */ -#define MSDC_DAT_RDDLY1_D5 (0x1F << 8) /* RW */ -#define MSDC_DAT_RDDLY1_D6 (0x1F << 16) /* RW */ -#define MSDC_DAT_RDDLY1_D7 (0x1F << 24) /* RW */ - -#define MSDC_CKGEN_MSDC_DLY_SEL (0x1F << 10) -#define MSDC_INT_DAT_LATCH_CK_SEL (0x7 << 7) -#define MSDC_CKGEN_MSDC_CK_SEL (0x1 << 6) -#define CARD_READY_FOR_DATA (1 << 8) -#define CARD_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) - -/*--------------------------------------------------------------------------*/ -/* Descriptor Structure */ -/*--------------------------------------------------------------------------*/ -struct gpd { - u32 hwo:1; /* could be changed by hw */ - u32 bdp:1; - u32 rsv0:6; - u32 chksum:8; - u32 intr:1; - u32 rsv1:15; - void *next; - void *ptr; - u32 buflen:16; - u32 extlen:8; - u32 rsv2:8; - u32 arg; - u32 blknum; - u32 cmd; -}; - -struct bd { - u32 eol:1; - u32 rsv0:7; - u32 chksum:8; - u32 rsv1:1; - u32 blkpad:1; - u32 dwpad:1; - u32 rsv2:13; - void *next; - void *ptr; - u32 buflen:16; - u32 rsv3:16; -}; - -struct msdc_dma { - struct gpd *gpd; /* pointer to gpd array */ - struct bd *bd; /* pointer to bd array */ - dma_addr_t gpd_addr; /* the physical address of gpd array */ - dma_addr_t bd_addr; /* the physical address of bd array */ -}; - -struct msdc_host { - struct msdc_hw *hw; - - struct mmc_host *mmc; /* mmc structure */ - struct mmc_command *cmd; - struct mmc_data *data; - struct mmc_request *mrq; - int cmd_rsp; - - int error; - spinlock_t lock; /* mutex */ - struct semaphore sem; - - u32 blksz; /* host block size */ - void __iomem *base; /* host base address */ - int id; /* host id */ - int pwr_ref; /* core power reference count */ - - u32 xfer_size; /* total transferred size */ - - struct msdc_dma dma; /* dma channel */ - u32 dma_xfer_size; /* dma transfer size in bytes */ - - u32 timeout_ns; /* data timeout ns */ - u32 timeout_clks; /* data timeout clks */ - - int irq; /* host interrupt */ - - struct delayed_work card_delaywork; - - struct completion cmd_done; - struct completion xfer_done; - struct pm_message pm_state; - - u32 mclk; /* mmc subsystem clock */ - u32 hclk; /* host clock speed */ - u32 sclk; /* SD/MS clock speed */ - u8 core_clkon; /* Host core clock on ? */ - u8 card_clkon; /* Card clock on ? */ - u8 core_power; /* core power */ - u8 power_mode; /* host power mode */ - u8 card_inserted; /* card inserted ? */ - u8 suspend; /* host suspended ? */ - u8 app_cmd; /* for app command */ - u32 app_cmd_arg; -}; - -static inline void sdr_set_bits(void __iomem *reg, u32 bs) -{ - u32 val = readl(reg); - - val |= bs; - writel(val, reg); -} - -static inline void sdr_clr_bits(void __iomem *reg, u32 bs) -{ - u32 val = readl(reg); - - val &= ~bs; - writel(val, reg); -} - -static inline void sdr_set_field(void __iomem *reg, u32 field, u32 val) -{ - unsigned int tv = readl(reg); - - tv &= ~field; - tv |= ((val) << (ffs((unsigned int)field) - 1)); - writel(tv, reg); -} - -static inline void sdr_get_field(void __iomem *reg, u32 field, u32 *val) -{ - unsigned int tv = readl(reg); - *val = ((tv & field) >> (ffs((unsigned int)field) - 1)); -} - -#endif diff --git a/drivers/staging/mt7621-mmc/sd.c b/drivers/staging/mt7621-mmc/sd.c deleted file mode 100644 index 04d23cc7cd4a..000000000000 --- a/drivers/staging/mt7621-mmc/sd.c +++ /dev/null @@ -1,2392 +0,0 @@ -/* Copyright Statement: - * - * This software/firmware and related documentation ("MediaTek Software") are - * protected under relevant copyright laws. The information contained herein - * is confidential and proprietary to MediaTek Inc. and/or its licensors. - * Without the prior written permission of MediaTek inc. and/or its licensors, - * any reproduction, modification, use or disclosure of MediaTek Software, - * and information contained herein, in whole or in part, shall be strictly prohibited. - * - * MediaTek Inc. (C) 2010. All rights reserved. - * - * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES - * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") - * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON - * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. - * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE - * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR - * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH - * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES - * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES - * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK - * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR - * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND - * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, - * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, - * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO - * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. - * - * The following software/firmware and/or related documentation ("MediaTek Software") - * have been modified by MediaTek Inc. All revisions are subject to any receiver's - * applicable license agreements with MediaTek Inc. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include "board.h" -#include "dbg.h" -#include "mt6575_sd.h" - -#ifdef CONFIG_SOC_MT7621 -#define RALINK_SYSCTL_BASE 0xbe000000 -#else -#define RALINK_SYSCTL_BASE 0xb0000000 -#endif - -#define DRV_NAME "mtk-sd" - -#if defined(CONFIG_SOC_MT7620) -#define HOST_MAX_MCLK (48000000) /* +/- by chhung */ -#elif defined(CONFIG_SOC_MT7621) -#define HOST_MAX_MCLK (50000000) /* +/- by chhung */ -#endif -#define HOST_MIN_MCLK (260000) - -#define HOST_MAX_BLKSZ (2048) - -#define MSDC_OCR_AVAIL (MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33) - -#define GPIO_PULL_DOWN (0) -#define GPIO_PULL_UP (1) - -#if 0 /* --- by chhung */ -#define MSDC_CLKSRC_REG (0xf100000C) -#define PDN_REG (0xF1000010) -#endif /* end of --- */ - -#define DEFAULT_DEBOUNCE (8) /* 8 cycles */ -#define DEFAULT_DTOC (40) /* data timeout counter. 65536x40 sclk. */ - -#define CMD_TIMEOUT (HZ / 10) /* 100ms */ -#define DAT_TIMEOUT (HZ / 2 * 5) /* 500ms x5 */ - -#define MAX_DMA_CNT (64 * 1024 - 512) /* a single transaction for WIFI may be 50K*/ - -#define MAX_GPD_NUM (1 + 1) /* one null gpd */ -#define MAX_BD_NUM (1024) - -#define MAX_HW_SGMTS (MAX_BD_NUM) -#define MAX_SGMT_SZ (MAX_DMA_CNT) -#define MAX_REQ_SZ (MAX_SGMT_SZ * 8) - -static int cd_active_low = 1; - -//================================= -#define PERI_MSDC0_PDN (15) -//#define PERI_MSDC1_PDN (16) -//#define PERI_MSDC2_PDN (17) -//#define PERI_MSDC3_PDN (18) - -#if 0 /* --- by chhung */ -/* gate means clock power down */ -static int g_clk_gate = 0; -#define msdc_gate_clock(id) \ - do { \ - g_clk_gate &= ~(1 << ((id) + PERI_MSDC0_PDN)); \ - } while (0) -/* not like power down register. 1 means clock on. */ -#define msdc_ungate_clock(id) \ - do { \ - g_clk_gate |= 1 << ((id) + PERI_MSDC0_PDN); \ - } while (0) - -// do we need sync object or not -void msdc_clk_status(int *status) -{ - *status = g_clk_gate; -} -#endif /* end of --- */ - -/* +++ by chhung */ -struct msdc_hw msdc0_hw = { - .clk_src = 0, - .flags = MSDC_CD_PIN_EN | MSDC_REMOVABLE, -// .flags = MSDC_WP_PIN_EN | MSDC_CD_PIN_EN | MSDC_REMOVABLE, -}; - -/* end of +++ */ - -static int msdc_rsp[] = { - 0, /* RESP_NONE */ - 1, /* RESP_R1 */ - 2, /* RESP_R2 */ - 3, /* RESP_R3 */ - 4, /* RESP_R4 */ - 1, /* RESP_R5 */ - 1, /* RESP_R6 */ - 1, /* RESP_R7 */ - 7, /* RESP_R1b */ -}; - -#define msdc_dma_on() sdr_clr_bits(host->base + MSDC_CFG, MSDC_CFG_PIO) - -static void msdc_reset_hw(struct msdc_host *host) -{ - sdr_set_bits(host->base + MSDC_CFG, MSDC_CFG_RST); - while (readl(host->base + MSDC_CFG) & MSDC_CFG_RST) - cpu_relax(); -} - -#define msdc_clr_int() \ - do { \ - volatile u32 val = readl(host->base + MSDC_INT); \ - writel(val, host->base + MSDC_INT); \ - } while (0) - -static void msdc_clr_fifo(struct msdc_host *host) -{ - sdr_set_bits(host->base + MSDC_FIFOCS, MSDC_FIFOCS_CLR); - while (readl(host->base + MSDC_FIFOCS) & MSDC_FIFOCS_CLR) - cpu_relax(); -} - -#define msdc_irq_save(val) \ - do { \ - val = readl(host->base + MSDC_INTEN); \ - sdr_clr_bits(host->base + MSDC_INTEN, val); \ - } while (0) - -#define msdc_irq_restore(val) \ - do { \ - sdr_set_bits(host->base + MSDC_INTEN, val); \ - } while (0) - -/* clock source for host: global */ -#if defined(CONFIG_SOC_MT7620) -static u32 hclks[] = {48000000}; /* +/- by chhung */ -#elif defined(CONFIG_SOC_MT7621) -static u32 hclks[] = {50000000}; /* +/- by chhung */ -#endif - -//============================================ -// the power for msdc host controller: global -// always keep the VMC on. -//============================================ -#define msdc_vcore_on(host) \ - do { \ - INIT_MSG("[+]VMC ref. count<%d>", ++host->pwr_ref); \ - (void)hwPowerOn(MT65XX_POWER_LDO_VMC, VOL_3300, "SD"); \ - } while (0) -#define msdc_vcore_off(host) \ - do { \ - INIT_MSG("[-]VMC ref. count<%d>", --host->pwr_ref); \ - (void)hwPowerDown(MT65XX_POWER_LDO_VMC, "SD"); \ - } while (0) - -//==================================== -// the vdd output for card: global -// always keep the VMCH on. -//==================================== -#define msdc_vdd_on(host) \ - do { \ - (void)hwPowerOn(MT65XX_POWER_LDO_VMCH, VOL_3300, "SD"); \ - } while (0) -#define msdc_vdd_off(host) \ - do { \ - (void)hwPowerDown(MT65XX_POWER_LDO_VMCH, "SD"); \ - } while (0) - -#define sdc_is_busy() (readl(host->base + SDC_STS) & SDC_STS_SDCBUSY) -#define sdc_is_cmd_busy() (readl(host->base + SDC_STS) & SDC_STS_CMDBUSY) - -#define sdc_send_cmd(cmd, arg) \ - do { \ - writel((arg), host->base + SDC_ARG); \ - writel((cmd), host->base + SDC_CMD); \ - } while (0) - -/* +++ by chhung */ -#ifndef __ASSEMBLY__ -#define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) -#else -#define PHYSADDR(a) ((a) & 0x1fffffff) -#endif -/* end of +++ */ -static unsigned int msdc_do_command(struct msdc_host *host, - struct mmc_command *cmd, - int tune, - unsigned long timeout); - -static int msdc_tune_cmdrsp(struct msdc_host *host, struct mmc_command *cmd); - -#ifdef MT6575_SD_DEBUG -static void msdc_dump_card_status(struct msdc_host *host, u32 status) -{ -/* N_MSG is currently a no-op */ -#if 0 - static char *state[] = { - "Idle", /* 0 */ - "Ready", /* 1 */ - "Ident", /* 2 */ - "Stby", /* 3 */ - "Tran", /* 4 */ - "Data", /* 5 */ - "Rcv", /* 6 */ - "Prg", /* 7 */ - "Dis", /* 8 */ - "Reserved", /* 9 */ - "Reserved", /* 10 */ - "Reserved", /* 11 */ - "Reserved", /* 12 */ - "Reserved", /* 13 */ - "Reserved", /* 14 */ - "I/O mode", /* 15 */ - }; -#endif - if (status & R1_OUT_OF_RANGE) - N_MSG(RSP, "[CARD_STATUS] Out of Range"); - if (status & R1_ADDRESS_ERROR) - N_MSG(RSP, "[CARD_STATUS] Address Error"); - if (status & R1_BLOCK_LEN_ERROR) - N_MSG(RSP, "[CARD_STATUS] Block Len Error"); - if (status & R1_ERASE_SEQ_ERROR) - N_MSG(RSP, "[CARD_STATUS] Erase Seq Error"); - if (status & R1_ERASE_PARAM) - N_MSG(RSP, "[CARD_STATUS] Erase Param"); - if (status & R1_WP_VIOLATION) - N_MSG(RSP, "[CARD_STATUS] WP Violation"); - if (status & R1_CARD_IS_LOCKED) - N_MSG(RSP, "[CARD_STATUS] Card is Locked"); - if (status & R1_LOCK_UNLOCK_FAILED) - N_MSG(RSP, "[CARD_STATUS] Lock/Unlock Failed"); - if (status & R1_COM_CRC_ERROR) - N_MSG(RSP, "[CARD_STATUS] Command CRC Error"); - if (status & R1_ILLEGAL_COMMAND) - N_MSG(RSP, "[CARD_STATUS] Illegal Command"); - if (status & R1_CARD_ECC_FAILED) - N_MSG(RSP, "[CARD_STATUS] Card ECC Failed"); - if (status & R1_CC_ERROR) - N_MSG(RSP, "[CARD_STATUS] CC Error"); - if (status & R1_ERROR) - N_MSG(RSP, "[CARD_STATUS] Error"); - if (status & R1_UNDERRUN) - N_MSG(RSP, "[CARD_STATUS] Underrun"); - if (status & R1_OVERRUN) - N_MSG(RSP, "[CARD_STATUS] Overrun"); - if (status & R1_CID_CSD_OVERWRITE) - N_MSG(RSP, "[CARD_STATUS] CID/CSD Overwrite"); - if (status & R1_WP_ERASE_SKIP) - N_MSG(RSP, "[CARD_STATUS] WP Eraser Skip"); - if (status & R1_CARD_ECC_DISABLED) - N_MSG(RSP, "[CARD_STATUS] Card ECC Disabled"); - if (status & R1_ERASE_RESET) - N_MSG(RSP, "[CARD_STATUS] Erase Reset"); - if (status & R1_READY_FOR_DATA) - N_MSG(RSP, "[CARD_STATUS] Ready for Data"); - if (status & R1_SWITCH_ERROR) - N_MSG(RSP, "[CARD_STATUS] Switch error"); - if (status & R1_APP_CMD) - N_MSG(RSP, "[CARD_STATUS] App Command"); - - N_MSG(RSP, "[CARD_STATUS] '%s' State", state[R1_CURRENT_STATE(status)]); -} - -static void msdc_dump_ocr_reg(struct msdc_host *host, u32 resp) -{ - if (resp & (1 << 7)) - N_MSG(RSP, "[OCR] Low Voltage Range"); - if (resp & (1 << 15)) - N_MSG(RSP, "[OCR] 2.7-2.8 volt"); - if (resp & (1 << 16)) - N_MSG(RSP, "[OCR] 2.8-2.9 volt"); - if (resp & (1 << 17)) - N_MSG(RSP, "[OCR] 2.9-3.0 volt"); - if (resp & (1 << 18)) - N_MSG(RSP, "[OCR] 3.0-3.1 volt"); - if (resp & (1 << 19)) - N_MSG(RSP, "[OCR] 3.1-3.2 volt"); - if (resp & (1 << 20)) - N_MSG(RSP, "[OCR] 3.2-3.3 volt"); - if (resp & (1 << 21)) - N_MSG(RSP, "[OCR] 3.3-3.4 volt"); - if (resp & (1 << 22)) - N_MSG(RSP, "[OCR] 3.4-3.5 volt"); - if (resp & (1 << 23)) - N_MSG(RSP, "[OCR] 3.5-3.6 volt"); - if (resp & (1 << 24)) - N_MSG(RSP, "[OCR] Switching to 1.8V Accepted (S18A)"); - if (resp & (1 << 30)) - N_MSG(RSP, "[OCR] Card Capacity Status (CCS)"); - if (resp & (1 << 31)) - N_MSG(RSP, "[OCR] Card Power Up Status (Idle)"); - else - N_MSG(RSP, "[OCR] Card Power Up Status (Busy)"); -} - -static void msdc_dump_rca_resp(struct msdc_host *host, u32 resp) -{ - u32 status = (((resp >> 15) & 0x1) << 23) | - (((resp >> 14) & 0x1) << 22) | - (((resp >> 13) & 0x1) << 19) | - (resp & 0x1fff); - - N_MSG(RSP, "[RCA] 0x%.4x", resp >> 16); - msdc_dump_card_status(host, status); -} - -static void msdc_dump_io_resp(struct msdc_host *host, u32 resp) -{ - u32 flags = (resp >> 8) & 0xFF; -#if 0 - char *state[] = {"DIS", "CMD", "TRN", "RFU"}; -#endif - if (flags & (1 << 7)) - N_MSG(RSP, "[IO] COM_CRC_ERR"); - if (flags & (1 << 6)) - N_MSG(RSP, "[IO] Illegal command"); - if (flags & (1 << 3)) - N_MSG(RSP, "[IO] Error"); - if (flags & (1 << 2)) - N_MSG(RSP, "[IO] RFU"); - if (flags & (1 << 1)) - N_MSG(RSP, "[IO] Function number error"); - if (flags & (1 << 0)) - N_MSG(RSP, "[IO] Out of range"); - - N_MSG(RSP, "[IO] State: %s, Data:0x%x", state[(resp >> 12) & 0x3], resp & 0xFF); -} -#endif - -static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) -{ - u32 timeout, clk_ns; - - host->timeout_ns = ns; - host->timeout_clks = clks; - - clk_ns = 1000000000UL / host->sclk; - timeout = ns / clk_ns + clks; - timeout = timeout >> 16; /* in 65536 sclk cycle unit */ - timeout = timeout > 1 ? timeout - 1 : 0; - timeout = timeout > 255 ? 255 : timeout; - - sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, timeout); - - N_MSG(OPS, "Set read data timeout: %dns %dclks -> %d x 65536 cycles", - ns, clks, timeout + 1); -} - -static void msdc_tasklet_card(struct work_struct *work) -{ - struct msdc_host *host = (struct msdc_host *)container_of(work, - struct msdc_host, card_delaywork.work); - u32 inserted; - u32 status = 0; - //u32 change = 0; - - spin_lock(&host->lock); - - status = readl(host->base + MSDC_PS); - if (cd_active_low) - inserted = (status & MSDC_PS_CDSTS) ? 0 : 1; - else - inserted = (status & MSDC_PS_CDSTS) ? 1 : 0; - -#if 0 - change = host->card_inserted ^ inserted; - host->card_inserted = inserted; - - if (change && !host->suspend) { - if (inserted) - host->mmc->f_max = HOST_MAX_MCLK; // work around - mmc_detect_change(host->mmc, msecs_to_jiffies(20)); - } -#else /* Make sure: handle the last interrupt */ - host->card_inserted = inserted; - - if (!host->suspend) { - host->mmc->f_max = HOST_MAX_MCLK; - mmc_detect_change(host->mmc, msecs_to_jiffies(20)); - } - - IRQ_MSG("card found<%s>", inserted ? "inserted" : "removed"); -#endif - - spin_unlock(&host->lock); -} - -#if 0 /* --- by chhung */ -/* For E2 only */ -static u8 clk_src_bit[4] = { - 0, 3, 5, 7 -}; - -static void msdc_select_clksrc(struct msdc_host *host, unsigned char clksrc) -{ - u32 val; - - BUG_ON(clksrc > 3); - INIT_MSG("set clock source to <%d>", clksrc); - - val = readl(host->base + MSDC_CLKSRC_REG); - if (readl(host->base + MSDC_ECO_VER) >= 4) { - val &= ~(0x3 << clk_src_bit[host->id]); - val |= clksrc << clk_src_bit[host->id]; - } else { - val &= ~0x3; val |= clksrc; - } - writel(val, host->base + MSDC_CLKSRC_REG); - - host->hclk = hclks[clksrc]; - host->hw->clk_src = clksrc; -} -#endif /* end of --- */ - -static void msdc_set_mclk(struct msdc_host *host, int ddr, unsigned int hz) -{ - //struct msdc_hw *hw = host->hw; - u32 mode; - u32 flags; - u32 div; - u32 sclk; - u32 hclk = host->hclk; - //u8 clksrc = hw->clk_src; - - if (!hz) { // set mmc system clock to 0 ? - //ERR_MSG("set mclk to 0!!!"); - msdc_reset_hw(host); - return; - } - - msdc_irq_save(flags); - - if (ddr) { - mode = 0x2; /* ddr mode and use divisor */ - if (hz >= (hclk >> 2)) { - div = 1; /* mean div = 1/4 */ - sclk = hclk >> 2; /* sclk = clk / 4 */ - } else { - div = (hclk + ((hz << 2) - 1)) / (hz << 2); - sclk = (hclk >> 2) / div; - } - } else if (hz >= hclk) { /* bug fix */ - mode = 0x1; /* no divisor and divisor is ignored */ - div = 0; - sclk = hclk; - } else { - mode = 0x0; /* use divisor */ - if (hz >= (hclk >> 1)) { - div = 0; /* mean div = 1/2 */ - sclk = hclk >> 1; /* sclk = clk / 2 */ - } else { - div = (hclk + ((hz << 2) - 1)) / (hz << 2); - sclk = (hclk >> 2) / div; - } - } - - /* set clock mode and divisor */ - sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKMOD, mode); - sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_CKDIV, div); - - /* wait clock stable */ - while (!(readl(host->base + MSDC_CFG) & MSDC_CFG_CKSTB)) - cpu_relax(); - - host->sclk = sclk; - host->mclk = hz; - msdc_set_timeout(host, host->timeout_ns, host->timeout_clks); // need? - - INIT_MSG("================"); - INIT_MSG("!!! Set<%dKHz> Source<%dKHz> -> sclk<%dKHz>", hz / 1000, hclk / 1000, sclk / 1000); - INIT_MSG("================"); - - msdc_irq_restore(flags); -} - -/* Fix me. when need to abort */ -static void msdc_abort_data(struct msdc_host *host) -{ - struct mmc_command *stop = host->mrq->stop; - - ERR_MSG("Need to Abort."); - - msdc_reset_hw(host); - msdc_clr_fifo(host); - msdc_clr_int(); - - // need to check FIFO count 0 ? - - if (stop) { /* try to stop, but may not success */ - ERR_MSG("stop when abort CMD<%d>", stop->opcode); - (void)msdc_do_command(host, stop, 0, CMD_TIMEOUT); - } - - //if (host->mclk >= 25000000) { - // msdc_set_mclk(host, 0, host->mclk >> 1); - //} -} - -#if 0 /* --- by chhung */ -static void msdc_pin_config(struct msdc_host *host, int mode) -{ - struct msdc_hw *hw = host->hw; - int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; - - /* Config WP pin */ - if (hw->flags & MSDC_WP_PIN_EN) { - if (hw->config_gpio_pin) /* NULL */ - hw->config_gpio_pin(MSDC_WP_PIN, pull); - } - - switch (mode) { - case MSDC_PIN_PULL_UP: - //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 1); /* Check & FIXME */ - //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 1); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 1); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); - break; - case MSDC_PIN_PULL_DOWN: - //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ - //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 1); /* Check & FIXME */ - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 1); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 1); - break; - case MSDC_PIN_PULL_NONE: - default: - //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPU, 0); /* Check & FIXME */ - //sdr_set_field(MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKPD, 0); /* Check & FIXME */ - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPU, 0); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDPD, 0); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPU, 0); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATPD, 0); - break; - } - - N_MSG(CFG, "Pins mode(%d), down(%d), up(%d)", - mode, MSDC_PIN_PULL_DOWN, MSDC_PIN_PULL_UP); -} - -void msdc_pin_reset(struct msdc_host *host, int mode) -{ - struct msdc_hw *hw = (struct msdc_hw *)host->hw; - int pull = (mode == MSDC_PIN_PULL_UP) ? GPIO_PULL_UP : GPIO_PULL_DOWN; - - /* Config reset pin */ - if (hw->flags & MSDC_RST_PIN_EN) { - if (hw->config_gpio_pin) /* NULL */ - hw->config_gpio_pin(MSDC_RST_PIN, pull); - - if (mode == MSDC_PIN_PULL_UP) - sdr_clr_bits(host->base + EMMC_IOCON, EMMC_IOCON_BOOTRST); - else - sdr_set_bits(host->base + EMMC_IOCON, EMMC_IOCON_BOOTRST); - } -} - -static void msdc_core_power(struct msdc_host *host, int on) -{ - N_MSG(CFG, "Turn %s %s power (copower: %d -> %d)", - on ? "on" : "off", "core", host->core_power, on); - - if (on && host->core_power == 0) { - msdc_vcore_on(host); - host->core_power = 1; - msleep(1); - } else if (!on && host->core_power == 1) { - msdc_vcore_off(host); - host->core_power = 0; - msleep(1); - } -} - -static void msdc_host_power(struct msdc_host *host, int on) -{ - N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "host"); - - if (on) { - //msdc_core_power(host, 1); // need do card detection. - msdc_pin_reset(host, MSDC_PIN_PULL_UP); - } else { - msdc_pin_reset(host, MSDC_PIN_PULL_DOWN); - //msdc_core_power(host, 0); - } -} - -static void msdc_card_power(struct msdc_host *host, int on) -{ - N_MSG(CFG, "Turn %s %s power ", on ? "on" : "off", "card"); - - if (on) { - msdc_pin_config(host, MSDC_PIN_PULL_UP); - //msdc_vdd_on(host); // need todo card detection. - msleep(1); - } else { - //msdc_vdd_off(host); - msdc_pin_config(host, MSDC_PIN_PULL_DOWN); - msleep(1); - } -} - -static void msdc_set_power_mode(struct msdc_host *host, u8 mode) -{ - N_MSG(CFG, "Set power mode(%d)", mode); - - if (host->power_mode == MMC_POWER_OFF && mode != MMC_POWER_OFF) { - msdc_host_power(host, 1); - msdc_card_power(host, 1); - } else if (host->power_mode != MMC_POWER_OFF && mode == MMC_POWER_OFF) { - msdc_card_power(host, 0); - msdc_host_power(host, 0); - } - host->power_mode = mode; -} -#endif /* end of --- */ - -#ifdef CONFIG_PM -/* - register as callback function of WIFI(combo_sdio_register_pm) . - can called by msdc_drv_suspend/resume too. -*/ -static void msdc_pm(pm_message_t state, void *data) -{ - struct msdc_host *host = (struct msdc_host *)data; - int evt = state.event; - - if (evt == PM_EVENT_USER_RESUME || evt == PM_EVENT_USER_SUSPEND) { - INIT_MSG("USR_%s: suspend<%d> power<%d>", - evt == PM_EVENT_USER_RESUME ? "EVENT_USER_RESUME" : "EVENT_USER_SUSPEND", - host->suspend, host->power_mode); - } - - if (evt == PM_EVENT_SUSPEND || evt == PM_EVENT_USER_SUSPEND) { - if (host->suspend) /* already suspend */ /* default 0*/ - return; - - /* for memory card. already power off by mmc */ - if (evt == PM_EVENT_SUSPEND && host->power_mode == MMC_POWER_OFF) - return; - - host->suspend = 1; - host->pm_state = state; /* default PMSG_RESUME */ - - } else if (evt == PM_EVENT_RESUME || evt == PM_EVENT_USER_RESUME) { - if (!host->suspend) { - //ERR_MSG("warning: already resume"); - return; - } - - /* No PM resume when USR suspend */ - if (evt == PM_EVENT_RESUME && host->pm_state.event == PM_EVENT_USER_SUSPEND) { - ERR_MSG("PM Resume when in USR Suspend"); /* won't happen. */ - return; - } - - host->suspend = 0; - host->pm_state = state; - - } -} -#endif - -static inline u32 msdc_cmd_find_resp(struct mmc_command *cmd) -{ - u32 opcode = cmd->opcode; - u32 resp; - - if (opcode == MMC_SET_RELATIVE_ADDR) { - resp = (mmc_cmd_type(cmd) == MMC_CMD_BCR) ? RESP_R6 : RESP_R1; - } else if (opcode == MMC_FAST_IO) { - resp = RESP_R4; - } else if (opcode == MMC_GO_IRQ_STATE) { - resp = RESP_R5; - } else if (opcode == MMC_SELECT_CARD) { - resp = (cmd->arg != 0) ? RESP_R1B : RESP_NONE; - } else if (opcode == SD_IO_RW_DIRECT || opcode == SD_IO_RW_EXTENDED) { - resp = RESP_R1; /* SDIO workaround. */ - } else if (opcode == SD_SEND_IF_COND && (mmc_cmd_type(cmd) == MMC_CMD_BCR)) { - resp = RESP_R1; - } else { - switch (mmc_resp_type(cmd)) { - case MMC_RSP_R1: - resp = RESP_R1; - break; - case MMC_RSP_R1B: - resp = RESP_R1B; - break; - case MMC_RSP_R2: - resp = RESP_R2; - break; - case MMC_RSP_R3: - resp = RESP_R3; - break; - case MMC_RSP_NONE: - default: - resp = RESP_NONE; - break; - } - } - - return resp; -} - -/*--------------------------------------------------------------------------*/ -/* mmc_host_ops members */ -/*--------------------------------------------------------------------------*/ -static unsigned int msdc_command_start(struct msdc_host *host, - struct mmc_command *cmd, - unsigned long timeout) -{ - u32 opcode = cmd->opcode; - u32 rawcmd; - u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | - MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | - MSDC_INT_ACMD19_DONE; - - u32 resp; - unsigned long tmo; - - /* Protocol layer does not provide response type, but our hardware needs - * to know exact type, not just size! - */ - resp = msdc_cmd_find_resp(cmd); - - cmd->error = 0; - /* rawcmd : - * vol_swt << 30 | auto_cmd << 28 | blklen << 16 | go_irq << 15 | - * stop << 14 | rw << 13 | dtype << 11 | rsptyp << 7 | brk << 6 | opcode - */ - rawcmd = opcode | msdc_rsp[resp] << 7 | host->blksz << 16; - - if (opcode == MMC_READ_MULTIPLE_BLOCK) { - rawcmd |= (2 << 11); - } else if (opcode == MMC_READ_SINGLE_BLOCK) { - rawcmd |= (1 << 11); - } else if (opcode == MMC_WRITE_MULTIPLE_BLOCK) { - rawcmd |= ((2 << 11) | (1 << 13)); - } else if (opcode == MMC_WRITE_BLOCK) { - rawcmd |= ((1 << 11) | (1 << 13)); - } else if (opcode == SD_IO_RW_EXTENDED) { - if (cmd->data->flags & MMC_DATA_WRITE) - rawcmd |= (1 << 13); - if (cmd->data->blocks > 1) - rawcmd |= (2 << 11); - else - rawcmd |= (1 << 11); - } else if (opcode == SD_IO_RW_DIRECT && cmd->flags == (unsigned int)-1) { - rawcmd |= (1 << 14); - } else if ((opcode == SD_APP_SEND_SCR) || - (opcode == SD_APP_SEND_NUM_WR_BLKS) || - (opcode == SD_SWITCH && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || - (opcode == SD_APP_SD_STATUS && (mmc_cmd_type(cmd) == MMC_CMD_ADTC)) || - (opcode == MMC_SEND_EXT_CSD && (mmc_cmd_type(cmd) == MMC_CMD_ADTC))) { - rawcmd |= (1 << 11); - } else if (opcode == MMC_STOP_TRANSMISSION) { - rawcmd |= (1 << 14); - rawcmd &= ~(0x0FFF << 16); - } - - N_MSG(CMD, "CMD<%d><0x%.8x> Arg<0x%.8x>", opcode, rawcmd, cmd->arg); - - tmo = jiffies + timeout; - - if (opcode == MMC_SEND_STATUS) { - for (;;) { - if (!sdc_is_cmd_busy()) - break; - - if (time_after(jiffies, tmo)) { - ERR_MSG("XXX cmd_busy timeout: before CMD<%d>", opcode); - cmd->error = -ETIMEDOUT; - msdc_reset_hw(host); - goto end; - } - } - } else { - for (;;) { - if (!sdc_is_busy()) - break; - if (time_after(jiffies, tmo)) { - ERR_MSG("XXX sdc_busy timeout: before CMD<%d>", opcode); - cmd->error = -ETIMEDOUT; - msdc_reset_hw(host); - goto end; - } - } - } - - //BUG_ON(in_interrupt()); - host->cmd = cmd; - host->cmd_rsp = resp; - - init_completion(&host->cmd_done); - - sdr_set_bits(host->base + MSDC_INTEN, wints); - sdc_send_cmd(rawcmd, cmd->arg); - -end: - return cmd->error; -} - -static unsigned int msdc_command_resp(struct msdc_host *host, - struct mmc_command *cmd, - int tune, - unsigned long timeout) - __must_hold(&host->lock) -{ - u32 opcode = cmd->opcode; - //u32 rawcmd; - u32 wints = MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | - MSDC_INT_ACMDRDY | MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | - MSDC_INT_ACMD19_DONE; - - BUG_ON(in_interrupt()); - //init_completion(&host->cmd_done); - //sdr_set_bits(host->base + MSDC_INTEN, wints); - - spin_unlock(&host->lock); - if (!wait_for_completion_timeout(&host->cmd_done, 10 * timeout)) { - ERR_MSG("XXX CMD<%d> wait_for_completion timeout ARG<0x%.8x>", opcode, cmd->arg); - cmd->error = -ETIMEDOUT; - msdc_reset_hw(host); - } - spin_lock(&host->lock); - - sdr_clr_bits(host->base + MSDC_INTEN, wints); - host->cmd = NULL; - -//end: -#ifdef MT6575_SD_DEBUG - switch (resp) { - case RESP_NONE: - N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)", opcode, cmd->error, resp); - break; - case RESP_R2: - N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= %.8x %.8x %.8x %.8x", - opcode, cmd->error, resp, cmd->resp[0], cmd->resp[1], - cmd->resp[2], cmd->resp[3]); - break; - default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ - N_MSG(RSP, "CMD_RSP(%d): %d RSP(%d)= 0x%.8x", - opcode, cmd->error, resp, cmd->resp[0]); - if (cmd->error == 0) { - switch (resp) { - case RESP_R1: - case RESP_R1B: - msdc_dump_card_status(host, cmd->resp[0]); - break; - case RESP_R3: - msdc_dump_ocr_reg(host, cmd->resp[0]); - break; - case RESP_R5: - msdc_dump_io_resp(host, cmd->resp[0]); - break; - case RESP_R6: - msdc_dump_rca_resp(host, cmd->resp[0]); - break; - } - } - break; - } -#endif - - /* do we need to save card's RCA when SD_SEND_RELATIVE_ADDR */ - - if (!tune) - return cmd->error; - - /* memory card CRC */ - if (host->hw->flags & MSDC_REMOVABLE && cmd->error == -EIO) { - /* check if has data phase */ - if (readl(host->base + SDC_CMD) & 0x1800) { - msdc_abort_data(host); - } else { - /* do basic: reset*/ - msdc_reset_hw(host); - msdc_clr_fifo(host); - msdc_clr_int(); - } - cmd->error = msdc_tune_cmdrsp(host, cmd); - } - - // check DAT0 - /* if (resp == RESP_R1B) { - while ((readl(host->base + MSDC_PS) & 0x10000) != 0x10000); - } */ - /* CMD12 Error Handle */ - - return cmd->error; -} - -static unsigned int msdc_do_command(struct msdc_host *host, - struct mmc_command *cmd, - int tune, - unsigned long timeout) -{ - if (msdc_command_start(host, cmd, timeout)) - goto end; - - if (msdc_command_resp(host, cmd, tune, timeout)) - goto end; - -end: - - N_MSG(CMD, " return<%d> resp<0x%.8x>", cmd->error, cmd->resp[0]); - return cmd->error; -} - -#if 0 /* --- by chhung */ -// DMA resume / start / stop -static void msdc_dma_resume(struct msdc_host *host) -{ - sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_RESUME, 1); - - N_MSG(DMA, "DMA resume"); -} -#endif /* end of --- */ - -static void msdc_dma_start(struct msdc_host *host) -{ - u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR; - - sdr_set_bits(host->base + MSDC_INTEN, wints); - //dsb(); /* --- by chhung */ - sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); - - N_MSG(DMA, "DMA start"); -} - -static void msdc_dma_stop(struct msdc_host *host) -{ - //u32 retries=500; - u32 wints = MSDC_INTEN_XFER_COMPL | MSDC_INTEN_DATTMO | MSDC_INTEN_DATCRCERR; - - N_MSG(DMA, "DMA status: 0x%.8x", readl(host->base + MSDC_DMA_CFG)); - //while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS); - - sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_STOP, 1); - while (readl(host->base + MSDC_DMA_CFG) & MSDC_DMA_CFG_STS) - ; - - //dsb(); /* --- by chhung */ - sdr_clr_bits(host->base + MSDC_INTEN, wints); /* Not just xfer_comp */ - - N_MSG(DMA, "DMA stop"); -} - -/* calc checksum */ -static u8 msdc_dma_calcs(u8 *buf, u32 len) -{ - u32 i, sum = 0; - - for (i = 0; i < len; i++) - sum += buf[i]; - return 0xFF - (u8)sum; -} - -static void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, - struct scatterlist *sg_cmd, unsigned int sglen) -{ - struct scatterlist *sg; - struct gpd *gpd; - struct bd *bd; - u32 j; - - BUG_ON(sglen > MAX_BD_NUM); /* not support currently */ - - N_MSG(DMA, "DMA sglen<%d> xfersz<%d>", sglen, host->xfer_size); - - gpd = dma->gpd; - bd = dma->bd; - - /* modify gpd*/ - //gpd->intr = 0; - gpd->hwo = 1; /* hw will clear it */ - gpd->bdp = 1; - gpd->chksum = 0; /* need to clear first. */ - gpd->chksum = msdc_dma_calcs((u8 *)gpd, 16); - - /* modify bd*/ - for_each_sg(sg_cmd, sg, sglen, j) { - bd[j].blkpad = 0; - bd[j].dwpad = 0; - bd[j].ptr = (void *)sg_dma_address(sg); - bd[j].buflen = sg_dma_len(sg); - - if (j == sglen - 1) - bd[j].eol = 1; /* the last bd */ - else - bd[j].eol = 0; - - bd[j].chksum = 0; /* checksume need to clear first */ - bd[j].chksum = msdc_dma_calcs((u8 *)(&bd[j]), 16); - } - - sdr_set_field(host->base + MSDC_DMA_CFG, MSDC_DMA_CFG_DECSEN, 1); - sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_BRUSTSZ, - MSDC_BRUST_64B); - sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_MODE, 1); - - writel(PHYSADDR((u32)dma->gpd_addr), host->base + MSDC_DMA_SA); - - N_MSG(DMA, "DMA_CTRL = 0x%x", readl(host->base + MSDC_DMA_CTRL)); - N_MSG(DMA, "DMA_CFG = 0x%x", readl(host->base + MSDC_DMA_CFG)); - N_MSG(DMA, "DMA_SA = 0x%x", readl(host->base + MSDC_DMA_SA)); -} - -static int msdc_do_request(struct mmc_host *mmc, struct mmc_request *mrq) - __must_hold(&host->lock) -{ - struct msdc_host *host = mmc_priv(mmc); - struct mmc_command *cmd; - struct mmc_data *data; - //u32 intsts = 0; - int read = 1, send_type = 0; - -#define SND_DAT 0 -#define SND_CMD 1 - - BUG_ON(mmc == NULL); - BUG_ON(mrq == NULL); - - host->error = 0; - - cmd = mrq->cmd; - data = mrq->cmd->data; - -#if 0 /* --- by chhung */ - //if(host->id ==1){ - N_MSG(OPS, "enable clock!"); - msdc_ungate_clock(host->id); - //} -#endif /* end of --- */ - - if (!data) { - send_type = SND_CMD; - if (msdc_do_command(host, cmd, 1, CMD_TIMEOUT) != 0) - goto done; - } else { - BUG_ON(data->blksz > HOST_MAX_BLKSZ); - send_type = SND_DAT; - - data->error = 0; - read = data->flags & MMC_DATA_READ ? 1 : 0; - host->data = data; - host->xfer_size = data->blocks * data->blksz; - host->blksz = data->blksz; - - if (read) { - if ((host->timeout_ns != data->timeout_ns) || - (host->timeout_clks != data->timeout_clks)) { - msdc_set_timeout(host, data->timeout_ns, data->timeout_clks); - } - } - - writel(data->blocks, host->base + SDC_BLK_NUM); - //msdc_clr_fifo(host); /* no need */ - - msdc_dma_on(); /* enable DMA mode first!! */ - init_completion(&host->xfer_done); - - /* start the command first*/ - if (msdc_command_start(host, cmd, CMD_TIMEOUT) != 0) - goto done; - - data->sg_count = dma_map_sg(mmc_dev(mmc), data->sg, - data->sg_len, - mmc_get_dma_dir(data)); - msdc_dma_setup(host, &host->dma, data->sg, - data->sg_count); - - /* then wait command done */ - if (msdc_command_resp(host, cmd, 1, CMD_TIMEOUT) != 0) - goto done; - - /* for read, the data coming too fast, then CRC error - start DMA no business with CRC. */ - //init_completion(&host->xfer_done); - msdc_dma_start(host); - - spin_unlock(&host->lock); - if (!wait_for_completion_timeout(&host->xfer_done, DAT_TIMEOUT)) { - ERR_MSG("XXX CMD<%d> wait xfer_done<%d> timeout!!", cmd->opcode, data->blocks * data->blksz); - ERR_MSG(" DMA_SA = 0x%x", - readl(host->base + MSDC_DMA_SA)); - ERR_MSG(" DMA_CA = 0x%x", - readl(host->base + MSDC_DMA_CA)); - ERR_MSG(" DMA_CTRL = 0x%x", - readl(host->base + MSDC_DMA_CTRL)); - ERR_MSG(" DMA_CFG = 0x%x", - readl(host->base + MSDC_DMA_CFG)); - data->error = -ETIMEDOUT; - - msdc_reset_hw(host); - msdc_clr_fifo(host); - msdc_clr_int(); - } - spin_lock(&host->lock); - msdc_dma_stop(host); - - /* Last: stop transfer */ - if (data->stop) { - if (msdc_do_command(host, data->stop, 0, CMD_TIMEOUT) != 0) - goto done; - } - } - -done: - if (data != NULL) { - host->data = NULL; - dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, - mmc_get_dma_dir(data)); - host->blksz = 0; - -#if 0 // don't stop twice! - if (host->hw->flags & MSDC_REMOVABLE && data->error) { - msdc_abort_data(host); - /* reset in IRQ, stop command has issued. -> No need */ - } -#endif - - N_MSG(OPS, "CMD<%d> data<%s %s> blksz<%d> block<%d> error<%d>", cmd->opcode, (dma ? "dma" : "pio"), - (read ? "read " : "write"), data->blksz, data->blocks, data->error); - } - -#if 0 /* --- by chhung */ -#if 1 - //if(host->id==1) { - if (send_type == SND_CMD) { - if (cmd->opcode == MMC_SEND_STATUS) { - if ((cmd->resp[0] & CARD_READY_FOR_DATA) || (CARD_CURRENT_STATE(cmd->resp[0]) != 7)) { - N_MSG(OPS, "disable clock, CMD13 IDLE"); - msdc_gate_clock(host->id); - } - } else { - N_MSG(OPS, "disable clock, CMD<%d>", cmd->opcode); - msdc_gate_clock(host->id); - } - } else { - if (read) { - N_MSG(OPS, "disable clock!!! Read CMD<%d>", cmd->opcode); - msdc_gate_clock(host->id); - } - } - //} -#else - msdc_gate_clock(host->id); -#endif -#endif /* end of --- */ - - if (mrq->cmd->error) - host->error = 0x001; - if (mrq->data && mrq->data->error) - host->error |= 0x010; - if (mrq->stop && mrq->stop->error) - host->error |= 0x100; - - //if (host->error) ERR_MSG("host->error<%d>", host->error); - - return host->error; -} - -static int msdc_app_cmd(struct mmc_host *mmc, struct msdc_host *host) -{ - struct mmc_command cmd; - struct mmc_request mrq; - u32 err; - - memset(&cmd, 0, sizeof(struct mmc_command)); - cmd.opcode = MMC_APP_CMD; -#if 0 /* bug: we meet mmc->card is null when ACMD6 */ - cmd.arg = mmc->card->rca << 16; -#else - cmd.arg = host->app_cmd_arg; -#endif - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - - memset(&mrq, 0, sizeof(struct mmc_request)); - mrq.cmd = &cmd; cmd.mrq = &mrq; - cmd.data = NULL; - - err = msdc_do_command(host, &cmd, 0, CMD_TIMEOUT); - return err; -} - -static int msdc_tune_cmdrsp(struct msdc_host *host, struct mmc_command *cmd) -{ - int result = -1; - u32 rsmpl, cur_rsmpl, orig_rsmpl; - u32 rrdly, cur_rrdly = 0xffffffff, orig_rrdly; - u32 skip = 1; - - /* ==== don't support 3.0 now ==== - 1: R_SMPL[1] - 2: PAD_CMD_RESP_RXDLY[26:22] - ==========================*/ - - // save the previous tune result - sdr_get_field(host->base + MSDC_IOCON, MSDC_IOCON_RSPL, &orig_rsmpl); - sdr_get_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_CMDRRDLY, - &orig_rrdly); - - rrdly = 0; - do { - for (rsmpl = 0; rsmpl < 2; rsmpl++) { - /* Lv1: R_SMPL[1] */ - cur_rsmpl = (orig_rsmpl + rsmpl) % 2; - if (skip == 1) { - skip = 0; - continue; - } - sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_RSPL, - cur_rsmpl); - - if (host->app_cmd) { - result = msdc_app_cmd(host->mmc, host); - if (result) { - ERR_MSG("TUNE_CMD app_cmd<%d> failed: RESP_RXDLY<%d>,R_SMPL<%d>", - host->mrq->cmd->opcode, cur_rrdly, cur_rsmpl); - continue; - } - } - result = msdc_do_command(host, cmd, 0, CMD_TIMEOUT); // not tune. - ERR_MSG("TUNE_CMD<%d> %s PAD_CMD_RESP_RXDLY[26:22]<%d> R_SMPL[1]<%d>", cmd->opcode, - (result == 0) ? "PASS" : "FAIL", cur_rrdly, cur_rsmpl); - - if (result == 0) - return 0; - if (result != -EIO) { - ERR_MSG("TUNE_CMD<%d> Error<%d> not -EIO", cmd->opcode, result); - return result; - } - - /* should be EIO */ - /* check if has data phase */ - if (readl(host->base + SDC_CMD) & 0x1800) - msdc_abort_data(host); - } - - /* Lv2: PAD_CMD_RESP_RXDLY[26:22] */ - cur_rrdly = (orig_rrdly + rrdly + 1) % 32; - sdr_set_field(host->base + MSDC_PAD_TUNE, - MSDC_PAD_TUNE_CMDRRDLY, cur_rrdly); - } while (++rrdly < 32); - - return result; -} - -/* Support SD2.0 Only */ -static int msdc_tune_bread(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct msdc_host *host = mmc_priv(mmc); - u32 ddr = 0; - u32 dcrc = 0; - u32 rxdly, cur_rxdly0, cur_rxdly1; - u32 dsmpl, cur_dsmpl, orig_dsmpl; - u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; - u32 cur_dat4, cur_dat5, cur_dat6, cur_dat7; - u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; - u32 orig_dat4, orig_dat5, orig_dat6, orig_dat7; - int result = -1; - u32 skip = 1; - - sdr_get_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, &orig_dsmpl); - - /* Tune Method 2. */ - sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); - - rxdly = 0; - do { - for (dsmpl = 0; dsmpl < 2; dsmpl++) { - cur_dsmpl = (orig_dsmpl + dsmpl) % 2; - if (skip == 1) { - skip = 0; - continue; - } - sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, - cur_dsmpl); - - if (host->app_cmd) { - result = msdc_app_cmd(host->mmc, host); - if (result) { - ERR_MSG("TUNE_BREAD app_cmd<%d> failed", host->mrq->cmd->opcode); - continue; - } - } - result = msdc_do_request(mmc, mrq); - - sdr_get_field(host->base + SDC_DCRC_STS, - SDC_DCRC_STS_POS | SDC_DCRC_STS_NEG, - &dcrc); /* RO */ - if (!ddr) - dcrc &= ~SDC_DCRC_STS_NEG; - ERR_MSG("TUNE_BREAD<%s> dcrc<0x%x> DATRDDLY0/1<0x%x><0x%x> dsmpl<0x%x>", - (result == 0 && dcrc == 0) ? "PASS" : "FAIL", dcrc, - readl(host->base + MSDC_DAT_RDDLY0), - readl(host->base + MSDC_DAT_RDDLY1), cur_dsmpl); - - /* Fix me: result is 0, but dcrc is still exist */ - if (result == 0 && dcrc == 0) { - goto done; - } else { - /* there is a case: command timeout, and data phase not processed */ - if (mrq->data->error != 0 && - mrq->data->error != -EIO) { - ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", - result, mrq->cmd->error, mrq->data->error); - goto done; - } - } - } - - cur_rxdly0 = readl(host->base + MSDC_DAT_RDDLY0); - cur_rxdly1 = readl(host->base + MSDC_DAT_RDDLY1); - - /* E1 ECO. YD: Reverse */ - if (readl(host->base + MSDC_ECO_VER) >= 4) { - orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; - orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; - orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; - orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; - orig_dat4 = (cur_rxdly1 >> 24) & 0x1F; - orig_dat5 = (cur_rxdly1 >> 16) & 0x1F; - orig_dat6 = (cur_rxdly1 >> 8) & 0x1F; - orig_dat7 = (cur_rxdly1 >> 0) & 0x1F; - } else { - orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; - orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; - orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; - orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; - orig_dat4 = (cur_rxdly1 >> 0) & 0x1F; - orig_dat5 = (cur_rxdly1 >> 8) & 0x1F; - orig_dat6 = (cur_rxdly1 >> 16) & 0x1F; - orig_dat7 = (cur_rxdly1 >> 24) & 0x1F; - } - - if (ddr) { - cur_dat0 = (dcrc & (1 << 0) || dcrc & (1 << 8)) ? ((orig_dat0 + 1) % 32) : orig_dat0; - cur_dat1 = (dcrc & (1 << 1) || dcrc & (1 << 9)) ? ((orig_dat1 + 1) % 32) : orig_dat1; - cur_dat2 = (dcrc & (1 << 2) || dcrc & (1 << 10)) ? ((orig_dat2 + 1) % 32) : orig_dat2; - cur_dat3 = (dcrc & (1 << 3) || dcrc & (1 << 11)) ? ((orig_dat3 + 1) % 32) : orig_dat3; - } else { - cur_dat0 = (dcrc & (1 << 0)) ? ((orig_dat0 + 1) % 32) : orig_dat0; - cur_dat1 = (dcrc & (1 << 1)) ? ((orig_dat1 + 1) % 32) : orig_dat1; - cur_dat2 = (dcrc & (1 << 2)) ? ((orig_dat2 + 1) % 32) : orig_dat2; - cur_dat3 = (dcrc & (1 << 3)) ? ((orig_dat3 + 1) % 32) : orig_dat3; - } - cur_dat4 = (dcrc & (1 << 4)) ? ((orig_dat4 + 1) % 32) : orig_dat4; - cur_dat5 = (dcrc & (1 << 5)) ? ((orig_dat5 + 1) % 32) : orig_dat5; - cur_dat6 = (dcrc & (1 << 6)) ? ((orig_dat6 + 1) % 32) : orig_dat6; - cur_dat7 = (dcrc & (1 << 7)) ? ((orig_dat7 + 1) % 32) : orig_dat7; - - cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); - cur_rxdly1 = (cur_dat4 << 24) | (cur_dat5 << 16) | (cur_dat6 << 8) | (cur_dat7 << 0); - - writel(cur_rxdly0, host->base + MSDC_DAT_RDDLY0); - writel(cur_rxdly1, host->base + MSDC_DAT_RDDLY1); - - } while (++rxdly < 32); - -done: - return result; -} - -static int msdc_tune_bwrite(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct msdc_host *host = mmc_priv(mmc); - - u32 wrrdly, cur_wrrdly = 0xffffffff, orig_wrrdly; - u32 dsmpl, cur_dsmpl, orig_dsmpl; - u32 rxdly, cur_rxdly0; - u32 orig_dat0, orig_dat1, orig_dat2, orig_dat3; - u32 cur_dat0, cur_dat1, cur_dat2, cur_dat3; - int result = -1; - u32 skip = 1; - - // MSDC_IOCON_DDR50CKD need to check. [Fix me] - - sdr_get_field(host->base + MSDC_PAD_TUNE, MSDC_PAD_TUNE_DATWRDLY, - &orig_wrrdly); - sdr_get_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, &orig_dsmpl); - - /* Tune Method 2. just DAT0 */ - sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 1); - cur_rxdly0 = readl(host->base + MSDC_DAT_RDDLY0); - - /* E1 ECO. YD: Reverse */ - if (readl(host->base + MSDC_ECO_VER) >= 4) { - orig_dat0 = (cur_rxdly0 >> 24) & 0x1F; - orig_dat1 = (cur_rxdly0 >> 16) & 0x1F; - orig_dat2 = (cur_rxdly0 >> 8) & 0x1F; - orig_dat3 = (cur_rxdly0 >> 0) & 0x1F; - } else { - orig_dat0 = (cur_rxdly0 >> 0) & 0x1F; - orig_dat1 = (cur_rxdly0 >> 8) & 0x1F; - orig_dat2 = (cur_rxdly0 >> 16) & 0x1F; - orig_dat3 = (cur_rxdly0 >> 24) & 0x1F; - } - - rxdly = 0; - do { - wrrdly = 0; - do { - for (dsmpl = 0; dsmpl < 2; dsmpl++) { - cur_dsmpl = (orig_dsmpl + dsmpl) % 2; - if (skip == 1) { - skip = 0; - continue; - } - sdr_set_field(host->base + MSDC_IOCON, - MSDC_IOCON_DSPL, cur_dsmpl); - - if (host->app_cmd) { - result = msdc_app_cmd(host->mmc, host); - if (result) { - ERR_MSG("TUNE_BWRITE app_cmd<%d> failed", host->mrq->cmd->opcode); - continue; - } - } - result = msdc_do_request(mmc, mrq); - - ERR_MSG("TUNE_BWRITE<%s> DSPL<%d> DATWRDLY<%d> MSDC_DAT_RDDLY0<0x%x>", - result == 0 ? "PASS" : "FAIL", - cur_dsmpl, cur_wrrdly, cur_rxdly0); - - if (result == 0) { - goto done; - } else { - /* there is a case: command timeout, and data phase not processed */ - if (mrq->data->error != -EIO) { - ERR_MSG("TUNE_READ: result<0x%x> cmd_error<%d> data_error<%d>", - result, mrq->cmd->error, mrq->data->error); - goto done; - } - } - } - cur_wrrdly = (orig_wrrdly + wrrdly + 1) % 32; - sdr_set_field(host->base + MSDC_PAD_TUNE, - MSDC_PAD_TUNE_DATWRDLY, cur_wrrdly); - } while (++wrrdly < 32); - - cur_dat0 = (orig_dat0 + rxdly) % 32; /* only adjust bit-1 for crc */ - cur_dat1 = orig_dat1; - cur_dat2 = orig_dat2; - cur_dat3 = orig_dat3; - - cur_rxdly0 = (cur_dat0 << 24) | (cur_dat1 << 16) | (cur_dat2 << 8) | (cur_dat3 << 0); - writel(cur_rxdly0, host->base + MSDC_DAT_RDDLY0); - } while (++rxdly < 32); - -done: - return result; -} - -static int msdc_get_card_status(struct mmc_host *mmc, struct msdc_host *host, u32 *status) -{ - struct mmc_command cmd; - struct mmc_request mrq; - u32 err; - - memset(&cmd, 0, sizeof(struct mmc_command)); - cmd.opcode = MMC_SEND_STATUS; - if (mmc->card) { - cmd.arg = mmc->card->rca << 16; - } else { - ERR_MSG("cmd13 mmc card is null"); - cmd.arg = host->app_cmd_arg; - } - cmd.flags = MMC_RSP_SPI_R2 | MMC_RSP_R1 | MMC_CMD_AC; - - memset(&mrq, 0, sizeof(struct mmc_request)); - mrq.cmd = &cmd; cmd.mrq = &mrq; - cmd.data = NULL; - - err = msdc_do_command(host, &cmd, 1, CMD_TIMEOUT); - - if (status) - *status = cmd.resp[0]; - - return err; -} - -static int msdc_check_busy(struct mmc_host *mmc, struct msdc_host *host) -{ - u32 err = 0; - u32 status = 0; - - do { - err = msdc_get_card_status(mmc, host, &status); - if (err) - return err; - /* need cmd12? */ - ERR_MSG("cmd<13> resp<0x%x>", status); - } while (R1_CURRENT_STATE(status) == 7); - - return err; -} - -/* failed when msdc_do_request */ -static int msdc_tune_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct msdc_host *host = mmc_priv(mmc); - struct mmc_data *data; - //u32 base = host->base; - int ret = 0, read; - - data = mrq->cmd->data; - - read = data->flags & MMC_DATA_READ ? 1 : 0; - - if (read) { - if (data->error == -EIO) - ret = msdc_tune_bread(mmc, mrq); - } else { - ret = msdc_check_busy(mmc, host); - if (ret) { - ERR_MSG("XXX cmd13 wait program done failed"); - return ret; - } - /* CRC and TO */ - /* Fix me: don't care card status? */ - ret = msdc_tune_bwrite(mmc, mrq); - } - - return ret; -} - -/* ops.request */ -static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct msdc_host *host = mmc_priv(mmc); - - //=== for sdio profile === -#if 0 /* --- by chhung */ - u32 old_H32, old_L32, new_H32, new_L32; - u32 ticks = 0, opcode = 0, sizes = 0, bRx = 0; -#endif /* end of --- */ - - WARN_ON(host->mrq); - - /* start to process */ - spin_lock(&host->lock); -#if 0 /* --- by chhung */ - if (sdio_pro_enable) { //=== for sdio profile === - if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) - GPT_GetCounter64(&old_L32, &old_H32); - } -#endif /* end of --- */ - - host->mrq = mrq; - - if (msdc_do_request(mmc, mrq)) { - if (host->hw->flags & MSDC_REMOVABLE && ralink_soc == MT762X_SOC_MT7621AT && mrq->data && mrq->data->error) - msdc_tune_request(mmc, mrq); - } - - /* ==== when request done, check if app_cmd ==== */ - if (mrq->cmd->opcode == MMC_APP_CMD) { - host->app_cmd = 1; - host->app_cmd_arg = mrq->cmd->arg; /* save the RCA */ - } else { - host->app_cmd = 0; - //host->app_cmd_arg = 0; - } - - host->mrq = NULL; - -#if 0 /* --- by chhung */ - //=== for sdio profile === - if (sdio_pro_enable) { - if (mrq->cmd->opcode == 52 || mrq->cmd->opcode == 53) { - GPT_GetCounter64(&new_L32, &new_H32); - ticks = msdc_time_calc(old_L32, old_H32, new_L32, new_H32); - - opcode = mrq->cmd->opcode; - if (mrq->cmd->data) { - sizes = mrq->cmd->data->blocks * mrq->cmd->data->blksz; - bRx = mrq->cmd->data->flags & MMC_DATA_READ ? 1 : 0; - } else { - bRx = mrq->cmd->arg & 0x80000000 ? 1 : 0; - } - - if (!mrq->cmd->error) - msdc_performance(opcode, sizes, bRx, ticks); - } - } -#endif /* end of --- */ - spin_unlock(&host->lock); - - mmc_request_done(mmc, mrq); - - return; -} - -/* called by ops.set_ios */ -static void msdc_set_buswidth(struct msdc_host *host, u32 width) -{ - u32 val = readl(host->base + SDC_CFG); - - val &= ~SDC_CFG_BUSWIDTH; - - switch (width) { - default: - case MMC_BUS_WIDTH_1: - width = 1; - val |= (MSDC_BUS_1BITS << 16); - break; - case MMC_BUS_WIDTH_4: - val |= (MSDC_BUS_4BITS << 16); - break; - case MMC_BUS_WIDTH_8: - val |= (MSDC_BUS_8BITS << 16); - break; - } - - writel(val, host->base + SDC_CFG); - - N_MSG(CFG, "Bus Width = %d", width); -} - -/* ops.set_ios */ -static void msdc_ops_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -{ - struct msdc_host *host = mmc_priv(mmc); - u32 ddr = 0; - -#ifdef MT6575_SD_DEBUG - static char *vdd[] = { - "1.50v", "1.55v", "1.60v", "1.65v", "1.70v", "1.80v", "1.90v", - "2.00v", "2.10v", "2.20v", "2.30v", "2.40v", "2.50v", "2.60v", - "2.70v", "2.80v", "2.90v", "3.00v", "3.10v", "3.20v", "3.30v", - "3.40v", "3.50v", "3.60v" - }; - static char *power_mode[] = { - "OFF", "UP", "ON" - }; - static char *bus_mode[] = { - "UNKNOWN", "OPENDRAIN", "PUSHPULL" - }; - static char *timing[] = { - "LEGACY", "MMC_HS", "SD_HS" - }; - - printk("SET_IOS: CLK(%dkHz), BUS(%s), BW(%u), PWR(%s), VDD(%s), TIMING(%s)", - ios->clock / 1000, bus_mode[ios->bus_mode], - (ios->bus_width == MMC_BUS_WIDTH_4) ? 4 : 1, - power_mode[ios->power_mode], vdd[ios->vdd], timing[ios->timing]); -#endif - - msdc_set_buswidth(host, ios->bus_width); - - /* Power control ??? */ - switch (ios->power_mode) { - case MMC_POWER_OFF: - case MMC_POWER_UP: - // msdc_set_power_mode(host, ios->power_mode); /* --- by chhung */ - break; - case MMC_POWER_ON: - host->power_mode = MMC_POWER_ON; - break; - default: - break; - } - - /* Clock control */ - if (host->mclk != ios->clock) { - if (ios->clock > 25000000) { - //if (!(host->hw->flags & MSDC_REMOVABLE)) { - INIT_MSG("SD data latch edge<%d>", MSDC_SMPL_FALLING); - sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_RSPL, - MSDC_SMPL_FALLING); - sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DSPL, - MSDC_SMPL_FALLING); - //} /* for tuning debug */ - } else { /* default value */ - writel(0x00000000, host->base + MSDC_IOCON); - // writel(0x00000000, host->base + MSDC_DAT_RDDLY0); - - // for MT7620 E2 and afterward - writel(0x10101010, host->base + MSDC_DAT_RDDLY0); - - writel(0x00000000, host->base + MSDC_DAT_RDDLY1); - // writel(0x00000000, host->base + MSDC_PAD_TUNE); - - // for MT7620 E2 and afterward - writel(0x84101010, host->base + MSDC_PAD_TUNE); - } - msdc_set_mclk(host, ddr, ios->clock); - } -} - -/* ops.get_ro */ -static int msdc_ops_get_ro(struct mmc_host *mmc) -{ - struct msdc_host *host = mmc_priv(mmc); - unsigned long flags; - int ro = 0; - - if (host->hw->flags & MSDC_WP_PIN_EN) { /* set for card */ - spin_lock_irqsave(&host->lock, flags); - ro = (readl(host->base + MSDC_PS) >> 31); - spin_unlock_irqrestore(&host->lock, flags); - } - return ro; -} - -/* ops.get_cd */ -static int msdc_ops_get_cd(struct mmc_host *mmc) -{ - struct msdc_host *host = mmc_priv(mmc); - unsigned long flags; - int present = 1; - - /* for sdio, MSDC_REMOVABLE not set, always return 1 */ - if (!(host->hw->flags & MSDC_REMOVABLE)) { - /* For sdio, read H/W always get<1>, but may timeout some times */ -#if 1 - host->card_inserted = 1; - return 1; -#else - host->card_inserted = (host->pm_state.event == PM_EVENT_USER_RESUME) ? 1 : 0; - INIT_MSG("sdio ops_get_cd<%d>", host->card_inserted); - return host->card_inserted; -#endif - } - - /* MSDC_CD_PIN_EN set for card */ - if (host->hw->flags & MSDC_CD_PIN_EN) { - spin_lock_irqsave(&host->lock, flags); -#if 0 - present = host->card_inserted; /* why not read from H/W: Fix me*/ -#else - // CD - present = readl(host->base + MSDC_PS) & MSDC_PS_CDSTS; - if (cd_active_low) - present = present ? 0 : 1; - else - present = present ? 1 : 0; - host->card_inserted = present; -#endif - spin_unlock_irqrestore(&host->lock, flags); - } else { - present = 0; /* TODO? Check DAT3 pins for card detection */ - } - - INIT_MSG("ops_get_cd return<%d>", present); - return present; -} - -static struct mmc_host_ops mt_msdc_ops = { - .request = msdc_ops_request, - .set_ios = msdc_ops_set_ios, - .get_ro = msdc_ops_get_ro, - .get_cd = msdc_ops_get_cd, -}; - -/*--------------------------------------------------------------------------*/ -/* interrupt handler */ -/*--------------------------------------------------------------------------*/ -static irqreturn_t msdc_irq(int irq, void *dev_id) -{ - struct msdc_host *host = (struct msdc_host *)dev_id; - struct mmc_data *data = host->data; - struct mmc_command *cmd = host->cmd; - - u32 cmdsts = MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO | MSDC_INT_CMDRDY | - MSDC_INT_ACMDCRCERR | MSDC_INT_ACMDTMO | MSDC_INT_ACMDRDY | - MSDC_INT_ACMD19_DONE; - u32 datsts = MSDC_INT_DATCRCERR | MSDC_INT_DATTMO; - - u32 intsts = readl(host->base + MSDC_INT); - u32 inten = readl(host->base + MSDC_INTEN); inten &= intsts; - - writel(intsts, host->base + MSDC_INT); /* clear interrupts */ - /* MSG will cause fatal error */ - - /* card change interrupt */ - if (intsts & MSDC_INT_CDSC) { - if (host->mmc->caps & MMC_CAP_NEEDS_POLL) - return IRQ_HANDLED; - IRQ_MSG("MSDC_INT_CDSC irq<0x%.8x>", intsts); - schedule_delayed_work(&host->card_delaywork, HZ); - /* tuning when plug card ? */ - } - - /* sdio interrupt */ - if (intsts & MSDC_INT_SDIOIRQ) { - IRQ_MSG("XXX MSDC_INT_SDIOIRQ"); /* seems not sdio irq */ - //mmc_signal_sdio_irq(host->mmc); - } - - /* transfer complete interrupt */ - if (data != NULL) { - if (inten & MSDC_INT_XFER_COMPL) { - data->bytes_xfered = host->xfer_size; - complete(&host->xfer_done); - } - - if (intsts & datsts) { - /* do basic reset, or stop command will sdc_busy */ - msdc_reset_hw(host); - msdc_clr_fifo(host); - msdc_clr_int(); - - if (intsts & MSDC_INT_DATTMO) { - IRQ_MSG("XXX CMD<%d> MSDC_INT_DATTMO", host->mrq->cmd->opcode); - data->error = -ETIMEDOUT; - } else if (intsts & MSDC_INT_DATCRCERR) { - IRQ_MSG("XXX CMD<%d> MSDC_INT_DATCRCERR, SDC_DCRC_STS<0x%x>", host->mrq->cmd->opcode, readl(host->base + SDC_DCRC_STS)); - data->error = -EIO; - } - - //if(readl(MSDC_INTEN) & MSDC_INT_XFER_COMPL) { - complete(&host->xfer_done); /* Read CRC come fast, XFER_COMPL not enabled */ - } - } - - /* command interrupts */ - if ((cmd != NULL) && (intsts & cmdsts)) { - if ((intsts & MSDC_INT_CMDRDY) || (intsts & MSDC_INT_ACMDRDY) || - (intsts & MSDC_INT_ACMD19_DONE)) { - u32 *rsp = &cmd->resp[0]; - - switch (host->cmd_rsp) { - case RESP_NONE: - break; - case RESP_R2: - *rsp++ = readl(host->base + SDC_RESP3); - *rsp++ = readl(host->base + SDC_RESP2); - *rsp++ = readl(host->base + SDC_RESP1); - *rsp++ = readl(host->base + SDC_RESP0); - break; - default: /* Response types 1, 3, 4, 5, 6, 7(1b) */ - if ((intsts & MSDC_INT_ACMDRDY) || (intsts & MSDC_INT_ACMD19_DONE)) - *rsp = readl(host->base + SDC_ACMD_RESP); - else - *rsp = readl(host->base + SDC_RESP0); - break; - } - } else if ((intsts & MSDC_INT_RSPCRCERR) || (intsts & MSDC_INT_ACMDCRCERR)) { - if (intsts & MSDC_INT_ACMDCRCERR) - IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDCRCERR", cmd->opcode); - else - IRQ_MSG("XXX CMD<%d> MSDC_INT_RSPCRCERR", cmd->opcode); - cmd->error = -EIO; - } else if ((intsts & MSDC_INT_CMDTMO) || (intsts & MSDC_INT_ACMDTMO)) { - if (intsts & MSDC_INT_ACMDTMO) - IRQ_MSG("XXX CMD<%d> MSDC_INT_ACMDTMO", cmd->opcode); - else - IRQ_MSG("XXX CMD<%d> MSDC_INT_CMDTMO", cmd->opcode); - cmd->error = -ETIMEDOUT; - msdc_reset_hw(host); - msdc_clr_fifo(host); - msdc_clr_int(); - } - complete(&host->cmd_done); - } - - /* mmc irq interrupts */ - if (intsts & MSDC_INT_MMCIRQ) - printk(KERN_INFO "msdc[%d] MMCIRQ: SDC_CSTS=0x%.8x\r\n", - host->id, readl(host->base + SDC_CSTS)); - -#ifdef MT6575_SD_DEBUG - { -/* msdc_int_reg *int_reg = (msdc_int_reg*)&intsts;*/ - N_MSG(INT, "IRQ_EVT(0x%x): MMCIRQ(%d) CDSC(%d), ACRDY(%d), ACTMO(%d), ACCRE(%d) AC19DN(%d)", - intsts, - int_reg->mmcirq, - int_reg->cdsc, - int_reg->atocmdrdy, - int_reg->atocmdtmo, - int_reg->atocmdcrc, - int_reg->atocmd19done); - N_MSG(INT, "IRQ_EVT(0x%x): SDIO(%d) CMDRDY(%d), CMDTMO(%d), RSPCRC(%d), CSTA(%d)", - intsts, - int_reg->sdioirq, - int_reg->cmdrdy, - int_reg->cmdtmo, - int_reg->rspcrc, - int_reg->csta); - N_MSG(INT, "IRQ_EVT(0x%x): XFCMP(%d) DXDONE(%d), DATTMO(%d), DATCRC(%d), DMAEMP(%d)", - intsts, - int_reg->xfercomp, - int_reg->dxferdone, - int_reg->dattmo, - int_reg->datcrc, - int_reg->dmaqempty); - } -#endif - - return IRQ_HANDLED; -} - -/*--------------------------------------------------------------------------*/ -/* platform_driver members */ -/*--------------------------------------------------------------------------*/ -/* called by msdc_drv_probe/remove */ -static void msdc_enable_cd_irq(struct msdc_host *host, int enable) -{ - struct msdc_hw *hw = host->hw; - - /* for sdio, not set */ - if ((hw->flags & MSDC_CD_PIN_EN) == 0) { - /* Pull down card detection pin since it is not avaiable */ - /* - if (hw->config_gpio_pin) - hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); - */ - sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN); - sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CDSC); - sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_INSWKUP); - return; - } - - N_MSG(CFG, "CD IRQ Enable(%d)", enable); - - if (enable) { - /* card detection circuit relies on the core power so that the core power - * shouldn't be turned off. Here adds a reference count to keep - * the core power alive. - */ - //msdc_vcore_on(host); //did in msdc_init_hw() - - if (hw->config_gpio_pin) /* NULL */ - hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_UP); - - sdr_set_field(host->base + MSDC_PS, MSDC_PS_CDDEBOUNCE, - DEFAULT_DEBOUNCE); - sdr_set_bits(host->base + MSDC_PS, MSDC_PS_CDEN); - sdr_set_bits(host->base + MSDC_INTEN, MSDC_INTEN_CDSC); - - /* not in document! Fix me */ - sdr_set_bits(host->base + SDC_CFG, SDC_CFG_INSWKUP); - } else { - if (hw->config_gpio_pin) /* NULL */ - hw->config_gpio_pin(MSDC_CD_PIN, GPIO_PULL_DOWN); - - sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_INSWKUP); - sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN); - sdr_clr_bits(host->base + MSDC_INTEN, MSDC_INTEN_CDSC); - - /* Here decreases a reference count to core power since card - * detection circuit is shutdown. - */ - //msdc_vcore_off(host); - } -} - -/* called by msdc_drv_probe */ -static void msdc_init_hw(struct msdc_host *host) -{ - - /* Power on */ -#if 0 /* --- by chhung */ - msdc_vcore_on(host); - msdc_pin_reset(host, MSDC_PIN_PULL_UP); - msdc_select_clksrc(host, hw->clk_src); - enable_clock(PERI_MSDC0_PDN + host->id, "SD"); - msdc_vdd_on(host); -#endif /* end of --- */ - /* Configure to MMC/SD mode */ - sdr_set_field(host->base + MSDC_CFG, MSDC_CFG_MODE, MSDC_SDMMC); - - /* Reset */ - msdc_reset_hw(host); - msdc_clr_fifo(host); - - /* Disable card detection */ - sdr_clr_bits(host->base + MSDC_PS, MSDC_PS_CDEN); - - /* Disable and clear all interrupts */ - sdr_clr_bits(host->base + MSDC_INTEN, readl(host->base + MSDC_INTEN)); - writel(readl(host->base + MSDC_INT), host->base + MSDC_INT); - -#if 1 - /* reset tuning parameter */ - writel(0x00090000, host->base + MSDC_PAD_CTL0); - writel(0x000A0000, host->base + MSDC_PAD_CTL1); - writel(0x000A0000, host->base + MSDC_PAD_CTL2); - // writel( 0x00000000, host->base + MSDC_PAD_TUNE); - - // for MT7620 E2 and afterward - writel(0x84101010, host->base + MSDC_PAD_TUNE); - - // writel(0x00000000, host->base + MSDC_DAT_RDDLY0); - - // for MT7620 E2 and afterward - writel(0x10101010, host->base + MSDC_DAT_RDDLY0); - - writel(0x00000000, host->base + MSDC_DAT_RDDLY1); - writel(0x00000000, host->base + MSDC_IOCON); -#if 0 // use MT7620 default value: 0x403c004f - /* bit0 modified: Rx Data Clock Source: 1 -> 2.0*/ - writel(0x003C000F, host->base + MSDC_PATCH_BIT0); -#endif - - if (readl(host->base + MSDC_ECO_VER) >= 4) { - if (host->id == 1) { - sdr_set_field(host->base + MSDC_PATCH_BIT1, - MSDC_PATCH_BIT1_WRDAT_CRCS, 1); - sdr_set_field(host->base + MSDC_PATCH_BIT1, - MSDC_PATCH_BIT1_CMD_RSP, 1); - - /* internal clock: latch read data */ - sdr_set_bits(host->base + MSDC_PATCH_BIT0, - MSDC_PATCH_BIT_CKGEN_CK); - } - } -#endif - - /* for safety, should clear SDC_CFG.SDIO_INT_DET_EN & set SDC_CFG.SDIO in - pre-loader,uboot,kernel drivers. and SDC_CFG.SDIO_INT_DET_EN will be only - set when kernel driver wants to use SDIO bus interrupt */ - /* Configure to enable SDIO mode. it's must otherwise sdio cmd5 failed */ - sdr_set_bits(host->base + SDC_CFG, SDC_CFG_SDIO); - - /* disable detect SDIO device interupt function */ - sdr_clr_bits(host->base + SDC_CFG, SDC_CFG_SDIOIDE); - - /* eneable SMT for glitch filter */ - sdr_set_bits(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKSMT); - sdr_set_bits(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDSMT); - sdr_set_bits(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATSMT); - -#if 1 - /* set clk, cmd, dat pad driving */ - sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 4); - sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 4); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 4); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 4); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 4); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 4); -#else - sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVN, 0); - sdr_set_field(host->base + MSDC_PAD_CTL0, MSDC_PAD_CTL0_CLKDRVP, 0); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVN, 0); - sdr_set_field(host->base + MSDC_PAD_CTL1, MSDC_PAD_CTL1_CMDDRVP, 0); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVN, 0); - sdr_set_field(host->base + MSDC_PAD_CTL2, MSDC_PAD_CTL2_DATDRVP, 0); -#endif - - /* set sampling edge */ - - /* write crc timeout detection */ - sdr_set_field(host->base + MSDC_PATCH_BIT0, 1 << 30, 1); - - /* Configure to default data timeout */ - sdr_set_field(host->base + SDC_CFG, SDC_CFG_DTOC, DEFAULT_DTOC); - - msdc_set_buswidth(host, MMC_BUS_WIDTH_1); - - N_MSG(FUC, "init hardware done!"); -} - -/* called by msdc_drv_remove */ -static void msdc_deinit_hw(struct msdc_host *host) -{ - /* Disable and clear all interrupts */ - sdr_clr_bits(host->base + MSDC_INTEN, readl(host->base + MSDC_INTEN)); - writel(readl(host->base + MSDC_INT), host->base + MSDC_INT); - - /* Disable card detection */ - msdc_enable_cd_irq(host, 0); - // msdc_set_power_mode(host, MMC_POWER_OFF); /* make sure power down */ /* --- by chhung */ -} - -/* init gpd and bd list in msdc_drv_probe */ -static void msdc_init_gpd_bd(struct msdc_host *host, struct msdc_dma *dma) -{ - struct gpd *gpd = dma->gpd; - struct bd *bd = dma->bd; - int i; - - /* we just support one gpd, but gpd->next must be set for desc - * DMA. That's why we alloc 2 gpd structurs. - */ - - memset(gpd, 0, sizeof(struct gpd) * 2); - - gpd->bdp = 1; /* hwo, cs, bd pointer */ - gpd->ptr = (void *)dma->bd_addr; /* physical address */ - gpd->next = (void *)((u32)dma->gpd_addr + sizeof(struct gpd)); - - memset(bd, 0, sizeof(struct bd) * MAX_BD_NUM); - for (i = 0; i < (MAX_BD_NUM - 1); i++) - bd[i].next = (void *)(dma->bd_addr + sizeof(*bd) * (i + 1)); -} - -static int msdc_drv_probe(struct platform_device *pdev) -{ - struct resource *res; - __iomem void *base; - struct mmc_host *mmc; - struct msdc_host *host; - struct msdc_hw *hw; - int ret; - - hw = &msdc0_hw; - - if (of_property_read_bool(pdev->dev.of_node, "mtk,wp-en")) - msdc0_hw.flags |= MSDC_WP_PIN_EN; - - /* Allocate MMC host for this device */ - mmc = mmc_alloc_host(sizeof(struct msdc_host), &pdev->dev); - if (!mmc) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto host_free; - } - - /* Set host parameters to mmc */ - mmc->ops = &mt_msdc_ops; - mmc->f_min = HOST_MIN_MCLK; - mmc->f_max = HOST_MAX_MCLK; - mmc->ocr_avail = MSDC_OCR_AVAIL; - - mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - - //TODO: read this as bus-width from dt (via mmc_of_parse) - mmc->caps |= MMC_CAP_4_BIT_DATA; - - cd_active_low = !of_property_read_bool(pdev->dev.of_node, "mediatek,cd-high"); - - if (of_property_read_bool(pdev->dev.of_node, "mediatek,cd-poll")) - mmc->caps |= MMC_CAP_NEEDS_POLL; - - /* MMC core transfer sizes tunable parameters */ - mmc->max_segs = MAX_HW_SGMTS; - - mmc->max_seg_size = MAX_SGMT_SZ; - mmc->max_blk_size = HOST_MAX_BLKSZ; - mmc->max_req_size = MAX_REQ_SZ; - mmc->max_blk_count = mmc->max_req_size; - - host = mmc_priv(mmc); - host->hw = hw; - host->mmc = mmc; - host->id = pdev->id; - if (host->id < 0 || host->id >= 4) - host->id = 0; - host->error = 0; - - host->irq = platform_get_irq(pdev, 0); - if (host->irq < 0) { - ret = -EINVAL; - goto host_free; - } - - host->base = base; - host->mclk = 0; /* mclk: the request clock of mmc sub-system */ - host->hclk = hclks[hw->clk_src]; /* hclk: clock of clock source to msdc controller */ - host->sclk = 0; /* sclk: the really clock after divition */ - host->pm_state = PMSG_RESUME; - host->suspend = 0; - host->core_clkon = 0; - host->card_clkon = 0; - host->core_power = 0; - host->power_mode = MMC_POWER_OFF; -// host->card_inserted = hw->flags & MSDC_REMOVABLE ? 0 : 1; - host->timeout_ns = 0; - host->timeout_clks = DEFAULT_DTOC * 65536; - - host->mrq = NULL; - //init_MUTEX(&host->sem); /* we don't need to support multiple threads access */ - - mmc_dev(mmc)->dma_mask = NULL; - - /* using dma_alloc_coherent*/ /* todo: using 1, for all 4 slots */ - host->dma.gpd = dma_alloc_coherent(&pdev->dev, - MAX_GPD_NUM * sizeof(struct gpd), - &host->dma.gpd_addr, GFP_KERNEL); - host->dma.bd = dma_alloc_coherent(&pdev->dev, - MAX_BD_NUM * sizeof(struct bd), - &host->dma.bd_addr, GFP_KERNEL); - if (!host->dma.gpd || !host->dma.bd) { - ret = -ENOMEM; - goto release_mem; - } - msdc_init_gpd_bd(host, &host->dma); - - INIT_DELAYED_WORK(&host->card_delaywork, msdc_tasklet_card); - spin_lock_init(&host->lock); - msdc_init_hw(host); - - /* TODO check weather flags 0 is correct, the mtk-sd driver uses - * IRQF_TRIGGER_LOW | IRQF_ONESHOT for flags - * - * for flags 0 the trigger polarity is determined by the - * device tree, but not the oneshot flag, but maybe it is also - * not needed because the soc could be oneshot safe. - */ - ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq, 0, pdev->name, - host); - if (ret) - goto release; - - platform_set_drvdata(pdev, mmc); - - ret = mmc_add_host(mmc); - if (ret) - goto release; - - /* Config card detection pin and enable interrupts */ - if (hw->flags & MSDC_CD_PIN_EN) { /* set for card */ - msdc_enable_cd_irq(host, 1); - } else { - msdc_enable_cd_irq(host, 0); - } - - return 0; - -release: - platform_set_drvdata(pdev, NULL); - msdc_deinit_hw(host); - cancel_delayed_work_sync(&host->card_delaywork); - -release_mem: - if (host->dma.gpd) - dma_free_coherent(&pdev->dev, MAX_GPD_NUM * sizeof(struct gpd), - host->dma.gpd, host->dma.gpd_addr); - if (host->dma.bd) - dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct bd), - host->dma.bd, host->dma.bd_addr); -host_free: - mmc_free_host(mmc); - - return ret; -} - -/* 4 device share one driver, using "drvdata" to show difference */ -static int msdc_drv_remove(struct platform_device *pdev) -{ - struct mmc_host *mmc; - struct msdc_host *host; - - mmc = platform_get_drvdata(pdev); - BUG_ON(!mmc); - - host = mmc_priv(mmc); - BUG_ON(!host); - - ERR_MSG("removed !!!"); - - platform_set_drvdata(pdev, NULL); - mmc_remove_host(host->mmc); - msdc_deinit_hw(host); - - cancel_delayed_work_sync(&host->card_delaywork); - - dma_free_coherent(&pdev->dev, MAX_GPD_NUM * sizeof(struct gpd), - host->dma.gpd, host->dma.gpd_addr); - dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct bd), - host->dma.bd, host->dma.bd_addr); - - mmc_free_host(host->mmc); - - return 0; -} - -/* Fix me: Power Flow */ -#ifdef CONFIG_PM - -static void msdc_drv_pm(struct platform_device *pdev, pm_message_t state) -{ - struct mmc_host *mmc = platform_get_drvdata(pdev); - if (mmc) { - struct msdc_host *host = mmc_priv(mmc); - msdc_pm(state, (void *)host); - } -} - -static int msdc_drv_suspend(struct platform_device *pdev, pm_message_t state) -{ - if (state.event == PM_EVENT_SUSPEND) - msdc_drv_pm(pdev, state); - return 0; -} - -static int msdc_drv_resume(struct platform_device *pdev) -{ - struct pm_message state; - - state.event = PM_EVENT_RESUME; - msdc_drv_pm(pdev, state); - return 0; -} -#endif - -static const struct of_device_id mt7620_sdhci_match[] = { - { .compatible = "ralink,mt7620-sdhci" }, - {}, -}; -MODULE_DEVICE_TABLE(of, mt7620_sdhci_match); - -static struct platform_driver mt_msdc_driver = { - .probe = msdc_drv_probe, - .remove = msdc_drv_remove, -#ifdef CONFIG_PM - .suspend = msdc_drv_suspend, - .resume = msdc_drv_resume, -#endif - .driver = { - .name = DRV_NAME, - .of_match_table = mt7620_sdhci_match, - }, -}; - -/*--------------------------------------------------------------------------*/ -/* module init/exit */ -/*--------------------------------------------------------------------------*/ -static int __init mt_msdc_init(void) -{ - int ret; - u32 reg; - - // Set the pins for sdxc to sdxc mode - //FIXME: this should be done by pinctl and not by the sd driver - reg = readl((void __iomem *)(RALINK_SYSCTL_BASE + 0x60)) & ~(0x3 << 18); - writel(reg, (void __iomem *)(RALINK_SYSCTL_BASE + 0x60)); - - ret = platform_driver_register(&mt_msdc_driver); - if (ret) { - printk(KERN_ERR DRV_NAME ": Can't register driver"); - return ret; - } - -#if defined(MT6575_SD_DEBUG) - msdc_debug_proc_init(); -#endif - return 0; -} - -static void __exit mt_msdc_exit(void) -{ - platform_driver_unregister(&mt_msdc_driver); -} - -module_init(mt_msdc_init); -module_exit(mt_msdc_exit); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("MediaTek MT6575 SD/MMC Card Driver"); -MODULE_AUTHOR("Infinity Chen "); diff --git a/drivers/staging/mt7621-spi/spi-mt7621.c b/drivers/staging/mt7621-spi/spi-mt7621.c index 578aa6824ad3..33c747bc8320 100644 --- a/drivers/staging/mt7621-spi/spi-mt7621.c +++ b/drivers/staging/mt7621-spi/spi-mt7621.c @@ -455,6 +455,7 @@ static int mt7621_spi_probe(struct platform_device *pdev) master = spi_alloc_master(&pdev->dev, sizeof(*rs)); if (master == NULL) { dev_info(&pdev->dev, "master allocation failed\n"); + clk_disable_unprepare(clk); return -ENOMEM; } @@ -480,6 +481,7 @@ static int mt7621_spi_probe(struct platform_device *pdev) ret = device_reset(&pdev->dev); if (ret) { dev_err(&pdev->dev, "SPI reset failed!\n"); + clk_disable_unprepare(clk); return ret; } diff --git a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c index 01c7cbdd70c5..fbbe0a7e5e6e 100644 --- a/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c +++ b/drivers/staging/qca-wifi-host-cmn/hif/src/hif_main.c @@ -1599,7 +1599,7 @@ irqreturn_t hif_wake_interrupt_handler(int irq, void *context) struct hif_softc *scn = context; struct hif_opaque_softc *hif_ctx = GET_HIF_OPAQUE_HDL(scn); - HIF_INFO("wake interrupt received on irq %d", irq); + HIF_DBG("wake interrupt received on irq %d", irq); if (hif_pm_runtime_get_monitor_wake_intr(hif_ctx)) { hif_pm_runtime_set_monitor_wake_intr(hif_ctx, 0); diff --git a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c index bb7f459ae748..7936429b1a2e 100644 --- a/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c +++ b/drivers/staging/qca-wifi-host-cmn/qdf/linux/src/qdf_lock.c @@ -241,19 +241,10 @@ qdf_export_symbol(qdf_mutex_release); * * Return: Pointer to the name if it is valid or a default string */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) -const char *qdf_wake_lock_name(qdf_wake_lock_t *lock) -{ - if (lock) - return lock->lock.name; - return "UNNAMED_WAKELOCK"; -} -#else const char *qdf_wake_lock_name(qdf_wake_lock_t *lock) { return "NO_WAKELOCK_SUPPORT"; } -#endif qdf_export_symbol(qdf_wake_lock_name); /** @@ -265,34 +256,10 @@ qdf_export_symbol(qdf_wake_lock_name); * QDF status success: if wake lock is initialized * QDF status failure: if wake lock was not initialized */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \ - defined(WAKEUP_SOURCE_DEV) -QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) -{ - qdf_mem_zero(lock, sizeof(*lock)); - lock->priv = wakeup_source_register(lock->lock.dev, name); - if (!(lock->priv)) { - QDF_BUG(0); - return QDF_STATUS_E_FAILURE; - } - - lock->lock = *(lock->priv); - - return QDF_STATUS_SUCCESS; -} -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) { - wakeup_source_init(&(lock->lock), name); - lock->priv = &(lock->lock); return QDF_STATUS_SUCCESS; } -#else -QDF_STATUS qdf_wake_lock_create(qdf_wake_lock_t *lock, const char *name) -{ - return QDF_STATUS_SUCCESS; -} -#endif qdf_export_symbol(qdf_wake_lock_create); /** @@ -304,22 +271,10 @@ qdf_export_symbol(qdf_wake_lock_create); * QDF status success: if wake lock is acquired * QDF status failure: if wake lock was not acquired */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason) { - host_diag_log_wlock(reason, qdf_wake_lock_name(lock), - WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, - WIFI_POWER_EVENT_WAKELOCK_TAKEN); - __pm_stay_awake(lock->priv); - return QDF_STATUS_SUCCESS; } -#else -QDF_STATUS qdf_wake_lock_acquire(qdf_wake_lock_t *lock, uint32_t reason) -{ - return QDF_STATUS_SUCCESS; -} -#endif qdf_export_symbol(qdf_wake_lock_acquire); /** @@ -331,27 +286,10 @@ qdf_export_symbol(qdf_wake_lock_acquire); * QDF status success: if wake lock is acquired * QDF status failure: if wake lock was not acquired */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) { - pm_wakeup_ws_event(lock->priv, msec, true); return QDF_STATUS_SUCCESS; } -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0) -QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) -{ - /* Wakelock for Rx is frequent. - * It is reported only during active debug - */ - __pm_wakeup_event(&(lock->lock), msec); - return QDF_STATUS_SUCCESS; -} -#else /* LINUX_VERSION_CODE */ -QDF_STATUS qdf_wake_lock_timeout_acquire(qdf_wake_lock_t *lock, uint32_t msec) -{ - return QDF_STATUS_SUCCESS; -} -#endif /* LINUX_VERSION_CODE */ qdf_export_symbol(qdf_wake_lock_timeout_acquire); /** @@ -363,22 +301,10 @@ qdf_export_symbol(qdf_wake_lock_timeout_acquire); * QDF status success: if wake lock is acquired * QDF status failure: if wake lock was not acquired */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) -QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason) -{ - host_diag_log_wlock(reason, qdf_wake_lock_name(lock), - WIFI_POWER_EVENT_DEFAULT_WAKELOCK_TIMEOUT, - WIFI_POWER_EVENT_WAKELOCK_RELEASED); - __pm_relax(lock->priv); - - return QDF_STATUS_SUCCESS; -} -#else QDF_STATUS qdf_wake_lock_release(qdf_wake_lock_t *lock, uint32_t reason) { return QDF_STATUS_SUCCESS; } -#endif qdf_export_symbol(qdf_wake_lock_release); /** @@ -389,25 +315,10 @@ qdf_export_symbol(qdf_wake_lock_release); * QDF status success: if wake lock is acquired * QDF status failure: if wake lock was not acquired */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 110)) || \ - defined(WAKEUP_SOURCE_DEV) -QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) -{ - wakeup_source_unregister(lock->priv); - return QDF_STATUS_SUCCESS; -} -#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) { - wakeup_source_trash(&(lock->lock)); return QDF_STATUS_SUCCESS; } -#else -QDF_STATUS qdf_wake_lock_destroy(qdf_wake_lock_t *lock) -{ - return QDF_STATUS_SUCCESS; -} -#endif qdf_export_symbol(qdf_wake_lock_destroy); /** diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_pmo_tlv.c b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_pmo_tlv.c index 3f2c2762e674..98d1b6c29b6e 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_pmo_tlv.c +++ b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_pmo_tlv.c @@ -1443,7 +1443,7 @@ static QDF_STATUS send_enable_disable_packet_filter_cmd_tlv( else cmd->enable = PACKET_FILTER_SET_DISABLE; - WMI_LOGE("%s: Packet filter enable %d for vdev_id %d", + WMI_LOGD("%s: Packet filter enable %d for vdev_id %d", __func__, cmd->enable, vdev_id); wmi_mtrace(WMI_PACKET_FILTER_ENABLE_CMDID, cmd->vdev_id, 0); @@ -1521,7 +1521,7 @@ static QDF_STATUS send_config_packet_filter_cmd_tlv(wmi_unified_t wmi_handle, } } - WMI_LOGE("Packet filter action %d filter with id: %d, num_params=%d", + WMI_LOGD("Packet filter action %d filter with id: %d, num_params=%d", cmd->filter_action, cmd->filter_id, cmd->num_params); /* send the command along with data */ wmi_mtrace(WMI_PACKET_FILTER_CONFIG_CMDID, cmd->vdev_id, 0); diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c index 3d10b9ec283d..1f6aa683f1d4 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c +++ b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c @@ -1825,7 +1825,7 @@ static QDF_STATUS send_wow_enable_cmd_tlv(wmi_unified_t wmi_handle, cmd->pause_iface_config = WOW_IFACE_PAUSE_DISABLED; cmd->flags = param->flags; - WMI_LOGI("suspend type: %s", + wmi_debug("suspend type: %s", cmd->pause_iface_config == WOW_IFACE_PAUSE_ENABLED ? "WOW_IFACE_PAUSE_ENABLED" : "WOW_IFACE_PAUSE_DISABLED"); diff --git a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_suspend_resume.c b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_suspend_resume.c index bbaabf4410bf..9c64b1bc2211 100644 --- a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_suspend_resume.c +++ b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_suspend_resume.c @@ -801,13 +801,13 @@ pmo_core_enable_wow_in_fw(struct wlan_objmgr_psoc *psoc, if (htc_can_suspend_link(pmo_core_psoc_get_htc_handle(psoc))) { if (qdf_is_drv_connected()) { - pmo_info("drv wow is enabled"); + pmo_debug("drv wow is enabled"); param.flags |= WMI_WOW_FLAG_ENABLE_DRV_PCIE_L1SS_SLEEP; } else { - pmo_info("non-drv wow is enabled"); + pmo_debug("non-drv wow is enabled"); } } else { - pmo_info("Prevent link down, non-drv wow is enabled"); + pmo_debug("Prevent link down, non-drv wow is enabled"); } status = pmo_tgt_psoc_send_wow_enable_req(psoc, ¶m); diff --git a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_wow.c b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_wow.c index 3f481a32dc44..041c1de3df81 100644 --- a/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_wow.c +++ b/drivers/staging/qcacld-3.0/components/pmo/core/src/wlan_pmo_wow.c @@ -316,7 +316,7 @@ bool pmo_core_is_wow_applicable(struct wlan_objmgr_psoc *psoc) } if (pmo_core_is_lpass_enabled(psoc)) { - pmo_info("lpass enabled, enabling wow"); + pmo_debug("lpass enabled, enabling wow"); return true; } diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_misc.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_misc.h index b105df1b3a98..a2485cc53ed3 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_misc.h +++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_misc.h @@ -42,7 +42,8 @@ #endif #ifdef MSM_PLATFORM -#define WLAN_INI_FILE "wlan/qca_cld/" PREFIX "WCNSS_qcom_cfg.ini" +#define WLAN_INI_FILE "wlan/qca_cld/qca6390/" PREFIX "WCNSS_qcom_cfg.ini" +#define WLAN_INI_FILE_DEF "wlan/qca_cld/" PREFIX "WCNSS_qcom_cfg.ini" #define WLAN_MAC_FILE "wlan/qca_cld/" PREFIX "wlan_mac.bin" #else #define WLAN_INI_FILE "wlan/" PREFIX "qcom_cfg.ini" diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c index 59b2f5f7d0fa..9b9c29f13c0d 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c @@ -1021,7 +1021,7 @@ static int __wlan_hdd_bus_suspend(struct wow_enable_params wow_params) void *dp_soc; struct pmo_wow_enable_params pmo_params; - hdd_info("starting bus suspend"); + hdd_debug("starting bus suspend"); hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); err = wlan_hdd_validate_context(hdd_ctx); @@ -1087,7 +1087,7 @@ static int __wlan_hdd_bus_suspend(struct wow_enable_params wow_params) */ pld_request_bus_bandwidth(hdd_ctx->parent_dev, PLD_BUS_WIDTH_NONE); - hdd_info("bus suspend succeeded"); + hdd_debug("bus suspend succeeded"); return 0; resume_pmo: @@ -1214,7 +1214,7 @@ int wlan_hdd_bus_resume(void) if (cds_is_driver_recovering()) return 0; - hdd_info("starting bus resume"); + hdd_debug("starting bus resume"); status = wlan_hdd_validate_context(hdd_ctx); if (status) { @@ -1273,7 +1273,7 @@ int wlan_hdd_bus_resume(void) goto out; } - hdd_info("bus resume succeeded"); + hdd_debug("bus resume succeeded"); return 0; out: diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c index 92609a0c72ac..7e13328197d3 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c @@ -218,32 +218,6 @@ static struct class *class; static dev_t device; static bool hdd_loaded = false; -#if 0 -static struct gwlan_loader *wlan_loader; -static ssize_t wlan_boot_cb(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count); -struct gwlan_loader { - bool loaded_state; - struct kobject *boot_wlan_obj; - struct attribute_group *attr_group; -}; - -static struct kobj_attribute wlan_boot_attribute = - __ATTR(boot_wlan, 0220, NULL, wlan_boot_cb); - -static struct attribute *attrs[] = { - &wlan_boot_attribute.attr, - NULL, -}; -#define MODULE_INITIALIZED 1 - -#ifdef MULTI_IF_NAME -#define WLAN_LOADER_NAME "boot_" MULTI_IF_NAME -#else -#define WLAN_LOADER_NAME "boot_wlan" -#endif -#endif /* the Android framework expects this param even though we don't use it */ #define BUF_LEN 20 @@ -11303,6 +11277,10 @@ struct hdd_context *hdd_context_create(struct device *dev) } status = cfg_parse(WLAN_INI_FILE); + if (!QDF_IS_STATUS_ERROR(status)) + goto cfg_done; + + status = cfg_parse(WLAN_INI_FILE_DEF); if (QDF_IS_STATUS_ERROR(status)) { hdd_err("Failed to parse cfg %s; status:%d\n", WLAN_INI_FILE, status); @@ -11310,6 +11288,7 @@ struct hdd_context *hdd_context_create(struct device *dev) goto err_free_config; } +cfg_done: ret = hdd_objmgr_create_and_store_psoc(hdd_ctx, DEFAULT_PSOC_ID); if (ret) { QDF_DEBUG_PANIC("Psoc creation fails!"); @@ -14894,6 +14873,8 @@ static int wlan_hdd_state_ctrl_param_open(struct inode *inode, return 0; } +static int hdd_driver_load(void); + static void __hdd_inform_wifi_off(void) { struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); @@ -14931,7 +14912,6 @@ void hdd_init_start_completion(void) INIT_COMPLETION(wlan_start_comp); } -static int hdd_driver_load(void); static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp, const char __user *user_buf, size_t count, @@ -15969,132 +15949,6 @@ static void hdd_driver_unload(void) hdd_qdf_deinit(); } -#if 0 -/** - * wlan_boot_cb() - Wlan boot callback - * @kobj: object whose directory we're creating the link in. - * @attr: attribute the user is interacting with - * @buff: the buffer containing the user data - * @count: number of bytes in the buffer - * - * This callback is invoked when the fs is ready to start the - * wlan driver initialization. - * - * Return: 'count' on success or a negative error code in case of failure - */ -static ssize_t wlan_boot_cb(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, - size_t count) -{ - - if (wlan_loader->loaded_state) { - hdd_err("wlan driver already initialized"); - return -EALREADY; - } - - if (hdd_driver_load()) - return -EIO; - - wlan_loader->loaded_state = MODULE_INITIALIZED; - - return count; -} - -/** - * hdd_sysfs_cleanup() - cleanup sysfs - * - * Return: None - * - */ -static void hdd_sysfs_cleanup(void) -{ - /* remove from group */ - if (wlan_loader->boot_wlan_obj && wlan_loader->attr_group) - sysfs_remove_group(wlan_loader->boot_wlan_obj, - wlan_loader->attr_group); - - /* unlink the object from parent */ - kobject_del(wlan_loader->boot_wlan_obj); - - /* free the object */ - kobject_put(wlan_loader->boot_wlan_obj); - - kfree(wlan_loader->attr_group); - kfree(wlan_loader); - - wlan_loader = NULL; -} - -/** - * wlan_init_sysfs() - Creates the sysfs to be invoked when the fs is - * ready - * - * This is creates the syfs entry boot_wlan. Which shall be invoked - * when the filesystem is ready. - * - * QDF API cannot be used here since this function is called even before - * initializing WLAN driver. - * - * Return: 0 for success, errno on failure - */ -static int wlan_init_sysfs(void) -{ - int ret = -ENOMEM; - - wlan_loader = kzalloc(sizeof(*wlan_loader), GFP_KERNEL); - if (!wlan_loader) - return -ENOMEM; - - wlan_loader->boot_wlan_obj = NULL; - wlan_loader->attr_group = kzalloc(sizeof(*(wlan_loader->attr_group)), - GFP_KERNEL); - if (!wlan_loader->attr_group) - goto error_return; - - wlan_loader->loaded_state = 0; - wlan_loader->attr_group->attrs = attrs; - - wlan_loader->boot_wlan_obj = kobject_create_and_add(WLAN_LOADER_NAME, - kernel_kobj); - if (!wlan_loader->boot_wlan_obj) { - hdd_err("sysfs create and add failed"); - goto error_return; - } - - ret = sysfs_create_group(wlan_loader->boot_wlan_obj, - wlan_loader->attr_group); - if (ret) { - hdd_err("sysfs create group failed; errno:%d", ret); - goto error_return; - } - - return 0; - -error_return: - hdd_sysfs_cleanup(); - - return ret; -} - -/** - * wlan_deinit_sysfs() - Removes the sysfs created to initialize the wlan - * - * Return: 0 on success or errno on failure - */ -static int wlan_deinit_sysfs(void) -{ - if (!wlan_loader) { - hdd_err("wlan_loader is null"); - return -EINVAL; - } - - hdd_sysfs_cleanup(); - return 0; -} - -#endif /* MODULE */ - /** * hdd_module_init() - Module init helper * @@ -17616,3 +17470,4 @@ static const struct kernel_param_ops timer_multiplier_ops = { module_param_cb(timer_multiplier, &timer_multiplier_ops, NULL, 0644); + diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_packet_filter.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_packet_filter.c index a9c6f2641529..974e78075b82 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_packet_filter.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_packet_filter.c @@ -46,7 +46,7 @@ int hdd_enable_default_pkt_filters(struct hdd_adapter *adapter) while (filters != 0) { if (filters & 0x1) { - hdd_err("setting filter[%d], of id = %d", + hdd_debug("setting filter[%d], of id = %d", i+1, filter_id); packet_filter_default_rules[i].filter_id = filter_id; wlan_hdd_set_filter(hdd_ctx, @@ -83,7 +83,7 @@ int hdd_disable_default_pkt_filters(struct hdd_adapter *adapter) while (filters != 0) { if (filters & 0x1) { - hdd_err("Clearing filter[%d], of id = %d", + hdd_debug("Clearing filter[%d], of id = %d", i+1, filter_id); packet_filter_default_rules.filter_action = HDD_RCV_FILTER_CLEAR; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c index 0a9396e34a2b..2fab759ef7da 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_power.c @@ -669,13 +669,13 @@ void hdd_disable_host_offloads(struct hdd_adapter *adapter, hdd_enter(); if (!ucfg_pmo_is_vdev_supports_offload(adapter->vdev)) { - hdd_info("offload is not supported on this vdev opmode: %d", + hdd_debug("offload is not supported on this vdev opmode: %d", adapter->device_mode); goto out; } if (!ucfg_pmo_is_vdev_connected(adapter->vdev)) { - hdd_info("vdev is not connected"); + hdd_debug("vdev is not connected"); goto out; } diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sysfs.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sysfs.c index 25d6d6a3fec8..83dc6162a9a7 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sysfs.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_sysfs.c @@ -694,6 +694,7 @@ void hdd_sysfs_destroy_powerstats_interface(void) } sysfs_remove_file(driver_kobject, &power_stats_attribute.attr); } +#endif void hdd_sysfs_create_driver_root_obj(void) { @@ -723,7 +724,6 @@ void hdd_sysfs_destroy_driver_root_obj(void) driver_kobject = NULL; } } -#endif #ifdef WLAN_FEATURE_BEACON_RECEPTION_STATS static int hdd_sysfs_create_bcn_reception_interface(struct hdd_adapter diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c index 68006ba768c0..56ad1a94c594 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_features.c @@ -1595,8 +1595,8 @@ static void wma_inc_wow_stats(t_wma_handle *wma, static void wma_wow_stats_display(struct wake_lock_stats *stats) { - WMA_LOGA("WLAN wake reason counters:"); - WMA_LOGA("uc:%d bc:%d v4_mc:%d v6_mc:%d ra:%d ns:%d na:%d " + WMA_LOGD("WLAN wake reason counters:"); + WMA_LOGD("uc:%d bc:%d v4_mc:%d v6_mc:%d ra:%d ns:%d na:%d " "icmp:%d icmpv6:%d", stats->ucast_wake_up_count, stats->bcast_wake_up_count, @@ -1608,7 +1608,7 @@ static void wma_wow_stats_display(struct wake_lock_stats *stats) stats->icmpv4_count, stats->icmpv6_count); - WMA_LOGA("assoc:%d disassoc:%d assoc_resp:%d reassoc:%d " + WMA_LOGD("assoc:%d disassoc:%d assoc_resp:%d reassoc:%d " "reassoc_resp:%d auth:%d deauth:%d action:%d", stats->mgmt_assoc, stats->mgmt_disassoc, @@ -1619,7 +1619,7 @@ static void wma_wow_stats_display(struct wake_lock_stats *stats) stats->mgmt_deauth, stats->mgmt_action); - WMA_LOGA("pno_match:%d pno_complete:%d gscan:%d " + WMA_LOGD("pno_match:%d pno_complete:%d gscan:%d " "low_rssi:%d rssi_breach:%d oem:%d scan_11d:%d", stats->pno_match_wake_up_count, stats->pno_complete_wake_up_count, @@ -2064,7 +2064,7 @@ static void wma_log_pkt_ipv4(uint8_t *data, uint32_t length) ip_addr[2], ip_addr[3]); src_port = *(uint16_t *)(data + IPV4_SRC_PORT_OFFSET); dst_port = *(uint16_t *)(data + IPV4_DST_PORT_OFFSET); - WMA_LOGI("Pkt_len: %u, src_port: %u, dst_port: %u", + WMA_LOGD("Pkt_len: %u, src_port: %u, dst_port: %u", qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(src_port), qdf_cpu_to_be16(dst_port)); @@ -2095,7 +2095,7 @@ static void wma_log_pkt_ipv6(uint8_t *data, uint32_t length) ip_addr[15]); src_port = *(uint16_t *)(data + IPV6_SRC_PORT_OFFSET); dst_port = *(uint16_t *)(data + IPV6_DST_PORT_OFFSET); - WMA_LOGI("Pkt_len: %u, src_port: %u, dst_port: %u", + WMA_LOGD("Pkt_len: %u, src_port: %u, dst_port: %u", qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(src_port), qdf_cpu_to_be16(dst_port)); @@ -2168,15 +2168,13 @@ static void wma_wow_parse_data_pkt(t_wma_handle *wma, src_mac = data + QDF_NBUF_SRC_MAC_OFFSET; dest_mac = data + QDF_NBUF_DEST_MAC_OFFSET; - wma_info("Src_mac: " QDF_MAC_ADDR_FMT ", Dst_mac: " QDF_MAC_ADDR_FMT, - QDF_MAC_ADDR_REF(src_mac), QDF_MAC_ADDR_REF(dest_mac)); wma_wow_inc_wake_lock_stats_by_dst_addr(wma, vdev_id, dest_mac); proto_subtype = wma_wow_get_pkt_proto_subtype(data, length); proto_subtype_name = wma_pkt_proto_subtype_to_string(proto_subtype); if (proto_subtype_name) - WMA_LOGI("WOW Wakeup: %s rcvd", proto_subtype_name); + WMA_LOGD("WOW Wakeup: %s rcvd", proto_subtype_name); switch (proto_subtype) { case QDF_PROTO_EAPOL_M1: @@ -2709,14 +2707,14 @@ static void wma_wake_event_log_reason(t_wma_handle *wma, /* "Unspecified" means APPS triggered wake, else firmware triggered */ if (wake_info->wake_reason != WOW_REASON_UNSPECIFIED) { vdev = &wma->interfaces[wake_info->vdev_id]; - WMA_LOGA("WLAN triggered wakeup: %s (%d), vdev: %d (%s)", + WMA_LOGD("WLAN triggered wakeup: %s (%d), vdev: %d (%s)", wma_wow_wake_reason_str(wake_info->wake_reason), wake_info->wake_reason, wake_info->vdev_id, wma_vdev_type_str(vdev->type)); wma_debug_assert_page_fault_wakeup(wake_info->wake_reason); } else if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle)) { - WMA_LOGA("Non-WLAN triggered wakeup: %s (%d)", + WMA_LOGD("Non-WLAN triggered wakeup: %s (%d)", wma_wow_wake_reason_str(wake_info->wake_reason), wake_info->wake_reason); } diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c index 676d549ef786..a8365e23157b 100644 --- a/drivers/staging/rtl8188eu/core/rtw_ap.c +++ b/drivers/staging/rtl8188eu/core/rtw_ap.c @@ -794,6 +794,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* SSID */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p && ie_len > 0) { + ie_len = min_t(int, ie_len, sizeof(pbss_network->Ssid.Ssid)); memset(&pbss_network->Ssid, 0, sizeof(struct ndis_802_11_ssid)); memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len); pbss_network->Ssid.SsidLength = ie_len; @@ -812,6 +813,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* get supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->ie_length - _BEACON_IE_OFFSET_)); if (p) { + ie_len = min_t(int, ie_len, NDIS_802_11_LENGTH_RATES_EX); memcpy(supportRate, p + 2, ie_len); supportRateNum = ie_len; } @@ -819,6 +821,8 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) /* get ext_supported rates */ p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->ie_length - _BEACON_IE_OFFSET_); if (p) { + ie_len = min_t(int, ie_len, + NDIS_802_11_LENGTH_RATES_EX - supportRateNum); memcpy(supportRate + supportRateNum, p + 2, ie_len); supportRateNum += ie_len; } @@ -932,6 +936,7 @@ int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) pht_cap->mcs.rx_mask[0] = 0xff; pht_cap->mcs.rx_mask[1] = 0x0; + ie_len = min_t(int, ie_len, sizeof(pmlmepriv->htpriv.ht_cap)); memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len); } diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 0003f0c38038..2e1f31b08e8b 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -1161,9 +1161,11 @@ static int rtw_wx_set_scan(struct net_device *dev, struct iw_request_info *a, break; } sec_len = *(pos++); len -= 1; - if (sec_len > 0 && sec_len <= len) { + if (sec_len > 0 && + sec_len <= len && + sec_len <= 32) { ssid[ssid_index].SsidLength = sec_len; - memcpy(ssid[ssid_index].Ssid, pos, ssid[ssid_index].SsidLength); + memcpy(ssid[ssid_index].Ssid, pos, sec_len); ssid_index++; } pos += sec_len; diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c index 276c965afc11..5c6630255ac2 100644 --- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c +++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c @@ -41,6 +41,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = { {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */ {USB_DEVICE(0x2C4E, 0x0102)}, /* MERCUSYS MW150US v2 */ {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */ + {USB_DEVICE(0x7392, 0xb811)}, /* Edimax EW-7811UN V2 */ {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */ {} /* Terminating entry */ }; diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c index 843e874b8a06..c5d67525b030 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c @@ -415,9 +415,10 @@ static int _rtl92e_wx_set_scan(struct net_device *dev, struct iw_scan_req *req = (struct iw_scan_req *)b; if (req->essid_len) { - ieee->current_network.ssid_len = req->essid_len; - memcpy(ieee->current_network.ssid, req->essid, - req->essid_len); + int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE); + + ieee->current_network.ssid_len = len; + memcpy(ieee->current_network.ssid, req->essid, len); } } diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index c01474a6db1e..2574275475d1 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1110,7 +1110,7 @@ struct rtllib_network { bool bWithAironetIE; bool bCkipSupported; bool bCcxRmEnable; - u16 CcxRmState[2]; + u8 CcxRmState[2]; bool bMBssidValid; u8 MBssidMask; u8 MBssid[ETH_ALEN]; diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index fa580ce1cf43..3bfd63fe4ac1 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1978,7 +1978,7 @@ static void rtllib_parse_mife_generic(struct rtllib_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x01) { if (info_element->len == 6) { - memcpy(network->CcxRmState, &info_element[4], 2); + memcpy(network->CcxRmState, &info_element->data[4], 2); if (network->CcxRmState[0] != 0) network->bCcxRmEnable = true; else diff --git a/drivers/staging/rtl8192u/r8192U_wx.c b/drivers/staging/rtl8192u/r8192U_wx.c index e4e6c979bedf..aa2206ccecee 100644 --- a/drivers/staging/rtl8192u/r8192U_wx.c +++ b/drivers/staging/rtl8192u/r8192U_wx.c @@ -333,8 +333,10 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, struct iw_scan_req *req = (struct iw_scan_req *)b; if (req->essid_len) { - ieee->current_network.ssid_len = req->essid_len; - memcpy(ieee->current_network.ssid, req->essid, req->essid_len); + int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE); + + ieee->current_network.ssid_len = len; + memcpy(ieee->current_network.ssid, req->essid, len); } } diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c index 620cee8b8514..db7bfdf9b4b2 100644 --- a/drivers/staging/rtl8712/rtl871x_cmd.c +++ b/drivers/staging/rtl8712/rtl871x_cmd.c @@ -242,8 +242,10 @@ u8 r8712_sitesurvey_cmd(struct _adapter *padapter, psurveyPara->ss_ssidlen = 0; memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1); if ((pssid != NULL) && (pssid->SsidLength)) { - memcpy(psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength); - psurveyPara->ss_ssidlen = cpu_to_le32(pssid->SsidLength); + int len = min_t(int, pssid->SsidLength, IW_ESSID_MAX_SIZE); + + memcpy(psurveyPara->ss_ssid, pssid->Ssid, len); + psurveyPara->ss_ssidlen = cpu_to_le32(len); } set_fwstate(pmlmepriv, _FW_UNDER_SURVEY); r8712_enqueue_cmd(pcmdpriv, ph2c); diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 2f490a4bf60a..4472dc76276a 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -946,7 +946,7 @@ static int r871x_wx_set_priv(struct net_device *dev, struct iw_point *dwrq = (struct iw_point *)awrq; len = dwrq->length; - ext = memdup_user(dwrq->pointer, len); + ext = strndup_user(dwrq->pointer, len); if (IS_ERR(ext)) return PTR_ERR(ext); diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c index 49ea780f9f42..dc69c41f3e38 100644 --- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c +++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c @@ -20,6 +20,7 @@ static const struct sdio_device_id sdio_ids[] = { SDIO_DEVICE(0x024c, 0x0525), }, { SDIO_DEVICE(0x024c, 0x0623), }, { SDIO_DEVICE(0x024c, 0x0626), }, + { SDIO_DEVICE(0x024c, 0x0627), }, { SDIO_DEVICE(0x024c, 0xb723), }, { /* end: all zeroes */ }, }; diff --git a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c index aa2f62acc994..4dd6f3fb5906 100644 --- a/drivers/staging/rtl8723bs/os_dep/wifi_regd.c +++ b/drivers/staging/rtl8723bs/os_dep/wifi_regd.c @@ -39,7 +39,7 @@ NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) static const struct ieee80211_regdomain rtw_regdom_rd = { - .n_reg_rules = 3, + .n_reg_rules = 2, .alpha2 = "99", .reg_rules = { RTW_2GHZ_CH01_11, diff --git a/drivers/staging/speakup/speakup_dectlk.c b/drivers/staging/speakup/speakup_dectlk.c index a144f28ee1a8..04de81559c6e 100644 --- a/drivers/staging/speakup/speakup_dectlk.c +++ b/drivers/staging/speakup/speakup_dectlk.c @@ -37,7 +37,7 @@ static unsigned char get_index(struct spk_synth *synth); static int in_escape; static int is_flushing; -static spinlock_t flush_lock; +static DEFINE_SPINLOCK(flush_lock); static DECLARE_WAIT_QUEUE_HEAD(flush); static struct var_t vars[] = { diff --git a/drivers/staging/speakup/spk_ttyio.c b/drivers/staging/speakup/spk_ttyio.c index 93742dbdee77..5c282e8522fb 100644 --- a/drivers/staging/speakup/spk_ttyio.c +++ b/drivers/staging/speakup/spk_ttyio.c @@ -47,9 +47,12 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty) { struct spk_ldisc_data *ldisc_data; + if (tty != speakup_tty) + /* Somebody tried to use this line discipline outside speakup */ + return -ENODEV; + if (tty->ops->write == NULL) return -EOPNOTSUPP; - speakup_tty = tty; ldisc_data = kmalloc(sizeof(struct spk_ldisc_data), GFP_KERNEL); if (!ldisc_data) @@ -57,7 +60,7 @@ static int spk_ttyio_ldisc_open(struct tty_struct *tty) sema_init(&ldisc_data->sem, 0); ldisc_data->buf_free = true; - speakup_tty->disc_data = ldisc_data; + tty->disc_data = ldisc_data; return 0; } @@ -177,9 +180,25 @@ static int spk_ttyio_initialise_ldisc(struct spk_synth *synth) tty_unlock(tty); + mutex_lock(&speakup_tty_mutex); + speakup_tty = tty; ret = tty_set_ldisc(tty, N_SPEAKUP); if (ret) - pr_err("speakup: Failed to set N_SPEAKUP on tty\n"); + speakup_tty = NULL; + mutex_unlock(&speakup_tty_mutex); + + if (!ret) + /* Success */ + return 0; + + pr_err("speakup: Failed to set N_SPEAKUP on tty\n"); + + tty_lock(tty); + if (tty->ops->close) + tty->ops->close(tty, NULL); + tty_unlock(tty); + + tty_kclose(tty); return ret; } diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index 25eb3891e34b..56bfb30b0ef5 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -89,8 +89,7 @@ static int cxgbit_is_ofld_imm(const struct sk_buff *skb) if (likely(cxgbit_skcb_flags(skb) & SKCBF_TX_ISO)) length += sizeof(struct cpl_tx_data_iso); -#define MAX_IMM_TX_PKT_LEN 256 - return length <= MAX_IMM_TX_PKT_LEN; + return length <= MAX_IMM_OFLD_TX_DATA_WR_LEN; } /* diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 2602b57936d4..58ccded1be85 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -492,8 +492,7 @@ EXPORT_SYMBOL(iscsit_queue_rsp); void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) { spin_lock_bh(&conn->cmd_lock); - if (!list_empty(&cmd->i_conn_node) && - !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) + if (!list_empty(&cmd->i_conn_node)) list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); @@ -4054,12 +4053,22 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) spin_lock_bh(&conn->cmd_lock); list_splice_init(&conn->conn_cmd_list, &tmp_list); - list_for_each_entry(cmd, &tmp_list, i_conn_node) { + list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { struct se_cmd *se_cmd = &cmd->se_cmd; if (se_cmd->se_tfo != NULL) { spin_lock_irq(&se_cmd->t_state_lock); - se_cmd->transport_state |= CMD_T_FABRIC_STOP; + if (se_cmd->transport_state & CMD_T_ABORTED) { + /* + * LIO's abort path owns the cleanup for this, + * so put it back on the list and let + * aborted_task handle it. + */ + list_move_tail(&cmd->i_conn_node, + &conn->conn_cmd_list); + } else { + se_cmd->transport_state |= CMD_T_FABRIC_STOP; + } spin_unlock_irq(&se_cmd->t_state_lock); } } diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 10db5656fd5d..949879f2f1d1 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3742,6 +3742,7 @@ core_scsi3_pri_read_keys(struct se_cmd *cmd) spin_unlock(&dev->t10_pr.registration_lock); put_unaligned_be32(add_len, &buf[4]); + target_set_cmd_data_length(cmd, 8 + add_len); transport_kunmap_data_sg(cmd); @@ -3760,7 +3761,7 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) struct t10_pr_registration *pr_reg; unsigned char *buf; u64 pr_res_key; - u32 add_len = 16; /* Hardcoded to 16 when a reservation is held. */ + u32 add_len = 0; if (cmd->data_length < 8) { pr_err("PRIN SA READ_RESERVATIONS SCSI Data Length: %u" @@ -3778,8 +3779,9 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) pr_reg = dev->dev_pr_res_holder; if (pr_reg) { /* - * Set the hardcoded Additional Length + * Set the Additional Length to 16 when a reservation is held */ + add_len = 16; put_unaligned_be32(add_len, &buf[4]); if (cmd->data_length < 22) @@ -3815,6 +3817,8 @@ core_scsi3_pri_read_reservation(struct se_cmd *cmd) (pr_reg->pr_res_type & 0x0f); } + target_set_cmd_data_length(cmd, 8 + add_len); + err: spin_unlock(&dev->dev_reservation_lock); transport_kunmap_data_sg(cmd); @@ -3833,7 +3837,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) struct se_device *dev = cmd->se_dev; struct t10_reservation *pr_tmpl = &dev->t10_pr; unsigned char *buf; - u16 add_len = 8; /* Hardcoded to 8. */ + u16 len = 8; /* Hardcoded to 8. */ if (cmd->data_length < 6) { pr_err("PRIN SA REPORT_CAPABILITIES SCSI Data Length:" @@ -3845,7 +3849,7 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) if (!buf) return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - put_unaligned_be16(add_len, &buf[0]); + put_unaligned_be16(len, &buf[0]); buf[2] |= 0x10; /* CRH: Compatible Reservation Hanlding bit. */ buf[2] |= 0x08; /* SIP_C: Specify Initiator Ports Capable bit */ buf[2] |= 0x04; /* ATP_C: All Target Ports Capable bit */ @@ -3874,6 +3878,8 @@ core_scsi3_pri_report_capabilities(struct se_cmd *cmd) buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ + target_set_cmd_data_length(cmd, len); + transport_kunmap_data_sg(cmd); return 0; @@ -4034,6 +4040,7 @@ core_scsi3_pri_read_full_status(struct se_cmd *cmd) * Set ADDITIONAL_LENGTH */ put_unaligned_be32(add_len, &buf[4]); + target_set_cmd_data_length(cmd, 8 + add_len); transport_kunmap_data_sg(cmd); diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 47d76c862014..02c4e3beb264 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -970,6 +970,14 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, return 0; fail: + if (bio) + bio_put(bio); + while (req->bio) { + bio = req->bio; + req->bio = bio->bi_next; + bio_put(bio); + } + req->biotail = NULL; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index f1b730b77a31..bdada97cd4fe 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -841,11 +841,9 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status) } EXPORT_SYMBOL(target_complete_cmd); -void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) +void target_set_cmd_data_length(struct se_cmd *cmd, int length) { - if ((scsi_status == SAM_STAT_GOOD || - cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) && - length < cmd->data_length) { + if (length < cmd->data_length) { if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { cmd->residual_count += cmd->data_length - length; } else { @@ -855,6 +853,15 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len cmd->data_length = length; } +} +EXPORT_SYMBOL(target_set_cmd_data_length); + +void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) +{ + if (scsi_status == SAM_STAT_GOOD || + cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) { + target_set_cmd_data_length(cmd, length); + } target_complete_cmd(cmd, scsi_status); } diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c index 7cdb5d7f6538..1709b8a99bd7 100644 --- a/drivers/target/target_core_xcopy.c +++ b/drivers/target/target_core_xcopy.c @@ -55,60 +55,83 @@ static int target_xcopy_gen_naa_ieee(struct se_device *dev, unsigned char *buf) return 0; } -struct xcopy_dev_search_info { - const unsigned char *dev_wwn; - struct se_device *found_dev; -}; - +/** + * target_xcopy_locate_se_dev_e4_iter - compare XCOPY NAA device identifiers + * + * @se_dev: device being considered for match + * @dev_wwn: XCOPY requested NAA dev_wwn + * @return: 1 on match, 0 on no-match + */ static int target_xcopy_locate_se_dev_e4_iter(struct se_device *se_dev, - void *data) + const unsigned char *dev_wwn) { - struct xcopy_dev_search_info *info = data; unsigned char tmp_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; int rc; - if (!se_dev->dev_attrib.emulate_3pc) + if (!se_dev->dev_attrib.emulate_3pc) { + pr_debug("XCOPY: emulate_3pc disabled on se_dev %p\n", se_dev); return 0; + } memset(&tmp_dev_wwn[0], 0, XCOPY_NAA_IEEE_REGEX_LEN); target_xcopy_gen_naa_ieee(se_dev, &tmp_dev_wwn[0]); - rc = memcmp(&tmp_dev_wwn[0], info->dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); - if (rc != 0) - return 0; - - info->found_dev = se_dev; - pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); - - rc = target_depend_item(&se_dev->dev_group.cg_item); + rc = memcmp(&tmp_dev_wwn[0], dev_wwn, XCOPY_NAA_IEEE_REGEX_LEN); if (rc != 0) { - pr_err("configfs_depend_item attempt failed: %d for se_dev: %p\n", - rc, se_dev); - return rc; + pr_debug("XCOPY: skip non-matching: %*ph\n", + XCOPY_NAA_IEEE_REGEX_LEN, tmp_dev_wwn); + return 0; } + pr_debug("XCOPY 0xe4: located se_dev: %p\n", se_dev); - pr_debug("Called configfs_depend_item for se_dev: %p se_dev->se_dev_group: %p\n", - se_dev, &se_dev->dev_group); return 1; } -static int target_xcopy_locate_se_dev_e4(const unsigned char *dev_wwn, - struct se_device **found_dev) +static int target_xcopy_locate_se_dev_e4(struct se_session *sess, + const unsigned char *dev_wwn, + struct se_device **_found_dev, + struct percpu_ref **_found_lun_ref) { - struct xcopy_dev_search_info info; - int ret; - - memset(&info, 0, sizeof(info)); - info.dev_wwn = dev_wwn; - - ret = target_for_each_device(target_xcopy_locate_se_dev_e4_iter, &info); - if (ret == 1) { - *found_dev = info.found_dev; - return 0; - } else { - pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); - return -EINVAL; + struct se_dev_entry *deve; + struct se_node_acl *nacl; + struct se_lun *this_lun = NULL; + struct se_device *found_dev = NULL; + + /* cmd with NULL sess indicates no associated $FABRIC_MOD */ + if (!sess) + goto err_out; + + pr_debug("XCOPY 0xe4: searching for: %*ph\n", + XCOPY_NAA_IEEE_REGEX_LEN, dev_wwn); + + nacl = sess->se_node_acl; + rcu_read_lock(); + hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link) { + struct se_device *this_dev; + int rc; + + this_lun = rcu_dereference(deve->se_lun); + this_dev = rcu_dereference_raw(this_lun->lun_se_dev); + + rc = target_xcopy_locate_se_dev_e4_iter(this_dev, dev_wwn); + if (rc) { + if (percpu_ref_tryget_live(&this_lun->lun_ref)) + found_dev = this_dev; + break; + } } + rcu_read_unlock(); + if (found_dev == NULL) + goto err_out; + + pr_debug("lun_ref held for se_dev: %p se_dev->se_dev_group: %p\n", + found_dev, &found_dev->dev_group); + *_found_dev = found_dev; + *_found_lun_ref = &this_lun->lun_ref; + return 0; +err_out: + pr_debug_ratelimited("Unable to locate 0xe4 descriptor for EXTENDED_COPY\n"); + return -EINVAL; } static int target_xcopy_parse_tiddesc_e4(struct se_cmd *se_cmd, struct xcopy_op *xop, @@ -255,12 +278,16 @@ static int target_xcopy_parse_target_descriptors(struct se_cmd *se_cmd, switch (xop->op_origin) { case XCOL_SOURCE_RECV_OP: - rc = target_xcopy_locate_se_dev_e4(xop->dst_tid_wwn, - &xop->dst_dev); + rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess, + xop->dst_tid_wwn, + &xop->dst_dev, + &xop->remote_lun_ref); break; case XCOL_DEST_RECV_OP: - rc = target_xcopy_locate_se_dev_e4(xop->src_tid_wwn, - &xop->src_dev); + rc = target_xcopy_locate_se_dev_e4(se_cmd->se_sess, + xop->src_tid_wwn, + &xop->src_dev, + &xop->remote_lun_ref); break; default: pr_err("XCOPY CSCD descriptor IDs not found in CSCD list - " @@ -412,18 +439,12 @@ static int xcopy_pt_get_cmd_state(struct se_cmd *se_cmd) static void xcopy_pt_undepend_remotedev(struct xcopy_op *xop) { - struct se_device *remote_dev; - if (xop->op_origin == XCOL_SOURCE_RECV_OP) - remote_dev = xop->dst_dev; + pr_debug("putting dst lun_ref for %p\n", xop->dst_dev); else - remote_dev = xop->src_dev; - - pr_debug("Calling configfs_undepend_item for" - " remote_dev: %p remote_dev->dev_group: %p\n", - remote_dev, &remote_dev->dev_group.cg_item); + pr_debug("putting src lun_ref for %p\n", xop->src_dev); - target_undepend_item(&remote_dev->dev_group.cg_item); + percpu_ref_put(xop->remote_lun_ref); } static void xcopy_pt_release_cmd(struct se_cmd *se_cmd) diff --git a/drivers/target/target_core_xcopy.h b/drivers/target/target_core_xcopy.h index 26ba4c3c9cff..974bc1e19ff2 100644 --- a/drivers/target/target_core_xcopy.h +++ b/drivers/target/target_core_xcopy.h @@ -29,6 +29,7 @@ struct xcopy_op { struct se_device *dst_dev; unsigned char dst_tid_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; unsigned char local_dev_wwn[XCOPY_NAA_IEEE_REGEX_LEN]; + struct percpu_ref *remote_lun_ref; sector_t src_lba; sector_t dst_lba; diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index a5afbe6dee68..7cb7efe62b01 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -538,7 +538,8 @@ void optee_free_pages_list(void *list, size_t num_entries) static bool is_normal_memory(pgprot_t p) { #if defined(CONFIG_ARM) - return (pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC; + return (((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEALLOC) || + ((pgprot_val(p) & L_PTE_MT_MASK) == L_PTE_MT_WRITEBACK)); #elif defined(CONFIG_ARM64) return (pgprot_val(p) & PTE_ATTRINDX_MASK) == PTE_ATTRINDX(MT_NORMAL); #else diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig index cc78d3711bfe..eacb7d309834 100644 --- a/drivers/thermal/qcom/Kconfig +++ b/drivers/thermal/qcom/Kconfig @@ -151,3 +151,14 @@ config QTI_CX_IPEAK_COOLING_DEVICE on the CX rail. If you want this support, you should say Y here. + +config QTI_THERMAL_QFPROM + tristate "Qualcomm Technologies Inc. thermal QFPROM driver" + depends on THERMAL + depends on QCOM_QFPROM + help + This driver enables or disables pre-configured thermal zones + selectively at runtime based on QFPROM nvmem cell bit value is + set or not. It supports to check multiple nvmem cell value for + multiple condtion. In that case, if any of the nvmem-cell condition + fails, driver just exits with default enabled thermal zones. diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile index 8a0b6190ec9f..9f5224a961dd 100644 --- a/drivers/thermal/qcom/Makefile +++ b/drivers/thermal/qcom/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE) += cpu_isolate.o obj-$(CONFIG_QTI_LMH_CPU_VDD_COOLING_DEVICE) += lmh_cpu_vdd_cdev.o obj-$(CONFIG_QTI_LIMITS_ISENSE_CDSP) += msm_isense_cdsp.o obj-$(CONFIG_QTI_CX_IPEAK_COOLING_DEVICE) += cx_ipeak_cdev.o +obj-$(CONFIG_QTI_THERMAL_QFPROM) += qti_thermal_qfprom.o diff --git a/drivers/thermal/qcom/qti_thermal_qfprom.c b/drivers/thermal/qcom/qti_thermal_qfprom.c new file mode 100644 index 000000000000..47b9b2cd6e8b --- /dev/null +++ b/drivers/thermal/qcom/qti_thermal_qfprom.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__ + +#include +#include +#include +#include +#include +#include +#include + +#include "../thermal_core.h" + +static int thermal_qfprom_read(struct platform_device *pdev, + const char *cname, unsigned int *efuse_val) +{ + struct nvmem_cell *cell; + size_t len; + char *buf; + + cell = nvmem_cell_get(&pdev->dev, cname); + if (IS_ERR(cell)) { + dev_err(&pdev->dev, "failed to get nvmem cell %s\n", cname); + return -EINVAL; + } + + buf = nvmem_cell_read(cell, &len); + nvmem_cell_put(cell); + if (IS_ERR_OR_NULL(buf)) { + dev_err(&pdev->dev, "failed to read nvmem cell %s\n", cname); + return -EINVAL; + } + + if (len <= 0 || len > sizeof(u32)) { + dev_err(&pdev->dev, "nvmem cell length out of range:%d\n", len); + kfree(buf); + return -EINVAL; + } + memcpy(efuse_val, buf, min(len, sizeof(*efuse_val))); + kfree(buf); + + return 0; +} + +static int thermal_zone_set_mode(struct platform_device *pdev, + enum thermal_device_mode mode) +{ + const char *name; + struct property *prop = NULL; + + of_property_for_each_string(pdev->dev.of_node, + mode == THERMAL_DEVICE_ENABLED ? + "qcom,thermal-zone-enable-list" : + "qcom,thermal-zone-disable-list", prop, name) { + struct thermal_zone_device *zone; + struct thermal_instance *pos; + + zone = thermal_zone_get_zone_by_name(name); + if (IS_ERR(zone)) { + dev_err(&pdev->dev, + "could not find %s thermal zone\n", name); + continue; + } + + if (!(zone->ops && zone->ops->set_mode)) { + dev_err(&pdev->dev, + "thermal zone ops is not supported for %s\n", + name); + continue; + } + + zone->ops->set_mode(zone, mode); + if (mode == THERMAL_DEVICE_DISABLED) { + /* Clear thermal zone device */ + mutex_lock(&zone->lock); + zone->temperature = THERMAL_TEMP_INVALID; + zone->passive = 0; + list_for_each_entry(pos, &zone->thermal_instances, + tz_node) { + pos->initialized = false; + pos->target = THERMAL_NO_TARGET; + mutex_lock(&pos->cdev->lock); + pos->cdev->updated = false; + mutex_unlock(&pos->cdev->lock); + thermal_cdev_update(pos->cdev); + } + mutex_unlock(&zone->lock); + } + dev_dbg(&pdev->dev, "thermal zone %s is %s\n", name, + mode == THERMAL_DEVICE_ENABLED ? + "enabled" : "disabled"); + } + + return 0; +} + +static void update_thermal_zones(struct platform_device *pdev) +{ + thermal_zone_set_mode(pdev, THERMAL_DEVICE_ENABLED); + thermal_zone_set_mode(pdev, THERMAL_DEVICE_DISABLED); +} + +static int thermal_qfprom_probe(struct platform_device *pdev) +{ + int err = 0; + const char *name; + struct property *prop = NULL; + u8 efuse_pass_cnt = 0; + + of_property_for_each_string(pdev->dev.of_node, + "nvmem-cell-names", prop, name) { + u32 efuse_val = 0, efuse_match_val = 0; + + err = thermal_qfprom_read(pdev, name, &efuse_val); + if (err) + return err; + + err = of_property_read_u32_index(pdev->dev.of_node, + "qcom,thermal-qfprom-bit-values", efuse_pass_cnt, + &efuse_match_val); + if (err) { + dev_err(&pdev->dev, + "Invalid qfprom bit value for index %d\n", + efuse_pass_cnt); + return err; + } + + dev_dbg(&pdev->dev, "efuse[%s] val:0x%x match val[%d]:0x%x\n", + name, efuse_val, efuse_pass_cnt, + efuse_match_val); + + /* if any of efuse condition fails, just exit */ + if (efuse_val != efuse_match_val) + return 0; + + efuse_pass_cnt++; + } + + if (efuse_pass_cnt) + update_thermal_zones(pdev); + + return err; +} + +static const struct of_device_id thermal_qfprom_match[] = { + { .compatible = "qcom,thermal-qfprom-device", }, + {}, +}; + +static struct platform_driver thermal_qfprom_driver = { + .probe = thermal_qfprom_probe, + .driver = { + .name = KBUILD_MODNAME, + .of_match_table = thermal_qfprom_match, + }, +}; + +int __init thermal_qfprom_init(void) +{ + int err; + + err = platform_driver_register(&thermal_qfprom_driver); + if (err) + pr_err("Failed to register thermal qfprom platform driver:%d\n", + err); + return err; +} + +late_initcall(thermal_qfprom_init); diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index ed8f0cdbfc54..a2610c18db24 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -1664,8 +1664,7 @@ static int __init thermal_init(void) mutex_init(&poweroff_lock); thermal_passive_wq = alloc_workqueue("thermal_passive_wq", - WQ_HIGHPRI | WQ_UNBOUND - | WQ_FREEZABLE, + WQ_UNBOUND | WQ_FREEZABLE, THERMAL_MAX_ACTIVE); if (!thermal_passive_wq) { result = -ENOMEM; diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index d436a1534fc2..384623c49cfe 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -408,12 +408,23 @@ static int ring_request_msix(struct tb_ring *ring, bool no_suspend) ring->vector = ret; - ring->irq = pci_irq_vector(ring->nhi->pdev, ring->vector); - if (ring->irq < 0) - return ring->irq; + ret = pci_irq_vector(ring->nhi->pdev, ring->vector); + if (ret < 0) + goto err_ida_remove; + + ring->irq = ret; irqflags = no_suspend ? IRQF_NO_SUSPEND : 0; - return request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring); + ret = request_irq(ring->irq, ring_msix, irqflags, "thunderbolt", ring); + if (ret) + goto err_ida_remove; + + return 0; + +err_ida_remove: + ida_simple_remove(&nhi->msix_ida, ring->vector); + + return ret; } static void ring_release_msix(struct tb_ring *ring) diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c index befe75490697..4eb51a123a6f 100644 --- a/drivers/thunderbolt/xdomain.c +++ b/drivers/thunderbolt/xdomain.c @@ -774,6 +774,7 @@ static void enumerate_services(struct tb_xdomain *xd) id = ida_simple_get(&xd->service_ids, 0, 0, GFP_KERNEL); if (id < 0) { + kfree(svc->key); kfree(svc); break; } diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index cbd006fb7fbb..c1166b45c288 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -163,11 +163,6 @@ static void omap_8250_mdr1_errataset(struct uart_8250_port *up, struct omap8250_priv *priv) { u8 timeout = 255; - u8 old_mdr1; - - old_mdr1 = serial_in(up, UART_OMAP_MDR1); - if (old_mdr1 == priv->mdr1) - return; serial_out(up, UART_OMAP_MDR1, priv->mdr1); udelay(2); diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index 4066cb2b79cb..7a6e26b12bf6 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -1915,16 +1915,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) unsigned int ucr1; unsigned long flags = 0; int locked = 1; - int retval; - - retval = clk_enable(sport->clk_per); - if (retval) - return; - retval = clk_enable(sport->clk_ipg); - if (retval) { - clk_disable(sport->clk_per); - return; - } if (sport->port.sysrq) locked = 0; @@ -1960,9 +1950,6 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count) if (locked) spin_unlock_irqrestore(&sport->port.lock, flags); - - clk_disable(sport->clk_ipg); - clk_disable(sport->clk_per); } /* @@ -2063,15 +2050,14 @@ imx_uart_console_setup(struct console *co, char *options) retval = uart_set_options(&sport->port, co, baud, parity, bits, flow); - clk_disable(sport->clk_ipg); if (retval) { - clk_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_ipg); goto error_console; } - retval = clk_prepare(sport->clk_per); + retval = clk_prepare_enable(sport->clk_per); if (retval) - clk_unprepare(sport->clk_ipg); + clk_disable_unprepare(sport->clk_ipg); error_console: return retval; diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 870f57b2e715..f697e6a1ac15 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -113,7 +113,7 @@ #define UART_CORE2X_VOTE (5000) #define UART_CONSOLE_CORE2X_VOTE (960) -#define WAKEBYTE_TIMEOUT_MSEC (2000) +#define WAKEBYTE_TIMEOUT_MSEC (100) #define WAIT_XFER_MAX_ITER (2) #define WAIT_XFER_MAX_TIMEOUT_US (10000) #define WAIT_XFER_MIN_TIMEOUT_US (9000) @@ -211,6 +211,7 @@ struct msm_geni_serial_port { struct completion m_cmd_timeout; struct completion s_cmd_timeout; spinlock_t rx_lock; + bool bypass_flow_control; }; static const struct uart_ops msm_geni_serial_pops; @@ -1454,7 +1455,8 @@ static int stop_rx_sequencer(struct uart_port *uport) } if (!uart_console(uport)) { - msm_geni_serial_set_manual_flow(false, port); + if (!port->bypass_flow_control) + msm_geni_serial_set_manual_flow(false, port); /* * Wait for the stale timeout to happen if there * is any data pending in the rx fifo. @@ -1571,7 +1573,7 @@ static int stop_rx_sequencer(struct uart_port *uport) port->s_cmd = false; exit_rx_seq: - if (!uart_console(uport)) + if (!uart_console(uport) && !port->bypass_flow_control) msm_geni_serial_set_manual_flow(true, port); geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS); @@ -2512,7 +2514,12 @@ static void msm_geni_serial_set_termios(struct uart_port *uport, return; } } + + //Client must control Flow, don't touch RFR during baud change. + port->bypass_flow_control = true; msm_geni_serial_stop_rx(uport); + port->bypass_flow_control = false; + /* baud rate */ baud = uart_get_baud_rate(uport, termios, old, 300, 4000000); port->cur_baud = baud; diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index fb9d369e0f50..330522be708f 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -637,6 +637,14 @@ static void wait_for_xmitr(struct uart_port *port) (val & STAT_TX_RDY(port)), 1, 10000); } +static void wait_for_xmite(struct uart_port *port) +{ + u32 val; + + readl_poll_timeout_atomic(port->membase + UART_STAT, val, + (val & STAT_TX_EMP), 1, 10000); +} + static void mvebu_uart_console_putchar(struct uart_port *port, int ch) { wait_for_xmitr(port); @@ -664,7 +672,7 @@ static void mvebu_uart_console_write(struct console *co, const char *s, uart_console_write(port, s, count, mvebu_uart_console_putchar); - wait_for_xmitr(port); + wait_for_xmite(port); if (ier) writel(ier, port->membase + UART_CTRL(port)); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index d2e387379abc..d3ef0f658303 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1421,6 +1421,10 @@ static void uart_set_ldisc(struct tty_struct *tty) { struct uart_state *state = tty->driver_data; struct uart_port *uport; + struct tty_port *port = &state->port; + + if (!tty_port_initialized(port)) + return; mutex_lock(&state->port.mutex); uport = uart_port_check(state); diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b4838ab8ba95..0e8b5f5b19f3 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2751,10 +2751,14 @@ void __do_SAK(struct tty_struct *tty) struct task_struct *g, *p; struct pid *session; int i; + unsigned long flags; if (!tty) return; - session = tty->session; + + spin_lock_irqsave(&tty->ctrl_lock, flags); + session = get_pid(tty->session); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); tty_ldisc_flush(tty); @@ -2786,6 +2790,7 @@ void __do_SAK(struct tty_struct *tty) task_unlock(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); + put_pid(session); #endif } diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c index c4ecd66fafef..ffcab80ba77d 100644 --- a/drivers/tty/tty_jobctrl.c +++ b/drivers/tty/tty_jobctrl.c @@ -103,8 +103,8 @@ static void __proc_set_tty(struct tty_struct *tty) put_pid(tty->session); put_pid(tty->pgrp); tty->pgrp = get_pid(task_pgrp(current)); - spin_unlock_irqrestore(&tty->ctrl_lock, flags); tty->session = get_pid(task_session(current)); + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (current->signal->tty) { tty_debug(tty, "current tty %s not NULL!!\n", current->signal->tty->name); @@ -293,20 +293,23 @@ void disassociate_ctty(int on_exit) spin_lock_irq(¤t->sighand->siglock); put_pid(current->signal->tty_old_pgrp); current->signal->tty_old_pgrp = NULL; - tty = tty_kref_get(current->signal->tty); + spin_unlock_irq(¤t->sighand->siglock); + if (tty) { unsigned long flags; + + tty_lock(tty); spin_lock_irqsave(&tty->ctrl_lock, flags); put_pid(tty->session); put_pid(tty->pgrp); tty->session = NULL; tty->pgrp = NULL; spin_unlock_irqrestore(&tty->ctrl_lock, flags); + tty_unlock(tty); tty_kref_put(tty); } - spin_unlock_irq(¤t->sighand->siglock); /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); session_clear_tty(task_session(current)); @@ -477,14 +480,19 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t return -ENOTTY; if (retval) return retval; - if (!current->signal->tty || - (current->signal->tty != real_tty) || - (real_tty->session != task_session(current))) - return -ENOTTY; + if (get_user(pgrp_nr, p)) return -EFAULT; if (pgrp_nr < 0) return -EINVAL; + + spin_lock_irq(&real_tty->ctrl_lock); + if (!current->signal->tty || + (current->signal->tty != real_tty) || + (real_tty->session != task_session(current))) { + retval = -ENOTTY; + goto out_unlock_ctrl; + } rcu_read_lock(); pgrp = find_vpid(pgrp_nr); retval = -ESRCH; @@ -494,12 +502,12 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t if (session_of_pgrp(pgrp) != task_session(current)) goto out_unlock; retval = 0; - spin_lock_irq(&tty->ctrl_lock); put_pid(real_tty->pgrp); real_tty->pgrp = get_pid(pgrp); - spin_unlock_irq(&tty->ctrl_lock); out_unlock: rcu_read_unlock(); +out_unlock_ctrl: + spin_unlock_irq(&real_tty->ctrl_lock); return retval; } @@ -511,20 +519,30 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t * * Obtain the session id of the tty. If there is no session * return an error. - * - * Locking: none. Reference to current->signal->tty is safe. */ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) { + unsigned long flags; + pid_t sid; + /* * (tty == real_tty) is a cheap way of * testing if the tty is NOT a master pty. */ if (tty == real_tty && current->signal->tty != real_tty) return -ENOTTY; + + spin_lock_irqsave(&real_tty->ctrl_lock, flags); if (!real_tty->session) - return -ENOTTY; - return put_user(pid_vnr(real_tty->session), p); + goto err; + sid = pid_vnr(real_tty->session); + spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); + + return put_user(sid, p); + +err: + spin_unlock_irqrestore(&real_tty->ctrl_lock, flags); + return -ENOTTY; } /* diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index 7c7ada0b3ea0..90c6e10b1ef9 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -495,7 +495,7 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos) p2[unicode & 0x3f] = fontpos; - p->sum += (fontpos << 20) + unicode; + p->sum += (fontpos << 20U) + unicode; return 0; } diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 3926be659147..0e3e16c51d3a 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -413,10 +413,10 @@ static int uio_get_minor(struct uio_device *idev) return retval; } -static void uio_free_minor(struct uio_device *idev) +static void uio_free_minor(unsigned long minor) { mutex_lock(&minor_lock); - idr_remove(&uio_idr, idev->minor); + idr_remove(&uio_idr, minor); mutex_unlock(&minor_lock); } @@ -988,7 +988,7 @@ int __uio_register_device(struct module *owner, err_uio_dev_add_attributes: device_del(&idev->dev); err_device_create: - uio_free_minor(idev); + uio_free_minor(idev->minor); put_device(&idev->dev); return ret; } @@ -1002,11 +1002,13 @@ EXPORT_SYMBOL_GPL(__uio_register_device); void uio_unregister_device(struct uio_info *info) { struct uio_device *idev; + unsigned long minor; if (!info || !info->uio_dev) return; idev = info->uio_dev; + minor = idev->minor; mutex_lock(&idev->info_lock); uio_dev_del_attributes(idev); @@ -1019,7 +1021,7 @@ void uio_unregister_device(struct uio_info *info) device_unregister(&idev->dev); - uio_free_minor(idev); + uio_free_minor(minor); return; } diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c index 19f5f5f2a48a..af420ec2a9f4 100644 --- a/drivers/usb/chipidea/ci_hdrc_imx.c +++ b/drivers/usb/chipidea/ci_hdrc_imx.c @@ -57,7 +57,8 @@ static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = { static const struct ci_hdrc_imx_platform_flag imx6ul_usb_data = { .flags = CI_HDRC_SUPPORTS_RUNTIME_PM | - CI_HDRC_TURN_VBUS_EARLY_ON, + CI_HDRC_TURN_VBUS_EARLY_ON | + CI_HDRC_DISABLE_DEVICE_STREAMING, }; static const struct ci_hdrc_imx_platform_flag imx7d_usb_data = { @@ -127,9 +128,13 @@ static struct imx_usbmisc_data *usbmisc_get_init_data(struct device *dev) misc_pdev = of_find_device_by_node(args.np); of_node_put(args.np); - if (!misc_pdev || !platform_get_drvdata(misc_pdev)) + if (!misc_pdev) return ERR_PTR(-EPROBE_DEFER); + if (!platform_get_drvdata(misc_pdev)) { + put_device(&misc_pdev->dev); + return ERR_PTR(-EPROBE_DEFER); + } data->dev = &misc_pdev->dev; if (of_find_property(np, "disable-over-current", NULL)) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 08751d1a765f..7f4f21ba8efc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -147,17 +147,29 @@ static inline int acm_set_control(struct acm *acm, int control) #define acm_send_break(acm, ms) \ acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) -static void acm_kill_urbs(struct acm *acm) +static void acm_poison_urbs(struct acm *acm) { int i; - usb_kill_urb(acm->ctrlurb); + usb_poison_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) - usb_kill_urb(acm->wb[i].urb); + usb_poison_urb(acm->wb[i].urb); for (i = 0; i < acm->rx_buflimit; i++) - usb_kill_urb(acm->read_urbs[i]); + usb_poison_urb(acm->read_urbs[i]); +} + +static void acm_unpoison_urbs(struct acm *acm) +{ + int i; + + for (i = 0; i < acm->rx_buflimit; i++) + usb_unpoison_urb(acm->read_urbs[i]); + for (i = 0; i < ACM_NW; i++) + usb_unpoison_urb(acm->wb[i].urb); + usb_unpoison_urb(acm->ctrlurb); } + /* * Write buffer management. * All of these assume proper locks taken by the caller. @@ -225,9 +237,10 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) rc = usb_submit_urb(wb->urb, GFP_ATOMIC); if (rc < 0) { - dev_err(&acm->data->dev, - "%s - usb_submit_urb(write bulk) failed: %d\n", - __func__, rc); + if (rc != -EPERM) + dev_err(&acm->data->dev, + "%s - usb_submit_urb(write bulk) failed: %d\n", + __func__, rc); acm_write_done(acm, wb); } return rc; @@ -312,8 +325,10 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf) acm->iocount.dsr++; if (difference & ACM_CTRL_DCD) acm->iocount.dcd++; - if (newctrl & ACM_CTRL_BRK) + if (newctrl & ACM_CTRL_BRK) { acm->iocount.brk++; + tty_insert_flip_char(&acm->port, 0, TTY_BREAK); + } if (newctrl & ACM_CTRL_RI) acm->iocount.rng++; if (newctrl & ACM_CTRL_FRAMING) @@ -480,11 +495,6 @@ static void acm_read_bulk_callback(struct urb *urb) dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n", rb->index, urb->actual_length, status); - if (!acm->dev) { - dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); - return; - } - switch (status) { case 0: usb_mark_last_busy(acm->dev); @@ -654,7 +664,8 @@ static void acm_port_dtr_rts(struct tty_port *port, int raise) res = acm_set_control(acm, val); if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE)) - dev_err(&acm->control->dev, "failed to set dtr/rts\n"); + /* This is broken in too many devices to spam the logs */ + dev_dbg(&acm->control->dev, "failed to set dtr/rts\n"); } static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) @@ -739,6 +750,7 @@ static void acm_port_shutdown(struct tty_port *port) * Need to grab write_lock to prevent race with resume, but no need to * hold it due to the tty-port initialised flag. */ + acm_poison_urbs(acm); spin_lock_irq(&acm->write_lock); spin_unlock_irq(&acm->write_lock); @@ -755,7 +767,8 @@ static void acm_port_shutdown(struct tty_port *port) usb_autopm_put_interface_async(acm->control); } - acm_kill_urbs(acm); + acm_unpoison_urbs(acm); + } static void acm_tty_cleanup(struct tty_struct *tty) @@ -1548,12 +1561,16 @@ static int acm_probe(struct usb_interface *intf, return 0; alloc_fail6: + if (!acm->combined_interfaces) { + /* Clear driver data so that disconnect() returns early. */ + usb_set_intfdata(data_interface, NULL); + usb_driver_release_interface(&acm_driver, data_interface); + } if (acm->country_codes) { device_remove_file(&acm->control->dev, &dev_attr_wCountryCodes); device_remove_file(&acm->control->dev, &dev_attr_iCountryCodeRelDate); - kfree(acm->country_codes); } device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); alloc_fail5: @@ -1585,8 +1602,14 @@ static void acm_disconnect(struct usb_interface *intf) if (!acm) return; - mutex_lock(&acm->mutex); acm->disconnected = true; + /* + * there is a circular dependency. acm_softint() can resubmit + * the URBs in error handling so we need to block any + * submission right away + */ + acm_poison_urbs(acm); + mutex_lock(&acm->mutex); if (acm->country_codes) { device_remove_file(&acm->control->dev, &dev_attr_wCountryCodes); @@ -1605,7 +1628,6 @@ static void acm_disconnect(struct usb_interface *intf) tty_kref_put(tty); } - acm_kill_urbs(acm); cancel_delayed_work_sync(&acm->dwork); tty_unregister_device(acm_tty_driver, acm->minor); @@ -1647,7 +1669,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) if (cnt) return 0; - acm_kill_urbs(acm); + acm_poison_urbs(acm); cancel_delayed_work_sync(&acm->dwork); acm->urbs_in_error_delay = 0; @@ -1665,6 +1687,8 @@ static int acm_resume(struct usb_interface *intf) if (--acm->susp_count) goto out; + acm_unpoison_urbs(acm); + if (tty_port_initialized(&acm->port)) { rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC); @@ -1738,6 +1762,15 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x045b, 0x023c), /* Renesas USB Download mode */ + .driver_info = DISABLE_ECHO, /* Don't echo banner */ + }, + { USB_DEVICE(0x045b, 0x0248), /* Renesas USB Download mode */ + .driver_info = DISABLE_ECHO, /* Don't echo banner */ + }, + { USB_DEVICE(0x045b, 0x024D), /* Renesas USB Download mode */ + .driver_info = DISABLE_ECHO, /* Don't echo banner */ + }, { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, @@ -1930,6 +1963,10 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x04d8, 0x0083), /* Bootloader mode */ .driver_info = IGNORE_DEVICE, }, + + { USB_DEVICE(0x04d8, 0xf58b), + .driver_info = IGNORE_DEVICE, + }, #endif /*Samsung phone in firmware update mode */ @@ -1960,6 +1997,11 @@ static const struct usb_device_id acm_ids[] = { .driver_info = SEND_ZERO_PACKET, }, + /* Exclude Goodix Fingerprint Reader */ + { USB_DEVICE(0x27c6, 0x5395), + .driver_info = IGNORE_DEVICE, + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) }, diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 55ad4c43b380..ae69635bb1fb 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -465,13 +465,23 @@ static int service_outstanding_interrupt(struct wdm_device *desc) if (!desc->resp_count || !--desc->resp_count) goto out; + if (test_bit(WDM_DISCONNECTING, &desc->flags)) { + rv = -ENODEV; + goto out; + } + if (test_bit(WDM_RESETTING, &desc->flags)) { + rv = -EIO; + goto out; + } + set_bit(WDM_RESPONDING, &desc->flags); spin_unlock_irq(&desc->iuspin); rv = usb_submit_urb(desc->response, GFP_KERNEL); spin_lock_irq(&desc->iuspin); if (rv) { - dev_err(&desc->intf->dev, - "usb_submit_urb failed with result %d\n", rv); + if (!test_bit(WDM_DISCONNECTING, &desc->flags)) + dev_err(&desc->intf->dev, + "usb_submit_urb failed with result %d\n", rv); /* make sure the next notification trigger a submit */ clear_bit(WDM_RESPONDING, &desc->flags); @@ -1026,9 +1036,9 @@ static void wdm_disconnect(struct usb_interface *intf) wake_up_all(&desc->wait); mutex_lock(&desc->rlock); mutex_lock(&desc->wlock); - kill_urbs(desc); cancel_work_sync(&desc->rxwork); cancel_work_sync(&desc->service_outs_intr); + kill_urbs(desc); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock); diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index db36a796af8c..5edf52a6edfc 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -274,8 +274,25 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i #define usblp_reset(usblp)\ usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0) -#define usblp_hp_channel_change_request(usblp, channel, buffer) \ - usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1) +static int usblp_hp_channel_change_request(struct usblp *usblp, int channel, u8 *new_channel) +{ + u8 *buf; + int ret; + + buf = kzalloc(1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, + USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, + channel, buf, 1); + if (ret == 0) + *new_channel = buf[0]; + + kfree(buf); + + return ret; +} /* * See the description for usblp_select_alts() below for the usage @@ -477,16 +494,24 @@ static int usblp_release(struct inode *inode, struct file *file) /* No kernel lock - fine */ static __poll_t usblp_poll(struct file *file, struct poll_table_struct *wait) { - __poll_t ret; + struct usblp *usblp = file->private_data; + __poll_t ret = 0; unsigned long flags; - struct usblp *usblp = file->private_data; /* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */ poll_wait(file, &usblp->rwait, wait); poll_wait(file, &usblp->wwait, wait); + + mutex_lock(&usblp->mut); + if (!usblp->present) + ret |= EPOLLHUP; + mutex_unlock(&usblp->mut); + spin_lock_irqsave(&usblp->lock, flags); - ret = ((usblp->bidir && usblp->rcomplete) ? EPOLLIN | EPOLLRDNORM : 0) | - ((usblp->no_paper || usblp->wcomplete) ? EPOLLOUT | EPOLLWRNORM : 0); + if (usblp->bidir && usblp->rcomplete) + ret |= EPOLLIN | EPOLLRDNORM; + if (usblp->no_paper || usblp->wcomplete) + ret |= EPOLLOUT | EPOLLWRNORM; spin_unlock_irqrestore(&usblp->lock, flags); return ret; } @@ -1310,14 +1335,17 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol) if (protocol < USBLP_FIRST_PROTOCOL || protocol > USBLP_LAST_PROTOCOL) return -EINVAL; - alts = usblp->protocol[protocol].alt_setting; - if (alts < 0) - return -EINVAL; - r = usb_set_interface(usblp->dev, usblp->ifnum, alts); - if (r < 0) { - printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", - alts, usblp->ifnum); - return r; + /* Don't unnecessarily set the interface if there's a single alt. */ + if (usblp->intf->num_altsetting > 1) { + alts = usblp->protocol[protocol].alt_setting; + if (alts < 0) + return -EINVAL; + r = usb_set_interface(usblp->dev, usblp->ifnum, alts); + if (r < 0) { + printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", + alts, usblp->ifnum); + return r; + } } usblp->bidir = (usblp->protocol[protocol].epread != NULL); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 00204824bffd..732e7f1687dd 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -463,11 +463,11 @@ static void snoop_urb(struct usb_device *udev, if (userurb) { /* Async */ if (when == SUBMIT) - dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %px, ep%d %s-%s, " "length %u\n", userurb, ep, t, d, length); else - dev_info(&udev->dev, "userurb %pK, ep%d %s-%s, " + dev_info(&udev->dev, "userurb %px, ep%d %s-%s, " "actual_length %u status %d\n", userurb, ep, t, d, length, timeout_or_status); @@ -1927,7 +1927,7 @@ static int proc_reapurb(struct usb_dev_state *ps, void __user *arg) if (as) { int retval; - snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); return retval; @@ -1944,7 +1944,7 @@ static int proc_reapurbnonblock(struct usb_dev_state *ps, void __user *arg) as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl(as, (void __user * __user *)arg); free_async(as); } else { @@ -2070,7 +2070,7 @@ static int proc_reapurb_compat(struct usb_dev_state *ps, void __user *arg) if (as) { int retval; - snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); return retval; @@ -2087,7 +2087,7 @@ static int proc_reapurbnonblock_compat(struct usb_dev_state *ps, void __user *ar as = async_getcompleted(ps); if (as) { - snoop(&ps->dev->dev, "reap %pK\n", as->userurb); + snoop(&ps->dev->dev, "reap %px\n", as->userurb); retval = processcompl_compat(as, (void __user * __user *)arg); free_async(as); } else { @@ -2512,7 +2512,7 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, #endif case USBDEVFS_DISCARDURB: - snoop(&dev->dev, "%s: DISCARDURB %pK\n", __func__, p); + snoop(&dev->dev, "%s: DISCARDURB %px\n", __func__, p); ret = proc_unlinkurb(ps, p); break; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5ad14cdd9762..b8a4707dfafa 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -342,12 +342,19 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Agfa SNAPSCAN 1212U */ + { USB_DEVICE(0x06bd, 0x0001), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, /* Guillemot Webcam Hercules Dualpix Exchange*/ { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Guillemot Hercules DJ Console audio card (BZ 208357) */ + { USB_DEVICE(0x06f8, 0xb000), .driver_info = + USB_QUIRK_ENDPOINT_BLACKLIST }, + /* Midiman M-Audio Keystation 88es */ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -384,6 +391,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* X-Rite/Gretag-Macbeth Eye-One Pro display colorimeter */ { USB_DEVICE(0x0971, 0x2000), .driver_info = USB_QUIRK_NO_SET_INTF }, + /* ELMO L-12F document camera */ + { USB_DEVICE(0x09a1, 0x0028), .driver_info = USB_QUIRK_DELAY_CTRL_MSG }, + /* Broadcom BCM92035DGROM BT dongle */ { USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -408,6 +418,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, + /* novation SoundControl XL */ + { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Huawei 4G LTE module */ { USB_DEVICE(0x12d1, 0x15bb), .driver_info = USB_QUIRK_DISCONNECT_SUSPEND }, @@ -421,6 +434,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x1532, 0x0116), .driver_info = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, + /* Lenovo ThinkCenter A630Z TI024Gen3 usb-audio */ + { USB_DEVICE(0x17ef, 0xa012), .driver_info = + USB_QUIRK_DISCONNECT_SUSPEND }, + /* BUILDWIN Photo Frame */ { USB_DEVICE(0x1908, 0x1315), .driver_info = USB_QUIRK_HONOR_BNUMINTERFACES }, @@ -481,12 +498,13 @@ static const struct usb_device_id usb_quirk_list[] = { /* DJI CineSSD */ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, + /* Fibocom L850-GL LTE Modem */ + { USB_DEVICE(0x2cb7, 0x0007), .driver_info = + USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + /* INTEL VALUE SSD */ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, - /* novation SoundControl XL */ - { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME }, - { } /* terminating entry must be last */ }; @@ -521,6 +539,8 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = { * Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST. */ static const struct usb_device_id usb_endpoint_blacklist[] = { + { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x01 }, + { USB_DEVICE_INTERFACE_NUMBER(0x06f8, 0xb000, 5), .driver_info = 0x81 }, { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 }, { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 }, { } diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 8e98b4df9b10..42f66718bc18 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -1453,7 +1453,6 @@ static void dwc2_hsotg_complete_oursetup(struct usb_ep *ep, static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, u32 windex) { - struct dwc2_hsotg_ep *ep; int dir = (windex & USB_DIR_IN) ? 1 : 0; int idx = windex & 0x7F; @@ -1463,12 +1462,7 @@ static struct dwc2_hsotg_ep *ep_from_windex(struct dwc2_hsotg *hsotg, if (idx > hsotg->num_of_eps) return NULL; - ep = index_to_ep(hsotg, idx, dir); - - if (idx && ep->dir_in != dir) - return NULL; - - return ep; + return index_to_ep(hsotg, idx, dir); } /** diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index a5c8329fd462..91686e1b24d9 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -1512,19 +1512,20 @@ static void dwc2_hc_start_transfer(struct dwc2_hsotg *hsotg, if (num_packets > max_hc_pkt_count) { num_packets = max_hc_pkt_count; chan->xfer_len = num_packets * chan->max_packet; + } else if (chan->ep_is_in) { + /* + * Always program an integral # of max packets + * for IN transfers. + * Note: This assumes that the input buffer is + * aligned and sized accordingly. + */ + chan->xfer_len = num_packets * chan->max_packet; } } else { /* Need 1 packet for transfer length of 0 */ num_packets = 1; } - if (chan->ep_is_in) - /* - * Always program an integral # of max packets for IN - * transfers - */ - chan->xfer_len = num_packets * chan->max_packet; - if (chan->ep_type == USB_ENDPOINT_XFER_INT || chan->ep_type == USB_ENDPOINT_XFER_ISOC) /* @@ -5559,7 +5560,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) dwc2_writel(hsotg, hprt0, HPRT0); /* Wait for the HPRT0.PrtSusp register field to be set */ - if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000)) + if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 5000)) dev_warn(hsotg->dev, "Suspend wasn't generated\n"); /* diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index a052d39b4375..d5f4ec1b73b1 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -500,7 +500,7 @@ static int dwc2_update_urb_state(struct dwc2_hsotg *hsotg, &short_read); if (urb->actual_length + xfer_length > urb->length) { - dev_warn(hsotg->dev, "%s(): trimming xfer length\n", __func__); + dev_dbg(hsotg->dev, "%s(): trimming xfer length\n", __func__); xfer_length = urb->length - urb->actual_length; } @@ -1977,6 +1977,18 @@ static void dwc2_hc_chhltd_intr_dma(struct dwc2_hsotg *hsotg, qtd->error_count++; dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb, qtd, DWC2_HC_XFER_XACT_ERR); + /* + * We can get here after a completed transaction + * (urb->actual_length >= urb->length) which was not reported + * as completed. If that is the case, and we do not abort + * the transfer, a transfer of size 0 will be enqueued + * subsequently. If urb->actual_length is not DMA-aligned, + * the buffer will then point to an unaligned address, and + * the resulting behavior is undefined. Bail out in that + * situation. + */ + if (qtd->urb->actual_length >= qtd->urb->length) + qtd->error_count = 3; dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd); dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR); } diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 794344785e07..fceb77909d93 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1778,7 +1778,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) if (PMSG_IS_AUTO(msg)) break; - ret = dwc3_core_init(dwc); + ret = dwc3_core_init_for_resume(dwc); if (ret) return ret; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9e12cc6c54c4..47af45824b6e 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -302,6 +302,7 @@ /* Global USB2 PHY Vendor Control Register */ #define DWC3_GUSB2PHYACC_NEWREGREQ BIT(25) +#define DWC3_GUSB2PHYACC_DONE BIT(24) #define DWC3_GUSB2PHYACC_BUSY BIT(23) #define DWC3_GUSB2PHYACC_WRITE BIT(22) #define DWC3_GUSB2PHYACC_ADDR(n) (n << 16) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index a6d0203e40b6..5bb5384f3612 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -234,8 +234,10 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) for (i = qcom->num_clocks - 1; i >= 0; i--) clk_disable_unprepare(qcom->clks[i]); + if (device_may_wakeup(qcom->dev)) + dwc3_qcom_enable_interrupts(qcom); + qcom->is_suspended = true; - dwc3_qcom_enable_interrupts(qcom); return 0; } @@ -248,7 +250,8 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom) if (!qcom->is_suspended) return 0; - dwc3_qcom_disable_interrupts(qcom); + if (device_may_wakeup(qcom->dev)) + dwc3_qcom_disable_interrupts(qcom); for (i = 0; i < qcom->num_clocks; i++) { ret = clk_prepare_enable(qcom->clks[i]); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8955fc90c9e2..381dae83d3c1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -699,8 +699,23 @@ static int dwc3_gadget_set_ep_config(struct dwc3_ep *dep, unsigned int action) params.param0 |= DWC3_DEPCFG_FIFO_NUMBER(dep->number >> 1); if (desc->bInterval) { - params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(desc->bInterval - 1); - dep->interval = 1 << (desc->bInterval - 1); + u8 bInterval_m1; + + /* + * Valid range for DEPCFG.bInterval_m1 is from 0 to 13, and it + * must be set to 0 when the controller operates in full-speed. + */ + bInterval_m1 = min_t(u8, desc->bInterval - 1, 13); + if (dwc->gadget.speed == USB_SPEED_FULL) + bInterval_m1 = 0; + + if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT && + dwc->gadget.speed == USB_SPEED_FULL) + dep->interval = desc->bInterval; + else + dep->interval = 1 << (desc->bInterval - 1); + + params.param1 |= DWC3_DEPCFG_BINTERVAL_M1(bInterval_m1); } return dwc3_send_gadget_ep_cmd(dep, DWC3_DEPCMD_SETEPCONFIG, ¶ms); diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c index f62b5f3c2d67..ffe3440abb74 100644 --- a/drivers/usb/dwc3/ulpi.c +++ b/drivers/usb/dwc3/ulpi.c @@ -7,6 +7,8 @@ * Author: Heikki Krogerus */ +#include +#include #include #include "core.h" @@ -17,14 +19,24 @@ DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \ DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a)) -static int dwc3_ulpi_busyloop(struct dwc3 *dwc) +#define DWC3_ULPI_BASE_DELAY DIV_ROUND_UP(NSEC_PER_SEC, 60000000L) + +static int dwc3_ulpi_busyloop(struct dwc3 *dwc, u8 addr, bool read) { - unsigned count = 1000; + unsigned long ns = 5L * DWC3_ULPI_BASE_DELAY; + unsigned int count = 1000; u32 reg; + if (addr >= ULPI_EXT_VENDOR_SPECIFIC) + ns += DWC3_ULPI_BASE_DELAY; + + if (read) + ns += DWC3_ULPI_BASE_DELAY; + while (count--) { + ndelay(ns); reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0)); - if (!(reg & DWC3_GUSB2PHYACC_BUSY)) + if (reg & DWC3_GUSB2PHYACC_DONE) return 0; cpu_relax(); } @@ -47,7 +59,7 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr) reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); - ret = dwc3_ulpi_busyloop(dwc); + ret = dwc3_ulpi_busyloop(dwc, addr, true); if (ret) return ret; @@ -71,7 +83,7 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val) reg |= DWC3_GUSB2PHYACC_WRITE | val; dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); - return dwc3_ulpi_busyloop(dwc); + return dwc3_ulpi_busyloop(dwc, addr, false); } static const struct ulpi_ops dwc3_ulpi_ops = { diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 90681a129a63..0cd4d0d4bdf5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -310,6 +310,7 @@ config USB_CONFIGFS_NCM depends on NET select USB_U_ETHER select USB_F_NCM + select CRC32 help NCM is an advanced protocol for Ethernet encapsulation, allows grouping of several ethernet frames into one USB transfer and @@ -381,6 +382,7 @@ config USB_CONFIGFS_EEM depends on NET select USB_U_ETHER select USB_F_EEM + select CRC32 help CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM and therefore can be supported by more hardware. Technically ECM and diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index 252f004d8c0b..174f7a2d4bd0 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -281,9 +281,16 @@ static ssize_t gadget_dev_desc_bcdUSB_store(struct config_item *item, static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page) { - char *udc_name = to_gadget_info(item)->composite.gadget_driver.udc_name; + struct gadget_info *gi = to_gadget_info(item); + char *udc_name; + int ret; + + mutex_lock(&gi->lock); + udc_name = gi->composite.gadget_driver.udc_name; + ret = sprintf(page, "%s\n", udc_name ?: ""); + mutex_unlock(&gi->lock); - return sprintf(page, "%s\n", udc_name ?: ""); + return ret; } static int unregister_gadget(struct gadget_info *gi) @@ -1885,7 +1892,7 @@ static struct config_group *gadgets_make( gi->composite.unbind = configfs_do_nothing; gi->composite.suspend = NULL; gi->composite.resume = NULL; - gi->composite.max_speed = USB_SPEED_SUPER; + gi->composite.max_speed = USB_SPEED_SUPER_PLUS; spin_lock_init(&gi->spinlock); mutex_init(&gi->lock); diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c index 57a8a522f45d..d8bff42a6d5d 100644 --- a/drivers/usb/gadget/function/f_acm.c +++ b/drivers/usb/gadget/function/f_acm.c @@ -684,7 +684,7 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function, - acm_ss_function, NULL); + acm_ss_function, acm_ss_function); if (status) goto fail; diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index b5f619021b2f..ad36375544c6 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -1048,6 +1048,12 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f) f->ss_descriptors = usb_copy_descriptors(midi_function); if (!f->ss_descriptors) goto fail_f_midi; + + if (gadget_is_superspeed_plus(c->cdev->gadget)) { + f->ssp_descriptors = usb_copy_descriptors(midi_function); + if (!f->ssp_descriptors) + goto fail_f_midi; + } } if (gadget_is_superspeed_plus(c->cdev->gadget)) { @@ -1386,7 +1392,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) midi->id = kstrdup(opts->id, GFP_KERNEL); if (opts->id && !midi->id) { status = -ENOMEM; - goto setup_fail; + goto midi_free; } midi->in_ports = opts->in_ports; midi->out_ports = opts->out_ports; @@ -1398,7 +1404,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) status = kfifo_alloc(&midi->in_req_fifo, midi->qlen, GFP_KERNEL); if (status) - goto setup_fail; + goto midi_free; spin_lock_init(&midi->transmit_lock); @@ -1415,9 +1421,13 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) fi->f = &midi->func; return &midi->func; +midi_free: + if (midi) + kfree(midi->id); + kfree(midi); setup_fail: mutex_unlock(&opts->lock); - kfree(midi); + return ERR_PTR(status); } diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c index c0b5378d74fd..0d8c7c03c3cb 100644 --- a/drivers/usb/gadget/function/f_mtp.c +++ b/drivers/usb/gadget/function/f_mtp.c @@ -55,8 +55,6 @@ ipc_log_string(_mtp_ipc_log, "%s: " fmt, __func__, ##__VA_ARGS__) #endif -#define MTP_RX_BUFFER_INIT_SIZE 1048576 -#define MTP_TX_BUFFER_INIT_SIZE 1048576 #define MTP_BULK_BUFFER_SIZE 16384 #define INTR_BUFFER_SIZE 28 #define MAX_INST_NAME_LEN 40 @@ -93,10 +91,10 @@ #define MAX_ITERATION 100 -unsigned int mtp_rx_req_len = MTP_RX_BUFFER_INIT_SIZE; +unsigned int mtp_rx_req_len = MTP_BULK_BUFFER_SIZE; module_param(mtp_rx_req_len, uint, 0644); -unsigned int mtp_tx_req_len = MTP_TX_BUFFER_INIT_SIZE; +unsigned int mtp_tx_req_len = MTP_BULK_BUFFER_SIZE; module_param(mtp_tx_req_len, uint, 0644); unsigned int mtp_tx_reqs = MTP_TX_REQ_MAX; @@ -544,6 +542,9 @@ static int mtp_create_bulk_endpoints(struct mtp_dev *dev, dev->ep_intr = ep; retry_tx_alloc: + if (mtp_tx_req_len > MTP_BULK_BUFFER_SIZE) + mtp_tx_reqs = 4; + /* now allocate requests for our endpoints */ for (i = 0; i < mtp_tx_reqs; i++) { req = mtp_request_new(dev->ep_in, mtp_tx_req_len); @@ -767,8 +768,8 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf, break; } - if (count > mtp_tx_req_len) - xfer = mtp_tx_req_len; + if (count > MTP_BULK_BUFFER_SIZE) + xfer = MTP_BULK_BUFFER_SIZE; else xfer = count; if (xfer && copy_from_user(req->buf, buf, xfer)) { @@ -862,8 +863,8 @@ static void send_file_work(struct work_struct *data) break; } - if (count > mtp_tx_req_len) - xfer = mtp_tx_req_len; + if (count > MTP_BULK_BUFFER_SIZE) + xfer = MTP_BULK_BUFFER_SIZE; else xfer = count; diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 8ed1295d7e35..0f47cd398d60 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -1126,6 +1126,7 @@ static int printer_func_bind(struct usb_configuration *c, printer_req_free(dev->in_ep, req); } + usb_free_all_descriptors(f); return ret; } diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index d5373bc70324..ee1882aa63db 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -89,8 +89,10 @@ static inline struct f_rndis *func_to_rndis(struct usb_function *f) /* peak (theoretical) bulk transfer rate in bits-per-second */ static unsigned int bitrate(struct usb_gadget *g) { + if (gadget_is_superspeed(g) && g->speed >= USB_SPEED_SUPER_PLUS) + return 4250000000U; if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) - return 13 * 1024 * 8 * 1000 * 8; + return 3750000000U; else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) return 13 * 512 * 8 * 1000 * 8; else diff --git a/drivers/usb/gadget/function/f_uac1.c b/drivers/usb/gadget/function/f_uac1.c index 2746a926a8d9..a215c836eba4 100644 --- a/drivers/usb/gadget/function/f_uac1.c +++ b/drivers/usb/gadget/function/f_uac1.c @@ -499,6 +499,7 @@ static void f_audio_disable(struct usb_function *f) uac1->as_out_alt = 0; uac1->as_in_alt = 0; + u_audio_stop_playback(&uac1->g_audio); u_audio_stop_capture(&uac1->g_audio); } diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c index 175acebf992e..99ade1e881c3 100644 --- a/drivers/usb/gadget/function/u_audio.c +++ b/drivers/usb/gadget/function/u_audio.c @@ -89,7 +89,12 @@ static void u_audio_iso_complete(struct usb_ep *ep, struct usb_request *req) struct snd_uac_chip *uac = prm->uac; /* i/f shutting down */ - if (!prm->ep_enabled || req->status == -ESHUTDOWN) + if (!prm->ep_enabled) { + usb_ep_free_request(ep, req); + return; + } + + if (req->status == -ESHUTDOWN) return; /* @@ -351,8 +356,14 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep) for (i = 0; i < params->req_number; i++) { if (prm->ureq[i].req) { - usb_ep_dequeue(ep, prm->ureq[i].req); - usb_ep_free_request(ep, prm->ureq[i].req); + if (usb_ep_dequeue(ep, prm->ureq[i].req)) + usb_ep_free_request(ep, prm->ureq[i].req); + /* + * If usb_ep_dequeue() cannot successfully dequeue the + * request, the request will be freed by the completion + * callback. + */ + prm->ureq[i].req = NULL; } } diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index ddab9e1fa082..28fba8db3b42 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -45,9 +45,10 @@ #define UETH__VERSION "29-May-2008" /* Experiments show that both Linux and Windows hosts allow up to 16k - * frame sizes. Set the max size to 15k+52 to prevent allocating 32k + * frame sizes. Set the max MTU size to 15k+52 to prevent allocating 32k * blocks and still have efficient handling. */ -#define GETHER_MAX_ETH_FRAME_LEN 15412 +#define GETHER_MAX_MTU_SIZE 15412 +#define GETHER_MAX_ETH_FRAME_LEN (GETHER_MAX_MTU_SIZE + ETH_HLEN) struct eth_dev { /* lock is held while accessing port_usb @@ -791,7 +792,7 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g, /* MTU range: 14 - 15412 */ net->min_mtu = ETH_HLEN; - net->max_mtu = GETHER_MAX_ETH_FRAME_LEN; + net->max_mtu = GETHER_MAX_MTU_SIZE; dev->gadget = g; SET_NETDEV_DEV(net, &g->dev); @@ -853,7 +854,7 @@ struct net_device *gether_setup_name_default(const char *netname) /* MTU range: 14 - 15412 */ net->min_mtu = ETH_HLEN; - net->max_mtu = GETHER_MAX_ETH_FRAME_LEN; + net->max_mtu = GETHER_MAX_MTU_SIZE; return net; } diff --git a/drivers/usb/gadget/function/u_ether_configfs.h b/drivers/usb/gadget/function/u_ether_configfs.h index 959f6665b40f..77328d159e3c 100644 --- a/drivers/usb/gadget/function/u_ether_configfs.h +++ b/drivers/usb/gadget/function/u_ether_configfs.h @@ -204,12 +204,11 @@ out: \ size_t len) \ { \ struct f_##_f_##_opts *opts = to_f_##_f_##_opts(item); \ - int ret; \ + int ret = -EINVAL; \ u8 val; \ \ mutex_lock(&opts->lock); \ - ret = sscanf(page, "%02hhx", &val); \ - if (ret > 0) { \ + if (sscanf(page, "%02hhx", &val) > 0) { \ opts->_n_ = val; \ ret = len; \ } \ diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c index af16672d5118..6680dcfe660e 100644 --- a/drivers/usb/gadget/legacy/acm_ms.c +++ b/drivers/usb/gadget/legacy/acm_ms.c @@ -203,8 +203,10 @@ static int acm_ms_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto fail_string_ids; + } usb_otg_descriptor_init(gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; diff --git a/drivers/usb/gadget/legacy/ether.c b/drivers/usb/gadget/legacy/ether.c index 30313b233680..99c7fc0d1d59 100644 --- a/drivers/usb/gadget/legacy/ether.c +++ b/drivers/usb/gadget/legacy/ether.c @@ -403,8 +403,10 @@ static int eth_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto fail1; + } usb_otg_descriptor_init(gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 25d417ad9000..09ed5f02c24f 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -2039,6 +2039,9 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) return 0; Enomem: + kfree(CHIP); + CHIP = NULL; + return -ENOMEM; } diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c index 57b6f66331cf..362284057d30 100644 --- a/drivers/usb/gadget/udc/amd5536udc_pci.c +++ b/drivers/usb/gadget/udc/amd5536udc_pci.c @@ -154,6 +154,11 @@ static int udc_pci_probe( pci_set_master(pdev); pci_try_set_mwi(pdev); + dev->phys_addr = resource; + dev->irq = pdev->irq; + dev->pdev = pdev; + dev->dev = &pdev->dev; + /* init dma pools */ if (use_dma) { retval = init_dma_pools(dev); @@ -161,11 +166,6 @@ static int udc_pci_probe( goto err_dma; } - dev->phys_addr = resource; - dev->irq = pdev->irq; - dev->pdev = pdev; - dev->dev = &pdev->dev; - /* general probing */ if (udc_probe(dev)) { retval = -ENODEV; diff --git a/drivers/usb/gadget/udc/aspeed-vhub/epn.c b/drivers/usb/gadget/udc/aspeed-vhub/epn.c index 5939eb1e97f2..ae853cf36966 100644 --- a/drivers/usb/gadget/udc/aspeed-vhub/epn.c +++ b/drivers/usb/gadget/udc/aspeed-vhub/epn.c @@ -420,7 +420,10 @@ static void ast_vhub_stop_active_req(struct ast_vhub_ep *ep, u32 state, reg, loops; /* Stop DMA activity */ - writel(0, ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); + if (ep->epn.desc_mode) + writel(VHUB_EP_DMA_CTRL_RESET, ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); + else + writel(0, ep->epn.regs + AST_VHUB_EP_DMA_CTLSTAT); /* Wait for it to complete */ for (loops = 0; loops < 1000; loops++) { diff --git a/drivers/usb/gadget/udc/bdc/Kconfig b/drivers/usb/gadget/udc/bdc/Kconfig index c74ac25dddcd..051091bd265b 100644 --- a/drivers/usb/gadget/udc/bdc/Kconfig +++ b/drivers/usb/gadget/udc/bdc/Kconfig @@ -15,7 +15,7 @@ if USB_BDC_UDC comment "Platform Support" config USB_BDC_PCI tristate "BDC support for PCIe based platforms" - depends on USB_PCI + depends on USB_PCI && BROKEN default USB_BDC_UDC help Enable support for platforms which have BDC connected through PCIe, such as Lego3 FPGA platform. diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 4e944c04be41..567b4372c49d 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1213,6 +1213,10 @@ int usb_add_gadget_udc_release(struct device *parent, struct usb_gadget *gadget, INIT_WORK(&gadget->work, usb_gadget_state_work); gadget->dev.parent = parent; + dma_set_coherent_mask(&gadget->dev, parent->coherent_dma_mask); + gadget->dev.dma_parms = parent->dma_parms; + gadget->dev.dma_mask = parent->dma_mask; + if (release) gadget->dev.release = release; else @@ -1508,10 +1512,13 @@ static ssize_t soft_connect_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { struct usb_udc *udc = container_of(dev, struct usb_udc, dev); + ssize_t ret; + mutex_lock(&udc_lock); if (!udc->driver) { dev_err(dev, "soft-connect without a gadget driver\n"); - return -EOPNOTSUPP; + ret = -EOPNOTSUPP; + goto out; } if (sysfs_streq(buf, "connect")) { @@ -1523,10 +1530,14 @@ static ssize_t soft_connect_store(struct device *dev, usb_gadget_udc_stop(udc); } else { dev_err(dev, "unsupported command '%s'\n", buf); - return -EINVAL; + ret = -EINVAL; + goto out; } - return n; + ret = n; +out: + mutex_unlock(&udc_lock); + return ret; } static DEVICE_ATTR_WO(soft_connect); diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index 24411706aabd..d56c22da3fca 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -2747,7 +2747,7 @@ static int __init init(void) { int retval = -ENOMEM; int i; - struct dummy *dum[MAX_NUM_UDC]; + struct dummy *dum[MAX_NUM_UDC] = {}; if (usb_disabled()) return -ENODEV; diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c index c3721225b61e..b706ad3034bc 100644 --- a/drivers/usb/gadget/udc/goku_udc.c +++ b/drivers/usb/gadget/udc/goku_udc.c @@ -1757,6 +1757,7 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err; } + pci_set_drvdata(pdev, dev); spin_lock_init(&dev->lock); dev->pdev = pdev; dev->gadget.ops = &goku_ops; @@ -1790,7 +1791,6 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) } dev->regs = (struct goku_udc_regs __iomem *) base; - pci_set_drvdata(pdev, dev); INFO(dev, "%s\n", driver_desc); INFO(dev, "version: " DRIVER_VERSION " %s\n", dmastr()); INFO(dev, "irq %d, pci mem %p\n", pdev->irq, base); diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index caf9f6b1cd34..d9282ca7ae8c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -574,6 +574,7 @@ static int ehci_run (struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp; u32 hcc_params; + int rc; hcd->uses_new_polling = 1; @@ -629,9 +630,20 @@ static int ehci_run (struct usb_hcd *hcd) down_write(&ehci_cf_port_reset_rwsem); ehci->rh_state = EHCI_RH_RUNNING; ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); + + /* Wait until HC become operational */ ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ msleep(5); + rc = ehci_handshake(ehci, &ehci->regs->status, STS_HALT, 0, 100 * 1000); + up_write(&ehci_cf_port_reset_rwsem); + + if (rc) { + ehci_err(ehci, "USB %x.%x, controller refused to start: %d\n", + ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), rc); + return rc; + } + ehci->last_periodic_enable = ktime_get_real(); temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 087402aec5cb..9f9ab5ccea88 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -345,6 +345,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) unlink_empty_async_suspended(ehci); + /* Some Synopsys controllers mistakenly leave IAA turned on */ + ehci_writel(ehci, STS_IAA, &ehci->regs->status); + /* Any IAA cycle that started before the suspend is now invalid */ end_iaa_cycle(ehci); ehci_handle_start_intr_unlinks(ehci); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 7d20296cbe9f..d31c425d6167 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -222,6 +222,7 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) err_pm_runtime: pm_runtime_put_sync(dev); + pm_runtime_disable(dev); err_phy: for (i = 0; i < omap->nports; i++) { diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c index afa321ab55fc..c9acc59f4add 100644 --- a/drivers/usb/host/max3421-hcd.c +++ b/drivers/usb/host/max3421-hcd.c @@ -1864,7 +1864,7 @@ max3421_probe(struct spi_device *spi) struct max3421_hcd *max3421_hcd; struct usb_hcd *hcd = NULL; struct max3421_hcd_platform_data *pdata = NULL; - int retval = -ENOMEM; + int retval; if (spi_setup(spi) < 0) { dev_err(&spi->dev, "Unable to setup SPI bus"); @@ -1906,6 +1906,7 @@ max3421_probe(struct spi_device *spi) goto error; } + retval = -ENOMEM; hcd = usb_create_hcd(&max3421_hcd_desc, &spi->dev, dev_name(&spi->dev)); if (!hcd) { diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index e88486d8084a..5916235adf35 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -101,7 +101,7 @@ static void io_watchdog_func(struct timer_list *t); /* Some boards misreport power switching/overcurrent */ -static bool distrust_firmware = true; +static bool distrust_firmware; module_param (distrust_firmware, bool, 0); MODULE_PARM_DESC (distrust_firmware, "true to distrust firmware power/overcurrent setup"); diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index c5e6e8d0b5ef..10d97261b433 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -3719,8 +3719,10 @@ static struct usb_hcd *oxu_create(struct platform_device *pdev, oxu->is_otg = otg; ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret < 0) + if (ret < 0) { + usb_put_hcd(hcd); return ERR_PTR(ret); + } device_wakeup_enable(hcd->self.controller); return hcd; diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c index 3c4abb5a1c3f..73aba464b66a 100644 --- a/drivers/usb/host/xhci-histb.c +++ b/drivers/usb/host/xhci-histb.c @@ -241,7 +241,7 @@ static int xhci_histb_probe(struct platform_device *pdev) /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) - return ret; + goto disable_pm; hcd = usb_create_hcd(driver, dev, dev_name(dev)); if (!hcd) { diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 64318a8935e1..07d2b301e07b 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1769,6 +1769,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd) hcd->state = HC_STATE_SUSPENDED; bus_state->next_statechange = jiffies + msecs_to_jiffies(10); spin_unlock_irqrestore(&xhci->lock, flags); + + if (bus_state->bus_suspended) + usleep_range(5000, 10000); + return 0; } diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 2c3b31109e16..09d5a789fcd5 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -395,6 +395,13 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_SPURIOUS_SUCCESS; if (mtk->lpm_support) xhci->quirks |= XHCI_LPM_SUPPORT; + + /* + * MTK xHCI 0.96: PSA is 1 by default even if doesn't support stream, + * and it's 3 when support it. + */ + if (xhci->hci_version < 0x100 && HCC_MAX_PSA(xhci->hcc_params) == 4) + xhci->quirks |= XHCI_BROKEN_STREAMS; } /* called during probe() after chip reset completes */ @@ -551,7 +558,8 @@ static int xhci_mtk_probe(struct platform_device *pdev) if (ret) goto put_usb3_hcd; - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + if (HCC_MAX_PSA(xhci->hcc_params) >= 4 && + !(xhci->quirks & XHCI_BROKEN_STREAMS)) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 0c6b6f14b169..42ff11e3c4dc 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -53,6 +53,7 @@ #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 #define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242 #define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142 +#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242 static const char hcd_name[] = "xhci_hcd"; @@ -237,11 +238,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) xhci->quirks |= XHCI_BROKEN_STREAMS; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) + pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) { xhci->quirks |= XHCI_TRUST_TX_LENGTH; + xhci->quirks |= XHCI_NO_64BIT_SUPPORT; + } if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && (pdev->device == PCI_DEVICE_ID_ASMEDIA_1142_XHCI || - pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI)) + pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI || + pdev->device == PCI_DEVICE_ID_ASMEDIA_3242_XHCI)) xhci->quirks |= XHCI_NO_64BIT_SUPPORT; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 20ea7f5cb044..3fc5bb8a66f5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -670,11 +670,16 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len, DMA_FROM_DEVICE); /* for in tranfers we need to copy the data from bounce to sg */ - len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf, - seg->bounce_len, seg->bounce_offs); - if (len != seg->bounce_len) - xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n", - len, seg->bounce_len); + if (urb->num_sgs) { + len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf, + seg->bounce_len, seg->bounce_offs); + if (len != seg->bounce_len) + xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n", + len, seg->bounce_len); + } else { + memcpy(urb->transfer_buffer + seg->bounce_offs, seg->bounce_buf, + seg->bounce_len); + } seg->bounce_len = 0; seg->bounce_offs = 0; } @@ -2835,6 +2840,8 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring, trb->field[0] = cpu_to_le32(field1); trb->field[1] = cpu_to_le32(field2); trb->field[2] = cpu_to_le32(field3); + /* make sure TRB is fully written before giving it to the controller */ + wmb(); trb->field[3] = cpu_to_le32(field4); trace_xhci_queue_trb(ring, trb); @@ -3178,12 +3185,16 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, /* create a max max_pkt sized bounce buffer pointed to by last trb */ if (usb_urb_dir_out(urb)) { - len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs, - seg->bounce_buf, new_buff_len, enqd_len); - if (len != new_buff_len) - xhci_warn(xhci, - "WARN Wrong bounce buffer write length: %zu != %d\n", - len, new_buff_len); + if (urb->num_sgs) { + len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs, + seg->bounce_buf, new_buff_len, enqd_len); + if (len != new_buff_len) + xhci_warn(xhci, "WARN Wrong bounce buffer write length: %zu != %d\n", + len, new_buff_len); + } else { + memcpy(seg->bounce_buf, urb->transfer_buffer + enqd_len, new_buff_len); + } + seg->bounce_dma = dma_map_single(dev, seg->bounce_buf, max_pkt, DMA_TO_DEVICE); } else { diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index fe37dacc695f..dc9cd8c519cf 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -578,6 +578,13 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb *tegra, enable); if (err < 0) break; + + /* + * wait 500us for LFPS detector to be disabled before + * sending ACK + */ + if (!enable) + usleep_range(500, 1000); } if (err < 0) { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 64a69b3c8ce9..242f17d29421 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1113,6 +1113,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) struct usb_hcd *secondary_hcd; int retval = 0; bool comp_timer_running = false; + bool pending_portevent = false; if (!hcd->state) return 0; @@ -1251,13 +1252,22 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) done: if (retval == 0) { - /* Resume root hubs only when have pending events. */ - if (xhci_pending_portevent(xhci)) { + /* + * Resume roothubs only if there are pending events. + * USB 3 devices resend U3 LFPS wake after a 100ms delay if + * the first wake signalling failed, give it that chance. + */ + pending_portevent = xhci_pending_portevent(xhci); + if (!pending_portevent) { + msleep(120); + pending_portevent = xhci_pending_portevent(xhci); + } + + if (pending_portevent) { usb_hcd_resume_root_hub(xhci->shared_hcd); usb_hcd_resume_root_hub(hcd); } } - /* * If system is subject to the Quirk, Compliance Mode Timer needs to * be re-initialized Always after a system resume. Ports are subject @@ -4593,19 +4603,19 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, { unsigned long long timeout_ns; + if (xhci->quirks & XHCI_INTEL_HOST) + timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc); + else + timeout_ns = udev->u1_params.sel; + /* Prevent U1 if service interval is shorter than U1 exit latency */ if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { - if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) { + if (xhci_service_interval_to_ns(desc) <= timeout_ns) { dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n"); return USB3_LPM_DISABLED; } } - if (xhci->quirks & XHCI_INTEL_HOST) - timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc); - else - timeout_ns = udev->u1_params.sel; - /* The U1 timeout is encoded in 1us intervals. * Don't return a timeout of zero, because that's USB3_LPM_DISABLED. */ @@ -4657,19 +4667,19 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, { unsigned long long timeout_ns; + if (xhci->quirks & XHCI_INTEL_HOST) + timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc); + else + timeout_ns = udev->u2_params.sel; + /* Prevent U2 if service interval is shorter than U2 exit latency */ if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { - if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) { + if (xhci_service_interval_to_ns(desc) <= timeout_ns) { dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n"); return USB3_LPM_DISABLED; } } - if (xhci->quirks & XHCI_INTEL_HOST) - timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc); - else - timeout_ns = udev->u2_params.sel; - /* The U2 timeout is encoded in 256us intervals */ timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000); /* If the necessary timeout value is bigger than what we can set in the diff --git a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig index 36bc28c884ad..47dabccafef4 100644 --- a/drivers/usb/misc/sisusbvga/Kconfig +++ b/drivers/usb/misc/sisusbvga/Kconfig @@ -15,7 +15,7 @@ config USB_SISUSBVGA config USB_SISUSBVGA_CON bool "Text console and mode switching support" if USB_SISUSBVGA - depends on VT + depends on VT && BROKEN select FONT_8x16 ---help--- Say Y here if you want a VGA text console via the USB dongle or diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c index 785080f79073..08b72bb22b7e 100644 --- a/drivers/usb/misc/yurex.c +++ b/drivers/usb/misc/yurex.c @@ -497,6 +497,9 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer, timeout = schedule_timeout(YUREX_WRITE_TIMEOUT); finish_wait(&dev->waitq, &wait); + /* make sure URB is idle after timeout or (spurious) CMD_ACK */ + usb_kill_urb(dev->cntl_urb); + mutex_unlock(&dev->io_mutex); if (retval < 0) { diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 7910c34d7464..b642cb3fb74c 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1905,10 +1905,14 @@ static void musb_pm_runtime_check_session(struct musb *musb) MUSB_DEVCTL_HR; switch (devctl & ~s) { case MUSB_QUIRK_B_DISCONNECT_99: - musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n"); - schedule_delayed_work(&musb->irq_work, - msecs_to_jiffies(1000)); - break; + if (musb->quirk_retries && !musb->flush_irq_work) { + musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n"); + schedule_delayed_work(&musb->irq_work, + msecs_to_jiffies(1000)); + musb->quirk_retries--; + break; + } + /* fall through */ case MUSB_QUIRK_B_INVALID_VBUS_91: if (musb->quirk_retries && !musb->flush_irq_work) { musb_dbg(musb, @@ -2145,32 +2149,35 @@ int musb_queue_resume_work(struct musb *musb, { struct musb_pending_work *w; unsigned long flags; + bool is_suspended; int error; if (WARN_ON(!callback)) return -EINVAL; - if (pm_runtime_active(musb->controller)) - return callback(musb, data); + spin_lock_irqsave(&musb->list_lock, flags); + is_suspended = musb->is_runtime_suspended; + + if (is_suspended) { + w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC); + if (!w) { + error = -ENOMEM; + goto out_unlock; + } - w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC); - if (!w) - return -ENOMEM; + w->callback = callback; + w->data = data; - w->callback = callback; - w->data = data; - spin_lock_irqsave(&musb->list_lock, flags); - if (musb->is_runtime_suspended) { list_add_tail(&w->node, &musb->pending_list); error = 0; - } else { - dev_err(musb->controller, "could not add resume work %p\n", - callback); - devm_kfree(musb->controller, w); - error = -EINPROGRESS; } + +out_unlock: spin_unlock_irqrestore(&musb->list_lock, flags); + if (!is_suspended) + error = callback(musb, data); + return error; } EXPORT_SYMBOL_GPL(musb_queue_resume_work); diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index f9bdd845a278..c0b806aeab39 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -348,10 +348,6 @@ static void *usbpd_ipc_log; #define ID_HDR_PRODUCT_AMA 5 #define ID_HDR_PRODUCT_VPD 6 -/* params for usb_blocking_sync */ -#define STOP_USB_HOST 0 -#define START_USB_HOST 1 - #define PD_MIN_SINK_CURRENT 900 #define PD_VBUS_MAX_VOLTAGE_LIMIT 9000000 @@ -398,7 +394,6 @@ struct usbpd { struct work_struct pdo_work; struct delayed_work fixed_pdo_work; struct delayed_work pps_monitor_work; - struct work_struct restart_host_work; struct hrtimer timer; bool sm_queued; @@ -424,8 +419,6 @@ struct usbpd { bool peer_usb_comm; bool peer_pr_swap; bool peer_dr_swap; - bool no_usb3dp_concurrency; - bool pd20_source_only; u32 sink_caps[7]; int num_sink_caps; @@ -522,7 +515,6 @@ struct usbpd { u8 src_cap_ext_db[PD_SRC_CAP_EXT_DB_LEN]; bool send_get_pps_status; u32 pps_status_db; - bool pps_disabled; bool send_get_status; u8 status_db[PD_STATUS_DB_LEN]; bool send_get_battery_cap; @@ -531,7 +523,6 @@ struct usbpd { u8 get_battery_status_db; bool send_get_battery_status; u32 battery_sts_dobj; - bool typec_analog_audio_connected; }; static LIST_HEAD(_usbpd); /* useful for debugging */ @@ -608,7 +599,7 @@ static inline void start_usb_host(struct usbpd *pd, bool ss) extcon_set_state_sync(pd->extcon, EXTCON_USB_HOST, 1); /* blocks until USB host is completely started */ - ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, START_USB_HOST); + ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 1); if (ret) { usbpd_err(&pd->dev, "err(%d) starting host", ret); return; @@ -677,24 +668,6 @@ static void usbpd_disable_active_work(struct work_struct *w) POWER_SUPPLY_PROP_PD_ACTIVE, &val); } -static void restart_usb_host_work(struct work_struct *w) -{ - struct usbpd *pd = container_of(w, struct usbpd, restart_host_work); - int ret; - - if (!pd->no_usb3dp_concurrency) - return; - - stop_usb_host(pd); - - /* blocks until USB host is completely stopped */ - ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, STOP_USB_HOST); - if (ret) { - usbpd_err(&pd->dev, "err(%d) stopping host", ret); - return; - } - - start_usb_host(pd, false); } /** @@ -729,7 +702,7 @@ static int usbpd_release_ss_lane(struct usbpd *pd, stop_usb_host(pd); /* blocks until USB host is completely stopped */ - ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, STOP_USB_HOST); + ret = extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 0); if (ret) { usbpd_err(&pd->dev, "err(%d) stopping host", ret); goto err_exit; @@ -803,7 +776,6 @@ static inline void pd_reset_protocol(struct usbpd *pd) memset(pd->rx_msgid, -1, sizeof(pd->rx_msgid)); memset(pd->tx_msgid, 0, sizeof(pd->tx_msgid)); pd->send_request = false; - pd->send_get_status = false; pd->send_pr_swap = false; pd->send_dr_swap = false; } @@ -1749,7 +1721,6 @@ static void handle_vdm_rx(struct usbpd *pd, struct rx_msg *rx_msg) /* Set to USB and DP cocurrency mode */ extcon_blocking_sync(pd->extcon, EXTCON_DISP_DP, 2); - queue_work(pd->wq, &pd->restart_host_work); } /* if it's a supported SVID, pass the message to the handler */ @@ -2107,8 +2078,7 @@ static void dr_swap(struct usbpd *pd) typec_set_data_role(pd->typec_port, TYPEC_HOST); /* ensure host is started before allowing DP */ - extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, - START_USB_HOST); + extcon_blocking_sync(pd->extcon, EXTCON_USB_HOST, 0); usbpd_send_svdm(pd, USBPD_SID, USBPD_SVDM_DISCOVER_IDENTITY, SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); @@ -2310,11 +2280,7 @@ static int usbpd_startup_common(struct usbpd *pd, * support up to PD 3.0; if peer is 2.0 * phy_msg_received() will handle the downgrade. */ - if ((pd->pd20_source_only) && - pd->current_state == PE_SRC_STARTUP) - pd->spec_rev = USBPD_REV_20; - else - pd->spec_rev = USBPD_REV_30; + pd->spec_rev = USBPD_REV_30; if (pd->pd_phy_opened) { pd_phy_close(); @@ -2442,10 +2408,7 @@ static void handle_state_src_startup_wait_for_vdm_resp(struct usbpd *pd, * Emarker may have negotiated down to rev 2.0. * Reset to 3.0 to begin SOP communication with sink */ - if (pd->pd20_source_only) - pd->spec_rev = USBPD_REV_20; - else - pd->spec_rev = USBPD_REV_30; + pd->spec_rev = USBPD_REV_30; pd->current_state = PE_SRC_SEND_CAPABILITIES; kick_sm(pd, ms); @@ -2879,7 +2842,6 @@ static void handle_state_snk_wait_for_capabilities(struct usbpd *pd, struct rx_msg *rx_msg) { union power_supply_propval val = {0}; - int i; pd->in_pr_swap = false; val.intval = 0; @@ -2898,14 +2860,6 @@ static void handle_state_snk_wait_for_capabilities(struct usbpd *pd, memcpy(&pd->received_pdos, rx_msg->payload, min_t(size_t, rx_msg->data_len, sizeof(pd->received_pdos))); - /* if pps is disabled clear all the received pdos */ - if (pd->pps_disabled) { - for (i = 0; i < ARRAY_SIZE(pd->received_pdos); i++) - if ((PD_SRC_PDO_TYPE(pd->received_pdos[i]) == - PD_SRC_PDO_TYPE_AUGMENTED)) - pd->received_pdos[i] = 0x00; - } - pd->src_cap_id++; usbpd_set_state(pd, PE_SNK_EVALUATE_CAPABILITY); @@ -3140,7 +3094,6 @@ static bool handle_ctrl_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) static bool handle_data_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) { u32 ado; - int i; switch (PD_MSG_HDR_TYPE(rx_msg->hdr)) { case MSG_SOURCE_CAPABILITIES: @@ -3150,14 +3103,6 @@ static bool handle_data_snk_ready(struct usbpd *pd, struct rx_msg *rx_msg) memcpy(&pd->received_pdos, rx_msg->payload, min_t(size_t, rx_msg->data_len, sizeof(pd->received_pdos))); - /* if pps is disabled clear all the received pdos */ - if (pd->pps_disabled) { - for (i = 0; i < ARRAY_SIZE(pd->received_pdos); i++) - if ((PD_SRC_PDO_TYPE(pd->received_pdos[i]) == - PD_SRC_PDO_TYPE_AUGMENTED)) - pd->received_pdos[i] = 0x00; - } - pd->src_cap_id++; usbpd_set_state(pd, PE_SNK_EVALUATE_CAPABILITY); @@ -3780,7 +3725,6 @@ static void handle_disconnect(struct usbpd *pd) pd->forced_pr = POWER_SUPPLY_TYPEC_PR_NONE; pd->current_state = PE_UNKNOWN; - pd_reset_protocol(pd); kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); typec_unregister_partner(pd->partner); @@ -3848,18 +3792,6 @@ static void usbpd_sm(struct work_struct *w) pd->typec_mode, pd->current_pr, usbpd_state_strings[pd->current_state]); - /* Register typec partner in case AAA is connected */ - if (pd->typec_mode == POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER) { - if (!pd->partner) { - memset(&pd->partner_identity, 0, - sizeof(pd->partner_identity)); - pd->partner_desc.usb_pd = false; - pd->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; - pd->partner = typec_register_partner(pd->typec_port, - &pd->partner_desc); - pd->typec_analog_audio_connected = true; - } - } hrtimer_cancel(&pd->timer); pd->sm_queued = false; @@ -3873,18 +3805,9 @@ static void usbpd_sm(struct work_struct *w) /* Disconnect? */ if (pd->current_pr == PR_NONE) { if (pd->current_state == PE_UNKNOWN && - pd->current_dr == DR_NONE) { - /* - * Since PD stack will not be loaded in case AAA is - * connected, call disconnect to unregister typec - * partner - */ - if (!pd->typec_analog_audio_connected && - pd->partner) - handle_disconnect(pd); - + pd->current_dr == DR_NONE) goto sm_done; - } + handle_disconnect(pd); goto sm_done; } @@ -3954,7 +3877,6 @@ static int usbpd_process_typec_mode(struct usbpd *pd, } pd->current_pr = PR_NONE; - pd->typec_analog_audio_connected = false; break; /* Sink states */ @@ -5752,7 +5674,6 @@ struct usbpd *usbpd_create(struct device *parent) INIT_DELAYED_WORK(&pd->fixed_pdo_work, usbpd_fixed_pdo_workfunc); INIT_DELAYED_WORK(&pd->pps_monitor_work, usbpd_pps_monitor_workfunc); INIT_WORK(&pd->disable_active_work, usbpd_disable_active_work); - INIT_WORK(&pd->restart_host_work, restart_usb_host_work); hrtimer_init(&pd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); pd->timer.function = pd_timeout; mutex_init(&pd->swap_lock); @@ -5829,9 +5750,6 @@ struct usbpd *usbpd_create(struct device *parent) extcon_set_property_capability(pd->extcon, EXTCON_USB_HOST, EXTCON_PROP_USB_SS); - if (device_property_read_bool(parent, "qcom,no-usb3-dp-concurrency")) - pd->no_usb3dp_concurrency = true; - pd->num_sink_caps = device_property_read_u32_array(parent, "qcom,default-sink-caps", NULL, 0); @@ -5873,9 +5791,6 @@ struct usbpd *usbpd_create(struct device *parent) pd->num_sink_caps = ARRAY_SIZE(default_snk_caps); } - if (device_property_read_bool(parent, "qcom,pd-20-source-only")) - pd->pd20_source_only = true; - /* * Register a Type-C class instance (/sys/class/typec/portX). * Note this is different than the /sys/class/usbpd/ created above. @@ -5902,8 +5817,6 @@ struct usbpd *usbpd_create(struct device *parent) } } - pd->pps_disabled = device_property_read_bool(parent, - "qcom,pps-disabled"); pd->current_pr = PR_NONE; pd->current_dr = DR_NONE; list_add_tail(&pd->instance, &_usbpd); @@ -5983,3 +5896,4 @@ module_exit(usbpd_exit); MODULE_DESCRIPTION("USB Power Delivery Policy Engine"); MODULE_LICENSE("GPL v2"); + diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index aeb53ec5cc6a..6b92a57382db 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -126,6 +126,7 @@ struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) } usbhs_pipe_clear_without_sequence(pipe, 0, 0); + usbhs_pipe_running(pipe, 0); __usbhsf_pkt_del(pkt); } diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c index 9e5afdde1adb..40576e7176d8 100644 --- a/drivers/usb/renesas_usbhs/pipe.c +++ b/drivers/usb/renesas_usbhs/pipe.c @@ -746,6 +746,8 @@ struct usbhs_pipe *usbhs_pipe_malloc(struct usbhs_priv *priv, void usbhs_pipe_free(struct usbhs_pipe *pipe) { + usbhsp_pipe_select(pipe); + usbhsp_pipe_cfg_set(pipe, 0xFFFF, 0); usbhsp_put_pipe(pipe); } diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index efadf2f6afa1..c87cb25e70ec 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -80,10 +80,12 @@ #define CH341_LCR_CS5 0x00 static const struct usb_device_id id_table[] = { - { USB_DEVICE(0x4348, 0x5523) }, + { USB_DEVICE(0x1a86, 0x5512) }, + { USB_DEVICE(0x1a86, 0x5523) }, { USB_DEVICE(0x1a86, 0x7522) }, { USB_DEVICE(0x1a86, 0x7523) }, - { USB_DEVICE(0x1a86, 0x5523) }, + { USB_DEVICE(0x4348, 0x5523) }, + { USB_DEVICE(0x9986, 0x7523) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 46ec30a2c516..7d602e6ccbc0 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -61,6 +61,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ { USB_DEVICE(0x0908, 0x01FF) }, /* Siemens RUGGEDCOM USB Serial Console */ + { USB_DEVICE(0x0988, 0x0578) }, /* Teraoka AD2000 */ { USB_DEVICE(0x0B00, 0x3070) }, /* Ingenico 3070 */ { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */ { USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */ @@ -145,6 +146,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88D8) }, /* Acuity Brands nLight Air Adapter */ { USB_DEVICE(0x10C4, 0x88FB) }, /* CESINEL MEDCAL STII Network Analyzer */ { USB_DEVICE(0x10C4, 0x8938) }, /* CESINEL MEDCAL S II Network Analyzer */ { USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */ @@ -201,6 +203,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ { USB_DEVICE(0x1901, 0x0195) }, /* GE B850/B650/B450 CP2104 DP UART interface */ { USB_DEVICE(0x1901, 0x0196) }, /* GE B850 CP2105 DP UART interface */ + { USB_DEVICE(0x1901, 0x0197) }, /* GE CS1000 Display serial interface */ + { USB_DEVICE(0x1901, 0x0198) }, /* GE CS1000 M.2 Key E serial interface */ + { USB_DEVICE(0x199B, 0xBA30) }, /* LORD WSDA-200-USB */ { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */ { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */ diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index e7f244cf2c07..a618276ead98 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -198,14 +197,12 @@ struct digi_port { int dp_throttle_restart; wait_queue_head_t dp_flush_wait; wait_queue_head_t dp_close_wait; /* wait queue for close */ - struct work_struct dp_wakeup_work; struct usb_serial_port *dp_port; }; /* Local Function Declarations */ -static void digi_wakeup_write_lock(struct work_struct *work); static int digi_write_oob_command(struct usb_serial_port *port, unsigned char *buf, int count, int interruptible); static int digi_write_inb_command(struct usb_serial_port *port, @@ -356,26 +353,6 @@ __releases(lock) return timeout; } - -/* - * Digi Wakeup Write - * - * Wake up port, line discipline, and tty processes sleeping - * on writes. - */ - -static void digi_wakeup_write_lock(struct work_struct *work) -{ - struct digi_port *priv = - container_of(work, struct digi_port, dp_wakeup_work); - struct usb_serial_port *port = priv->dp_port; - unsigned long flags; - - spin_lock_irqsave(&priv->dp_port_lock, flags); - tty_port_tty_wakeup(&port->port); - spin_unlock_irqrestore(&priv->dp_port_lock, flags); -} - /* * Digi Write OOB Command * @@ -987,6 +964,7 @@ static void digi_write_bulk_callback(struct urb *urb) unsigned long flags; int ret = 0; int status = urb->status; + bool wakeup; /* port and serial sanity check */ if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) { @@ -1013,6 +991,7 @@ static void digi_write_bulk_callback(struct urb *urb) } /* try to send any buffered data on this port */ + wakeup = true; spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_write_urb_in_use = 0; if (priv->dp_out_buf_len > 0) { @@ -1028,19 +1007,18 @@ static void digi_write_bulk_callback(struct urb *urb) if (ret == 0) { priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; + wakeup = false; } } - /* wake up processes sleeping on writes immediately */ - tty_port_tty_wakeup(&port->port); - /* also queue up a wakeup at scheduler time, in case we */ - /* lost the race in write_chan(). */ - schedule_work(&priv->dp_wakeup_work); - spin_unlock_irqrestore(&priv->dp_port_lock, flags); + if (ret && ret != -EPERM) dev_err_console(port, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); + + if (wakeup) + tty_port_tty_wakeup(&port->port); } static int digi_write_room(struct tty_struct *tty) @@ -1240,7 +1218,6 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) init_waitqueue_head(&priv->dp_transmit_idle_wait); init_waitqueue_head(&priv->dp_flush_wait); init_waitqueue_head(&priv->dp_close_wait); - INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); priv->dp_port = port; init_waitqueue_head(&port->write_wait); @@ -1509,13 +1486,14 @@ static int digi_read_oob_callback(struct urb *urb) rts = C_CRTSCTS(tty); if (tty && opcode == DIGI_CMD_READ_INPUT_SIGNALS) { + bool wakeup = false; + spin_lock_irqsave(&priv->dp_port_lock, flags); /* convert from digi flags to termiox flags */ if (val & DIGI_READ_INPUT_SIGNALS_CTS) { priv->dp_modem_signals |= TIOCM_CTS; - /* port must be open to use tty struct */ if (rts) - tty_port_tty_wakeup(&port->port); + wakeup = true; } else { priv->dp_modem_signals &= ~TIOCM_CTS; /* port must be open to use tty struct */ @@ -1534,6 +1512,9 @@ static int digi_read_oob_callback(struct urb *urb) priv->dp_modem_signals &= ~TIOCM_CD; spin_unlock_irqrestore(&priv->dp_port_lock, flags); + + if (wakeup) + tty_port_tty_wakeup(&port->port); } else if (opcode == DIGI_CMD_TRANSMIT_IDLE) { spin_lock_irqsave(&priv->dp_port_lock, flags); priv->dp_transmit_idle = 1; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index b2364e379429..a5891cb2c72e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1370,8 +1370,9 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) index_value = get_ftdi_divisor(tty, port); value = (u16)index_value; index = (u16)(index_value >> 16); - if ((priv->chip_type == FT2232C) || (priv->chip_type == FT2232H) || - (priv->chip_type == FT4232H) || (priv->chip_type == FT232H)) { + if (priv->chip_type == FT2232C || priv->chip_type == FT2232H || + priv->chip_type == FT4232H || priv->chip_type == FT232H || + priv->chip_type == FTX) { /* Probably the BM type needs the MSB of the encoded fractional * divider also moved like for the chips above. Any infos? */ index = (u16)((index << 8) | priv->interface); diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index dab8c18e726f..44c902c7d240 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -3021,26 +3021,32 @@ static int edge_startup(struct usb_serial *serial) response = -ENODEV; } - usb_free_urb(edge_serial->interrupt_read_urb); - kfree(edge_serial->interrupt_in_buffer); - - usb_free_urb(edge_serial->read_urb); - kfree(edge_serial->bulk_in_buffer); - - kfree(edge_serial); - - return response; + goto error; } /* start interrupt read for this edgeport this interrupt will * continue as long as the edgeport is connected */ response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL); - if (response) + if (response) { dev_err(ddev, "%s - Error %d submitting control urb\n", __func__, response); + + goto error; + } } return response; + +error: + usb_free_urb(edge_serial->interrupt_read_urb); + kfree(edge_serial->interrupt_in_buffer); + + usb_free_urb(edge_serial->read_urb); + kfree(edge_serial->bulk_in_buffer); + + kfree(edge_serial); + + return response; } diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 734f18d0a7f7..6dc93652afc1 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -536,23 +536,29 @@ static int iuu_uart_flush(struct usb_serial_port *port) struct device *dev = &port->dev; int i; int status; - u8 rxcmd = IUU_UART_RX; + u8 *rxcmd; struct iuu_private *priv = usb_get_serial_port_data(port); if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0) return -EIO; + rxcmd = kmalloc(1, GFP_KERNEL); + if (!rxcmd) + return -ENOMEM; + + rxcmd[0] = IUU_UART_RX; + for (i = 0; i < 2; i++) { - status = bulk_immediate(port, &rxcmd, 1); + status = bulk_immediate(port, rxcmd, 1); if (status != IUU_OPERATION_OK) { dev_dbg(dev, "%s - uart_flush_write error\n", __func__); - return status; + goto out_free; } status = read_immediate(port, &priv->len, 1); if (status != IUU_OPERATION_OK) { dev_dbg(dev, "%s - uart_flush_read error\n", __func__); - return status; + goto out_free; } if (priv->len > 0) { @@ -560,12 +566,16 @@ static int iuu_uart_flush(struct usb_serial_port *port) status = read_immediate(port, priv->buf, priv->len); if (status != IUU_OPERATION_OK) { dev_dbg(dev, "%s - uart_flush_read error\n", __func__); - return status; + goto out_free; } } } dev_dbg(dev, "%s - uart_flush_read OK!\n", __func__); iuu_led(port, 0, 0xF000, 0, 0xFF); + +out_free: + kfree(rxcmd); + return status; } diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 38d43c4b7ce5..766969cf72b2 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -40,11 +40,12 @@ #define DRIVER_AUTHOR "Brian Warner " #define DRIVER_DESC "USB Keyspan PDA Converter driver" +#define KEYSPAN_TX_THRESHOLD 16 + struct keyspan_pda_private { int tx_room; int tx_throttled; - struct work_struct wakeup_work; - struct work_struct unthrottle_work; + struct work_struct unthrottle_work; struct usb_serial *serial; struct usb_serial_port *port; }; @@ -97,15 +98,6 @@ static const struct usb_device_id id_table_fake_xircom[] = { }; #endif -static void keyspan_pda_wakeup_write(struct work_struct *work) -{ - struct keyspan_pda_private *priv = - container_of(work, struct keyspan_pda_private, wakeup_work); - struct usb_serial_port *port = priv->port; - - tty_port_tty_wakeup(&port->port); -} - static void keyspan_pda_request_unthrottle(struct work_struct *work) { struct keyspan_pda_private *priv = @@ -120,7 +112,7 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) 7, /* request_unthrottle */ USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, - 16, /* value: threshold */ + KEYSPAN_TX_THRESHOLD, 0, /* index */ NULL, 0, @@ -139,6 +131,8 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) int retval; int status = urb->status; struct keyspan_pda_private *priv; + unsigned long flags; + priv = usb_get_serial_port_data(port); switch (status) { @@ -172,18 +166,21 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) break; case 1: /* status interrupt */ - if (len < 3) { + if (len < 2) { dev_warn(&port->dev, "short interrupt message received\n"); break; } - dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]); + dev_dbg(&port->dev, "rx int, d1=%d\n", data[1]); switch (data[1]) { case 1: /* modemline change */ break; case 2: /* tx unthrottle interrupt */ + spin_lock_irqsave(&port->lock, flags); priv->tx_throttled = 0; + priv->tx_room = max(priv->tx_room, KEYSPAN_TX_THRESHOLD); + spin_unlock_irqrestore(&port->lock, flags); /* queue up a wakeup at scheduler time */ - schedule_work(&priv->wakeup_work); + usb_serial_port_softint(port); break; default: break; @@ -443,6 +440,7 @@ static int keyspan_pda_write(struct tty_struct *tty, int request_unthrottle = 0; int rc = 0; struct keyspan_pda_private *priv; + unsigned long flags; priv = usb_get_serial_port_data(port); /* guess how much room is left in the device's ring buffer, and if we @@ -462,13 +460,13 @@ static int keyspan_pda_write(struct tty_struct *tty, the TX urb is in-flight (wait until it completes) the device is full (wait until it says there is room) */ - spin_lock_bh(&port->lock); + spin_lock_irqsave(&port->lock, flags); if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) { - spin_unlock_bh(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); return 0; } clear_bit(0, &port->write_urbs_free); - spin_unlock_bh(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); /* At this point the URB is in our control, nobody else can submit it again (the only sudden transition was the one from EINPROGRESS to @@ -514,7 +512,8 @@ static int keyspan_pda_write(struct tty_struct *tty, goto exit; } } - if (count > priv->tx_room) { + + if (count >= priv->tx_room) { /* we're about to completely fill the Tx buffer, so we'll be throttled afterwards. */ count = priv->tx_room; @@ -547,7 +546,7 @@ static int keyspan_pda_write(struct tty_struct *tty, rc = count; exit: - if (rc < 0) + if (rc <= 0) set_bit(0, &port->write_urbs_free); return rc; } @@ -556,27 +555,28 @@ static int keyspan_pda_write(struct tty_struct *tty, static void keyspan_pda_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; - struct keyspan_pda_private *priv; set_bit(0, &port->write_urbs_free); - priv = usb_get_serial_port_data(port); /* queue up a wakeup at scheduler time */ - schedule_work(&priv->wakeup_work); + usb_serial_port_softint(port); } static int keyspan_pda_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - struct keyspan_pda_private *priv; - priv = usb_get_serial_port_data(port); - /* used by n_tty.c for processing of tabs and such. Giving it our - conservative guess is probably good enough, but needs testing by - running a console through the device. */ - return priv->tx_room; -} + struct keyspan_pda_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + int room = 0; + spin_lock_irqsave(&port->lock, flags); + if (test_bit(0, &port->write_urbs_free) && !priv->tx_throttled) + room = priv->tx_room; + spin_unlock_irqrestore(&port->lock, flags); + + return room; +} static int keyspan_pda_chars_in_buffer(struct tty_struct *tty) { @@ -656,8 +656,12 @@ static int keyspan_pda_open(struct tty_struct *tty, } static void keyspan_pda_close(struct usb_serial_port *port) { + struct keyspan_pda_private *priv = usb_get_serial_port_data(port); + usb_kill_urb(port->write_urb); usb_kill_urb(port->interrupt_in_urb); + + cancel_work_sync(&priv->unthrottle_work); } @@ -715,7 +719,6 @@ static int keyspan_pda_port_probe(struct usb_serial_port *port) if (!priv) return -ENOMEM; - INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write); INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle); priv->serial = port->serial; priv->port = port; diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 5ee48b0650c4..5f6b82ebccc5 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -276,12 +276,12 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) priv->cfg.unknown2 = cfg->unknown2; spin_unlock_irqrestore(&priv->lock, flags); + kfree(cfg); + /* READ_ON and urb submission */ rc = usb_serial_generic_open(tty, port); - if (rc) { - retval = rc; - goto err_free_cfg; - } + if (rc) + return rc; rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), @@ -324,8 +324,6 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) KLSI_TIMEOUT); err_generic_close: usb_serial_generic_close(port); -err_free_cfg: - kfree(cfg); return retval; } diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index c0232b67a40f..1e3ee2bfbcd0 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -638,6 +638,8 @@ static void parport_mos7715_restore_state(struct parport *pp, spin_unlock(&release_lock); return; } + mos_parport->shadowDCR = s->u.pc.ctr; + mos_parport->shadowECR = s->u.pc.ecr; write_parport_reg_nonblock(mos_parport, MOS7720_DCR, mos_parport->shadowDCR); write_parport_reg_nonblock(mos_parport, MOS7720_ECR, @@ -1248,8 +1250,10 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, if (urb->transfer_buffer == NULL) { urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); - if (!urb->transfer_buffer) + if (!urb->transfer_buffer) { + bytes_sent = -ENOMEM; goto exit; + } } transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 4a7bd26841af..c78dfb7fd394 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1340,8 +1340,10 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, if (urb->transfer_buffer == NULL) { urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, GFP_ATOMIC); - if (!urb->transfer_buffer) + if (!urb->transfer_buffer) { + bytes_sent = -ENOMEM; goto exit; + } } transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f28344f03141..aeaa3756f6ee 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -419,11 +419,14 @@ static void option_instat_callback(struct urb *urb); #define CINTERION_PRODUCT_PH8 0x0053 #define CINTERION_PRODUCT_AHXX 0x0055 #define CINTERION_PRODUCT_PLXX 0x0060 +#define CINTERION_PRODUCT_EXS82 0x006c #define CINTERION_PRODUCT_PH8_2RMNET 0x0082 #define CINTERION_PRODUCT_PH8_AUDIO 0x0083 #define CINTERION_PRODUCT_AHXX_2RMNET 0x0084 #define CINTERION_PRODUCT_AHXX_AUDIO 0x0085 #define CINTERION_PRODUCT_CLS8 0x00b0 +#define CINTERION_PRODUCT_MV31_MBIM 0x00b3 +#define CINTERION_PRODUCT_MV31_RMNET 0x00b7 /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c @@ -562,6 +565,9 @@ static void option_instat_callback(struct urb *urb); /* Device flags */ +/* Highest interface number which can be used with NCTRL() and RSVD() */ +#define FLAG_IFNUM_MAX 7 + /* Interface does not support modem-control requests */ #define NCTRL(ifnum) ((BIT(ifnum) & 0xff) << 8) @@ -1105,15 +1111,16 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0xff, 0xff), .driver_info = NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EG95, 0xff, 0, 0) }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0xff, 0xff), - .driver_info = NUMEP2 }, - { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96, 0xff, 0, 0) }, + { USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_BG96), + .driver_info = RSVD(4) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0xff, 0xff), .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff), .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0620, 0xff, 0xff, 0x30) }, /* EM160R-GL */ + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0620, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10), @@ -1562,7 +1569,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1272, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1273, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1274, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1275, 0xff, 0xff, 0xff) }, + { USB_DEVICE(ZTE_VENDOR_ID, 0x1275), /* ZTE P685M */ + .driver_info = RSVD(3) | RSVD(4) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1276, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1277, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1278, 0xff, 0xff, 0xff) }, @@ -1902,12 +1910,17 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_AUDIO, 0xff) }, { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_CLS8, 0xff), .driver_info = RSVD(0) | RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EXS82, 0xff) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) }, { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */ { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_MBIM, 0xff), + .driver_info = RSVD(3)}, + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV31_RMNET, 0xff), + .driver_info = RSVD(0)}, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100), .driver_info = RSVD(4) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120), @@ -2046,12 +2059,14 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, { USB_DEVICE(0x0489, 0xe0b5), /* Foxconn T77W968 ESIM */ .driver_info = RSVD(0) | RSVD(1) | RSVD(6) }, - { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 */ + { USB_DEVICE(0x1508, 0x1001), /* Fibocom NL668 (IOT version) */ .driver_info = RSVD(4) | RSVD(5) | RSVD(6) }, { USB_DEVICE(0x2cb7, 0x0104), /* Fibocom NL678 series */ .driver_info = RSVD(4) | RSVD(5) }, { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */ .driver_info = RSVD(6) }, + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ @@ -2098,6 +2113,14 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, option_ids); +static bool iface_is_reserved(unsigned long device_flags, u8 ifnum) +{ + if (ifnum > FLAG_IFNUM_MAX) + return false; + + return device_flags & RSVD(ifnum); +} + static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { @@ -2114,7 +2137,7 @@ static int option_probe(struct usb_serial *serial, * the same class/subclass/protocol as the serial interfaces. Look at * the Windows driver .INF files for reserved interface numbers. */ - if (device_flags & RSVD(iface_desc->bInterfaceNumber)) + if (iface_is_reserved(device_flags, iface_desc->bInterfaceNumber)) return -ENODEV; /* @@ -2130,6 +2153,14 @@ static int option_probe(struct usb_serial *serial, return 0; } +static bool iface_no_modem_control(unsigned long device_flags, u8 ifnum) +{ + if (ifnum > FLAG_IFNUM_MAX) + return false; + + return device_flags & NCTRL(ifnum); +} + static int option_attach(struct usb_serial *serial) { struct usb_interface_descriptor *iface_desc; @@ -2145,7 +2176,7 @@ static int option_attach(struct usb_serial *serial) iface_desc = &serial->interface->cur_altsetting->desc; - if (!(device_flags & NCTRL(iface_desc->bInterfaceNumber))) + if (!iface_no_modem_control(device_flags, iface_desc->bInterfaceNumber)) data->use_send_setup = 1; if (device_flags & ZLP) diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 96cb0409dd89..737b765d0f6e 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -651,6 +651,13 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) need_auto_sense = 1; } + /* Some devices (Kindle) require another command after SYNC CACHE */ + if ((us->fflags & US_FL_SENSE_AFTER_SYNC) && + srb->cmnd[0] == SYNCHRONIZE_CACHE) { + usb_stor_dbg(us, "-- sense after SYNC CACHE\n"); + need_auto_sense = 1; + } + /* * If we have a failure, we're going to do a REQUEST_SENSE * automatically. Note that we differentiate between a command diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 658b0cd8e27e..1fc7143c35a3 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -874,6 +874,9 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_NO_READ_CAPACITY_16) sdev->no_read_capacity_16 = 1; + /* Some disks cannot handle WRITE_SAME */ + if (devinfo->flags & US_FL_NO_SAME) + sdev->no_write_same = 1; /* * Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 88275842219e..861153d294b6 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2211,6 +2211,18 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), +/* + * Reported by Matthias Schwarzott + * The Amazon Kindle treats SYNCHRONIZE CACHE as an indication that + * the host may be finished with it, and automatically ejects its + * emulated media unless it receives another command within one second. + */ +UNUSUAL_DEV( 0x1949, 0x0004, 0x0000, 0x9999, + "Amazon", + "Kindle", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_SENSE_AFTER_SYNC ), + /* * Reported by Oliver Neukum * This device morphes spontaneously into another device if the access diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index dcdfcdfd2ad1..cb7b15ecb7ab 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -35,12 +35,15 @@ UNUSUAL_DEV(0x054c, 0x087d, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_OPCODES), -/* Reported-by: Julian Groß */ +/* + * Initially Reported-by: Julian Groß + * Further reports David C. Partridge + */ UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999, "LaCie", "2Big Quadra USB3", USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_REPORT_OPCODES), + US_FL_NO_REPORT_OPCODES | US_FL_NO_SAME), /* * Apricorn USB3 dongle sometimes returns "USBSUSBSUSBS" in response to SCSI @@ -87,6 +90,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA), +/* Reported-by: Thinh Nguyen */ +UNUSUAL_DEV(0x154b, 0xf00b, 0x0000, 0x9999, + "PNY", + "Pro Elite SSD", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_ATA_1X), + /* Reported-by: Thinh Nguyen */ UNUSUAL_DEV(0x154b, 0xf00d, 0x0000, 0x9999, "PNY", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 9a79cd9762f3..2349dfa3b176 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -541,6 +541,9 @@ void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) case 'j': f |= US_FL_NO_REPORT_LUNS; break; + case 'k': + f |= US_FL_NO_SAME; + break; case 'l': f |= US_FL_NOT_LOCKABLE; break; diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 7931e6cecc70..0081c1073b08 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -46,6 +46,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a int sockfd = 0; struct socket *socket; int rv; + struct task_struct *tcp_rx = NULL; + struct task_struct *tcp_tx = NULL; if (!sdev) { dev_err(dev, "sdev is null\n"); @@ -61,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a dev_info(dev, "stub up\n"); + mutex_lock(&sdev->ud.sysfs_lock); spin_lock_irq(&sdev->ud.lock); if (sdev->ud.status != SDEV_ST_AVAILABLE) { @@ -69,23 +72,49 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a } socket = sockfd_lookup(sockfd, &err); - if (!socket) + if (!socket) { + dev_err(dev, "failed to lookup sock"); goto err; + } - sdev->ud.tcp_socket = socket; - sdev->ud.sockfd = sockfd; + if (socket->type != SOCK_STREAM) { + dev_err(dev, "Expecting SOCK_STREAM - found %d", + socket->type); + goto sock_err; + } + /* unlock and create threads and get tasks */ spin_unlock_irq(&sdev->ud.lock); + tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx"); + if (IS_ERR(tcp_rx)) { + sockfd_put(socket); + goto unlock_mutex; + } + tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx"); + if (IS_ERR(tcp_tx)) { + kthread_stop(tcp_rx); + sockfd_put(socket); + goto unlock_mutex; + } - sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud, - "stub_rx"); - sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud, - "stub_tx"); + /* get task structs now */ + get_task_struct(tcp_rx); + get_task_struct(tcp_tx); + /* lock and update sdev->ud state */ spin_lock_irq(&sdev->ud.lock); + sdev->ud.tcp_socket = socket; + sdev->ud.sockfd = sockfd; + sdev->ud.tcp_rx = tcp_rx; + sdev->ud.tcp_tx = tcp_tx; sdev->ud.status = SDEV_ST_USED; spin_unlock_irq(&sdev->ud.lock); + wake_up_process(sdev->ud.tcp_rx); + wake_up_process(sdev->ud.tcp_tx); + + mutex_unlock(&sdev->ud.sysfs_lock); + } else { dev_info(dev, "stub down\n"); @@ -96,12 +125,17 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a spin_unlock_irq(&sdev->ud.lock); usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); + mutex_unlock(&sdev->ud.sysfs_lock); } return count; +sock_err: + sockfd_put(socket); err: spin_unlock_irq(&sdev->ud.lock); +unlock_mutex: + mutex_unlock(&sdev->ud.sysfs_lock); return -EINVAL; } static DEVICE_ATTR_WO(usbip_sockfd); @@ -267,6 +301,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev) sdev->ud.side = USBIP_STUB; sdev->ud.status = SDEV_ST_AVAILABLE; spin_lock_init(&sdev->ud.lock); + mutex_init(&sdev->ud.sysfs_lock); sdev->ud.tcp_socket = NULL; sdev->ud.sockfd = -1; diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h index 8be857a4fa13..a7e6ce96f62c 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -263,6 +263,9 @@ struct usbip_device { /* lock for status */ spinlock_t lock; + /* mutex for synchronizing sysfs store paths */ + struct mutex sysfs_lock; + int sockfd; struct socket *tcp_socket; diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 5d88917c9631..086ca76dd053 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -70,6 +70,7 @@ static void event_handler(struct work_struct *work) while ((ud = get_event()) != NULL) { usbip_dbg_eh("pending event %lx\n", ud->event); + mutex_lock(&ud->sysfs_lock); /* * NOTE: shutdown must come first. * Shutdown the device. @@ -90,6 +91,7 @@ static void event_handler(struct work_struct *work) ud->eh_ops.unusable(ud); unset_event(ud, USBIP_EH_UNUSABLE); } + mutex_unlock(&ud->sysfs_lock); wake_up(&ud->eh_waitq); } diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index d5a036bf904b..b13ed5a7618d 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -396,6 +396,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, default: usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n", wValue); + if (wValue >= 32) + goto error; vhci_hcd->port_status[rhport] &= ~(1 << wValue); break; } @@ -592,6 +594,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, pr_err("invalid port number %d\n", wIndex); goto error; } + if (wValue >= 32) + goto error; if (hcd->speed == HCD_USB3) { if ((vhci_hcd->port_status[rhport] & USB_SS_PORT_STAT_POWER) != 0) { @@ -1097,6 +1101,7 @@ static void vhci_device_init(struct vhci_device *vdev) vdev->ud.side = USBIP_VHCI; vdev->ud.status = VDEV_ST_NULL; spin_lock_init(&vdev->ud.lock); + mutex_init(&vdev->ud.sysfs_lock); INIT_LIST_HEAD(&vdev->priv_rx); INIT_LIST_HEAD(&vdev->priv_tx); diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index be37aec250c2..ebc7be1d9820 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -185,6 +185,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) usbip_dbg_vhci_sysfs("enter\n"); + mutex_lock(&vdev->ud.sysfs_lock); + /* lock */ spin_lock_irqsave(&vhci->lock, flags); spin_lock(&vdev->ud.lock); @@ -195,6 +197,7 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) /* unlock */ spin_unlock(&vdev->ud.lock); spin_unlock_irqrestore(&vhci->lock, flags); + mutex_unlock(&vdev->ud.sysfs_lock); return -EINVAL; } @@ -205,6 +208,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); + mutex_unlock(&vdev->ud.sysfs_lock); + return 0; } @@ -312,6 +317,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, struct vhci *vhci; int err; unsigned long flags; + struct task_struct *tcp_rx = NULL; + struct task_struct *tcp_tx = NULL; /* * @rhport: port number of vhci_hcd @@ -347,14 +354,43 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, else vdev = &vhci->vhci_hcd_hs->vdev[rhport]; + mutex_lock(&vdev->ud.sysfs_lock); + /* Extract socket from fd. */ socket = sockfd_lookup(sockfd, &err); - if (!socket) - return -EINVAL; + if (!socket) { + dev_err(dev, "failed to lookup sock"); + err = -EINVAL; + goto unlock_mutex; + } + if (socket->type != SOCK_STREAM) { + dev_err(dev, "Expecting SOCK_STREAM - found %d", + socket->type); + sockfd_put(socket); + err = -EINVAL; + goto unlock_mutex; + } - /* now need lock until setting vdev status as used */ + /* create threads before locking */ + tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx"); + if (IS_ERR(tcp_rx)) { + sockfd_put(socket); + err = -EINVAL; + goto unlock_mutex; + } + tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx"); + if (IS_ERR(tcp_tx)) { + kthread_stop(tcp_rx); + sockfd_put(socket); + err = -EINVAL; + goto unlock_mutex; + } + + /* get task structs now */ + get_task_struct(tcp_rx); + get_task_struct(tcp_tx); - /* begin a lock */ + /* now begin lock until setting vdev status set */ spin_lock_irqsave(&vhci->lock, flags); spin_lock(&vdev->ud.lock); @@ -364,13 +400,16 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, spin_unlock_irqrestore(&vhci->lock, flags); sockfd_put(socket); + kthread_stop_put(tcp_rx); + kthread_stop_put(tcp_tx); dev_err(dev, "port %d already used\n", rhport); /* * Will be retried from userspace * if there's another free port. */ - return -EBUSY; + err = -EBUSY; + goto unlock_mutex; } dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n", @@ -382,18 +421,28 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, vdev->speed = speed; vdev->ud.sockfd = sockfd; vdev->ud.tcp_socket = socket; + vdev->ud.tcp_rx = tcp_rx; + vdev->ud.tcp_tx = tcp_tx; vdev->ud.status = VDEV_ST_NOTASSIGNED; spin_unlock(&vdev->ud.lock); spin_unlock_irqrestore(&vhci->lock, flags); /* end the lock */ - vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx"); - vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx"); + wake_up_process(vdev->ud.tcp_rx); + wake_up_process(vdev->ud.tcp_tx); rh_port_connect(vdev, speed); + dev_info(dev, "Device attached\n"); + + mutex_unlock(&vdev->ud.sysfs_lock); + return count; + +unlock_mutex: + mutex_unlock(&vdev->ud.sysfs_lock); + return err; } static DEVICE_ATTR_WO(attach); diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c index 1634d8698e15..74568325d8c0 100644 --- a/drivers/usb/usbip/vudc_dev.c +++ b/drivers/usb/usbip/vudc_dev.c @@ -571,6 +571,7 @@ static int init_vudc_hw(struct vudc *udc) init_waitqueue_head(&udc->tx_waitq); spin_lock_init(&ud->lock); + mutex_init(&ud->sysfs_lock); ud->status = SDEV_ST_AVAILABLE; ud->side = USBIP_VUDC; diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index 6dcd3ff655c3..de2babadd146 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "usbip_common.h" @@ -90,8 +91,9 @@ static ssize_t dev_desc_read(struct file *file, struct kobject *kobj, } static BIN_ATTR_RO(dev_desc, sizeof(struct usb_device_descriptor)); -static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *attr, - const char *in, size_t count) +static ssize_t usbip_sockfd_store(struct device *dev, + struct device_attribute *attr, + const char *in, size_t count) { struct vudc *udc = (struct vudc *) dev_get_drvdata(dev); int rv; @@ -100,6 +102,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a struct socket *socket; unsigned long flags; int ret; + struct task_struct *tcp_rx = NULL; + struct task_struct *tcp_tx = NULL; rv = kstrtoint(in, 0, &sockfd); if (rv != 0) @@ -109,6 +113,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a dev_err(dev, "no device"); return -ENODEV; } + mutex_lock(&udc->ud.sysfs_lock); spin_lock_irqsave(&udc->lock, flags); /* Don't export what we don't have */ if (!udc->driver || !udc->pullup) { @@ -138,24 +143,56 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a goto unlock_ud; } - udc->ud.tcp_socket = socket; + if (socket->type != SOCK_STREAM) { + dev_err(dev, "Expecting SOCK_STREAM - found %d", + socket->type); + ret = -EINVAL; + goto sock_err; + } + /* unlock and create threads and get tasks */ spin_unlock_irq(&udc->ud.lock); spin_unlock_irqrestore(&udc->lock, flags); - udc->ud.tcp_rx = kthread_get_run(&v_rx_loop, - &udc->ud, "vudc_rx"); - udc->ud.tcp_tx = kthread_get_run(&v_tx_loop, - &udc->ud, "vudc_tx"); + tcp_rx = kthread_create(&v_rx_loop, &udc->ud, "vudc_rx"); + if (IS_ERR(tcp_rx)) { + sockfd_put(socket); + return -EINVAL; + } + tcp_tx = kthread_create(&v_tx_loop, &udc->ud, "vudc_tx"); + if (IS_ERR(tcp_tx)) { + kthread_stop(tcp_rx); + sockfd_put(socket); + return -EINVAL; + } + + /* get task structs now */ + get_task_struct(tcp_rx); + get_task_struct(tcp_tx); + /* lock and update udc->ud state */ spin_lock_irqsave(&udc->lock, flags); spin_lock_irq(&udc->ud.lock); + + udc->ud.tcp_socket = socket; + udc->ud.tcp_rx = tcp_rx; + udc->ud.tcp_tx = tcp_tx; udc->ud.status = SDEV_ST_USED; + spin_unlock_irq(&udc->ud.lock); ktime_get_ts64(&udc->start_time); v_start_timer(udc); udc->connected = 1; + + spin_unlock_irqrestore(&udc->lock, flags); + + wake_up_process(udc->ud.tcp_rx); + wake_up_process(udc->ud.tcp_tx); + + mutex_unlock(&udc->ud.sysfs_lock); + return count; + } else { if (!udc->connected) { dev_err(dev, "Device not connected"); @@ -174,13 +211,17 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a } spin_unlock_irqrestore(&udc->lock, flags); + mutex_unlock(&udc->ud.sysfs_lock); return count; +sock_err: + sockfd_put(socket); unlock_ud: spin_unlock_irq(&udc->ud.lock); unlock: spin_unlock_irqrestore(&udc->lock, flags); + mutex_unlock(&udc->ud.sysfs_lock); return ret; } diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 58e7336b2748..c48e1d84efb6 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -118,8 +118,6 @@ static void vfio_pci_probe_mmaps(struct vfio_pci_device *vdev) int bar; struct vfio_pci_dummy_resource *dummy_res; - INIT_LIST_HEAD(&vdev->dummy_resources_list); - for (bar = PCI_STD_RESOURCES; bar <= PCI_STD_RESOURCE_END; bar++) { res = vdev->pdev->resource + bar; @@ -1380,8 +1378,8 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf) mutex_unlock(&vdev->vma_lock); - if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) ret = VM_FAULT_SIGBUS; up_out: @@ -1522,6 +1520,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mutex_init(&vdev->igate); spin_lock_init(&vdev->irqlock); mutex_init(&vdev->ioeventfds_lock); + INIT_LIST_HEAD(&vdev->dummy_resources_list); INIT_LIST_HEAD(&vdev->ioeventfds_list); mutex_init(&vdev->vma_lock); INIT_LIST_HEAD(&vdev->vma_list); diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c index c0cd824be2b7..460760d0becf 100644 --- a/drivers/vfio/platform/vfio_platform_common.c +++ b/drivers/vfio/platform/vfio_platform_common.c @@ -273,7 +273,7 @@ static int vfio_platform_open(void *device_data) ret = pm_runtime_get_sync(vdev->device); if (ret < 0) - goto err_pm; + goto err_rst; ret = vfio_platform_call_reset(vdev, &extra_dbg); if (ret && vdev->reset_required) { @@ -290,7 +290,6 @@ static int vfio_platform_open(void *device_data) err_rst: pm_runtime_put(vdev->device); -err_pm: vfio_platform_irq_cleanup(vdev); err_irq: vfio_platform_regions_cleanup(vdev); diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 88c8c158ec25..0c7bbc92b22a 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -613,6 +613,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) size_t len, total_len = 0; int err; struct vhost_net_ubuf_ref *uninitialized_var(ubufs); + struct ubuf_info *ubuf; bool zcopy_used; int sent_pkts = 0; @@ -645,9 +646,7 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) /* use msg_control to pass vhost zerocopy ubuf info to skb */ if (zcopy_used) { - struct ubuf_info *ubuf; ubuf = nvq->ubuf_info + nvq->upend_idx; - vq->heads[nvq->upend_idx].id = cpu_to_vhost32(vq, head); vq->heads[nvq->upend_idx].len = VHOST_DMA_IN_PROGRESS; ubuf->callback = vhost_zerocopy_callback; @@ -675,7 +674,8 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) err = sock->ops->sendmsg(sock, &msg, len); if (unlikely(err < 0)) { if (zcopy_used) { - vhost_net_ubuf_put(ubufs); + if (vq->heads[ubuf->desc].len == VHOST_DMA_IN_PROGRESS) + vhost_net_ubuf_put(ubufs); nvq->upend_idx = ((unsigned)nvq->upend_idx - 1) % UIO_MAXIOV; } diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5cf3d1996f47..47f1b8408246 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -323,8 +323,8 @@ static void vhost_vq_reset(struct vhost_dev *dev, vq->kick = NULL; vq->call_ctx = NULL; vq->log_ctx = NULL; - vhost_reset_is_le(vq); vhost_disable_cross_endian(vq); + vhost_reset_is_le(vq); vq->busyloop_timeout = 0; vq->umem = NULL; vq->iotlb = NULL; diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index dc143de69971..14bcf2f6b0d6 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -182,13 +182,11 @@ int backlight_device_set_brightness(struct backlight_device *bd, rc = -EINVAL; else { if ((!bd->use_count && brightness) || (bd->use_count && !brightness)) { - pr_info("%s: set brightness to %lu\n", __func__, brightness); if (!bd->use_count) bd->use_count++; else bd->use_count--; } - pr_debug("set brightness to %lu\n", brightness); bd->props.brightness = brightness; rc = backlight_update_status(bd); } diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index d70a0b35faab..5403133beab9 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -1303,6 +1303,7 @@ config FB_ATY select FB_CFB_IMAGEBLIT select FB_BACKLIGHT if FB_ATY_BACKLIGHT select FB_MACMODES if PPC + select FB_ATY_CT if SPARC64 && PCI help This driver supports graphics boards with the ATI Mach64 chips. Say Y if you have such a graphics board. @@ -1313,7 +1314,6 @@ config FB_ATY config FB_ATY_CT bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" depends on PCI && FB_ATY - default y if SPARC64 && PCI help Say Y here to support use of ATI's 64-bit Rage boards (or other boards based on the Mach64 CT, VT, GT, and LT chipsets) as a diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c index 4ed55e6bbb84..6d01ae3984c7 100644 --- a/drivers/video/fbdev/atmel_lcdfb.c +++ b/drivers/video/fbdev/atmel_lcdfb.c @@ -1071,8 +1071,8 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo) } INIT_LIST_HEAD(&pdata->pwr_gpios); - ret = -ENOMEM; for (i = 0; i < gpiod_count(dev, "atmel,power-control"); i++) { + ret = -ENOMEM; gpiod = devm_gpiod_get_index(dev, "atmel,power-control", i, GPIOD_ASIS); if (IS_ERR(gpiod)) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 5742a0dc774e..cf0e025416e5 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1306,6 +1306,9 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; + if (!ops->cursor) + return; + ops->cursor(vc, info, mode, get_color(vc, info, c, 1), get_color(vc, info, c, 0)); } diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index 403d8cd3e582..c907f96d6890 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -712,7 +712,10 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) goto err1; } - fb_virt = ioremap(par->mem->start, screen_fb_size); + /* + * Map the VRAM cacheable for performance. + */ + fb_virt = ioremap_wc(par->mem->start, screen_fb_size); if (!fb_virt) goto err2; diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile index 309c6d2fe2f9..37f193e23c63 100644 --- a/drivers/video/fbdev/msm/Makefile +++ b/drivers/video/fbdev/msm/Makefile @@ -12,6 +12,7 @@ mdss-mdp-objs += mdss_mdp_pp.o mdss_mdp_pp_debug.o mdss_mdp_pp_cache_config.o md mdss-mdp-objs += mdss_mdp_intf_video.o mdss-mdp-objs += mdss_mdp_intf_cmd.o mdss-mdp-objs += mdss_mdp_intf_writeback.o +mdss-mdp-objs += mdss_rotator.o mdss-mdp-objs += mdss_mdp_overlay.o mdss-mdp-objs += mdss_mdp_layer.o mdss-mdp-objs += mdss_mdp_splash_logo.o diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c new file mode 100644 index 000000000000..25d9d6dfc71e --- /dev/null +++ b/drivers/video/fbdev/msm/mdss_rotator.c @@ -0,0 +1,3035 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2014-2018, 2021, The Linux Foundation. All rights reserved. */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mdss_rotator_internal.h" +#include "mdss_mdp.h" +#include "mdss_debug.h" +#include "mdss_sync.h" + +/* waiting for hw time out, 3 vsync for 30fps*/ +#define ROT_HW_ACQUIRE_TIMEOUT_IN_MS 100 + +/* acquire fence time out, following other driver fence time out practice */ +#define ROT_FENCE_WAIT_TIMEOUT MSEC_PER_SEC +/* + * Max rotator hw blocks possible. Used for upper array limits instead of + * alloc and freeing small array + */ +#define ROT_MAX_HW_BLOCKS 2 + +#define ROT_CHECK_BOUNDS(offset, size, max_size) \ + (((size) > (max_size)) || ((offset) > ((max_size) - (size)))) + +#define CLASS_NAME "rotator" +#define DRIVER_NAME "mdss_rotator" + +#define MDP_REG_BUS_VECTOR_ENTRY(ab_val, ib_val) \ + { \ + .src = MSM_BUS_MASTER_AMPSS_M0, \ + .dst = MSM_BUS_SLAVE_DISPLAY_CFG, \ + .ab = (ab_val), \ + .ib = (ib_val), \ + } + +#define BUS_VOTE_19_MHZ 153600000 + +static struct msm_bus_vectors rot_reg_bus_vectors[] = { + MDP_REG_BUS_VECTOR_ENTRY(0, 0), + MDP_REG_BUS_VECTOR_ENTRY(0, BUS_VOTE_19_MHZ), +}; +static struct msm_bus_paths rot_reg_bus_usecases[ARRAY_SIZE( + rot_reg_bus_vectors)]; +static struct msm_bus_scale_pdata rot_reg_bus_scale_table = { + .usecase = rot_reg_bus_usecases, + .num_usecases = ARRAY_SIZE(rot_reg_bus_usecases), + .name = "mdss_rot_reg", + .active_only = 1, +}; + +static struct mdss_rot_mgr *rot_mgr; +static void mdss_rotator_wq_handler(struct work_struct *work); + +static int mdss_rotator_bus_scale_set_quota(struct mdss_rot_bus_data_type *bus, + u64 quota) +{ + int new_uc_idx; + int ret; + + if (bus->bus_hdl < 1) { + pr_err("invalid bus handle %d\n", bus->bus_hdl); + return -EINVAL; + } + + if (bus->curr_quota_val == quota) { + pr_debug("bw request already requested\n"); + return 0; + } + + if (!quota) { + new_uc_idx = 0; + } else { + struct msm_bus_vectors *vect = NULL; + struct msm_bus_scale_pdata *bw_table = + bus->bus_scale_pdata; + u64 port_quota = quota; + u32 total_axi_port_cnt; + int i; + + new_uc_idx = (bus->curr_bw_uc_idx % + (bw_table->num_usecases - 1)) + 1; + + total_axi_port_cnt = bw_table->usecase[new_uc_idx].num_paths; + if (total_axi_port_cnt == 0) { + pr_err("Number of bw paths is 0\n"); + return -ENODEV; + } + do_div(port_quota, total_axi_port_cnt); + + for (i = 0; i < total_axi_port_cnt; i++) { + vect = &bw_table->usecase[new_uc_idx].vectors[i]; + vect->ab = port_quota; + vect->ib = 0; + } + } + bus->curr_bw_uc_idx = new_uc_idx; + bus->curr_quota_val = quota; + + pr_debug("uc_idx=%d quota=%llu\n", new_uc_idx, quota); + MDSS_XLOG(new_uc_idx, ((quota >> 32) & 0xFFFFFFFF), + (quota & 0xFFFFFFFF)); + ATRACE_BEGIN("msm_bus_scale_req_rot"); + ret = msm_bus_scale_client_update_request(bus->bus_hdl, + new_uc_idx); + ATRACE_END("msm_bus_scale_req_rot"); + return ret; +} + +static int mdss_rotator_enable_reg_bus(struct mdss_rot_mgr *mgr, u64 quota) +{ + int ret = 0, changed = 0; + u32 usecase_ndx = 0; + + if (!mgr || !mgr->reg_bus.bus_hdl) + return 0; + + if (quota) + usecase_ndx = 1; + + if (usecase_ndx != mgr->reg_bus.curr_bw_uc_idx) { + mgr->reg_bus.curr_bw_uc_idx = usecase_ndx; + changed++; + } + + pr_debug("%s, changed=%d register bus %s\n", __func__, changed, + quota ? "Enable":"Disable"); + + if (changed) { + ATRACE_BEGIN("msm_bus_scale_req_rot_reg"); + ret = msm_bus_scale_client_update_request(mgr->reg_bus.bus_hdl, + usecase_ndx); + ATRACE_END("msm_bus_scale_req_rot_reg"); + } + + return ret; +} + +/* + * Clock rate of all open sessions working a particular hw block + * are added together to get the required rate for that hw block. + * The max of each hw block becomes the final clock rate voted for + */ +static unsigned long mdss_rotator_clk_rate_calc( + struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private) +{ + struct mdss_rot_perf *perf; + unsigned long clk_rate[ROT_MAX_HW_BLOCKS] = {0}; + unsigned long total_clk_rate = 0; + int i, wb_idx; + + mutex_lock(&private->perf_lock); + list_for_each_entry(perf, &private->perf_list, list) { + bool rate_accounted_for = false; + + mutex_lock(&perf->work_dis_lock); + /* + * If there is one session that has two work items across + * different hw blocks rate is accounted for in both blocks. + */ + for (i = 0; i < mgr->queue_count; i++) { + if (perf->work_distribution[i]) { + clk_rate[i] += perf->clk_rate; + rate_accounted_for = true; + } + } + + /* + * Sessions that are open but not distributed on any hw block + * Still need to be accounted for. Rate is added to last known + * wb idx. + */ + wb_idx = perf->last_wb_idx; + if ((!rate_accounted_for) && (wb_idx >= 0) && + (wb_idx < mgr->queue_count)) + clk_rate[wb_idx] += perf->clk_rate; + mutex_unlock(&perf->work_dis_lock); + } + mutex_unlock(&private->perf_lock); + + for (i = 0; i < mgr->queue_count; i++) + total_clk_rate = max(clk_rate[i], total_clk_rate); + + pr_debug("Total clk rate calc=%lu\n", total_clk_rate); + return total_clk_rate; +} + +static struct clk *mdss_rotator_get_clk(struct mdss_rot_mgr *mgr, u32 clk_idx) +{ + if (clk_idx >= MDSS_CLK_ROTATOR_END_IDX) { + pr_err("Invalid clk index:%u\n", clk_idx); + return NULL; + } + + return mgr->rot_clk[clk_idx]; +} + +static void mdss_rotator_set_clk_rate(struct mdss_rot_mgr *mgr, + unsigned long rate, u32 clk_idx) +{ + unsigned long clk_rate; + struct clk *clk = mdss_rotator_get_clk(mgr, clk_idx); + int ret; + + if (clk) { + mutex_lock(&mgr->clk_lock); + clk_rate = clk_round_rate(clk, rate); + if (IS_ERR_VALUE(clk_rate)) { + pr_err("unable to round rate err=%ld\n", clk_rate); + } else if (clk_rate != clk_get_rate(clk)) { + ret = clk_set_rate(clk, clk_rate); + if (IS_ERR_VALUE((unsigned long)ret)) { + pr_err("clk_set_rate failed, err:%d\n", ret); + } else { + pr_debug("rotator clk rate=%lu\n", clk_rate); + MDSS_XLOG(clk_rate); + } + } + mutex_unlock(&mgr->clk_lock); + } else { + pr_err("rotator clk not setup properly\n"); + } +} + +static void mdss_rotator_footswitch_ctrl(struct mdss_rot_mgr *mgr, bool on) +{ + int ret; + + if (mgr->regulator_enable == on) { + pr_err("Regulators already in selected mode on=%d\n", on); + return; + } + + pr_debug("%s: rotator regulators\n", on ? "Enable" : "Disable"); + ret = msm_dss_enable_vreg(mgr->module_power.vreg_config, + mgr->module_power.num_vreg, on); + if (ret) { + pr_warn("Rotator regulator failed to %s\n", + on ? "enable" : "disable"); + return; + } + + mgr->regulator_enable = on; +} + +static int mdss_rotator_clk_ctrl(struct mdss_rot_mgr *mgr, int enable) +{ + struct clk *clk; + int ret = 0; + int i, changed = 0; + + mutex_lock(&mgr->clk_lock); + if (enable) { + if (mgr->rot_enable_clk_cnt == 0) + changed++; + mgr->rot_enable_clk_cnt++; + } else { + if (mgr->rot_enable_clk_cnt) { + mgr->rot_enable_clk_cnt--; + if (mgr->rot_enable_clk_cnt == 0) + changed++; + } else { + pr_err("Can not be turned off\n"); + } + } + + if (changed) { + pr_debug("Rotator clk %s\n", enable ? "enable" : "disable"); + for (i = 0; i < MDSS_CLK_ROTATOR_END_IDX; i++) { + clk = mgr->rot_clk[i]; + if (enable) { + ret = clk_prepare_enable(clk); + if (ret) { + pr_err("enable failed clk_idx %d\n", i); + goto error; + } + } else { + clk_disable_unprepare(clk); + } + } + mutex_lock(&mgr->bus_lock); + if (enable) { + /* Active+Sleep */ + msm_bus_scale_client_update_context( + mgr->data_bus.bus_hdl, false, + mgr->data_bus.curr_bw_uc_idx); + trace_rotator_bw_ao_as_context(0); + } else { + /* Active Only */ + msm_bus_scale_client_update_context( + mgr->data_bus.bus_hdl, true, + mgr->data_bus.curr_bw_uc_idx); + trace_rotator_bw_ao_as_context(1); + } + mutex_unlock(&mgr->bus_lock); + } + mutex_unlock(&mgr->clk_lock); + + return ret; +error: + for (i--; i >= 0; i--) + clk_disable_unprepare(mgr->rot_clk[i]); + mutex_unlock(&mgr->clk_lock); + return ret; +} + +int mdss_rotator_resource_ctrl(struct mdss_rot_mgr *mgr, int enable) +{ + int changed = 0; + int ret = 0; + + mutex_lock(&mgr->clk_lock); + if (enable) { + if (mgr->res_ref_cnt == 0) + changed++; + mgr->res_ref_cnt++; + } else { + if (mgr->res_ref_cnt) { + mgr->res_ref_cnt--; + if (mgr->res_ref_cnt == 0) + changed++; + } else { + pr_err("Rot resource already off\n"); + } + } + + pr_debug("%s: res_cnt=%d changed=%d enable=%d\n", + __func__, mgr->res_ref_cnt, changed, enable); + MDSS_XLOG(mgr->res_ref_cnt, changed, enable); + + if (changed) { + if (enable) + mdss_rotator_footswitch_ctrl(mgr, true); + else + mdss_rotator_footswitch_ctrl(mgr, false); + } + mutex_unlock(&mgr->clk_lock); + return ret; +} + +/* caller is expected to hold perf->work_dis_lock lock */ +static bool mdss_rotator_is_work_pending(struct mdss_rot_mgr *mgr, + struct mdss_rot_perf *perf) +{ + int i; + + for (i = 0; i < mgr->queue_count; i++) { + if (perf->work_distribution[i]) { + pr_debug("Work is still scheduled to complete\n"); + return true; + } + } + return false; +} + +static int mdss_rotator_install_fence_fd(struct mdss_rot_entry_container *req) +{ + int i; + int ret = 0; + struct sync_file *sync_file; + + for (i = 0; i < req->count; i++) { + sync_file = sync_file_create((struct dma_fence *) + (req->entries[i].output_fence)); + if (!sync_file) { + ret = -ENOMEM; + break; + } + fd_install(req->entries[i].output_fence_fd, sync_file->file); + } + return ret; +} + +static int mdss_rotator_create_fence(struct mdss_rot_entry *entry) +{ + int ret = 0, fd; + u32 val; + struct mdss_fence *fence; + struct mdss_rot_timeline *rot_timeline; + + if (!entry->queue) + return -EINVAL; + + rot_timeline = &entry->queue->timeline; + + mutex_lock(&rot_timeline->lock); + val = rot_timeline->next_value + 1; + + fence = mdss_get_sync_fence(rot_timeline->timeline, + rot_timeline->fence_name, NULL, val); + if (fence == NULL) { + pr_err("cannot create sync point\n"); + goto sync_pt_create_err; + } + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) { + pr_err("fail to get unused fd\n"); + ret = fd; + goto get_fd_err; + } + + rot_timeline->next_value++; + mutex_unlock(&rot_timeline->lock); + + entry->output_fence_fd = fd; + entry->output_fence = fence; + pr_debug("output sync point created at %s:val=%u\n", + mdss_get_sync_fence_name(fence), val); + + return 0; + +get_fd_err: + mdss_put_sync_fence(fence); +sync_pt_create_err: + mutex_unlock(&rot_timeline->lock); + return ret; +} + +static void mdss_rotator_clear_fence(struct mdss_rot_entry *entry) +{ + struct mdss_rot_timeline *rot_timeline; + + if (entry->input_fence) { + mdss_put_sync_fence(entry->input_fence); + entry->input_fence = NULL; + } + + rot_timeline = &entry->queue->timeline; + + /* fence failed to copy to user space */ + if (entry->output_fence) { + mdss_put_sync_fence(entry->output_fence); + entry->output_fence = NULL; + put_unused_fd(entry->output_fence_fd); + + mutex_lock(&rot_timeline->lock); + rot_timeline->next_value--; + mutex_unlock(&rot_timeline->lock); + } +} + +static int mdss_rotator_signal_output(struct mdss_rot_entry *entry) +{ + struct mdss_rot_timeline *rot_timeline; + + if (!entry->queue) + return -EINVAL; + + rot_timeline = &entry->queue->timeline; + + if (entry->output_signaled) { + pr_debug("output already signaled\n"); + return 0; + } + + mutex_lock(&rot_timeline->lock); + mdss_inc_timeline(rot_timeline->timeline, 1); + mutex_unlock(&rot_timeline->lock); + + entry->output_signaled = true; + + return 0; +} + +static int mdss_rotator_wait_for_input(struct mdss_rot_entry *entry) +{ + int ret; + + if (!entry->input_fence) { + pr_debug("invalid input fence, no wait\n"); + return 0; + } + + ret = mdss_wait_sync_fence(entry->input_fence, ROT_FENCE_WAIT_TIMEOUT); + mdss_put_sync_fence(entry->input_fence); + entry->input_fence = NULL; + return ret; +} + +static int mdss_rotator_import_buffer(struct mdp_layer_buffer *buffer, + struct mdss_mdp_data *data, u32 flags, struct device *dev, bool input) +{ + int i, ret = 0; + struct msmfb_data planes[MAX_PLANES]; + int dir = DMA_TO_DEVICE; + + if (!input) + dir = DMA_FROM_DEVICE; + + memset(planes, 0, sizeof(planes)); + + if (buffer->plane_count > MAX_PLANES) { + pr_err("buffer plane_count exceeds MAX_PLANES limit:%d\n", + buffer->plane_count); + return -EINVAL; + } + + for (i = 0; i < buffer->plane_count; i++) { + planes[i].memory_id = buffer->planes[i].fd; + planes[i].offset = buffer->planes[i].offset; + } + + ret = mdss_mdp_data_get_and_validate_size(data, planes, + buffer->plane_count, flags, dev, true, dir, buffer); + data->state = MDP_BUF_STATE_READY; + data->last_alloc = local_clock(); + + return ret; +} + +static int mdss_rotator_map_and_check_data(struct mdss_rot_entry *entry) +{ + int ret; + struct mdp_layer_buffer *input; + struct mdp_layer_buffer *output; + struct mdss_mdp_format_params *fmt; + struct mdss_mdp_plane_sizes ps; + bool rotation; + + input = &entry->item.input; + output = &entry->item.output; + + rotation = (entry->item.flags & MDP_ROTATION_90) ? true : false; + + ATRACE_BEGIN(__func__); + ret = mdss_iommu_ctrl(1); + if (IS_ERR_VALUE((unsigned long)ret)) { + ATRACE_END(__func__); + return ret; + } + + /* if error during map, the caller will release the data */ + entry->src_buf.state = MDP_BUF_STATE_ACTIVE; + ret = mdss_mdp_data_map(&entry->src_buf, true, DMA_TO_DEVICE); + if (ret) { + pr_err("source buffer mapping failed ret:%d\n", ret); + goto end; + } + + entry->dst_buf.state = MDP_BUF_STATE_ACTIVE; + ret = mdss_mdp_data_map(&entry->dst_buf, true, DMA_FROM_DEVICE); + if (ret) { + pr_err("destination buffer mapping failed ret:%d\n", ret); + goto end; + } + + fmt = mdss_mdp_get_format_params(input->format); + if (!fmt) { + pr_err("invalid input format:%d\n", input->format); + ret = -EINVAL; + goto end; + } + + ret = mdss_mdp_get_plane_sizes( + fmt, input->width, input->height, &ps, 0, rotation); + if (ret) { + pr_err("fail to get input plane size ret=%d\n", ret); + goto end; + } + + ret = mdss_mdp_data_check(&entry->src_buf, &ps, fmt); + if (ret) { + pr_err("fail to check input data ret=%d\n", ret); + goto end; + } + + fmt = mdss_mdp_get_format_params(output->format); + if (!fmt) { + pr_err("invalid output format:%d\n", output->format); + ret = -EINVAL; + goto end; + } + + ret = mdss_mdp_get_plane_sizes( + fmt, output->width, output->height, &ps, 0, rotation); + if (ret) { + pr_err("fail to get output plane size ret=%d\n", ret); + goto end; + } + + ret = mdss_mdp_data_check(&entry->dst_buf, &ps, fmt); + if (ret) { + pr_err("fail to check output data ret=%d\n", ret); + goto end; + } + +end: + mdss_iommu_ctrl(0); + ATRACE_END(__func__); + + return ret; +} + +static struct mdss_rot_perf *__mdss_rotator_find_session( + struct mdss_rot_file_private *private, + u32 session_id) +{ + struct mdss_rot_perf *perf, *perf_next; + bool found = false; + + list_for_each_entry_safe(perf, perf_next, &private->perf_list, list) { + if (perf->config.session_id == session_id) { + found = true; + break; + } + } + if (!found) + perf = NULL; + return perf; +} + +static struct mdss_rot_perf *mdss_rotator_find_session( + struct mdss_rot_file_private *private, + u32 session_id) +{ + struct mdss_rot_perf *perf; + + mutex_lock(&private->perf_lock); + perf = __mdss_rotator_find_session(private, session_id); + mutex_unlock(&private->perf_lock); + return perf; +} + +static void mdss_rotator_release_data(struct mdss_rot_entry *entry) +{ + struct mdss_mdp_data *src_buf = &entry->src_buf; + struct mdss_mdp_data *dst_buf = &entry->dst_buf; + + mdss_mdp_data_free(src_buf, true, DMA_TO_DEVICE); + src_buf->last_freed = local_clock(); + src_buf->state = MDP_BUF_STATE_UNUSED; + + mdss_mdp_data_free(dst_buf, true, DMA_FROM_DEVICE); + dst_buf->last_freed = local_clock(); + dst_buf->state = MDP_BUF_STATE_UNUSED; +} + +static int mdss_rotator_import_data(struct mdss_rot_mgr *mgr, + struct mdss_rot_entry *entry) +{ + int ret; + struct mdp_layer_buffer *input; + struct mdp_layer_buffer *output; + u32 flag = 0; + + input = &entry->item.input; + output = &entry->item.output; + + if (entry->item.flags & MDP_ROTATION_SECURE) + flag = MDP_SECURE_OVERLAY_SESSION; + + ret = mdss_rotator_import_buffer(input, &entry->src_buf, flag, + &mgr->pdev->dev, true); + if (ret) { + pr_err("fail to import input buffer\n"); + return ret; + } + + /* + * driver assumes output buffer is ready to be written + * immediately + */ + ret = mdss_rotator_import_buffer(output, &entry->dst_buf, flag, + &mgr->pdev->dev, false); + if (ret) { + pr_err("fail to import output buffer\n"); + return ret; + } + + return ret; +} + +static struct mdss_rot_hw_resource *mdss_rotator_hw_alloc( + struct mdss_rot_mgr *mgr, u32 pipe_id, u32 wb_id) +{ + struct mdss_rot_hw_resource *hw; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + u32 pipe_ndx, offset = mdss_mdp_get_wb_ctl_support(mdata, true); + int ret = 0; + + hw = kzalloc(sizeof(struct mdss_rot_hw_resource), + GFP_KERNEL); + if (!hw) + return ERR_PTR(-ENOMEM); + + hw->ctl = mdss_mdp_ctl_alloc(mdata, offset); + if (IS_ERR_OR_NULL(hw->ctl)) { + pr_err("unable to allocate ctl\n"); + ret = -ENODEV; + goto error; + } + + if (wb_id == MDSS_ROTATION_HW_ANY) + hw->wb = mdss_mdp_wb_alloc(MDSS_MDP_WB_ROTATOR, hw->ctl->num); + else + hw->wb = mdss_mdp_wb_assign(wb_id, hw->ctl->num); + + if (IS_ERR_OR_NULL(hw->wb)) { + pr_err("unable to allocate wb\n"); + ret = -ENODEV; + goto error; + } + hw->ctl->wb = hw->wb; + hw->mixer = mdss_mdp_mixer_assign(hw->wb->num, true, true); + + if (IS_ERR_OR_NULL(hw->mixer)) { + pr_err("unable to allocate wb mixer\n"); + ret = -ENODEV; + goto error; + } + hw->ctl->mixer_left = hw->mixer; + hw->mixer->ctl = hw->ctl; + + hw->mixer->rotator_mode = true; + + switch (hw->mixer->num) { + case MDSS_MDP_WB_LAYERMIXER0: + hw->ctl->opmode = MDSS_MDP_CTL_OP_ROT0_MODE; + break; + case MDSS_MDP_WB_LAYERMIXER1: + hw->ctl->opmode = MDSS_MDP_CTL_OP_ROT1_MODE; + break; + default: + pr_err("invalid layer mixer=%d\n", hw->mixer->num); + ret = -EINVAL; + goto error; + } + + hw->ctl->ops.start_fnc = mdss_mdp_writeback_start; + hw->ctl->power_state = MDSS_PANEL_POWER_ON; + hw->ctl->wb_type = MDSS_MDP_WB_CTL_TYPE_BLOCK; + + + if (hw->ctl->ops.start_fnc) + ret = hw->ctl->ops.start_fnc(hw->ctl); + + if (ret) + goto error; + + if (pipe_id >= mdata->ndma_pipes) + goto error; + + pipe_ndx = mdata->dma_pipes[pipe_id].ndx; + hw->pipe = mdss_mdp_pipe_assign(mdata, hw->mixer, + pipe_ndx, MDSS_MDP_PIPE_RECT0); + if (IS_ERR_OR_NULL(hw->pipe)) { + pr_err("dma pipe allocation failed\n"); + ret = -ENODEV; + goto error; + } + + hw->pipe->mixer_left = hw->mixer; + hw->pipe_id = hw->wb->num; + hw->wb_id = hw->wb->num; + + return hw; +error: + if (!IS_ERR_OR_NULL(hw->pipe)) + mdss_mdp_pipe_destroy(hw->pipe); + if (!IS_ERR_OR_NULL(hw->ctl)) { + if (hw->ctl->ops.stop_fnc) + hw->ctl->ops.stop_fnc(hw->ctl, MDSS_PANEL_POWER_OFF); + mdss_mdp_ctl_free(hw->ctl); + } + kfree(hw); + + return ERR_PTR(ret); +} + +static void mdss_rotator_free_hw(struct mdss_rot_mgr *mgr, + struct mdss_rot_hw_resource *hw) +{ + struct mdss_mdp_mixer *mixer; + struct mdss_mdp_ctl *ctl; + + mixer = hw->pipe->mixer_left; + + mdss_mdp_pipe_destroy(hw->pipe); + + ctl = mdss_mdp_ctl_mixer_switch(mixer->ctl, + MDSS_MDP_WB_CTL_TYPE_BLOCK); + if (ctl) { + if (ctl->ops.stop_fnc) + ctl->ops.stop_fnc(ctl, MDSS_PANEL_POWER_OFF); + mdss_mdp_ctl_free(ctl); + } + + kfree(hw); +} + +struct mdss_rot_hw_resource *mdss_rotator_get_hw_resource( + struct mdss_rot_queue *queue, struct mdss_rot_entry *entry) +{ + struct mdss_rot_hw_resource *hw = queue->hw; + + if (!hw) { + pr_err("no hw in the queue\n"); + return NULL; + } + + mutex_lock(&queue->hw_lock); + + if (hw->workload) { + hw = ERR_PTR(-EBUSY); + goto get_hw_resource_err; + } + hw->workload = entry; + +get_hw_resource_err: + mutex_unlock(&queue->hw_lock); + return hw; +} + +static void mdss_rotator_put_hw_resource(struct mdss_rot_queue *queue, + struct mdss_rot_hw_resource *hw) +{ + mutex_lock(&queue->hw_lock); + hw->workload = NULL; + mutex_unlock(&queue->hw_lock); +} + +/* + * caller will need to call mdss_rotator_deinit_queue when + * the function returns error + */ +static int mdss_rotator_init_queue(struct mdss_rot_mgr *mgr) +{ + int i, size, ret = 0; + char name[32]; + + size = sizeof(struct mdss_rot_queue) * mgr->queue_count; + mgr->queues = devm_kzalloc(&mgr->pdev->dev, size, GFP_KERNEL); + if (!mgr->queues) + return -ENOMEM; + + for (i = 0; i < mgr->queue_count; i++) { + snprintf(name, sizeof(name), "rot_workq_%d", i); + pr_debug("work queue name=%s\n", name); + mgr->queues[i].rot_work_queue = alloc_ordered_workqueue("%s", + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, name); + if (!mgr->queues[i].rot_work_queue) { + ret = -EPERM; + break; + } + + snprintf(name, sizeof(name), "rot_timeline_%d", i); + pr_debug("timeline name=%s\n", name); + mgr->queues[i].timeline.timeline = + mdss_create_timeline(name); + if (!mgr->queues[i].timeline.timeline) { + ret = -EPERM; + break; + } + + size = sizeof(mgr->queues[i].timeline.fence_name); + snprintf(mgr->queues[i].timeline.fence_name, size, + "rot_fence_%d", i); + mutex_init(&mgr->queues[i].timeline.lock); + + mutex_init(&mgr->queues[i].hw_lock); + } + + return ret; +} + +static void mdss_rotator_deinit_queue(struct mdss_rot_mgr *mgr) +{ + int i; + + if (!mgr->queues) + return; + + for (i = 0; i < mgr->queue_count; i++) { + if (mgr->queues[i].rot_work_queue) + destroy_workqueue(mgr->queues[i].rot_work_queue); + + if (mgr->queues[i].timeline.timeline) { + struct mdss_timeline *obj; + + obj = (struct mdss_timeline *) + mgr->queues[i].timeline.timeline; + mdss_destroy_timeline(obj); + } + } +} + +/* + * mdss_rotator_assign_queue() - Function assign rotation work onto hw + * @mgr: Rotator manager. + * @entry: Contains details on rotator work item being requested + * @private: Private struct used for access rot session performance struct + * + * This Function allocates hw required to complete rotation work item + * requested. + * + * Caller is responsible for calling cleanup function if error is returned + */ +static int mdss_rotator_assign_queue(struct mdss_rot_mgr *mgr, + struct mdss_rot_entry *entry, + struct mdss_rot_file_private *private) +{ + struct mdss_rot_perf *perf; + struct mdss_rot_queue *queue; + struct mdss_rot_hw_resource *hw; + struct mdp_rotation_item *item = &entry->item; + u32 wb_idx = item->wb_idx; + u32 pipe_idx = item->pipe_idx; + int ret = 0; + + /* + * todo: instead of always assign writeback block 0, we can + * apply some load balancing logic in the future + */ + if (wb_idx == MDSS_ROTATION_HW_ANY) { + wb_idx = 0; + pipe_idx = 0; + } + + if (wb_idx >= mgr->queue_count) { + pr_err("Invalid wb idx = %d\n", wb_idx); + return -EINVAL; + } + + queue = mgr->queues + wb_idx; + + mutex_lock(&queue->hw_lock); + + if (!queue->hw) { + hw = mdss_rotator_hw_alloc(mgr, pipe_idx, wb_idx); + if (IS_ERR_OR_NULL(hw)) { + pr_err("fail to allocate hw\n"); + ret = PTR_ERR(hw); + } else { + queue->hw = hw; + } + } + + if (queue->hw) { + entry->queue = queue; + queue->hw->pending_count++; + } + + mutex_unlock(&queue->hw_lock); + + perf = mdss_rotator_find_session(private, item->session_id); + if (!perf) { + pr_err("Could not find session based on rotation work item\n"); + return -EINVAL; + } + + entry->perf = perf; + perf->last_wb_idx = wb_idx; + + return ret; +} + +static void mdss_rotator_unassign_queue(struct mdss_rot_mgr *mgr, + struct mdss_rot_entry *entry) +{ + struct mdss_rot_queue *queue = entry->queue; + + if (!queue) + return; + + entry->queue = NULL; + + mutex_lock(&queue->hw_lock); + + if (!queue->hw) { + pr_err("entry assigned a queue with no hw\n"); + mutex_unlock(&queue->hw_lock); + return; + } + + queue->hw->pending_count--; + if (queue->hw->pending_count == 0) { + mdss_rotator_free_hw(mgr, queue->hw); + queue->hw = NULL; + } + + mutex_unlock(&queue->hw_lock); +} + +static void mdss_rotator_queue_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, + struct mdss_rot_entry_container *req) +{ + struct mdss_rot_entry *entry; + struct mdss_rot_queue *queue; + unsigned long clk_rate; + u32 wb_idx; + int i; + + for (i = 0; i < req->count; i++) { + entry = req->entries + i; + queue = entry->queue; + wb_idx = queue->hw->wb_id; + mutex_lock(&entry->perf->work_dis_lock); + entry->perf->work_distribution[wb_idx]++; + mutex_unlock(&entry->perf->work_dis_lock); + entry->work_assigned = true; + } + + clk_rate = mdss_rotator_clk_rate_calc(mgr, private); + mdss_rotator_set_clk_rate(mgr, clk_rate, MDSS_CLK_ROTATOR_CORE); + + for (i = 0; i < req->count; i++) { + entry = req->entries + i; + queue = entry->queue; + entry->output_fence = NULL; + queue_work(queue->rot_work_queue, &entry->commit_work); + } +} + +static int mdss_rotator_calc_perf(struct mdss_rot_perf *perf) +{ + struct mdp_rotation_config *config = &perf->config; + u32 read_bw, write_bw; + struct mdss_mdp_format_params *in_fmt, *out_fmt; + + in_fmt = mdss_mdp_get_format_params(config->input.format); + if (!in_fmt) { + pr_err("invalid input format\n"); + return -EINVAL; + } + out_fmt = mdss_mdp_get_format_params(config->output.format); + if (!out_fmt) { + pr_err("invalid output format\n"); + return -EINVAL; + } + if (!config->input.width || + (0xffffffff/config->input.width < config->input.height)) + return -EINVAL; + + perf->clk_rate = config->input.width * config->input.height; + + if (!perf->clk_rate || + (0xffffffff/perf->clk_rate < config->frame_rate)) + return -EINVAL; + + perf->clk_rate *= config->frame_rate; + /* rotator processes 4 pixels per clock */ + perf->clk_rate /= 4; + + read_bw = config->input.width * config->input.height * + config->frame_rate; + if (in_fmt->chroma_sample == MDSS_MDP_CHROMA_420) + read_bw = (read_bw * 3) / 2; + else + read_bw *= in_fmt->bpp; + + write_bw = config->output.width * config->output.height * + config->frame_rate; + if (out_fmt->chroma_sample == MDSS_MDP_CHROMA_420) + write_bw = (write_bw * 3) / 2; + else + write_bw *= out_fmt->bpp; + + read_bw = apply_comp_ratio_factor(read_bw, in_fmt, + &config->input.comp_ratio); + write_bw = apply_comp_ratio_factor(write_bw, out_fmt, + &config->output.comp_ratio); + + perf->bw = read_bw + write_bw; + return 0; +} + +static int mdss_rotator_update_perf(struct mdss_rot_mgr *mgr) +{ + struct mdss_rot_file_private *priv; + struct mdss_rot_perf *perf; + int not_in_suspend_mode; + u64 total_bw = 0; + + ATRACE_BEGIN(__func__); + + not_in_suspend_mode = !atomic_read(&mgr->device_suspended); + + if (not_in_suspend_mode) { + mutex_lock(&mgr->file_lock); + list_for_each_entry(priv, &mgr->file_list, list) { + mutex_lock(&priv->perf_lock); + list_for_each_entry(perf, &priv->perf_list, list) { + total_bw += perf->bw; + } + mutex_unlock(&priv->perf_lock); + } + mutex_unlock(&mgr->file_lock); + } + + mutex_lock(&mgr->bus_lock); + total_bw += mgr->pending_close_bw_vote; + mdss_rotator_enable_reg_bus(mgr, total_bw); + mdss_rotator_bus_scale_set_quota(&mgr->data_bus, total_bw); + mutex_unlock(&mgr->bus_lock); + + ATRACE_END(__func__); + return 0; +} + +static void mdss_rotator_release_from_work_distribution( + struct mdss_rot_mgr *mgr, + struct mdss_rot_entry *entry) +{ + if (entry->work_assigned) { + bool free_perf = false; + u32 wb_idx = entry->queue->hw->wb_id; + + mutex_lock(&mgr->lock); + mutex_lock(&entry->perf->work_dis_lock); + if (entry->perf->work_distribution[wb_idx]) + entry->perf->work_distribution[wb_idx]--; + + if (!entry->perf->work_distribution[wb_idx] + && list_empty(&entry->perf->list)) { + /* close session has offloaded perf free to us */ + free_perf = true; + } + mutex_unlock(&entry->perf->work_dis_lock); + entry->work_assigned = false; + if (free_perf) { + mutex_lock(&mgr->bus_lock); + mgr->pending_close_bw_vote -= entry->perf->bw; + mutex_unlock(&mgr->bus_lock); + mdss_rotator_resource_ctrl(mgr, false); + kfree(entry->perf->work_distribution); + kfree(entry->perf); + mdss_rotator_update_perf(mgr); + mdss_rotator_clk_ctrl(mgr, false); + entry->perf = NULL; + } + mutex_unlock(&mgr->lock); + } +} + +static void mdss_rotator_release_entry(struct mdss_rot_mgr *mgr, + struct mdss_rot_entry *entry) +{ + mdss_rotator_release_from_work_distribution(mgr, entry); + mdss_rotator_clear_fence(entry); + mdss_rotator_release_data(entry); + mdss_rotator_unassign_queue(mgr, entry); +} + +static int mdss_rotator_config_dnsc_factor(struct mdss_rot_mgr *mgr, + struct mdss_rot_entry *entry) +{ + int ret = 0; + u16 src_w, src_h, dst_w, dst_h, bit; + struct mdp_rotation_item *item = &entry->item; + struct mdss_mdp_format_params *fmt; + + src_w = item->src_rect.w; + src_h = item->src_rect.h; + + if (item->flags & MDP_ROTATION_90) { + dst_w = item->dst_rect.h; + dst_h = item->dst_rect.w; + } else { + dst_w = item->dst_rect.w; + dst_h = item->dst_rect.h; + } + + if (!mgr->has_downscale && + (src_w != dst_w || src_h != dst_h)) { + pr_err("rotator downscale not supported\n"); + ret = -EINVAL; + goto dnsc_err; + } + + entry->dnsc_factor_w = 0; + entry->dnsc_factor_h = 0; + + if ((src_w != dst_w) || (src_h != dst_h)) { + if ((src_w % dst_w) || (src_h % dst_h)) { + ret = -EINVAL; + goto dnsc_err; + } + entry->dnsc_factor_w = src_w / dst_w; + bit = fls(entry->dnsc_factor_w); + /* + * New Chipsets supports downscale upto 1/64 + * change the Bit check from 5 to 7 to support 1/64 down scale + */ + if ((entry->dnsc_factor_w & ~BIT(bit - 1)) || (bit > 7)) { + ret = -EINVAL; + goto dnsc_err; + } + entry->dnsc_factor_h = src_h / dst_h; + bit = fls(entry->dnsc_factor_h); + if ((entry->dnsc_factor_h & ~BIT(bit - 1)) || (bit > 7)) { + ret = -EINVAL; + goto dnsc_err; + } + } + + fmt = mdss_mdp_get_format_params(item->output.format); + if (mdss_mdp_is_ubwc_format(fmt) && + (entry->dnsc_factor_h || entry->dnsc_factor_w)) { + pr_err("ubwc not supported with downscale %d\n", + item->output.format); + ret = -EINVAL; + } + +dnsc_err: + + /* Downscaler does not support asymmetrical dnsc */ + if (entry->dnsc_factor_w != entry->dnsc_factor_h) + ret = -EINVAL; + + if (ret) { + pr_err("Invalid rotator downscale ratio %dx%d->%dx%d\n", + src_w, src_h, dst_w, dst_h); + entry->dnsc_factor_w = 0; + entry->dnsc_factor_h = 0; + } + return ret; +} + +static bool mdss_rotator_verify_format(struct mdss_rot_mgr *mgr, + struct mdss_mdp_format_params *in_fmt, + struct mdss_mdp_format_params *out_fmt, bool rotation) +{ + u8 in_v_subsample, in_h_subsample; + u8 out_v_subsample, out_h_subsample; + + if (!mgr->has_ubwc && (mdss_mdp_is_ubwc_format(in_fmt) || + mdss_mdp_is_ubwc_format(out_fmt))) { + pr_err("Rotator doesn't allow ubwc\n"); + return -EINVAL; + } + + if (!(out_fmt->flag & VALID_ROT_WB_FORMAT)) { + pr_err("Invalid output format\n"); + return false; + } + + if (in_fmt->is_yuv != out_fmt->is_yuv) { + pr_err("Rotator does not support CSC\n"); + return false; + } + + /* Forcing same pixel depth */ + if (memcmp(in_fmt->bits, out_fmt->bits, sizeof(in_fmt->bits))) { + /* Exception is that RGB can drop alpha or add X */ + if (in_fmt->is_yuv || out_fmt->alpha_enable || + (in_fmt->bits[C2_R_Cr] != out_fmt->bits[C2_R_Cr]) || + (in_fmt->bits[C0_G_Y] != out_fmt->bits[C0_G_Y]) || + (in_fmt->bits[C1_B_Cb] != out_fmt->bits[C1_B_Cb])) { + pr_err("Bit format does not match\n"); + return false; + } + } + + /* Need to make sure that sub-sampling persists through rotation */ + if (rotation) { + mdss_mdp_get_v_h_subsample_rate(in_fmt->chroma_sample, + &in_v_subsample, &in_h_subsample); + mdss_mdp_get_v_h_subsample_rate(out_fmt->chroma_sample, + &out_v_subsample, &out_h_subsample); + + if ((in_v_subsample != out_h_subsample) || + (in_h_subsample != out_v_subsample)) { + pr_err("Rotation has invalid subsampling\n"); + return false; + } + } else { + if (in_fmt->chroma_sample != out_fmt->chroma_sample) { + pr_err("Format subsampling mismatch\n"); + return false; + } + } + + pr_debug("in_fmt=%0d, out_fmt=%d, has_ubwc=%d\n", + in_fmt->format, out_fmt->format, mgr->has_ubwc); + return true; +} + +static int mdss_rotator_verify_config(struct mdss_rot_mgr *mgr, + struct mdp_rotation_config *config) +{ + struct mdss_mdp_format_params *in_fmt, *out_fmt; + u8 in_v_subsample, in_h_subsample; + u8 out_v_subsample, out_h_subsample; + u32 input, output; + bool rotation; + + input = config->input.format; + output = config->output.format; + rotation = (config->flags & MDP_ROTATION_90) ? true : false; + + in_fmt = mdss_mdp_get_format_params(input); + if (!in_fmt) { + pr_err("Unrecognized input format:%u\n", input); + return -EINVAL; + } + + out_fmt = mdss_mdp_get_format_params(output); + if (!out_fmt) { + pr_err("Unrecognized output format:%u\n", output); + return -EINVAL; + } + + mdss_mdp_get_v_h_subsample_rate(in_fmt->chroma_sample, + &in_v_subsample, &in_h_subsample); + mdss_mdp_get_v_h_subsample_rate(out_fmt->chroma_sample, + &out_v_subsample, &out_h_subsample); + + /* Dimension of image needs to be divisible by subsample rate */ + if ((config->input.height % in_v_subsample) || + (config->input.width % in_h_subsample)) { + pr_err("In ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n", + config->input.width, config->input.height, + in_v_subsample, in_h_subsample); + return -EINVAL; + } + + if ((config->output.height % out_v_subsample) || + (config->output.width % out_h_subsample)) { + pr_err("Out ROI, subsample mismatch, w=%d, h=%d, vss%d, hss%d\n", + config->output.width, config->output.height, + out_v_subsample, out_h_subsample); + return -EINVAL; + } + + if (!mdss_rotator_verify_format(mgr, in_fmt, + out_fmt, rotation)) { + pr_err("Rot format pairing invalid, in_fmt:%d, out_fmt:%d\n", + input, output); + return -EINVAL; + } + + return 0; +} + +static int mdss_rotator_validate_item_matches_session( + struct mdp_rotation_config *config, struct mdp_rotation_item *item) +{ + int ret; + + ret = __compare_session_item_rect(&config->input, + &item->src_rect, item->input.format, true); + if (ret) + return ret; + + ret = __compare_session_item_rect(&config->output, + &item->dst_rect, item->output.format, false); + if (ret) + return ret; + + ret = __compare_session_rotations(config->flags, item->flags); + if (ret) + return ret; + + return 0; +} + +static int mdss_rotator_validate_img_roi(struct mdp_rotation_item *item) +{ + struct mdss_mdp_format_params *fmt; + uint32_t width, height; + int ret = 0; + + width = item->input.width; + height = item->input.height; + if (item->flags & MDP_ROTATION_DEINTERLACE) { + width *= 2; + height /= 2; + } + + /* Check roi bounds */ + if (ROT_CHECK_BOUNDS(item->src_rect.x, item->src_rect.w, width) || + ROT_CHECK_BOUNDS(item->src_rect.y, item->src_rect.h, + height)) { + pr_err("invalid src flag=%08x img wh=%dx%d rect=%d,%d,%d,%d\n", + item->flags, width, height, item->src_rect.x, + item->src_rect.y, item->src_rect.w, item->src_rect.h); + return -EINVAL; + } + if (ROT_CHECK_BOUNDS(item->dst_rect.x, item->dst_rect.w, + item->output.width) || + ROT_CHECK_BOUNDS(item->dst_rect.y, item->dst_rect.h, + item->output.height)) { + pr_err("invalid dst img wh=%dx%d rect=%d,%d,%d,%d\n", + item->output.width, item->output.height, + item->dst_rect.x, item->dst_rect.y, item->dst_rect.w, + item->dst_rect.h); + return -EINVAL; + } + + fmt = mdss_mdp_get_format_params(item->output.format); + if (!fmt) { + pr_err("invalid output format:%d\n", item->output.format); + return -EINVAL; + } + + if (mdss_mdp_is_ubwc_format(fmt)) + ret = mdss_mdp_validate_offset_for_ubwc_format(fmt, + item->dst_rect.x, item->dst_rect.y); + + return ret; +} + +static int mdss_rotator_validate_fmt_and_item_flags( + struct mdp_rotation_config *config, struct mdp_rotation_item *item) +{ + struct mdss_mdp_format_params *fmt; + + fmt = mdss_mdp_get_format_params(item->input.format); + if ((item->flags & MDP_ROTATION_DEINTERLACE) && + mdss_mdp_is_ubwc_format(fmt)) { + pr_err("cannot perform mdp deinterlace on tiled formats\n"); + return -EINVAL; + } + return 0; +} + +static int mdss_rotator_validate_entry(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, + struct mdss_rot_entry *entry) +{ + int ret; + struct mdp_rotation_item *item; + struct mdss_rot_perf *perf; + + item = &entry->item; + + if (item->wb_idx != item->pipe_idx) { + pr_err("invalid writeback and pipe idx\n"); + return -EINVAL; + } + + if (item->wb_idx != MDSS_ROTATION_HW_ANY && + item->wb_idx > mgr->queue_count) { + pr_err("invalid writeback idx\n"); + return -EINVAL; + } + + perf = mdss_rotator_find_session(private, item->session_id); + if (!perf) { + pr_err("Could not find session:%u\n", item->session_id); + return -EINVAL; + } + + ret = mdss_rotator_validate_item_matches_session(&perf->config, item); + if (ret) { + pr_err("Work item does not match session:%u\n", + item->session_id); + return ret; + } + + ret = mdss_rotator_validate_img_roi(item); + if (ret) { + pr_err("Image roi is invalid\n"); + return ret; + } + + ret = mdss_rotator_validate_fmt_and_item_flags(&perf->config, item); + if (ret) + return ret; + + ret = mdss_rotator_config_dnsc_factor(mgr, entry); + if (ret) { + pr_err("fail to configure downscale factor\n"); + return ret; + } + return ret; +} + +/* + * Upon failure from the function, caller needs to make sure + * to call mdss_rotator_remove_request to clean up resources. + */ +static int mdss_rotator_add_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, + struct mdss_rot_entry_container *req) +{ + struct mdss_rot_entry *entry; + struct mdp_rotation_item *item; + u32 flag = 0; + int i, ret; + + for (i = 0; i < req->count; i++) { + entry = req->entries + i; + item = &entry->item; + + if (item->flags & MDP_ROTATION_SECURE) + flag = MDP_SECURE_OVERLAY_SESSION; + + ret = mdss_rotator_validate_entry(mgr, private, entry); + if (ret) { + pr_err("fail to validate the entry\n"); + return ret; + } + + ret = mdss_rotator_import_data(mgr, entry); + if (ret) { + pr_err("fail to import the data\n"); + return ret; + } + + if (item->input.fence >= 0) { + entry->input_fence = mdss_get_fd_sync_fence( + item->input.fence); + if (!entry->input_fence) { + pr_err("invalid input fence fd\n"); + return -EINVAL; + } + } + + ret = mdss_rotator_assign_queue(mgr, entry, private); + if (ret) { + pr_err("fail to assign queue to entry\n"); + return ret; + } + + entry->request = req; + + INIT_WORK(&entry->commit_work, mdss_rotator_wq_handler); + + ret = mdss_rotator_create_fence(entry); + if (ret) { + pr_err("fail to create fence\n"); + return ret; + } + item->output.fence = entry->output_fence_fd; + + pr_debug("Entry added. wbidx=%u, src{%u,%u,%u,%u}f=%u\n" + "dst{%u,%u,%u,%u}f=%u session_id=%u\n", item->wb_idx, + item->src_rect.x, item->src_rect.y, + item->src_rect.w, item->src_rect.h, item->input.format, + item->dst_rect.x, item->dst_rect.y, + item->dst_rect.w, item->dst_rect.h, item->output.format, + item->session_id); + } + + mutex_lock(&private->req_lock); + list_add(&req->list, &private->req_list); + mutex_unlock(&private->req_lock); + + return 0; +} + +static void mdss_rotator_remove_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, + struct mdss_rot_entry_container *req) +{ + int i; + + mutex_lock(&private->req_lock); + for (i = 0; i < req->count; i++) + mdss_rotator_release_entry(mgr, req->entries + i); + list_del_init(&req->list); + mutex_unlock(&private->req_lock); +} + +/* This function should be called with req_lock */ +static void mdss_rotator_cancel_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_entry_container *req) +{ + struct mdss_rot_entry *entry; + int i; + + /* + * To avoid signal the rotation entry output fence in the wrong + * order, all the entries in the same request needs to be cancelled + * first, before signaling the output fence. + */ + for (i = req->count - 1; i >= 0; i--) { + entry = req->entries + i; + cancel_work_sync(&entry->commit_work); + } + + for (i = req->count - 1; i >= 0; i--) { + entry = req->entries + i; + mdss_rotator_signal_output(entry); + mdss_rotator_release_entry(mgr, entry); + } + + list_del_init(&req->list); + kfree(req); +} + +static void mdss_rotator_cancel_all_requests(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private) +{ + struct mdss_rot_entry_container *req, *req_next; + + pr_debug("Canceling all rotator requests\n"); + + mutex_lock(&private->req_lock); + list_for_each_entry_safe(req, req_next, &private->req_list, list) + mdss_rotator_cancel_request(mgr, req); + mutex_unlock(&private->req_lock); +} + +static void mdss_rotator_free_competed_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private) +{ + struct mdss_rot_entry_container *req, *req_next; + + mutex_lock(&private->req_lock); + list_for_each_entry_safe(req, req_next, &private->req_list, list) { + if (atomic_read(&req->pending_count) == 0) { + list_del_init(&req->list); + kfree(req); + } + } + mutex_unlock(&private->req_lock); +} + +static void mdss_rotator_release_rotator_perf_session( + struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private) +{ + struct mdss_rot_perf *perf, *perf_next; + + pr_debug("Releasing all rotator request\n"); + mdss_rotator_cancel_all_requests(mgr, private); + + mutex_lock(&private->perf_lock); + list_for_each_entry_safe(perf, perf_next, &private->perf_list, list) { + list_del_init(&perf->list); + kfree(perf->work_distribution); + kfree(perf); + } + mutex_unlock(&private->perf_lock); +} + +static void mdss_rotator_release_all(struct mdss_rot_mgr *mgr) +{ + struct mdss_rot_file_private *priv, *priv_next; + + mutex_lock(&mgr->file_lock); + list_for_each_entry_safe(priv, priv_next, &mgr->file_list, list) { + mdss_rotator_release_rotator_perf_session(mgr, priv); + mdss_rotator_resource_ctrl(mgr, false); + list_del_init(&priv->list); + priv->file->private_data = NULL; + kfree(priv); + } + mutex_unlock(&rot_mgr->file_lock); + + mdss_rotator_update_perf(mgr); +} + +static int mdss_rotator_prepare_hw(struct mdss_rot_hw_resource *hw, + struct mdss_rot_entry *entry) +{ + struct mdss_mdp_pipe *pipe; + struct mdss_mdp_ctl *orig_ctl, *rot_ctl; + int ret; + + pipe = hw->pipe; + orig_ctl = pipe->mixer_left->ctl; + if (orig_ctl->shared_lock) + mutex_lock(orig_ctl->shared_lock); + + rot_ctl = mdss_mdp_ctl_mixer_switch(orig_ctl, + MDSS_MDP_WB_CTL_TYPE_BLOCK); + if (!rot_ctl) { + ret = -EINVAL; + goto error; + } else { + hw->ctl = rot_ctl; + pipe->mixer_left = rot_ctl->mixer_left; + } + + return 0; + +error: + if (orig_ctl->shared_lock) + mutex_unlock(orig_ctl->shared_lock); + return ret; +} + +static void mdss_rotator_translate_rect(struct mdss_rect *dst, + struct mdp_rect *src) +{ + dst->x = src->x; + dst->y = src->y; + dst->w = src->w; + dst->h = src->h; +} + +static u32 mdss_rotator_translate_flags(u32 input) +{ + u32 output = 0; + + if (input & MDP_ROTATION_NOP) + output |= MDP_ROT_NOP; + if (input & MDP_ROTATION_FLIP_LR) + output |= MDP_FLIP_LR; + if (input & MDP_ROTATION_FLIP_UD) + output |= MDP_FLIP_UD; + if (input & MDP_ROTATION_90) + output |= MDP_ROT_90; + if (input & MDP_ROTATION_DEINTERLACE) + output |= MDP_DEINTERLACE; + if (input & MDP_ROTATION_SECURE) + output |= MDP_SECURE_OVERLAY_SESSION; + if (input & MDP_ROTATION_BWC_EN) + output |= MDP_BWC_EN; + + return output; +} + +static int mdss_rotator_config_hw(struct mdss_rot_hw_resource *hw, + struct mdss_rot_entry *entry) +{ + struct mdss_mdp_pipe *pipe; + struct mdp_rotation_item *item; + struct mdss_rot_perf *perf; + int ret; + + ATRACE_BEGIN(__func__); + pipe = hw->pipe; + item = &entry->item; + perf = entry->perf; + + pipe->flags = mdss_rotator_translate_flags(item->flags); + pipe->src_fmt = mdss_mdp_get_format_params(item->input.format); + pipe->img_width = item->input.width; + pipe->img_height = item->input.height; + mdss_rotator_translate_rect(&pipe->src, &item->src_rect); + mdss_rotator_translate_rect(&pipe->dst, &item->src_rect); + pipe->scaler.enable = 0; + pipe->frame_rate = perf->config.frame_rate; + + pipe->params_changed++; + + mdss_mdp_smp_release(pipe); + + ret = mdss_mdp_smp_reserve(pipe); + if (ret) { + pr_err("unable to mdss_mdp_smp_reserve rot data\n"); + goto done; + } + + ret = mdss_mdp_overlay_setup_scaling(pipe); + if (ret) { + pr_err("scaling setup failed %d\n", ret); + goto done; + } + + ret = mdss_mdp_pipe_queue_data(pipe, &entry->src_buf); + pr_debug("Config pipe. src{%u,%u,%u,%u}f=%u\n" + "dst{%u,%u,%u,%u}f=%u session_id=%u\n", + item->src_rect.x, item->src_rect.y, + item->src_rect.w, item->src_rect.h, item->input.format, + item->dst_rect.x, item->dst_rect.y, + item->dst_rect.w, item->dst_rect.h, item->output.format, + item->session_id); + MDSS_XLOG(item->input.format, pipe->img_width, pipe->img_height, + pipe->flags); +done: + ATRACE_END(__func__); + return ret; +} + +static int mdss_rotator_kickoff_entry(struct mdss_rot_hw_resource *hw, + struct mdss_rot_entry *entry) +{ + int ret; + struct mdss_mdp_writeback_arg wb_args = { + .data = &entry->dst_buf, + .priv_data = entry, + }; + + ret = mdss_mdp_writeback_display_commit(hw->ctl, &wb_args); + return ret; +} + +static int mdss_rotator_wait_for_entry(struct mdss_rot_hw_resource *hw, + struct mdss_rot_entry *entry) +{ + int ret; + struct mdss_mdp_ctl *ctl = hw->ctl; + + ret = mdss_mdp_display_wait4comp(ctl); + if (ctl->shared_lock) + mutex_unlock(ctl->shared_lock); + return ret; +} + +static int mdss_rotator_commit_entry(struct mdss_rot_hw_resource *hw, + struct mdss_rot_entry *entry) +{ + int ret; + + ret = mdss_rotator_prepare_hw(hw, entry); + if (ret) { + pr_err("fail to prepare hw resource %d\n", ret); + return ret; + } + + ret = mdss_rotator_config_hw(hw, entry); + if (ret) { + pr_err("fail to configure hw resource %d\n", ret); + return ret; + } + + ret = mdss_rotator_kickoff_entry(hw, entry); + if (ret) { + pr_err("fail to do kickoff %d\n", ret); + return ret; + } + + ret = mdss_rotator_wait_for_entry(hw, entry); + if (ret) { + pr_err("fail to wait for completion %d\n", ret); + return ret; + } + + return ret; +} + +static int mdss_rotator_handle_entry(struct mdss_rot_hw_resource *hw, + struct mdss_rot_entry *entry) +{ + int ret; + + ret = mdss_rotator_wait_for_input(entry); + if (ret) { + pr_err("wait for input buffer failed %d\n", ret); + return ret; + } + + ret = mdss_rotator_map_and_check_data(entry); + if (ret) { + pr_err("fail to prepare input/output data %d\n", ret); + return ret; + } + + ret = mdss_rotator_commit_entry(hw, entry); + if (ret) + pr_err("rotator commit failed %d\n", ret); + + return ret; +} + +static void mdss_rotator_wq_handler(struct work_struct *work) +{ + struct mdss_rot_entry *entry; + struct mdss_rot_entry_container *request; + struct mdss_rot_hw_resource *hw; + int ret; + + entry = container_of(work, struct mdss_rot_entry, commit_work); + request = entry->request; + + if (!request) { + pr_err("fatal error, no request with entry\n"); + return; + } + + hw = mdss_rotator_get_hw_resource(entry->queue, entry); + if (!hw) { + pr_err("no hw for the queue\n"); + goto get_hw_res_err; + } + + ret = mdss_rotator_handle_entry(hw, entry); + if (ret) { + struct mdp_rotation_item *item = &entry->item; + + pr_err("Rot req fail. src{%u,%u,%u,%u}f=%u\n" + "dst{%u,%u,%u,%u}f=%u session_id=%u, wbidx%d, pipe_id=%d\n", + item->src_rect.x, item->src_rect.y, + item->src_rect.w, item->src_rect.h, item->input.format, + item->dst_rect.x, item->dst_rect.y, + item->dst_rect.w, item->dst_rect.h, item->output.format, + item->session_id, item->wb_idx, item->pipe_idx); + } + + mdss_rotator_put_hw_resource(entry->queue, hw); + +get_hw_res_err: + mdss_rotator_signal_output(entry); + mdss_rotator_release_entry(rot_mgr, entry); + atomic_dec(&request->pending_count); +} + +static int mdss_rotator_validate_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, + struct mdss_rot_entry_container *req) +{ + int i, ret = 0; + struct mdss_rot_entry *entry; + + for (i = 0; i < req->count; i++) { + entry = req->entries + i; + ret = mdss_rotator_validate_entry(mgr, private, + entry); + if (ret) { + pr_err("fail to validate the entry\n"); + return ret; + } + } + + return ret; +} + +static u32 mdss_rotator_generator_session_id(struct mdss_rot_mgr *mgr) +{ + u32 id; + + mutex_lock(&mgr->lock); + id = mgr->session_id_generator++; + mutex_unlock(&mgr->lock); + return id; +} + +static int mdss_rotator_open_session(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, unsigned long arg) +{ + struct mdp_rotation_config config; + struct mdss_rot_perf *perf; + int ret; + + ret = copy_from_user(&config, (void __user *)arg, sizeof(config)); + if (ret) { + pr_err("fail to copy session data\n"); + return ret; + } + + ret = mdss_rotator_verify_config(mgr, &config); + if (ret) { + pr_err("Rotator verify format failed\n"); + return ret; + } + + perf = kzalloc(sizeof(*perf), GFP_KERNEL); + if (!perf) + return -ENOMEM; + + ATRACE_BEGIN(__func__); /* Open session votes for bw */ + perf->work_distribution = kcalloc(mgr->queue_count, sizeof(u32), + GFP_KERNEL); + if (!perf->work_distribution) { + ret = -ENOMEM; + goto alloc_err; + } + + config.session_id = mdss_rotator_generator_session_id(mgr); + perf->config = config; + perf->last_wb_idx = -1; + mutex_init(&perf->work_dis_lock); + + INIT_LIST_HEAD(&perf->list); + + ret = mdss_rotator_calc_perf(perf); + if (ret) { + pr_err("error setting the session%d\n", ret); + goto copy_user_err; + } + + ret = copy_to_user((void *)arg, &config, sizeof(config)); + if (ret) { + pr_err("fail to copy to user\n"); + goto copy_user_err; + } + + mutex_lock(&private->perf_lock); + list_add(&perf->list, &private->perf_list); + mutex_unlock(&private->perf_lock); + + ret = mdss_rotator_resource_ctrl(mgr, true); + if (ret) { + pr_err("Failed to aqcuire rotator resources\n"); + goto resource_err; + } + + mdss_rotator_clk_ctrl(rot_mgr, true); + ret = mdss_rotator_update_perf(mgr); + if (ret) { + pr_err("fail to open session, not enough clk/bw\n"); + goto perf_err; + } + pr_debug("open session id=%u in{%u,%u}f:%u out{%u,%u}f:%u\n", + config.session_id, config.input.width, config.input.height, + config.input.format, config.output.width, config.output.height, + config.output.format); + + goto done; +perf_err: + mdss_rotator_clk_ctrl(rot_mgr, false); + mdss_rotator_resource_ctrl(mgr, false); +resource_err: + mutex_lock(&private->perf_lock); + list_del_init(&perf->list); + mutex_unlock(&private->perf_lock); +copy_user_err: + kfree(perf->work_distribution); +alloc_err: + kfree(perf); +done: + ATRACE_END(__func__); + return ret; +} + +static int mdss_rotator_close_session(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, unsigned long arg) +{ + struct mdss_rot_perf *perf; + bool offload_release_work = false; + u32 id; + + id = (u32)arg; + mutex_lock(&mgr->lock); + mutex_lock(&private->perf_lock); + perf = __mdss_rotator_find_session(private, id); + if (!perf) { + mutex_unlock(&private->perf_lock); + mutex_unlock(&mgr->lock); + pr_err("Trying to close session that does not exist\n"); + return -EINVAL; + } + + ATRACE_BEGIN(__func__); + mutex_lock(&perf->work_dis_lock); + if (mdss_rotator_is_work_pending(mgr, perf)) { + pr_debug("Work is still pending, offload free to wq\n"); + mutex_lock(&mgr->bus_lock); + mgr->pending_close_bw_vote += perf->bw; + mutex_unlock(&mgr->bus_lock); + offload_release_work = true; + } + list_del_init(&perf->list); + mutex_unlock(&perf->work_dis_lock); + mutex_unlock(&private->perf_lock); + + if (offload_release_work) + goto done; + + mdss_rotator_resource_ctrl(mgr, false); + kfree(perf->work_distribution); + kfree(perf); + mdss_rotator_update_perf(mgr); + mdss_rotator_clk_ctrl(rot_mgr, false); +done: + pr_debug("Closed session id:%u\n", id); + ATRACE_END(__func__); + mutex_unlock(&mgr->lock); + return 0; +} + +static int mdss_rotator_config_session(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, unsigned long arg) +{ + int ret = 0; + struct mdss_rot_perf *perf; + struct mdp_rotation_config config; + + ret = copy_from_user(&config, (void __user *)arg, + sizeof(config)); + if (ret) { + pr_err("fail to copy session data\n"); + return ret; + } + + ret = mdss_rotator_verify_config(mgr, &config); + if (ret) { + pr_err("Rotator verify format failed\n"); + return ret; + } + + mutex_lock(&mgr->lock); + perf = mdss_rotator_find_session(private, config.session_id); + if (!perf) { + pr_err("No session with id=%u could be found\n", + config.session_id); + mutex_unlock(&mgr->lock); + return -EINVAL; + } + + ATRACE_BEGIN(__func__); + mutex_lock(&private->perf_lock); + perf->config = config; + ret = mdss_rotator_calc_perf(perf); + mutex_unlock(&private->perf_lock); + + if (ret) { + pr_err("error in configuring the session %d\n", ret); + goto done; + } + + ret = mdss_rotator_update_perf(mgr); + + pr_debug("reconfig session id=%u in{%u,%u}f:%u out{%u,%u}f:%u\n", + config.session_id, config.input.width, config.input.height, + config.input.format, config.output.width, config.output.height, + config.output.format); +done: + ATRACE_END(__func__); + mutex_unlock(&mgr->lock); + return ret; +} + +struct mdss_rot_entry_container *mdss_rotator_req_init( + struct mdss_rot_mgr *mgr, struct mdp_rotation_item *items, + u32 count, u32 flags) +{ + struct mdss_rot_entry_container *req; + int size, i; + + /* + * Check input and output plane_count from each given item + * are within the MAX_PLANES limit + */ + for (i = 0 ; i < count; i++) { + if ((items[i].input.plane_count > MAX_PLANES) || + (items[i].output.plane_count > MAX_PLANES)) { + pr_err("Input/Output plane_count exceeds MAX_PLANES limit, input:%d, output:%d\n", + items[i].input.plane_count, + items[i].output.plane_count); + return ERR_PTR(-EINVAL); + } + } + + size = sizeof(struct mdss_rot_entry_container); + size += sizeof(struct mdss_rot_entry) * count; + req = kzalloc(size, GFP_KERNEL); + + if (!req) + return ERR_PTR(-ENOMEM); + + + INIT_LIST_HEAD(&req->list); + req->count = count; + req->entries = (struct mdss_rot_entry *) + ((void *)req + sizeof(struct mdss_rot_entry_container)); + req->flags = flags; + atomic_set(&req->pending_count, count); + + for (i = 0; i < count; i++) + req->entries[i].item = items[i]; + + return req; +} + +static int mdss_rotator_handle_request_common(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, + struct mdss_rot_entry_container *req, + struct mdp_rotation_item *items) +{ + int i, ret; + + mdss_rotator_free_competed_request(mgr, private); + + ret = mdss_rotator_add_request(mgr, private, req); + if (ret) { + pr_err("fail to add rotation request\n"); + mdss_rotator_remove_request(mgr, private, req); + return ret; + } + + for (i = 0; i < req->count; i++) + items[i].output.fence = + req->entries[i].item.output.fence; + + return ret; +} + +static int mdss_rotator_handle_request(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, unsigned long arg) +{ + struct mdp_rotation_request user_req; + struct mdp_rotation_item *items = NULL; + struct mdss_rot_entry_container *req = NULL; + int size, ret; + uint32_t req_count; + struct mdss_data_type *mdata = mdss_mdp_get_mdata(); + + if (mdata->handoff_pending) { + pr_err("Rotator request failed. Handoff pending\n"); + return -EPERM; + } + + if (mdss_get_sd_client_cnt()) { + pr_err("rot request not permitted during secure display session\n"); + return -EPERM; + } + + ret = copy_from_user(&user_req, (void __user *)arg, + sizeof(user_req)); + if (ret) { + pr_err("fail to copy rotation request\n"); + return ret; + } + + req_count = user_req.count; + if ((!req_count) || (req_count > MAX_LAYER_COUNT)) { + pr_err("invalid rotator req count :%d\n", req_count); + return -EINVAL; + } + + /* + * here, we make a copy of the items so that we can copy + * all the output fences to the client in one call. Otherwise, + * we will have to call multiple copy_to_user + */ + size = sizeof(struct mdp_rotation_item) * req_count; + items = kzalloc(size, GFP_KERNEL); + if (!items) { + pr_err("fail to allocate rotation items\n"); + return -ENOMEM; + } + ret = copy_from_user(items, user_req.list, size); + if (ret) { + pr_err("fail to copy rotation items\n"); + goto handle_request_err; + } + + req = mdss_rotator_req_init(mgr, items, user_req.count, user_req.flags); + if (IS_ERR_OR_NULL(req)) { + pr_err("fail to allocate rotation request\n"); + ret = PTR_ERR(req); + goto handle_request_err; + } + + mutex_lock(&mgr->lock); + + if (req->flags & MDSS_ROTATION_REQUEST_VALIDATE) { + ret = mdss_rotator_validate_request(mgr, private, req); + goto handle_request_err1; + } + + ret = mdss_rotator_handle_request_common(mgr, private, req, items); + if (ret) { + pr_err("fail to handle request\n"); + goto handle_request_err1; + } + + ret = copy_to_user(user_req.list, items, size); + if (ret) { + pr_err("fail to copy output fence to user\n"); + mdss_rotator_remove_request(mgr, private, req); + goto handle_request_err1; + } + + ret = mdss_rotator_install_fence_fd(req); + if (ret) { + pr_err("get_unused_fd_flags failed error:0x%x\n", ret); + mdss_rotator_remove_request(mgr, private, req); + goto handle_request_err1; + } + + mdss_rotator_queue_request(mgr, private, req); + + mutex_unlock(&mgr->lock); + + kfree(items); + return ret; + +handle_request_err1: + mutex_unlock(&mgr->lock); +handle_request_err: + kfree(items); + kfree(req); + return ret; +} + +static int mdss_rotator_open(struct inode *inode, struct file *file) +{ + struct mdss_rot_file_private *private; + + if (!rot_mgr) + return -ENODEV; + + if (atomic_read(&rot_mgr->device_suspended)) + return -EPERM; + + private = kzalloc(sizeof(*private), + GFP_KERNEL); + if (!private) + return -ENOMEM; + + mutex_init(&private->req_lock); + mutex_init(&private->perf_lock); + INIT_LIST_HEAD(&private->req_list); + INIT_LIST_HEAD(&private->perf_list); + INIT_LIST_HEAD(&private->list); + + mutex_lock(&rot_mgr->file_lock); + list_add(&private->list, &rot_mgr->file_list); + file->private_data = private; + private->file = file; + mutex_unlock(&rot_mgr->file_lock); + + return 0; +} + +static bool mdss_rotator_file_priv_allowed(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *priv) +{ + struct mdss_rot_file_private *_priv, *_priv_next; + bool ret = false; + + mutex_lock(&mgr->file_lock); + list_for_each_entry_safe(_priv, _priv_next, &mgr->file_list, list) { + if (_priv == priv) { + ret = true; + break; + } + } + mutex_unlock(&mgr->file_lock); + return ret; +} + +static int mdss_rotator_close(struct inode *inode, struct file *file) +{ + struct mdss_rot_file_private *private; + + if (!rot_mgr) + return -ENODEV; + + if (!file->private_data) + return -EINVAL; + + private = (struct mdss_rot_file_private *)file->private_data; + + if (!(mdss_rotator_file_priv_allowed(rot_mgr, private))) { + pr_err("Calling close with unrecognized rot_file_private\n"); + return -EINVAL; + } + + mdss_rotator_release_rotator_perf_session(rot_mgr, private); + + mutex_lock(&rot_mgr->file_lock); + list_del_init(&private->list); + kfree(private); + file->private_data = NULL; + mutex_unlock(&rot_mgr->file_lock); + + mdss_rotator_update_perf(rot_mgr); + return 0; +} + +#ifdef CONFIG_COMPAT +static int mdss_rotator_handle_request32(struct mdss_rot_mgr *mgr, + struct mdss_rot_file_private *private, unsigned long arg) +{ + struct mdp_rotation_request32 user_req32; + struct mdp_rotation_item *items = NULL; + struct mdss_rot_entry_container *req = NULL; + int size, ret; + uint32_t req_count; + + if (mdss_get_sd_client_cnt()) { + pr_err("rot request not permitted during secure display session\n"); + return -EPERM; + } + + ret = copy_from_user(&user_req32, (void __user *)arg, + sizeof(user_req32)); + if (ret) { + pr_err("fail to copy rotation request\n"); + return ret; + } + + req_count = user_req32.count; + if ((!req_count) || (req_count > MAX_LAYER_COUNT)) { + pr_err("invalid rotator req count :%d\n", req_count); + return -EINVAL; + } + + size = sizeof(struct mdp_rotation_item) * req_count; + items = kzalloc(size, GFP_KERNEL); + if (!items) { + pr_err("fail to allocate rotation items\n"); + return -ENOMEM; + } + ret = copy_from_user(items, compat_ptr(user_req32.list), size); + if (ret) { + pr_err("fail to copy rotation items\n"); + goto handle_request32_err; + } + + req = mdss_rotator_req_init(mgr, items, user_req32.count, + user_req32.flags); + if (IS_ERR_OR_NULL(req)) { + pr_err("fail to allocate rotation request\n"); + ret = PTR_ERR(req); + goto handle_request32_err; + } + + mutex_lock(&mgr->lock); + + if (req->flags & MDSS_ROTATION_REQUEST_VALIDATE) { + ret = mdss_rotator_validate_request(mgr, private, req); + goto handle_request32_err1; + } + + ret = mdss_rotator_handle_request_common(mgr, private, req, items); + if (ret) { + pr_err("fail to handle request\n"); + goto handle_request32_err1; + } + + ret = copy_to_user(compat_ptr(user_req32.list), items, size); + if (ret) { + pr_err("fail to copy output fence to user\n"); + mdss_rotator_remove_request(mgr, private, req); + goto handle_request32_err1; + } + + ret = mdss_rotator_install_fence_fd(req); + if (ret) { + pr_err("get_unused_fd_flags failed error:0x%x\n", ret); + mdss_rotator_remove_request(mgr, private, req); + goto handle_request32_err1; + } + + mdss_rotator_queue_request(mgr, private, req); + + mutex_unlock(&mgr->lock); + + kfree(items); + return ret; + +handle_request32_err1: + mutex_unlock(&mgr->lock); +handle_request32_err: + kfree(items); + kfree(req); + return ret; +} + +static unsigned int __do_compat_ioctl_rot(unsigned int cmd32) +{ + unsigned int cmd; + + switch (cmd32) { + case MDSS_ROTATION_REQUEST32: + cmd = MDSS_ROTATION_REQUEST; + break; + case MDSS_ROTATION_OPEN32: + cmd = MDSS_ROTATION_OPEN; + break; + case MDSS_ROTATION_CLOSE32: + cmd = MDSS_ROTATION_CLOSE; + break; + case MDSS_ROTATION_CONFIG32: + cmd = MDSS_ROTATION_CONFIG; + break; + default: + cmd = cmd32; + break; + } + + return cmd; +} + +static long mdss_rotator_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct mdss_rot_file_private *private; + int ret = -EINVAL; + + if (!rot_mgr) + return -ENODEV; + + if (atomic_read(&rot_mgr->device_suspended)) + return -EPERM; + + if (!file->private_data) + return -EINVAL; + + private = (struct mdss_rot_file_private *)file->private_data; + + if (!(mdss_rotator_file_priv_allowed(rot_mgr, private))) { + pr_err("Calling ioctl with unrecognized rot_file_private\n"); + return -EINVAL; + } + + cmd = __do_compat_ioctl_rot(cmd); + + switch (cmd) { + case MDSS_ROTATION_REQUEST: + ATRACE_BEGIN("rotator_request32"); + ret = mdss_rotator_handle_request32(rot_mgr, private, arg); + ATRACE_END("rotator_request32"); + break; + case MDSS_ROTATION_OPEN: + ret = mdss_rotator_open_session(rot_mgr, private, arg); + break; + case MDSS_ROTATION_CLOSE: + ret = mdss_rotator_close_session(rot_mgr, private, arg); + break; + case MDSS_ROTATION_CONFIG: + ret = mdss_rotator_config_session(rot_mgr, private, arg); + break; + default: + pr_err("unexpected IOCTL %d\n", cmd); + } + + if (ret) + pr_err("rotator ioctl=%d failed, err=%d\n", cmd, ret); + return ret; + +} +#endif + +static long mdss_rotator_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct mdss_rot_file_private *private; + int ret = -EINVAL; + + if (!rot_mgr) + return -ENODEV; + + if (atomic_read(&rot_mgr->device_suspended)) + return -EPERM; + + if (!file->private_data) + return -EINVAL; + + private = (struct mdss_rot_file_private *)file->private_data; + + if (!(mdss_rotator_file_priv_allowed(rot_mgr, private))) { + pr_err("Calling ioctl with unrecognized rot_file_private\n"); + return -EINVAL; + } + + switch (cmd) { + case MDSS_ROTATION_REQUEST: + ATRACE_BEGIN("rotator_request"); + ret = mdss_rotator_handle_request(rot_mgr, private, arg); + ATRACE_END("rotator_request"); + break; + case MDSS_ROTATION_OPEN: + ret = mdss_rotator_open_session(rot_mgr, private, arg); + break; + case MDSS_ROTATION_CLOSE: + ret = mdss_rotator_close_session(rot_mgr, private, arg); + break; + case MDSS_ROTATION_CONFIG: + ret = mdss_rotator_config_session(rot_mgr, private, arg); + break; + default: + pr_err("unexpected IOCTL %d\n", cmd); + } + + if (ret) + pr_err("rotator ioctl=%d failed, err=%d\n", cmd, ret); + return ret; +} + +static ssize_t caps_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t len = PAGE_SIZE; + int cnt = 0; + + if (!rot_mgr) + return cnt; + +#define SPRINT(fmt, ...) \ + (cnt += scnprintf(buf + cnt, len - cnt, fmt, ##__VA_ARGS__)) + + SPRINT("wb_count=%d\n", rot_mgr->queue_count); + SPRINT("downscale=%d\n", rot_mgr->has_downscale); + + return cnt; +} + +static DEVICE_ATTR_RO(caps); + +static struct attribute *mdss_rotator_fs_attrs[] = { + &dev_attr_caps.attr, + NULL +}; + +static struct attribute_group mdss_rotator_fs_attr_group = { + .attrs = mdss_rotator_fs_attrs +}; + +static const struct file_operations mdss_rotator_fops = { + .owner = THIS_MODULE, + .open = mdss_rotator_open, + .release = mdss_rotator_close, + .unlocked_ioctl = mdss_rotator_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = mdss_rotator_compat_ioctl, +#endif +}; + +static int mdss_rotator_parse_dt_bus(struct mdss_rot_mgr *mgr, + struct platform_device *dev) +{ + struct device_node *node; + int ret = 0, i; + bool register_bus_needed; + int usecases; + + mgr->data_bus.bus_scale_pdata = msm_bus_cl_get_pdata(dev); + if (IS_ERR_OR_NULL(mgr->data_bus.bus_scale_pdata)) { + ret = PTR_ERR(mgr->data_bus.bus_scale_pdata); + if (!ret) { + ret = -EINVAL; + pr_err("msm_bus_cl_get_pdata failed. ret=%d\n", ret); + mgr->data_bus.bus_scale_pdata = NULL; + } + } + + register_bus_needed = of_property_read_bool(dev->dev.of_node, + "qcom,mdss-has-reg-bus"); + if (register_bus_needed) { + node = of_get_child_by_name( + dev->dev.of_node, "qcom,mdss-rot-reg-bus"); + if (!node) { + mgr->reg_bus.bus_scale_pdata = &rot_reg_bus_scale_table; + usecases = mgr->reg_bus.bus_scale_pdata->num_usecases; + for (i = 0; i < usecases; i++) { + rot_reg_bus_usecases[i].num_paths = 1; + rot_reg_bus_usecases[i].vectors = + &rot_reg_bus_vectors[i]; + } + } else { + mgr->reg_bus.bus_scale_pdata = + msm_bus_pdata_from_node(dev, node); + if (IS_ERR_OR_NULL(mgr->reg_bus.bus_scale_pdata)) { + ret = PTR_ERR(mgr->reg_bus.bus_scale_pdata); + if (!ret) + ret = -EINVAL; + pr_err("reg_rot_bus failed rc=%d\n", ret); + mgr->reg_bus.bus_scale_pdata = NULL; + } + } + } + return ret; +} + +static int mdss_rotator_parse_dt(struct mdss_rot_mgr *mgr, + struct platform_device *dev) +{ + int ret = 0; + u32 data; + + ret = of_property_read_u32(dev->dev.of_node, + "qcom,mdss-wb-count", &data); + if (ret) { + pr_err("Error in device tree\n"); + return ret; + } + if (data > ROT_MAX_HW_BLOCKS) { + pr_err("Err, num of wb block (%d) larger than sw max %d\n", + data, ROT_MAX_HW_BLOCKS); + return -EINVAL; + } + + rot_mgr->queue_count = data; + rot_mgr->has_downscale = of_property_read_bool(dev->dev.of_node, + "qcom,mdss-has-downscale"); + rot_mgr->has_ubwc = of_property_read_bool(dev->dev.of_node, + "qcom,mdss-has-ubwc"); + + ret = mdss_rotator_parse_dt_bus(mgr, dev); + if (ret) + pr_err("Failed to parse bus data\n"); + + return ret; +} + +static void mdss_rotator_put_dt_vreg_data(struct device *dev, + struct dss_module_power *mp) +{ + if (!mp) { + DEV_ERR("%s: invalid input\n", __func__); + return; + } + + msm_dss_config_vreg(dev, mp->vreg_config, mp->num_vreg, 0); + mp->num_vreg = 0; +} + +static int mdss_rotator_get_dt_vreg_data(struct device *dev, + struct dss_module_power *mp) +{ + const char *st = NULL; + struct device_node *of_node = NULL; + int dt_vreg_total = 0; + int i; + int rc; + + if (!dev || !mp) { + DEV_ERR("%s: invalid input\n", __func__); + return -EINVAL; + } + + of_node = dev->of_node; + + dt_vreg_total = of_property_count_strings(of_node, "qcom,supply-names"); + if (dt_vreg_total < 0) { + DEV_ERR("%s: vreg not found. rc=%d\n", __func__, + dt_vreg_total); + return 0; + } + mp->num_vreg = dt_vreg_total; + mp->vreg_config = devm_kzalloc(dev, sizeof(struct dss_vreg) * + dt_vreg_total, GFP_KERNEL); + if (!mp->vreg_config) { + DEV_ERR("%s: can't alloc vreg mem\n", __func__); + return -ENOMEM; + } + + /* vreg-name */ + for (i = 0; i < dt_vreg_total; i++) { + rc = of_property_read_string_index(of_node, + "qcom,supply-names", i, &st); + if (rc) { + DEV_ERR("%s: error reading name. i=%d, rc=%d\n", + __func__, i, rc); + goto error; + } + snprintf(mp->vreg_config[i].vreg_name, 32, "%s", st); + } + msm_dss_config_vreg(dev, mp->vreg_config, mp->num_vreg, 1); + + for (i = 0; i < dt_vreg_total; i++) { + DEV_DBG("%s: %s min=%d, max=%d, enable=%d disable=%d\n", + __func__, + mp->vreg_config[i].vreg_name, + mp->vreg_config[i].min_voltage, + mp->vreg_config[i].max_voltage, + mp->vreg_config[i].load[DSS_REG_MODE_ENABLE], + mp->vreg_config[i].load[DSS_REG_MODE_DISABLE]); + } + return rc; + +error: + mp->num_vreg = 0; + return rc; +} + +static void mdss_rotator_bus_scale_unregister(struct mdss_rot_mgr *mgr) +{ + pr_debug("unregister bus_hdl=%x, reg_bus_hdl=%x\n", + mgr->data_bus.bus_hdl, mgr->reg_bus.bus_hdl); + + if (mgr->data_bus.bus_hdl) + msm_bus_scale_unregister_client(mgr->data_bus.bus_hdl); + + if (mgr->reg_bus.bus_hdl) + msm_bus_scale_unregister_client(mgr->reg_bus.bus_hdl); +} + +static int mdss_rotator_bus_scale_register(struct mdss_rot_mgr *mgr) +{ + if (!mgr->data_bus.bus_scale_pdata) { + pr_err("Scale table is NULL\n"); + return -EINVAL; + } + + mgr->data_bus.bus_hdl = + msm_bus_scale_register_client( + mgr->data_bus.bus_scale_pdata); + if (!mgr->data_bus.bus_hdl) { + pr_err("bus_client register failed\n"); + return -EINVAL; + } + pr_debug("registered bus_hdl=%x\n", mgr->data_bus.bus_hdl); + + if (mgr->reg_bus.bus_scale_pdata) { + mgr->reg_bus.bus_hdl = + msm_bus_scale_register_client( + mgr->reg_bus.bus_scale_pdata); + if (!mgr->reg_bus.bus_hdl) { + pr_err("register bus_client register failed\n"); + mdss_rotator_bus_scale_unregister(mgr); + return -EINVAL; + } + pr_debug("registered register bus_hdl=%x\n", + mgr->reg_bus.bus_hdl); + } + + return 0; +} + +static int mdss_rotator_clk_register(struct platform_device *pdev, + struct mdss_rot_mgr *mgr, char *clk_name, u32 clk_idx) +{ + struct clk *tmp; + + pr_debug("registered clk_reg\n"); + + if (clk_idx >= MDSS_CLK_ROTATOR_END_IDX) { + pr_err("invalid clk index %d\n", clk_idx); + return -EINVAL; + } + + if (mgr->rot_clk[clk_idx]) { + pr_err("Stomping on clk prev registered:%d\n", clk_idx); + return -EINVAL; + } + + tmp = devm_clk_get(&pdev->dev, clk_name); + if (IS_ERR(tmp)) { + pr_err("unable to get clk: %s\n", clk_name); + return PTR_ERR(tmp); + } + mgr->rot_clk[clk_idx] = tmp; + return 0; +} + +static int mdss_rotator_res_init(struct platform_device *pdev, + struct mdss_rot_mgr *mgr) +{ + int ret; + + ret = mdss_rotator_get_dt_vreg_data(&pdev->dev, &mgr->module_power); + if (ret) + return ret; + + ret = mdss_rotator_clk_register(pdev, mgr, + "iface_clk", MDSS_CLK_ROTATOR_AHB); + if (ret) + goto error; + + ret = mdss_rotator_clk_register(pdev, mgr, + "rot_core_clk", MDSS_CLK_ROTATOR_CORE); + if (ret) + goto error; + + ret = mdss_rotator_bus_scale_register(mgr); + if (ret) + goto error; + + return 0; +error: + mdss_rotator_put_dt_vreg_data(&pdev->dev, &mgr->module_power); + return ret; +} + +static int mdss_rotator_probe(struct platform_device *pdev) +{ + int ret; + + rot_mgr = devm_kzalloc(&pdev->dev, sizeof(struct mdss_rot_mgr), + GFP_KERNEL); + if (!rot_mgr) + return -ENOMEM; + + rot_mgr->pdev = pdev; + ret = mdss_rotator_parse_dt(rot_mgr, pdev); + if (ret) { + pr_err("fail to parse the dt\n"); + goto error_parse_dt; + } + + mutex_init(&rot_mgr->lock); + mutex_init(&rot_mgr->clk_lock); + mutex_init(&rot_mgr->bus_lock); + atomic_set(&rot_mgr->device_suspended, 0); + ret = mdss_rotator_init_queue(rot_mgr); + if (ret) { + pr_err("fail to init queue\n"); + goto error_get_dev_num; + } + + mutex_init(&rot_mgr->file_lock); + INIT_LIST_HEAD(&rot_mgr->file_list); + + platform_set_drvdata(pdev, rot_mgr); + + ret = alloc_chrdev_region(&rot_mgr->dev_num, 0, 1, DRIVER_NAME); + if (ret < 0) { + pr_err("alloc_chrdev_region failed ret = %d\n", ret); + goto error_get_dev_num; + } + + rot_mgr->class = class_create(THIS_MODULE, CLASS_NAME); + if (IS_ERR(rot_mgr->class)) { + ret = PTR_ERR(rot_mgr->class); + pr_err("couldn't create class rc = %d\n", ret); + goto error_class_create; + } + + rot_mgr->device = device_create(rot_mgr->class, NULL, + rot_mgr->dev_num, NULL, DRIVER_NAME); + if (IS_ERR(rot_mgr->device)) { + ret = PTR_ERR(rot_mgr->device); + pr_err("device_create failed %d\n", ret); + goto error_class_device_create; + } + + cdev_init(&rot_mgr->cdev, &mdss_rotator_fops); + ret = cdev_add(&rot_mgr->cdev, + MKDEV(MAJOR(rot_mgr->dev_num), 0), 1); + if (ret < 0) { + pr_err("cdev_add failed %d\n", ret); + goto error_cdev_add; + } + + ret = sysfs_create_group(&rot_mgr->device->kobj, + &mdss_rotator_fs_attr_group); + if (ret) + pr_err("unable to register rotator sysfs nodes\n"); + + ret = mdss_rotator_res_init(pdev, rot_mgr); + if (ret < 0) { + pr_err("res_init failed %d\n", ret); + goto error_res_init; + } + return 0; + +error_res_init: + cdev_del(&rot_mgr->cdev); +error_cdev_add: + device_destroy(rot_mgr->class, rot_mgr->dev_num); +error_class_device_create: + class_destroy(rot_mgr->class); +error_class_create: + unregister_chrdev_region(rot_mgr->dev_num, 1); +error_get_dev_num: + mdss_rotator_deinit_queue(rot_mgr); +error_parse_dt: + return ret; +} + +static int mdss_rotator_remove(struct platform_device *dev) +{ + struct mdss_rot_mgr *mgr; + + mgr = (struct mdss_rot_mgr *)platform_get_drvdata(dev); + if (!mgr) + return -ENODEV; + + sysfs_remove_group(&rot_mgr->device->kobj, &mdss_rotator_fs_attr_group); + + mdss_rotator_release_all(mgr); + + mdss_rotator_put_dt_vreg_data(&dev->dev, &mgr->module_power); + mdss_rotator_bus_scale_unregister(mgr); + cdev_del(&rot_mgr->cdev); + device_destroy(rot_mgr->class, rot_mgr->dev_num); + class_destroy(rot_mgr->class); + unregister_chrdev_region(rot_mgr->dev_num, 1); + + mdss_rotator_deinit_queue(rot_mgr); + return 0; +} + +static void mdss_rotator_suspend_cancel_rot_work(struct mdss_rot_mgr *mgr) +{ + struct mdss_rot_file_private *priv, *priv_next; + + mutex_lock(&mgr->file_lock); + list_for_each_entry_safe(priv, priv_next, &mgr->file_list, list) { + mdss_rotator_cancel_all_requests(mgr, priv); + } + mutex_unlock(&rot_mgr->file_lock); +} + +#if defined(CONFIG_PM) +static int mdss_rotator_suspend(struct platform_device *dev, pm_message_t state) +{ + struct mdss_rot_mgr *mgr; + + mgr = (struct mdss_rot_mgr *)platform_get_drvdata(dev); + if (!mgr) + return -ENODEV; + + atomic_inc(&mgr->device_suspended); + mdss_rotator_suspend_cancel_rot_work(mgr); + mdss_rotator_update_perf(mgr); + return 0; +} + +static int mdss_rotator_resume(struct platform_device *dev) +{ + struct mdss_rot_mgr *mgr; + + mgr = (struct mdss_rot_mgr *)platform_get_drvdata(dev); + if (!mgr) + return -ENODEV; + + atomic_dec(&mgr->device_suspended); + mdss_rotator_update_perf(mgr); + return 0; +} +#endif + +static const struct of_device_id mdss_rotator_dt_match[] = { + { .compatible = "qcom,mdss_rotator",}, + {} +}; + +MODULE_DEVICE_TABLE(of, mdss_rotator_dt_match); + +static struct platform_driver mdss_rotator_driver = { + .probe = mdss_rotator_probe, + .remove = mdss_rotator_remove, +#if defined(CONFIG_PM) + .suspend = mdss_rotator_suspend, + .resume = mdss_rotator_resume, +#endif + .driver = { + .name = "mdss_rotator", + .of_match_table = mdss_rotator_dt_match, + .pm = NULL, + } +}; + +static int __init mdss_rotator_init(void) +{ + return platform_driver_register(&mdss_rotator_driver); +} + +static void __exit mdss_rotator_exit(void) +{ + return platform_driver_unregister(&mdss_rotator_driver); +} + +module_init(mdss_rotator_init); +module_exit(mdss_rotator_exit); + +MODULE_DESCRIPTION("MSM Rotator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 709d4de11f40..fa7f4c61524d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -515,7 +515,7 @@ config SUNXI_WATCHDOG config COH901327_WATCHDOG bool "ST-Ericsson COH 901 327 watchdog" - depends on ARCH_U300 || (ARM && COMPILE_TEST) + depends on ARCH_U300 || (ARM && COMMON_CLK && COMPILE_TEST) default y if MACH_U300 select WATCHDOG_CORE help @@ -651,6 +651,7 @@ config MOXART_WDT config SIRFSOC_WATCHDOG tristate "SiRFSOC watchdog" + depends on HAS_IOMEM depends on ARCH_SIRF || COMPILE_TEST select WATCHDOG_CORE default y diff --git a/drivers/watchdog/mei_wdt.c b/drivers/watchdog/mei_wdt.c index 8023cf28657a..c862dd38b6f5 100644 --- a/drivers/watchdog/mei_wdt.c +++ b/drivers/watchdog/mei_wdt.c @@ -382,6 +382,7 @@ static int mei_wdt_register(struct mei_wdt *wdt) watchdog_set_drvdata(&wdt->wdd, wdt); watchdog_stop_on_reboot(&wdt->wdd); + watchdog_stop_on_unregister(&wdt->wdd); ret = watchdog_register_device(&wdt->wdd); if (ret) { diff --git a/drivers/watchdog/qcom-wdt.c b/drivers/watchdog/qcom-wdt.c index 780971318810..1a0005a8fadb 100644 --- a/drivers/watchdog/qcom-wdt.c +++ b/drivers/watchdog/qcom-wdt.c @@ -121,7 +121,7 @@ static int qcom_wdt_restart(struct watchdog_device *wdd, unsigned long action, */ wmb(); - msleep(150); + mdelay(150); return 0; } diff --git a/drivers/watchdog/sprd_wdt.c b/drivers/watchdog/sprd_wdt.c index b6c65afd3677..86cf93af951b 100644 --- a/drivers/watchdog/sprd_wdt.c +++ b/drivers/watchdog/sprd_wdt.c @@ -116,18 +116,6 @@ static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout, u32 tmr_step = timeout * SPRD_WDT_CNT_STEP; u32 prtmr_step = pretimeout * SPRD_WDT_CNT_STEP; - sprd_wdt_unlock(wdt->base); - writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & - SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH); - writel_relaxed((tmr_step & SPRD_WDT_LOW_VALUE_MASK), - wdt->base + SPRD_WDT_LOAD_LOW); - writel_relaxed((prtmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & - SPRD_WDT_LOW_VALUE_MASK, - wdt->base + SPRD_WDT_IRQ_LOAD_HIGH); - writel_relaxed(prtmr_step & SPRD_WDT_LOW_VALUE_MASK, - wdt->base + SPRD_WDT_IRQ_LOAD_LOW); - sprd_wdt_lock(wdt->base); - /* * Waiting the load value operation done, * it needs two or three RTC clock cycles. @@ -142,6 +130,19 @@ static int sprd_wdt_load_value(struct sprd_wdt *wdt, u32 timeout, if (delay_cnt >= SPRD_WDT_LOAD_TIMEOUT) return -EBUSY; + + sprd_wdt_unlock(wdt->base); + writel_relaxed((tmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & + SPRD_WDT_LOW_VALUE_MASK, wdt->base + SPRD_WDT_LOAD_HIGH); + writel_relaxed((tmr_step & SPRD_WDT_LOW_VALUE_MASK), + wdt->base + SPRD_WDT_LOAD_LOW); + writel_relaxed((prtmr_step >> SPRD_WDT_CNT_HIGH_SHIFT) & + SPRD_WDT_LOW_VALUE_MASK, + wdt->base + SPRD_WDT_IRQ_LOAD_HIGH); + writel_relaxed(prtmr_step & SPRD_WDT_LOW_VALUE_MASK, + wdt->base + SPRD_WDT_IRQ_LOAD_LOW); + sprd_wdt_lock(wdt->base); + return 0; } @@ -360,15 +361,10 @@ static int __maybe_unused sprd_wdt_pm_resume(struct device *dev) if (ret) return ret; - if (watchdog_active(&wdt->wdd)) { + if (watchdog_active(&wdt->wdd)) ret = sprd_wdt_start(&wdt->wdd); - if (ret) { - sprd_wdt_disable(wdt); - return ret; - } - } - return 0; + return ret; } static const struct dev_pm_ops sprd_wdt_pm_ops = { diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c index 8b1f37ffb65a..5c600a370650 100644 --- a/drivers/watchdog/watchdog_core.c +++ b/drivers/watchdog/watchdog_core.c @@ -246,15 +246,19 @@ static int __watchdog_register_device(struct watchdog_device *wdd) } if (test_bit(WDOG_STOP_ON_REBOOT, &wdd->status)) { - wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; - - ret = register_reboot_notifier(&wdd->reboot_nb); - if (ret) { - pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", - wdd->id, ret); - watchdog_dev_unregister(wdd); - ida_simple_remove(&watchdog_ida, id); - return ret; + if (!wdd->ops->stop) + pr_warn("watchdog%d: stop_on_reboot not supported\n", wdd->id); + else { + wdd->reboot_nb.notifier_call = watchdog_reboot_notifier; + + ret = register_reboot_notifier(&wdd->reboot_nb); + if (ret) { + pr_err("watchdog%d: Cannot register reboot notifier (%d)\n", + wdd->id, ret); + watchdog_dev_unregister(wdd); + ida_simple_remove(&watchdog_ida, id); + return ret; + } } } diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index b23edf64c2b2..76b766d14d02 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -686,7 +686,7 @@ static void __init balloon_add_region(unsigned long start_pfn, for (pfn = start_pfn; pfn < extra_pfn_end; pfn++) { page = pfn_to_page(pfn); - /* totalram_pages and totalhigh_pages do not + /* totalram_pages() and totalhigh_pages do not include the boot-time balloon extension, so don't subtract from it. */ __balloon_append(page); diff --git a/drivers/xen/events/events_2l.c b/drivers/xen/events/events_2l.c index f026624898e7..77cc80bcb479 100644 --- a/drivers/xen/events/events_2l.c +++ b/drivers/xen/events/events_2l.c @@ -47,6 +47,11 @@ static unsigned evtchn_2l_max_channels(void) return EVTCHN_2L_NR_CHANNELS; } +static void evtchn_2l_remove(evtchn_port_t evtchn, unsigned int cpu) +{ + clear_bit(evtchn, BM(per_cpu(cpu_evtchn_mask, cpu))); +} + static void evtchn_2l_bind_to_cpu(struct irq_info *info, unsigned cpu) { clear_bit(info->evtchn, BM(per_cpu(cpu_evtchn_mask, info->cpu))); @@ -71,12 +76,6 @@ static bool evtchn_2l_is_pending(unsigned port) return sync_test_bit(port, BM(&s->evtchn_pending[0])); } -static bool evtchn_2l_test_and_set_mask(unsigned port) -{ - struct shared_info *s = HYPERVISOR_shared_info; - return sync_test_and_set_bit(port, BM(&s->evtchn_mask[0])); -} - static void evtchn_2l_mask(unsigned port) { struct shared_info *s = HYPERVISOR_shared_info; @@ -354,18 +353,27 @@ static void evtchn_2l_resume(void) EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); } +static int evtchn_2l_percpu_deinit(unsigned int cpu) +{ + memset(per_cpu(cpu_evtchn_mask, cpu), 0, sizeof(xen_ulong_t) * + EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD); + + return 0; +} + static const struct evtchn_ops evtchn_ops_2l = { .max_channels = evtchn_2l_max_channels, .nr_channels = evtchn_2l_max_channels, + .remove = evtchn_2l_remove, .bind_to_cpu = evtchn_2l_bind_to_cpu, .clear_pending = evtchn_2l_clear_pending, .set_pending = evtchn_2l_set_pending, .is_pending = evtchn_2l_is_pending, - .test_and_set_mask = evtchn_2l_test_and_set_mask, .mask = evtchn_2l_mask, .unmask = evtchn_2l_unmask, .handle_events = evtchn_2l_handle_events, .resume = evtchn_2l_resume, + .percpu_deinit = evtchn_2l_percpu_deinit, }; void __init xen_evtchn_2l_init(void) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index aca845675279..b370144682ed 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -98,6 +98,7 @@ static DEFINE_RWLOCK(evtchn_rwlock); * evtchn_rwlock * IRQ-desc lock * percpu eoi_list_lock + * irq_info->lock */ static LIST_HEAD(xen_irq_list_head); @@ -219,6 +220,8 @@ static int xen_irq_info_common_setup(struct irq_info *info, info->irq = irq; info->evtchn = evtchn; info->cpu = cpu; + info->mask_reason = EVT_MASK_REASON_EXPLICIT; + raw_spin_lock_init(&info->lock); ret = set_evtchn_to_irq(evtchn, irq); if (ret < 0) @@ -285,6 +288,7 @@ static int xen_irq_info_pirq_setup(unsigned irq, static void xen_irq_info_cleanup(struct irq_info *info) { set_evtchn_to_irq(info->evtchn, -1); + xen_evtchn_port_remove(info->evtchn, info->cpu); info->evtchn = 0; } @@ -365,6 +369,34 @@ unsigned int cpu_from_evtchn(unsigned int evtchn) return ret; } +static void do_mask(struct irq_info *info, u8 reason) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&info->lock, flags); + + if (!info->mask_reason) + mask_evtchn(info->evtchn); + + info->mask_reason |= reason; + + raw_spin_unlock_irqrestore(&info->lock, flags); +} + +static void do_unmask(struct irq_info *info, u8 reason) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&info->lock, flags); + + info->mask_reason &= ~reason; + + if (!info->mask_reason) + unmask_evtchn(info->evtchn); + + raw_spin_unlock_irqrestore(&info->lock, flags); +} + #ifdef CONFIG_X86 static bool pirq_check_eoi_map(unsigned irq) { @@ -492,7 +524,7 @@ static void xen_irq_lateeoi_locked(struct irq_info *info, bool spurious) } info->eoi_time = 0; - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_EOI_PENDING); } static void xen_irq_lateeoi_worker(struct work_struct *work) @@ -661,6 +693,12 @@ static void xen_evtchn_close(unsigned int port) BUG(); } +static void event_handler_exit(struct irq_info *info) +{ + smp_store_release(&info->is_active, 0); + clear_evtchn(info->evtchn); +} + static void pirq_query_unmask(int irq) { struct physdev_irq_status_query irq_status; @@ -679,7 +717,8 @@ static void pirq_query_unmask(int irq) static void eoi_pirq(struct irq_data *data) { - int evtchn = evtchn_from_irq(data->irq); + struct irq_info *info = info_for_irq(data->irq); + int evtchn = info ? info->evtchn : 0; struct physdev_eoi eoi = { .irq = pirq_from_irq(data->irq) }; int rc = 0; @@ -688,16 +727,15 @@ static void eoi_pirq(struct irq_data *data) if (unlikely(irqd_is_setaffinity_pending(data)) && likely(!irqd_irq_disabled(data))) { - int masked = test_and_set_mask(evtchn); + do_mask(info, EVT_MASK_REASON_TEMPORARY); - clear_evtchn(evtchn); + event_handler_exit(info); irq_move_masked_irq(data); - if (!masked) - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_TEMPORARY); } else - clear_evtchn(evtchn); + event_handler_exit(info); if (pirq_needs_eoi(data->irq)) { rc = HYPERVISOR_physdev_op(PHYSDEVOP_eoi, &eoi); @@ -748,7 +786,8 @@ static unsigned int __startup_pirq(unsigned int irq) goto err; out: - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_EXPLICIT); + eoi_pirq(irq_get_irq_data(irq)); return 0; @@ -775,7 +814,7 @@ static void shutdown_pirq(struct irq_data *data) if (!VALID_EVTCHN(evtchn)) return; - mask_evtchn(evtchn); + do_mask(info, EVT_MASK_REASON_EXPLICIT); xen_evtchn_close(evtchn); xen_irq_info_cleanup(info); } @@ -1532,6 +1571,8 @@ void handle_irq_for_port(evtchn_port_t port, struct evtchn_loop_ctrl *ctrl) } info = info_for_irq(irq); + if (xchg_acquire(&info->is_active, 1)) + return; if (ctrl->defer_eoi) { info->eoi_cpu = smp_processor_id(); @@ -1634,10 +1675,10 @@ void rebind_evtchn_irq(int evtchn, int irq) } /* Rebind an evtchn so that it gets delivered to a specific cpu */ -static int xen_rebind_evtchn_to_cpu(int evtchn, unsigned int tcpu) +static int xen_rebind_evtchn_to_cpu(struct irq_info *info, unsigned int tcpu) { struct evtchn_bind_vcpu bind_vcpu; - int masked; + evtchn_port_t evtchn = info ? info->evtchn : 0; if (!VALID_EVTCHN(evtchn)) return -1; @@ -1653,7 +1694,7 @@ static int xen_rebind_evtchn_to_cpu(int evtchn, unsigned int tcpu) * Mask the event while changing the VCPU binding to prevent * it being delivered on an unexpected VCPU. */ - masked = test_and_set_mask(evtchn); + do_mask(info, EVT_MASK_REASON_TEMPORARY); /* * If this fails, it usually just indicates that we're dealing with a @@ -1663,8 +1704,7 @@ static int xen_rebind_evtchn_to_cpu(int evtchn, unsigned int tcpu) if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) bind_evtchn_to_cpu(evtchn, tcpu); - if (!masked) - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_TEMPORARY); return 0; } @@ -1673,7 +1713,7 @@ static int set_affinity_irq(struct irq_data *data, const struct cpumask *dest, bool force) { unsigned tcpu = cpumask_first_and(dest, cpu_online_mask); - int ret = xen_rebind_evtchn_to_cpu(evtchn_from_irq(data->irq), tcpu); + int ret = xen_rebind_evtchn_to_cpu(info_for_irq(data->irq), tcpu); if (!ret) irq_data_update_effective_affinity(data, cpumask_of(tcpu)); @@ -1692,39 +1732,41 @@ EXPORT_SYMBOL_GPL(xen_set_affinity_evtchn); static void enable_dynirq(struct irq_data *data) { - int evtchn = evtchn_from_irq(data->irq); + struct irq_info *info = info_for_irq(data->irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; if (VALID_EVTCHN(evtchn)) - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_EXPLICIT); } static void disable_dynirq(struct irq_data *data) { - int evtchn = evtchn_from_irq(data->irq); + struct irq_info *info = info_for_irq(data->irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; if (VALID_EVTCHN(evtchn)) - mask_evtchn(evtchn); + do_mask(info, EVT_MASK_REASON_EXPLICIT); } static void ack_dynirq(struct irq_data *data) { - int evtchn = evtchn_from_irq(data->irq); + struct irq_info *info = info_for_irq(data->irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; if (!VALID_EVTCHN(evtchn)) return; if (unlikely(irqd_is_setaffinity_pending(data)) && likely(!irqd_irq_disabled(data))) { - int masked = test_and_set_mask(evtchn); + do_mask(info, EVT_MASK_REASON_TEMPORARY); - clear_evtchn(evtchn); + event_handler_exit(info); irq_move_masked_irq(data); - if (!masked) - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_TEMPORARY); } else - clear_evtchn(evtchn); + event_handler_exit(info); } static void mask_ack_dynirq(struct irq_data *data) @@ -1733,18 +1775,39 @@ static void mask_ack_dynirq(struct irq_data *data) ack_dynirq(data); } +static void lateeoi_ack_dynirq(struct irq_data *data) +{ + struct irq_info *info = info_for_irq(data->irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; + + if (VALID_EVTCHN(evtchn)) { + do_mask(info, EVT_MASK_REASON_EOI_PENDING); + ack_dynirq(data); + } +} + +static void lateeoi_mask_ack_dynirq(struct irq_data *data) +{ + struct irq_info *info = info_for_irq(data->irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; + + if (VALID_EVTCHN(evtchn)) { + do_mask(info, EVT_MASK_REASON_EXPLICIT); + ack_dynirq(data); + } +} + static int retrigger_dynirq(struct irq_data *data) { - unsigned int evtchn = evtchn_from_irq(data->irq); - int masked; + struct irq_info *info = info_for_irq(data->irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; if (!VALID_EVTCHN(evtchn)) return 0; - masked = test_and_set_mask(evtchn); + do_mask(info, EVT_MASK_REASON_TEMPORARY); set_evtchn(evtchn); - if (!masked) - unmask_evtchn(evtchn); + do_unmask(info, EVT_MASK_REASON_TEMPORARY); return 1; } @@ -1839,10 +1902,11 @@ static void restore_cpu_ipis(unsigned int cpu) /* Clear an irq's pending state, in preparation for polling on it */ void xen_clear_irq_pending(int irq) { - int evtchn = evtchn_from_irq(irq); + struct irq_info *info = info_for_irq(irq); + evtchn_port_t evtchn = info ? info->evtchn : 0; if (VALID_EVTCHN(evtchn)) - clear_evtchn(evtchn); + event_handler_exit(info); } EXPORT_SYMBOL(xen_clear_irq_pending); void xen_set_irq_pending(int irq) @@ -1950,8 +2014,8 @@ static struct irq_chip xen_lateeoi_chip __read_mostly = { .irq_mask = disable_dynirq, .irq_unmask = enable_dynirq, - .irq_ack = mask_ack_dynirq, - .irq_mask_ack = mask_ack_dynirq, + .irq_ack = lateeoi_ack_dynirq, + .irq_mask_ack = lateeoi_mask_ack_dynirq, .irq_set_affinity = set_affinity_irq, .irq_retrigger = retrigger_dynirq, @@ -1987,16 +2051,6 @@ static struct irq_chip xen_percpu_chip __read_mostly = { .irq_ack = ack_dynirq, }; -int xen_set_callback_via(uint64_t via) -{ - struct xen_hvm_param a; - a.domid = DOMID_SELF; - a.index = HVM_PARAM_CALLBACK_IRQ; - a.value = via; - return HYPERVISOR_hvm_op(HVMOP_set_param, &a); -} -EXPORT_SYMBOL_GPL(xen_set_callback_via); - #ifdef CONFIG_XEN_PVHVM /* Vector callbacks are better than PCI interrupts to receive event * channel notifications because we can receive vector callbacks on any diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c index 33462521bfd0..360a7f8cdf75 100644 --- a/drivers/xen/events/events_fifo.c +++ b/drivers/xen/events/events_fifo.c @@ -209,12 +209,6 @@ static bool evtchn_fifo_is_pending(unsigned port) return sync_test_bit(EVTCHN_FIFO_BIT(PENDING, word), BM(word)); } -static bool evtchn_fifo_test_and_set_mask(unsigned port) -{ - event_word_t *word = event_word_from_port(port); - return sync_test_and_set_bit(EVTCHN_FIFO_BIT(MASKED, word), BM(word)); -} - static void evtchn_fifo_mask(unsigned port) { event_word_t *word = event_word_from_port(port); @@ -420,7 +414,6 @@ static const struct evtchn_ops evtchn_ops_fifo = { .clear_pending = evtchn_fifo_clear_pending, .set_pending = evtchn_fifo_set_pending, .is_pending = evtchn_fifo_is_pending, - .test_and_set_mask = evtchn_fifo_test_and_set_mask, .mask = evtchn_fifo_mask, .unmask = evtchn_fifo_unmask, .handle_events = evtchn_fifo_handle_events, diff --git a/drivers/xen/events/events_internal.h b/drivers/xen/events/events_internal.h index b9b4f5919893..cc37b711491c 100644 --- a/drivers/xen/events/events_internal.h +++ b/drivers/xen/events/events_internal.h @@ -35,13 +35,19 @@ struct irq_info { struct list_head eoi_list; short refcnt; short spurious_cnt; - enum xen_irq_type type; /* type */ + short type; /* type */ + u8 mask_reason; /* Why is event channel masked */ +#define EVT_MASK_REASON_EXPLICIT 0x01 +#define EVT_MASK_REASON_TEMPORARY 0x02 +#define EVT_MASK_REASON_EOI_PENDING 0x04 + u8 is_active; /* Is event just being handled? */ unsigned irq; unsigned int evtchn; /* event channel */ unsigned short cpu; /* cpu bound */ unsigned short eoi_cpu; /* EOI must happen on this cpu */ unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */ u64 eoi_time; /* Time in jiffies when to EOI. */ + raw_spinlock_t lock; union { unsigned short virq; @@ -67,12 +73,12 @@ struct evtchn_ops { unsigned (*nr_channels)(void); int (*setup)(struct irq_info *info); + void (*remove)(evtchn_port_t port, unsigned int cpu); void (*bind_to_cpu)(struct irq_info *info, unsigned cpu); void (*clear_pending)(unsigned port); void (*set_pending)(unsigned port); bool (*is_pending)(unsigned port); - bool (*test_and_set_mask)(unsigned port); void (*mask)(unsigned port); void (*unmask)(unsigned port); @@ -109,6 +115,13 @@ static inline int xen_evtchn_port_setup(struct irq_info *info) return 0; } +static inline void xen_evtchn_port_remove(evtchn_port_t evtchn, + unsigned int cpu) +{ + if (evtchn_ops->remove) + evtchn_ops->remove(evtchn, cpu); +} + static inline void xen_evtchn_port_bind_to_cpu(struct irq_info *info, unsigned cpu) { @@ -130,11 +143,6 @@ static inline bool test_evtchn(unsigned port) return evtchn_ops->is_pending(port); } -static inline bool test_and_set_mask(unsigned port) -{ - return evtchn_ops->test_and_set_mask(port); -} - static inline void mask_evtchn(unsigned port) { return evtchn_ops->mask(port); diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 9d8e02cfd480..e519063e421e 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -323,44 +323,47 @@ int gntdev_map_grant_pages(struct gntdev_grant_map *map) * to the kernel linear addresses of the struct pages. * These ptes are completely different from the user ptes dealt * with find_grant_ptes. + * Note that GNTMAP_device_map isn't needed here: The + * dev_bus_addr output field gets consumed only from ->map_ops, + * and by not requesting it when mapping we also avoid needing + * to mirror dev_bus_addr into ->unmap_ops (and holding an extra + * reference to the page in the hypervisor). */ + unsigned int flags = (map->flags & ~GNTMAP_device_map) | + GNTMAP_host_map; + for (i = 0; i < map->count; i++) { unsigned long address = (unsigned long) pfn_to_kaddr(page_to_pfn(map->pages[i])); BUG_ON(PageHighMem(map->pages[i])); - gnttab_set_map_op(&map->kmap_ops[i], address, - map->flags | GNTMAP_host_map, + gnttab_set_map_op(&map->kmap_ops[i], address, flags, map->grants[i].ref, map->grants[i].domid); gnttab_set_unmap_op(&map->kunmap_ops[i], address, - map->flags | GNTMAP_host_map, -1); + flags, -1); } } pr_debug("map %d+%d\n", map->index, map->count); err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL, map->pages, map->count); - if (err) - return err; for (i = 0; i < map->count; i++) { - if (map->map_ops[i].status) { + if (map->map_ops[i].status == GNTST_okay) + map->unmap_ops[i].handle = map->map_ops[i].handle; + else if (!err) err = -EINVAL; - continue; - } - map->unmap_ops[i].handle = map->map_ops[i].handle; - if (use_ptemod) - map->kunmap_ops[i].handle = map->kmap_ops[i].handle; -#ifdef CONFIG_XEN_GRANT_DMA_ALLOC - else if (map->dma_vaddr) { - unsigned long bfn; + if (map->flags & GNTMAP_device_map) + map->unmap_ops[i].dev_bus_addr = map->map_ops[i].dev_bus_addr; - bfn = pfn_to_bfn(page_to_pfn(map->pages[i])); - map->unmap_ops[i].dev_bus_addr = __pfn_to_phys(bfn); + if (use_ptemod) { + if (map->kmap_ops[i].status == GNTST_okay) + map->kunmap_ops[i].handle = map->kmap_ops[i].handle; + else if (!err) + err = -EINVAL; } -#endif } return err; } @@ -842,17 +845,18 @@ struct gntdev_copy_batch { s16 __user *status[GNTDEV_COPY_BATCH]; unsigned int nr_ops; unsigned int nr_pages; + bool writeable; }; static int gntdev_get_page(struct gntdev_copy_batch *batch, void __user *virt, - bool writeable, unsigned long *gfn) + unsigned long *gfn) { unsigned long addr = (unsigned long)virt; struct page *page; unsigned long xen_pfn; int ret; - ret = get_user_pages_fast(addr, 1, writeable, &page); + ret = get_user_pages_fast(addr, 1, batch->writeable, &page); if (ret < 0) return ret; @@ -868,9 +872,13 @@ static void gntdev_put_pages(struct gntdev_copy_batch *batch) { unsigned int i; - for (i = 0; i < batch->nr_pages; i++) + for (i = 0; i < batch->nr_pages; i++) { + if (batch->writeable && !PageDirty(batch->pages[i])) + set_page_dirty_lock(batch->pages[i]); put_page(batch->pages[i]); + } batch->nr_pages = 0; + batch->writeable = false; } static int gntdev_copy(struct gntdev_copy_batch *batch) @@ -959,8 +967,9 @@ static int gntdev_grant_copy_seg(struct gntdev_copy_batch *batch, virt = seg->source.virt + copied; off = (unsigned long)virt & ~XEN_PAGE_MASK; len = min(len, (size_t)XEN_PAGE_SIZE - off); + batch->writeable = false; - ret = gntdev_get_page(batch, virt, false, &gfn); + ret = gntdev_get_page(batch, virt, &gfn); if (ret < 0) return ret; @@ -978,8 +987,9 @@ static int gntdev_grant_copy_seg(struct gntdev_copy_batch *batch, virt = seg->dest.virt + copied; off = (unsigned long)virt & ~XEN_PAGE_MASK; len = min(len, (size_t)XEN_PAGE_SIZE - off); + batch->writeable = true; - ret = gntdev_get_page(batch, virt, true, &gfn); + ret = gntdev_get_page(batch, virt, &gfn); if (ret < 0) return ret; diff --git a/drivers/xen/platform-pci.c b/drivers/xen/platform-pci.c index 5d7dcad0b0a0..4cec8146609a 100644 --- a/drivers/xen/platform-pci.c +++ b/drivers/xen/platform-pci.c @@ -162,7 +162,6 @@ static int platform_pci_probe(struct pci_dev *pdev, ret = gnttab_init(); if (ret) goto grant_out; - xenbus_probe(NULL); return 0; grant_out: gnttab_free_auto_xlat_frames(); diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 7e6e682104dc..a8486432be05 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -743,14 +743,15 @@ static int remap_pfn_fn(pte_t *ptep, pgtable_t token, unsigned long addr, return 0; } -static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata) +static long privcmd_ioctl_mmap_resource(struct file *file, + struct privcmd_mmap_resource __user *udata) { struct privcmd_data *data = file->private_data; struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct privcmd_mmap_resource kdata; xen_pfn_t *pfns = NULL; - struct xen_mem_acquire_resource xdata; + struct xen_mem_acquire_resource xdata = { }; int rc; if (copy_from_user(&kdata, udata, sizeof(kdata))) @@ -760,6 +761,22 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata) if (data->domid != DOMID_INVALID && data->domid != kdata.dom) return -EPERM; + /* Both fields must be set or unset */ + if (!!kdata.addr != !!kdata.num) + return -EINVAL; + + xdata.domid = kdata.dom; + xdata.type = kdata.type; + xdata.id = kdata.id; + + if (!kdata.addr && !kdata.num) { + /* Query the size of the resource. */ + rc = HYPERVISOR_memory_op(XENMEM_acquire_resource, &xdata); + if (rc) + return rc; + return __put_user(xdata.nr_frames, &udata->num); + } + down_write(&mm->mmap_sem); vma = find_vma(mm, kdata.addr); @@ -793,10 +810,6 @@ static long privcmd_ioctl_mmap_resource(struct file *file, void __user *udata) } else vma->vm_private_data = PRIV_VMA_LOCKED; - memset(&xdata, 0, sizeof(xdata)); - xdata.domid = kdata.dom; - xdata.type = kdata.type; - xdata.id = kdata.id; xdata.frame = kdata.idx; xdata.nr_frames = kdata.num; set_xen_guest_handle(xdata.frame_list, pfns); diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index 3bbed47da3fa..1e2a996c7515 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c @@ -688,7 +688,7 @@ static int xen_pcibk_xenbus_probe(struct xenbus_device *dev, /* watch the backend node for backend configuration information */ err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch, - xen_pcibk_be_watch); + NULL, xen_pcibk_be_watch); if (err) goto out; diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 1abc0a55b8d9..614d067ffe12 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -422,12 +422,12 @@ static int scsiback_gnttab_data_map_batch(struct gnttab_map_grant_ref *map, return 0; err = gnttab_map_refs(map, NULL, pg, cnt); - BUG_ON(err); for (i = 0; i < cnt; i++) { if (unlikely(map[i].status != GNTST_okay)) { pr_err("invalid buffer -- could not remap it\n"); map[i].handle = SCSIBACK_INVALID_HANDLE; - err = -ENOMEM; + if (!err) + err = -ENOMEM; } else { get_page(pg[i]); } diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c index 55988b8418ee..bf5c7a48a457 100644 --- a/drivers/xen/xen-selfballoon.c +++ b/drivers/xen/xen-selfballoon.c @@ -189,7 +189,7 @@ static void selfballoon_process(struct work_struct *work) bool reset_timer = false; if (xen_selfballooning_enabled) { - cur_pages = totalram_pages; + cur_pages = totalram_pages(); tgt_pages = cur_pages; /* default is no change */ goal_pages = vm_memory_committed() + totalreserve_pages + @@ -227,7 +227,7 @@ static void selfballoon_process(struct work_struct *work) if (tgt_pages < floor_pages) tgt_pages = floor_pages; balloon_set_new_target(tgt_pages + - balloon_stats.current_pages - totalram_pages); + balloon_stats.current_pages - totalram_pages()); reset_timer = true; } #ifdef CONFIG_FRONTSWAP @@ -569,7 +569,7 @@ int xen_selfballoon_init(bool use_selfballooning, bool use_frontswap_selfshrink) * much more reliably and response faster in some cases. */ if (!selfballoon_reserved_mb) { - reserve_pages = totalram_pages / 10; + reserve_pages = totalram_pages() / 10; selfballoon_reserved_mb = PAGES2MB(reserve_pages); } schedule_delayed_work(&selfballoon_worker, selfballoon_interval * HZ); diff --git a/drivers/xen/xenbus/xenbus.h b/drivers/xen/xenbus/xenbus.h index d75a2385b37c..88516a8a9f93 100644 --- a/drivers/xen/xenbus/xenbus.h +++ b/drivers/xen/xenbus/xenbus.h @@ -44,6 +44,8 @@ struct xen_bus_type { int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename); int (*probe)(struct xen_bus_type *bus, const char *type, const char *dir); + bool (*otherend_will_handle)(struct xenbus_watch *watch, + const char *path, const char *token); void (*otherend_changed)(struct xenbus_watch *watch, const char *path, const char *token); struct bus_type bus; diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index f7b553faadb1..e35bb6b87449 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -114,18 +114,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate); */ int xenbus_watch_path(struct xenbus_device *dev, const char *path, struct xenbus_watch *watch, + bool (*will_handle)(struct xenbus_watch *, + const char *, const char *), void (*callback)(struct xenbus_watch *, const char *, const char *)) { int err; watch->node = path; + watch->will_handle = will_handle; watch->callback = callback; err = register_xenbus_watch(watch); if (err) { watch->node = NULL; + watch->will_handle = NULL; watch->callback = NULL; xenbus_dev_fatal(dev, err, "adding watch on %s", path); } @@ -152,6 +156,8 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path); */ int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch, + bool (*will_handle)(struct xenbus_watch *, + const char *, const char *), void (*callback)(struct xenbus_watch *, const char *, const char *), const char *pathfmt, ...) @@ -168,7 +174,7 @@ int xenbus_watch_pathfmt(struct xenbus_device *dev, xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch"); return -ENOMEM; } - err = xenbus_watch_path(dev, path, watch, callback); + err = xenbus_watch_path(dev, path, watch, will_handle, callback); if (err) kfree(path); diff --git a/drivers/xen/xenbus/xenbus_comms.c b/drivers/xen/xenbus/xenbus_comms.c index eb5151fc8efa..e5fda0256feb 100644 --- a/drivers/xen/xenbus/xenbus_comms.c +++ b/drivers/xen/xenbus/xenbus_comms.c @@ -57,16 +57,8 @@ DEFINE_MUTEX(xs_response_mutex); static int xenbus_irq; static struct task_struct *xenbus_task; -static DECLARE_WORK(probe_work, xenbus_probe); - - static irqreturn_t wake_waiting(int irq, void *unused) { - if (unlikely(xenstored_ready == 0)) { - xenstored_ready = 1; - schedule_work(&probe_work); - } - wake_up(&xb_waitq); return IRQ_HANDLED; } diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 5b471889d723..652894d61967 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c @@ -136,6 +136,7 @@ static int watch_otherend(struct xenbus_device *dev) container_of(dev->dev.bus, struct xen_bus_type, bus); return xenbus_watch_pathfmt(dev, &dev->otherend_watch, + bus->otherend_will_handle, bus->otherend_changed, "%s/%s", dev->otherend, "state"); } @@ -682,29 +683,107 @@ void unregister_xenstore_notifier(struct notifier_block *nb) } EXPORT_SYMBOL_GPL(unregister_xenstore_notifier); -void xenbus_probe(struct work_struct *unused) +static void xenbus_probe(void) { xenstored_ready = 1; + /* + * In the HVM case, xenbus_init() deferred its call to + * xs_init() in case callbacks were not operational yet. + * So do it now. + */ + if (xen_store_domain_type == XS_HVM) + xs_init(); + /* Notify others that xenstore is up */ blocking_notifier_call_chain(&xenstore_chain, 0, NULL); } -EXPORT_SYMBOL_GPL(xenbus_probe); -static int __init xenbus_probe_initcall(void) +/* + * Returns true when XenStore init must be deferred in order to + * allow the PCI platform device to be initialised, before we + * can actually have event channel interrupts working. + */ +static bool xs_hvm_defer_init_for_callback(void) { - if (!xen_domain()) - return -ENODEV; +#ifdef CONFIG_XEN_PVHVM + return xen_store_domain_type == XS_HVM && + !xen_have_vector_callback; +#else + return false; +#endif +} - if (xen_initial_domain() || xen_hvm_domain()) - return 0; +static int xenbus_probe_thread(void *unused) +{ + DEFINE_WAIT(w); - xenbus_probe(NULL); + /* + * We actually just want to wait for *any* trigger of xb_waitq, + * and run xenbus_probe() the moment it occurs. + */ + prepare_to_wait(&xb_waitq, &w, TASK_INTERRUPTIBLE); + schedule(); + finish_wait(&xb_waitq, &w); + + DPRINTK("probing"); + xenbus_probe(); return 0; } +static int __init xenbus_probe_initcall(void) +{ + /* + * Probe XenBus here in the XS_PV case, and also XS_HVM unless we + * need to wait for the platform PCI device to come up. + */ + if (xen_store_domain_type == XS_PV || + (xen_store_domain_type == XS_HVM && + !xs_hvm_defer_init_for_callback())) + xenbus_probe(); + + /* + * For XS_LOCAL, spawn a thread which will wait for xenstored + * or a xenstore-stubdom to be started, then probe. It will be + * triggered when communication starts happening, by waiting + * on xb_waitq. + */ + if (xen_store_domain_type == XS_LOCAL) { + struct task_struct *probe_task; + + probe_task = kthread_run(xenbus_probe_thread, NULL, + "xenbus_probe"); + if (IS_ERR(probe_task)) + return PTR_ERR(probe_task); + } + return 0; +} device_initcall(xenbus_probe_initcall); +int xen_set_callback_via(uint64_t via) +{ + struct xen_hvm_param a; + int ret; + + a.domid = DOMID_SELF; + a.index = HVM_PARAM_CALLBACK_IRQ; + a.value = via; + + ret = HYPERVISOR_hvm_op(HVMOP_set_param, &a); + if (ret) + return ret; + + /* + * If xenbus_probe_initcall() deferred the xenbus_probe() + * due to the callback not functioning yet, we can do it now. + */ + if (!xenstored_ready && xs_hvm_defer_init_for_callback()) + xenbus_probe(); + + return ret; +} +EXPORT_SYMBOL_GPL(xen_set_callback_via); + /* Set up event channel for xenstored which is run as a local process * (this is normally used only in dom0) */ @@ -817,11 +896,17 @@ static int __init xenbus_init(void) break; } - /* Initialize the interface to xenstore. */ - err = xs_init(); - if (err) { - pr_warn("Error initializing xenstore comms: %i\n", err); - goto out_error; + /* + * HVM domains may not have a functional callback yet. In that + * case let xs_init() be called from xenbus_probe(), which will + * get invoked at an appropriate time. + */ + if (xen_store_domain_type != XS_HVM) { + err = xs_init(); + if (err) { + pr_warn("Error initializing xenstore comms: %i\n", err); + goto out_error; + } } if ((xen_store_domain_type != XS_LOCAL) && diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index b0bed4faf44c..4bb603051d5b 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c @@ -180,6 +180,12 @@ static int xenbus_probe_backend(struct xen_bus_type *bus, const char *type, return err; } +static bool frontend_will_handle(struct xenbus_watch *watch, + const char *path, const char *token) +{ + return watch->nr_pending == 0; +} + static void frontend_changed(struct xenbus_watch *watch, const char *path, const char *token) { @@ -191,6 +197,7 @@ static struct xen_bus_type xenbus_backend = { .levels = 3, /* backend/type// */ .get_bus_id = backend_bus_id, .probe = xenbus_probe_backend, + .otherend_will_handle = frontend_will_handle, .otherend_changed = frontend_changed, .bus = { .name = "xen-backend", diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index 3a06eb699f33..12e02eb01f59 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -705,9 +705,13 @@ int xs_watch_msg(struct xs_watch_event *event) spin_lock(&watches_lock); event->handle = find_watch(event->token); - if (event->handle != NULL) { + if (event->handle != NULL && + (!event->handle->will_handle || + event->handle->will_handle(event->handle, + event->path, event->token))) { spin_lock(&watch_events_lock); list_add_tail(&event->list, &watch_events); + event->handle->nr_pending++; wake_up(&watch_events_waitq); spin_unlock(&watch_events_lock); } else @@ -765,6 +769,8 @@ int register_xenbus_watch(struct xenbus_watch *watch) sprintf(token, "%lX", (long)watch); + watch->nr_pending = 0; + down_read(&xs_watch_rwsem); spin_lock(&watches_lock); @@ -814,11 +820,14 @@ void unregister_xenbus_watch(struct xenbus_watch *watch) /* Cancel pending watch events. */ spin_lock(&watch_events_lock); - list_for_each_entry_safe(event, tmp, &watch_events, list) { - if (event->handle != watch) - continue; - list_del(&event->list); - kfree(event); + if (watch->nr_pending) { + list_for_each_entry_safe(event, tmp, &watch_events, list) { + if (event->handle != watch) + continue; + list_del(&event->list); + kfree(event); + } + watch->nr_pending = 0; } spin_unlock(&watch_events_lock); @@ -865,7 +874,6 @@ void xs_suspend_cancel(void) static int xenwatch_thread(void *unused) { - struct list_head *ent; struct xs_watch_event *event; xenwatch_pid = current->pid; @@ -880,13 +888,15 @@ static int xenwatch_thread(void *unused) mutex_lock(&xenwatch_mutex); spin_lock(&watch_events_lock); - ent = watch_events.next; - if (ent != &watch_events) - list_del(ent); + event = list_first_entry_or_null(&watch_events, + struct xs_watch_event, list); + if (event) { + list_del(&event->list); + event->handle->nr_pending--; + } spin_unlock(&watch_events_lock); - if (ent != &watch_events) { - event = list_entry(ent, struct xs_watch_event, list); + if (event) { event->handle->callback(event->handle, event->path, event->token); kfree(event); diff --git a/fs/affs/namei.c b/fs/affs/namei.c index 41c5749f4db7..5400a876d73f 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -460,8 +460,10 @@ affs_xrename(struct inode *old_dir, struct dentry *old_dentry, return -EIO; bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino); - if (!bh_new) + if (!bh_new) { + affs_brelse(bh_old); return -EIO; + } /* Remove old header from its parent directory. */ affs_lock_dir(old_dir); diff --git a/fs/afs/main.c b/fs/afs/main.c index 107427688edd..8ecb127be63f 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c @@ -190,7 +190,7 @@ static int __init afs_init(void) goto error_cache; #endif - ret = register_pernet_subsys(&afs_net_ops); + ret = register_pernet_device(&afs_net_ops); if (ret < 0) goto error_net; @@ -210,7 +210,7 @@ static int __init afs_init(void) error_proc: afs_fs_exit(); error_fs: - unregister_pernet_subsys(&afs_net_ops); + unregister_pernet_device(&afs_net_ops); error_net: #ifdef CONFIG_AFS_FSCACHE fscache_unregister_netfs(&afs_cache_netfs); @@ -241,7 +241,7 @@ static void __exit afs_exit(void) proc_remove(afs_proc_symlink); afs_fs_exit(); - unregister_pernet_subsys(&afs_net_ops); + unregister_pernet_device(&afs_net_ops); #ifdef CONFIG_AFS_FSCACHE fscache_unregister_netfs(&afs_cache_netfs); #endif diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 975dd0dbc252..6e6400489298 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -161,6 +161,25 @@ static int padzero(unsigned long elf_bss) #define ELF_BASE_PLATFORM NULL #endif +/* + * Use get_random_int() to implement AT_RANDOM while avoiding depletion + * of the entropy pool. + */ +static void get_atrandom_bytes(unsigned char *buf, size_t nbytes) +{ + unsigned char *p = buf; + + while (nbytes) { + unsigned int random_variable; + size_t chunk = min(nbytes, sizeof(random_variable)); + + random_variable = get_random_int(); + memcpy(p, &random_variable, chunk); + p += chunk; + nbytes -= chunk; + } +} + static int create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, unsigned long load_addr, unsigned long interp_load_addr) @@ -220,7 +239,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, /* * Generate 16 random bytes for userspace PRNG seeding. */ - get_random_bytes(k_rand_bytes, sizeof(k_rand_bytes)); + get_atrandom_bytes(k_rand_bytes, sizeof(k_rand_bytes)); u_rand_bytes = (elf_addr_t __user *) STACK_ALLOC(p, sizeof(k_rand_bytes)); if (__copy_to_user(u_rand_bytes, k_rand_bytes, sizeof(k_rand_bytes))) @@ -692,7 +711,8 @@ static int load_elf_binary(struct linux_binprm *bprm) struct file *interpreter = NULL; /* to shut gcc up */ unsigned long load_addr = 0, load_bias = 0; int load_addr_set = 0; - char * elf_interpreter = NULL; + char elf_interpreter[PATH_MAX] __aligned(8); + bool interp_present = false; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; unsigned long elf_bss, elf_brk; @@ -707,34 +727,28 @@ static int load_elf_binary(struct linux_binprm *bprm) struct { struct elfhdr elf_ex; struct elfhdr interp_elf_ex; - } *loc; + } loc; struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE; loff_t pos; - loc = kmalloc(sizeof(*loc), GFP_KERNEL); - if (!loc) { - retval = -ENOMEM; - goto out_ret; - } - /* Get the exec-header */ - loc->elf_ex = *((struct elfhdr *)bprm->buf); + loc.elf_ex = *((struct elfhdr *)bprm->buf); retval = -ENOEXEC; /* First of all, some simple consistency checks */ - if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0) + if (memcmp(loc.elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out; - if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN) + if (loc.elf_ex.e_type != ET_EXEC && loc.elf_ex.e_type != ET_DYN) goto out; - if (!elf_check_arch(&loc->elf_ex)) + if (!elf_check_arch(&loc.elf_ex)) goto out; if (elf_check_fdpic(&loc->elf_ex)) goto out; if (!bprm->file->f_op->mmap) goto out; - elf_phdata = load_elf_phdrs(&loc->elf_ex, bprm->file); + elf_phdata = load_elf_phdrs(&loc.elf_ex, bprm->file); if (!elf_phdata) goto out; @@ -747,7 +761,7 @@ static int load_elf_binary(struct linux_binprm *bprm) start_data = 0; end_data = 0; - for (i = 0; i < loc->elf_ex.e_phnum; i++) { + for (i = 0; i < loc.elf_ex.e_phnum; i++) { if (elf_ppnt->p_type == PT_INTERP) { /* This is the program interpreter used for * shared libraries - for now assume that this @@ -758,29 +772,24 @@ static int load_elf_binary(struct linux_binprm *bprm) elf_ppnt->p_filesz < 2) goto out_free_ph; - retval = -ENOMEM; - elf_interpreter = kmalloc(elf_ppnt->p_filesz, - GFP_KERNEL); - if (!elf_interpreter) - goto out_free_ph; - + interp_present = true; pos = elf_ppnt->p_offset; retval = kernel_read(bprm->file, elf_interpreter, elf_ppnt->p_filesz, &pos); if (retval != elf_ppnt->p_filesz) { if (retval >= 0) retval = -EIO; - goto out_free_interp; + goto out_free_ph; } /* make sure path is NULL terminated */ retval = -ENOEXEC; if (elf_interpreter[elf_ppnt->p_filesz - 1] != '\0') - goto out_free_interp; + goto out_free_ph; interpreter = open_exec(elf_interpreter); retval = PTR_ERR(interpreter); if (IS_ERR(interpreter)) - goto out_free_interp; + goto out_free_ph; /* * If the binary is not readable then enforce @@ -791,9 +800,9 @@ static int load_elf_binary(struct linux_binprm *bprm) /* Get the exec headers */ pos = 0; - retval = kernel_read(interpreter, &loc->interp_elf_ex, - sizeof(loc->interp_elf_ex), &pos); - if (retval != sizeof(loc->interp_elf_ex)) { + retval = kernel_read(interpreter, &loc.interp_elf_ex, + sizeof(loc.interp_elf_ex), &pos); + if (retval != sizeof(loc.interp_elf_ex)) { if (retval >= 0) retval = -EIO; goto out_free_dentry; @@ -805,7 +814,7 @@ static int load_elf_binary(struct linux_binprm *bprm) } elf_ppnt = elf_phdata; - for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) + for (i = 0; i < loc.elf_ex.e_phnum; i++, elf_ppnt++) switch (elf_ppnt->p_type) { case PT_GNU_STACK: if (elf_ppnt->p_flags & PF_X) @@ -815,7 +824,7 @@ static int load_elf_binary(struct linux_binprm *bprm) break; case PT_LOPROC ... PT_HIPROC: - retval = arch_elf_pt_proc(&loc->elf_ex, elf_ppnt, + retval = arch_elf_pt_proc(&loc.elf_ex, elf_ppnt, bprm->file, false, &arch_state); if (retval) @@ -824,28 +833,28 @@ static int load_elf_binary(struct linux_binprm *bprm) } /* Some simple consistency checks for the interpreter */ - if (elf_interpreter) { + if (interp_present) { retval = -ELIBBAD; /* Not an ELF interpreter */ - if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) + if (memcmp(loc.interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out_free_dentry; /* Verify the interpreter has a valid arch */ - if (!elf_check_arch(&loc->interp_elf_ex) || - elf_check_fdpic(&loc->interp_elf_ex)) + if (!elf_check_arch(&loc.interp_elf_ex) || + elf_check_fdpic(&loc.interp_elf_ex)) goto out_free_dentry; /* Load the interpreter program headers */ - interp_elf_phdata = load_elf_phdrs(&loc->interp_elf_ex, + interp_elf_phdata = load_elf_phdrs(&loc.interp_elf_ex, interpreter); if (!interp_elf_phdata) goto out_free_dentry; /* Pass PT_LOPROC..PT_HIPROC headers to arch code */ elf_ppnt = interp_elf_phdata; - for (i = 0; i < loc->interp_elf_ex.e_phnum; i++, elf_ppnt++) + for (i = 0; i < loc.interp_elf_ex.e_phnum; i++, elf_ppnt++) switch (elf_ppnt->p_type) { case PT_LOPROC ... PT_HIPROC: - retval = arch_elf_pt_proc(&loc->interp_elf_ex, + retval = arch_elf_pt_proc(&loc.interp_elf_ex, elf_ppnt, interpreter, true, &arch_state); if (retval) @@ -859,8 +868,8 @@ static int load_elf_binary(struct linux_binprm *bprm) * still possible to return an error to the code that invoked * the exec syscall. */ - retval = arch_check_elf(&loc->elf_ex, - !!interpreter, &loc->interp_elf_ex, + retval = arch_check_elf(&loc.elf_ex, + !!interpreter, &loc.interp_elf_ex, &arch_state); if (retval) goto out_free_dentry; @@ -872,8 +881,8 @@ static int load_elf_binary(struct linux_binprm *bprm) /* Do this immediately, since STACK_TOP as used in setup_arg_pages may depend on the personality. */ - SET_PERSONALITY2(loc->elf_ex, &arch_state); - if (elf_read_implies_exec(loc->elf_ex, executable_stack)) + SET_PERSONALITY2(loc.elf_ex, &arch_state); + if (elf_read_implies_exec(loc.elf_ex, executable_stack)) current->personality |= READ_IMPLIES_EXEC; if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) @@ -894,7 +903,7 @@ static int load_elf_binary(struct linux_binprm *bprm) /* Now we do a little grungy work by mmapping the ELF image into the correct location in memory. */ for(i = 0, elf_ppnt = elf_phdata; - i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { + i < loc.elf_ex.e_phnum; i++, elf_ppnt++) { int elf_prot = 0, elf_flags, elf_fixed = MAP_FIXED_NOREPLACE; unsigned long k, vaddr; unsigned long total_size = 0; @@ -950,9 +959,9 @@ static int load_elf_binary(struct linux_binprm *bprm) * If we are loading ET_EXEC or we have already performed * the ET_DYN load_addr calculations, proceed normally. */ - if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { + if (loc.elf_ex.e_type == ET_EXEC || load_addr_set) { elf_flags |= elf_fixed; - } else if (loc->elf_ex.e_type == ET_DYN) { + } else if (loc.elf_ex.e_type == ET_DYN) { /* * This logic is run once for the first LOAD Program * Header for ET_DYN binaries to calculate the @@ -983,7 +992,7 @@ static int load_elf_binary(struct linux_binprm *bprm) * independently randomized mmap region (0 load_bias * without MAP_FIXED). */ - if (elf_interpreter) { + if (interp_present) { load_bias = ELF_ET_DYN_BASE; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); @@ -1001,7 +1010,7 @@ static int load_elf_binary(struct linux_binprm *bprm) load_bias = ELF_PAGESTART(load_bias - vaddr); total_size = total_mapping_size(elf_phdata, - loc->elf_ex.e_phnum); + loc.elf_ex.e_phnum); if (!total_size) { retval = -EINVAL; goto out_free_dentry; @@ -1019,7 +1028,7 @@ static int load_elf_binary(struct linux_binprm *bprm) if (!load_addr_set) { load_addr_set = 1; load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset); - if (loc->elf_ex.e_type == ET_DYN) { + if (loc.elf_ex.e_type == ET_DYN) { load_bias += error - ELF_PAGESTART(load_bias + vaddr); load_addr += load_bias; @@ -1060,7 +1069,7 @@ static int load_elf_binary(struct linux_binprm *bprm) } } - loc->elf_ex.e_entry += load_bias; + loc.elf_ex.e_entry += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; @@ -1081,10 +1090,10 @@ static int load_elf_binary(struct linux_binprm *bprm) goto out_free_dentry; } - if (elf_interpreter) { + if (interp_present) { unsigned long interp_map_addr = 0; - elf_entry = load_elf_interp(&loc->interp_elf_ex, + elf_entry = load_elf_interp(&loc.interp_elf_ex, interpreter, &interp_map_addr, load_bias, interp_elf_phdata); @@ -1094,7 +1103,7 @@ static int load_elf_binary(struct linux_binprm *bprm) * adjustment */ interp_load_addr = elf_entry; - elf_entry += loc->interp_elf_ex.e_entry; + elf_entry += loc.interp_elf_ex.e_entry; } if (BAD_ADDR(elf_entry)) { retval = IS_ERR((void *)elf_entry) ? @@ -1105,9 +1114,8 @@ static int load_elf_binary(struct linux_binprm *bprm) allow_write_access(interpreter); fput(interpreter); - kfree(elf_interpreter); } else { - elf_entry = loc->elf_ex.e_entry; + elf_entry = loc.elf_ex.e_entry; if (BAD_ADDR(elf_entry)) { retval = -EINVAL; goto out_free_dentry; @@ -1120,12 +1128,12 @@ static int load_elf_binary(struct linux_binprm *bprm) set_binfmt(&elf_format); #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES - retval = arch_setup_additional_pages(bprm, !!elf_interpreter); + retval = arch_setup_additional_pages(bprm, interp_present); if (retval < 0) goto out; #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ - retval = create_elf_tables(bprm, &loc->elf_ex, + retval = create_elf_tables(bprm, &loc.elf_ex, load_addr, interp_load_addr); if (retval < 0) goto out; @@ -1145,7 +1153,7 @@ static int load_elf_binary(struct linux_binprm *bprm) * growing down), and into the unused ELF_ET_DYN_BASE region. */ if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && - loc->elf_ex.e_type == ET_DYN && !interpreter) + loc.elf_ex.e_type == ET_DYN && !interpreter) current->mm->brk = current->mm->start_brk = ELF_ET_DYN_BASE; @@ -1183,8 +1191,6 @@ static int load_elf_binary(struct linux_binprm *bprm) start_thread(regs, elf_entry, bprm->p); retval = 0; out: - kfree(loc); -out_ret: return retval; /* error cleanup */ @@ -1193,8 +1199,6 @@ static int load_elf_binary(struct linux_binprm *bprm) allow_write_access(interpreter); if (interpreter) fput(interpreter); -out_free_interp: - kfree(elf_interpreter); out_free_ph: kfree(elf_phdata); goto out; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index aa4a7a23ff99..27a04f492541 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -694,12 +694,24 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer, struct super_block *sb = file_inode(file)->i_sb; struct dentry *root = sb->s_root, *dentry; int err = 0; + struct file *f = NULL; e = create_entry(buffer, count); if (IS_ERR(e)) return PTR_ERR(e); + if (e->flags & MISC_FMT_OPEN_FILE) { + f = open_exec(e->interpreter); + if (IS_ERR(f)) { + pr_notice("register: failed to install interpreter file %s\n", + e->interpreter); + kfree(e); + return PTR_ERR(f); + } + e->interp_file = f; + } + inode_lock(d_inode(root)); dentry = lookup_one_len(e->name, root, strlen(e->name)); err = PTR_ERR(dentry); @@ -723,21 +735,6 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer, goto out2; } - if (e->flags & MISC_FMT_OPEN_FILE) { - struct file *f; - - f = open_exec(e->interpreter); - if (IS_ERR(f)) { - err = PTR_ERR(f); - pr_notice("register: failed to install interpreter file %s\n", e->interpreter); - simple_release_fs(&bm_mnt, &entry_count); - iput(inode); - inode = NULL; - goto out2; - } - e->interp_file = f; - } - e->dentry = dget(dentry); inode->i_private = e; inode->i_fop = &bm_entry_operations; @@ -754,6 +751,8 @@ static ssize_t bm_register_write(struct file *file, const char __user *buffer, inode_unlock(d_inode(root)); if (err) { + if (f) + filp_close(f, NULL); kfree(e); return err; } diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index f36b2a386aae..2bdd24425a68 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -267,9 +267,12 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, ret = btrfs_inc_ref(trans, root, cow, 1); else ret = btrfs_inc_ref(trans, root, cow, 0); - - if (ret) + if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); return ret; + } btrfs_mark_buffer_dirty(cow); *cow_ret = cow; @@ -1411,7 +1414,9 @@ get_old_root(struct btrfs_root *root, u64 time_seq) "failed to read tree block %llu from get_old_root", logical); } else { + btrfs_tree_read_lock(old); eb = btrfs_clone_extent_buffer(old); + btrfs_tree_read_unlock(old); free_extent_buffer(old); } } else if (old_root) { diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 14855972dee3..fea5ccfade5c 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -642,7 +642,7 @@ static int btrfs_delayed_inode_reserve_metadata( btrfs_ino(inode), num_bytes, 1); } else { - btrfs_qgroup_free_meta_prealloc(root, fs_info->nodesize); + btrfs_qgroup_free_meta_prealloc(root, num_bytes); } return ret; } diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index 36c0490156ac..4d1d2657d70c 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -54,6 +54,17 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info) ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0); if (ret) { no_valid_dev_replace_entry_found: + /* + * We don't have a replace item or it's corrupted. If there is + * a replace target, fail the mount. + */ + if (btrfs_find_device(fs_info->fs_devices, + BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) { + btrfs_err(fs_info, + "found replace target device without a valid replace item"); + ret = -EUCLEAN; + goto out; + } ret = 0; dev_replace->replace_state = BTRFS_DEV_REPLACE_ITEM_STATE_NEVER_STARTED; @@ -107,8 +118,19 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info) case BTRFS_IOCTL_DEV_REPLACE_STATE_NEVER_STARTED: case BTRFS_IOCTL_DEV_REPLACE_STATE_FINISHED: case BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED: - dev_replace->srcdev = NULL; - dev_replace->tgtdev = NULL; + /* + * We don't have an active replace item but if there is a + * replace target, fail the mount. + */ + if (btrfs_find_device(fs_info->fs_devices, + BTRFS_DEV_REPLACE_DEVID, NULL, NULL, false)) { + btrfs_err(fs_info, + "replace devid present without an active replace item"); + ret = -EUCLEAN; + } else { + dev_replace->srcdev = NULL; + dev_replace->tgtdev = NULL; + } break; case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED: case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED: diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 301111922a1a..dabf153843e9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3913,6 +3913,10 @@ int btree_write_cache_pages(struct address_space *mapping, if (!ret) { free_extent_buffer(eb); continue; + } else if (ret < 0) { + done = 1; + free_extent_buffer(eb); + break; } ret = write_one_eb(eb, fs_info, wbc, &epd); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 646152f30584..a202f2f12b1c 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -3016,8 +3016,11 @@ static int btrfs_zero_range(struct inode *inode, goto out; ret = btrfs_qgroup_reserve_data(inode, &data_reserved, alloc_start, bytes_to_reserve); - if (ret) + if (ret) { + unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, + lockend, &cached_state); goto out; + } ret = btrfs_prealloc_file_range(inode, mode, alloc_start, alloc_end - alloc_start, i_blocksize(inode), diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 652b0b16e93e..6511cb71986c 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -743,8 +743,10 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, while (num_entries) { e = kmem_cache_zalloc(btrfs_free_space_cachep, GFP_NOFS); - if (!e) + if (!e) { + ret = -ENOMEM; goto free_cache; + } ret = io_ctl_read_entry(&io_ctl, e, &type); if (ret) { @@ -753,6 +755,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, } if (!e->bytes) { + ret = -1; kmem_cache_free(btrfs_free_space_cachep, e); goto free_cache; } @@ -773,6 +776,7 @@ static int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, e->bitmap = kmem_cache_zalloc( btrfs_free_space_bitmap_cachep, GFP_NOFS); if (!e->bitmap) { + ret = -ENOMEM; kmem_cache_free( btrfs_free_space_cachep, e); goto free_cache; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 64d459ca76d0..8c6f619c9ee6 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -9472,7 +9472,7 @@ int __init btrfs_init_cachep(void) btrfs_free_space_bitmap_cachep = kmem_cache_create("btrfs_free_space_bitmap", PAGE_SIZE, PAGE_SIZE, - SLAB_RED_ZONE, NULL); + SLAB_MEM_SPREAD, NULL); if (!btrfs_free_space_bitmap_cachep) goto fail; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 01a90fa03c24..1c053e10b33b 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1239,6 +1239,7 @@ static int cluster_pages_for_defrag(struct inode *inode, u64 page_start; u64 page_end; u64 page_cnt; + u64 start = (u64)start_index << PAGE_SHIFT; int ret; int i; int i_done; @@ -1255,8 +1256,7 @@ static int cluster_pages_for_defrag(struct inode *inode, page_cnt = min_t(u64, (u64)num_pages, (u64)file_end - start_index + 1); ret = btrfs_delalloc_reserve_space(inode, &data_reserved, - start_index << PAGE_SHIFT, - page_cnt << PAGE_SHIFT); + start, page_cnt << PAGE_SHIFT); if (ret) return ret; i_done = 0; @@ -1346,8 +1346,7 @@ static int cluster_pages_for_defrag(struct inode *inode, btrfs_mod_outstanding_extents(BTRFS_I(inode), 1); spin_unlock(&BTRFS_I(inode)->lock); btrfs_delalloc_release_space(inode, data_reserved, - start_index << PAGE_SHIFT, - (page_cnt - i_done) << PAGE_SHIFT, true); + start, (page_cnt - i_done) << PAGE_SHIFT, true); } @@ -1374,8 +1373,7 @@ static int cluster_pages_for_defrag(struct inode *inode, put_page(pages[i]); } btrfs_delalloc_release_space(inode, data_reserved, - start_index << PAGE_SHIFT, - page_cnt << PAGE_SHIFT, true); + start, page_cnt << PAGE_SHIFT, true); btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT); extent_changeset_free(data_reserved); return ret; @@ -1844,7 +1842,10 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, if (vol_args->flags & BTRFS_SUBVOL_RDONLY) readonly = true; if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) { - if (vol_args->size > PAGE_SIZE) { + u64 nums; + + if (vol_args->size < sizeof(*inherit) || + vol_args->size > PAGE_SIZE) { ret = -EINVAL; goto free_args; } @@ -1853,6 +1854,20 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, ret = PTR_ERR(inherit); goto free_args; } + + if (inherit->num_qgroups > PAGE_SIZE || + inherit->num_ref_copies > PAGE_SIZE || + inherit->num_excl_copies > PAGE_SIZE) { + ret = -EINVAL; + goto free_inherit; + } + + nums = inherit->num_qgroups + 2 * inherit->num_ref_copies + + 2 * inherit->num_excl_copies; + if (vol_args->size != struct_size(inherit, qgroups, nums)) { + ret = -EINVAL; + goto free_inherit; + } } ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, @@ -4217,6 +4232,8 @@ static int btrfs_clone(struct inode *src, struct inode *inode, ret = -EINTR; goto out; } + + cond_resched(); } ret = 0; diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index c8ed4db73b84..7bda5586e433 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -488,13 +488,13 @@ int btrfs_read_qgroup_config(struct btrfs_fs_info *fs_info) break; } out: + btrfs_free_path(path); fs_info->qgroup_flags |= flags; if (!(fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_ON)) clear_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags); else if (fs_info->qgroup_flags & BTRFS_QGROUP_STATUS_FLAG_RESCAN && ret >= 0) ret = qgroup_rescan_init(fs_info, rescan_progress, 0); - btrfs_free_path(path); if (ret < 0) { ulist_free(fs_info->qgroup_ulist); @@ -2774,6 +2774,12 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans, return ret; } +static bool rescan_should_stop(struct btrfs_fs_info *fs_info) +{ + return btrfs_fs_closing(fs_info) || + test_bit(BTRFS_FS_STATE_REMOUNTING, &fs_info->fs_state); +} + static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) { struct btrfs_fs_info *fs_info = container_of(work, struct btrfs_fs_info, @@ -2782,6 +2788,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) struct btrfs_trans_handle *trans = NULL; int err = -ENOMEM; int ret = 0; + bool stopped = false; path = btrfs_alloc_path(); if (!path) @@ -2794,7 +2801,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) path->skip_locking = 1; err = 0; - while (!err && !btrfs_fs_closing(fs_info)) { + while (!err && !(stopped = rescan_should_stop(fs_info))) { trans = btrfs_start_transaction(fs_info->fs_root, 0); if (IS_ERR(trans)) { err = PTR_ERR(trans); @@ -2837,7 +2844,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) } mutex_lock(&fs_info->qgroup_rescan_lock); - if (!btrfs_fs_closing(fs_info)) + if (!stopped) fs_info->qgroup_flags &= ~BTRFS_QGROUP_STATUS_FLAG_RESCAN; if (trans) { ret = update_qgroup_status_item(trans); @@ -2856,7 +2863,7 @@ static void btrfs_qgroup_rescan_worker(struct btrfs_work *work) btrfs_end_transaction(trans); - if (btrfs_fs_closing(fs_info)) { + if (stopped) { btrfs_info(fs_info, "qgroup scan paused"); } else if (err >= 0) { btrfs_info(fs_info, "qgroup scan completed%s", diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 927f9f3daddb..a91f74cf5cd1 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -1182,22 +1182,19 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio) int nr_data = rbio->nr_data; int stripe; int pagenr; - int p_stripe = -1; - int q_stripe = -1; + bool has_qstripe; struct bio_list bio_list; struct bio *bio; int ret; bio_list_init(&bio_list); - if (rbio->real_stripes - rbio->nr_data == 1) { - p_stripe = rbio->real_stripes - 1; - } else if (rbio->real_stripes - rbio->nr_data == 2) { - p_stripe = rbio->real_stripes - 2; - q_stripe = rbio->real_stripes - 1; - } else { + if (rbio->real_stripes - rbio->nr_data == 1) + has_qstripe = false; + else if (rbio->real_stripes - rbio->nr_data == 2) + has_qstripe = true; + else BUG(); - } /* at this point we either have a full stripe, * or we've read the full stripe from the drive. @@ -1241,7 +1238,7 @@ static noinline void finish_rmw(struct btrfs_raid_bio *rbio) SetPageUptodate(p); pointers[stripe++] = kmap(p); - if (q_stripe != -1) { + if (has_qstripe) { /* * raid6, add the qstripe and call the @@ -2340,8 +2337,7 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio, int nr_data = rbio->nr_data; int stripe; int pagenr; - int p_stripe = -1; - int q_stripe = -1; + bool has_qstripe; struct page *p_page = NULL; struct page *q_page = NULL; struct bio_list bio_list; @@ -2351,14 +2347,12 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio, bio_list_init(&bio_list); - if (rbio->real_stripes - rbio->nr_data == 1) { - p_stripe = rbio->real_stripes - 1; - } else if (rbio->real_stripes - rbio->nr_data == 2) { - p_stripe = rbio->real_stripes - 2; - q_stripe = rbio->real_stripes - 1; - } else { + if (rbio->real_stripes - rbio->nr_data == 1) + has_qstripe = false; + else if (rbio->real_stripes - rbio->nr_data == 2) + has_qstripe = true; + else BUG(); - } if (bbio->num_tgtdevs && bbio->tgtdev_map[rbio->scrubp]) { is_replace = 1; @@ -2380,17 +2374,22 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio, goto cleanup; SetPageUptodate(p_page); - if (q_stripe != -1) { + if (has_qstripe) { + /* RAID6, allocate and map temp space for the Q stripe */ q_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); if (!q_page) { __free_page(p_page); goto cleanup; } SetPageUptodate(q_page); + pointers[rbio->real_stripes - 1] = kmap(q_page); } atomic_set(&rbio->error, 0); + /* Map the parity stripe just once */ + pointers[nr_data] = kmap(p_page); + for_each_set_bit(pagenr, rbio->dbitmap, rbio->stripe_npages) { struct page *p; void *parity; @@ -2400,17 +2399,8 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio, pointers[stripe] = kmap(p); } - /* then add the parity stripe */ - pointers[stripe++] = kmap(p_page); - - if (q_stripe != -1) { - - /* - * raid6, add the qstripe and call the - * library function to fill in our p/q - */ - pointers[stripe++] = kmap(q_page); - + if (has_qstripe) { + /* RAID6, call the library function to fill in our P/Q */ raid6_call.gen_syndrome(rbio->real_stripes, PAGE_SIZE, pointers); } else { @@ -2431,12 +2421,14 @@ static noinline void finish_parity_scrub(struct btrfs_raid_bio *rbio, for (stripe = 0; stripe < nr_data; stripe++) kunmap(page_in_rbio(rbio, stripe, pagenr, 0)); - kunmap(p_page); } + kunmap(p_page); __free_page(p_page); - if (q_page) + if (q_page) { + kunmap(q_page); __free_page(q_page); + } writeback: /* diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c index 5dec52bd2897..b26739d0e991 100644 --- a/fs/btrfs/ref-verify.c +++ b/fs/btrfs/ref-verify.c @@ -854,6 +854,7 @@ int btrfs_ref_tree_mod(struct btrfs_root *root, u64 bytenr, u64 num_bytes, "dropping a ref for a root that doesn't have a ref on the block"); dump_block_entry(fs_info, be); dump_ref_action(fs_info, ra); + kfree(ref); kfree(ra); goto out_unlock; } diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index eedcb7bf50e9..e6e4e6fb2add 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1291,9 +1291,7 @@ static void __del_reloc_root(struct btrfs_root *root) RB_CLEAR_NODE(&node->rb_node); } spin_unlock(&rc->reloc_root_tree.lock); - if (!node) - return; - BUG_ON((struct btrfs_root *)node->data != root); + ASSERT(!node || (struct btrfs_root *)node->data == root); } spin_lock(&fs_info->trans_lock); diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index ed61c0daef41..128398dde081 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -238,6 +238,7 @@ struct waiting_dir_move { * after this directory is moved, we can try to rmdir the ino rmdir_ino. */ u64 rmdir_ino; + u64 rmdir_gen; bool orphanized; }; @@ -308,7 +309,7 @@ static int is_waiting_for_move(struct send_ctx *sctx, u64 ino); static struct waiting_dir_move * get_waiting_dir_move(struct send_ctx *sctx, u64 ino); -static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino); +static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino, u64 gen); static int need_send_hole(struct send_ctx *sctx) { @@ -2304,7 +2305,7 @@ static int get_cur_path(struct send_ctx *sctx, u64 ino, u64 gen, fs_path_reset(name); - if (is_waiting_for_rm(sctx, ino)) { + if (is_waiting_for_rm(sctx, ino, gen)) { ret = gen_unique_name(sctx, ino, gen, name); if (ret < 0) goto out; @@ -2863,8 +2864,8 @@ static int orphanize_inode(struct send_ctx *sctx, u64 ino, u64 gen, return ret; } -static struct orphan_dir_info * -add_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino) +static struct orphan_dir_info *add_orphan_dir_info(struct send_ctx *sctx, + u64 dir_ino, u64 dir_gen) { struct rb_node **p = &sctx->orphan_dirs.rb_node; struct rb_node *parent = NULL; @@ -2873,20 +2874,23 @@ add_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino) while (*p) { parent = *p; entry = rb_entry(parent, struct orphan_dir_info, node); - if (dir_ino < entry->ino) { + if (dir_ino < entry->ino) p = &(*p)->rb_left; - } else if (dir_ino > entry->ino) { + else if (dir_ino > entry->ino) p = &(*p)->rb_right; - } else { + else if (dir_gen < entry->gen) + p = &(*p)->rb_left; + else if (dir_gen > entry->gen) + p = &(*p)->rb_right; + else return entry; - } } odi = kmalloc(sizeof(*odi), GFP_KERNEL); if (!odi) return ERR_PTR(-ENOMEM); odi->ino = dir_ino; - odi->gen = 0; + odi->gen = dir_gen; odi->last_dir_index_offset = 0; rb_link_node(&odi->node, parent, p); @@ -2894,8 +2898,8 @@ add_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino) return odi; } -static struct orphan_dir_info * -get_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino) +static struct orphan_dir_info *get_orphan_dir_info(struct send_ctx *sctx, + u64 dir_ino, u64 gen) { struct rb_node *n = sctx->orphan_dirs.rb_node; struct orphan_dir_info *entry; @@ -2906,15 +2910,19 @@ get_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino) n = n->rb_left; else if (dir_ino > entry->ino) n = n->rb_right; + else if (gen < entry->gen) + n = n->rb_left; + else if (gen > entry->gen) + n = n->rb_right; else return entry; } return NULL; } -static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino) +static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino, u64 gen) { - struct orphan_dir_info *odi = get_orphan_dir_info(sctx, dir_ino); + struct orphan_dir_info *odi = get_orphan_dir_info(sctx, dir_ino, gen); return odi != NULL; } @@ -2959,7 +2967,7 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen, key.type = BTRFS_DIR_INDEX_KEY; key.offset = 0; - odi = get_orphan_dir_info(sctx, dir); + odi = get_orphan_dir_info(sctx, dir, dir_gen); if (odi) key.offset = odi->last_dir_index_offset; @@ -2990,7 +2998,7 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen, dm = get_waiting_dir_move(sctx, loc.objectid); if (dm) { - odi = add_orphan_dir_info(sctx, dir); + odi = add_orphan_dir_info(sctx, dir, dir_gen); if (IS_ERR(odi)) { ret = PTR_ERR(odi); goto out; @@ -2998,12 +3006,13 @@ static int can_rmdir(struct send_ctx *sctx, u64 dir, u64 dir_gen, odi->gen = dir_gen; odi->last_dir_index_offset = found_key.offset; dm->rmdir_ino = dir; + dm->rmdir_gen = dir_gen; ret = 0; goto out; } if (loc.objectid > send_progress) { - odi = add_orphan_dir_info(sctx, dir); + odi = add_orphan_dir_info(sctx, dir, dir_gen); if (IS_ERR(odi)) { ret = PTR_ERR(odi); goto out; @@ -3043,6 +3052,7 @@ static int add_waiting_dir_move(struct send_ctx *sctx, u64 ino, bool orphanized) return -ENOMEM; dm->ino = ino; dm->rmdir_ino = 0; + dm->rmdir_gen = 0; dm->orphanized = orphanized; while (*p) { @@ -3188,7 +3198,7 @@ static int path_loop(struct send_ctx *sctx, struct fs_path *name, while (ino != BTRFS_FIRST_FREE_OBJECTID) { fs_path_reset(name); - if (is_waiting_for_rm(sctx, ino)) + if (is_waiting_for_rm(sctx, ino, gen)) break; if (is_waiting_for_move(sctx, ino)) { if (*ancestor_ino == 0) @@ -3228,6 +3238,7 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) u64 parent_ino, parent_gen; struct waiting_dir_move *dm = NULL; u64 rmdir_ino = 0; + u64 rmdir_gen; u64 ancestor; bool is_orphan; int ret; @@ -3242,6 +3253,7 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) dm = get_waiting_dir_move(sctx, pm->ino); ASSERT(dm); rmdir_ino = dm->rmdir_ino; + rmdir_gen = dm->rmdir_gen; is_orphan = dm->orphanized; free_waiting_dir_move(sctx, dm); @@ -3278,6 +3290,7 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) dm = get_waiting_dir_move(sctx, pm->ino); ASSERT(dm); dm->rmdir_ino = rmdir_ino; + dm->rmdir_gen = rmdir_gen; } goto out; } @@ -3296,7 +3309,7 @@ static int apply_dir_move(struct send_ctx *sctx, struct pending_dir_move *pm) struct orphan_dir_info *odi; u64 gen; - odi = get_orphan_dir_info(sctx, rmdir_ino); + odi = get_orphan_dir_info(sctx, rmdir_ino, rmdir_gen); if (!odi) { /* already deleted */ goto finish; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 40f5b4dcb927..521f6c2091ad 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -1845,6 +1845,14 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) btrfs_scrub_cancel(fs_info); btrfs_pause_balance(fs_info); + /* + * Pause the qgroup rescan worker if it is running. We don't want + * it to be still running after we are in RO mode, as after that, + * by the time we unmount, it might have left a transaction open, + * so we would leak the transaction and/or crash. + */ + btrfs_qgroup_wait_for_completion(fs_info, false); + ret = btrfs_commit_super(fs_info); if (ret) goto restore; diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 8829d89eb4af..1b52c960682d 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1249,7 +1249,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) struct btrfs_root *gang[8]; int i; int ret; - int err = 0; spin_lock(&fs_info->fs_roots_radix_lock); while (1) { @@ -1261,6 +1260,8 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) break; for (i = 0; i < ret; i++) { struct btrfs_root *root = gang[i]; + int ret2; + radix_tree_tag_clear(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); @@ -1282,17 +1283,17 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) root->node); } - err = btrfs_update_root(trans, fs_info->tree_root, + ret2 = btrfs_update_root(trans, fs_info->tree_root, &root->root_key, &root->root_item); + if (ret2) + return ret2; spin_lock(&fs_info->fs_roots_radix_lock); - if (err) - break; btrfs_qgroup_free_meta_all_pertrans(root); } } spin_unlock(&fs_info->fs_roots_radix_lock); - return err; + return 0; } /* diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 05daa2b816c3..662711200eeb 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -857,7 +857,13 @@ static noinline struct btrfs_device *device_list_add(const char *path, if (device->bdev != path_bdev) { bdput(path_bdev); mutex_unlock(&fs_devices->device_list_mutex); - btrfs_warn_in_rcu(device->fs_info, + /* + * device->fs_info may not be reliable here, so + * pass in a NULL instead. This avoids a + * possible use-after-free when the fs_info and + * fs_info->sb are already torn down. + */ + btrfs_warn_in_rcu(NULL, "duplicate device %s devid %llu generation %llu scanned by %s (%d)", path, devid, found_transid, current->comm, @@ -974,22 +980,13 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step) continue; } - if (device->devid == BTRFS_DEV_REPLACE_DEVID) { - /* - * In the first step, keep the device which has - * the correct fsid and the devid that is used - * for the dev_replace procedure. - * In the second step, the dev_replace state is - * read from the device tree and it is known - * whether the procedure is really active or - * not, which means whether this device is - * used or whether it should be removed. - */ - if (step == 0 || test_bit(BTRFS_DEV_STATE_REPLACE_TGT, - &device->dev_state)) { - continue; - } - } + /* + * We have already validated the presence of BTRFS_DEV_REPLACE_DEVID, + * in btrfs_init_dev_replace() so just continue. + */ + if (device->devid == BTRFS_DEV_REPLACE_DEVID) + continue; + if (device->bdev) { blkdev_put(device->bdev, device->mode); device->bdev = NULL; @@ -998,9 +995,6 @@ void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step) if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) { list_del_init(&device->dev_alloc_list); clear_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); - if (!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, - &device->dev_state)) - fs_devices->rw_devices--; } list_del_init(&device->dev_list); fs_devices->num_devices--; @@ -2459,9 +2453,6 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path btrfs_set_super_num_devices(fs_info->super_copy, orig_super_num_devices + 1); - /* add sysfs device entry */ - btrfs_sysfs_add_device_link(fs_devices, device); - /* * we've got more storage, clear any full flags on the space * infos @@ -2469,6 +2460,10 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path btrfs_clear_space_info_full(fs_info); mutex_unlock(&fs_info->chunk_mutex); + + /* Add sysfs device entry */ + btrfs_sysfs_add_device_link(fs_devices, device); + mutex_unlock(&fs_devices->device_list_mutex); if (seeding_dev) { @@ -4016,6 +4011,8 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info) btrfs_warn(fs_info, "balance: cannot set exclusive op status, resume manually"); + btrfs_release_path(path); + mutex_lock(&fs_info->balance_mutex); BUG_ON(fs_info->balance_ctl); spin_lock(&fs_info->balance_lock); diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index c0dbf8b7762b..6e871a382209 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1047,12 +1047,19 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release) { struct ceph_mds_session *session = cap->session; struct ceph_inode_info *ci = cap->ci; - struct ceph_mds_client *mdsc = - ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc; + struct ceph_mds_client *mdsc; int removed = 0; + /* 'ci' being NULL means the remove have already occurred */ + if (!ci) { + dout("%s: cap inode is NULL\n", __func__); + return; + } + dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode); + mdsc = ceph_inode_to_client(&ci->vfs_inode)->mdsc; + /* remove from inode's cap rbtree, and clear auth cap */ rb_erase(&cap->ci_node, &ci->i_caps); if (ci->i_auth_cap == cap) diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 65da12ff5449..e042179e03c7 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -812,7 +812,7 @@ static inline int default_congestion_kb(void) * This allows larger machines to have larger/more transfers. * Limit the default to 256M */ - congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10); + congestion_kb = (16*int_sqrt(totalram_pages())) << (PAGE_SHIFT-10); if (congestion_kb > 256*1024) congestion_kb = 256*1024; diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index a2b2355e7f01..9986817532b1 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -501,7 +501,13 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, else if (map_chars == SFM_MAP_UNI_RSVD) { bool end_of_string; - if (i == srclen - 1) + /** + * Remap spaces and periods found at the end of every + * component of the path. The special cases of '.' and + * '..' do not need to be dealt with explicitly because + * they are addressed in namei.c:link_path_walk(). + **/ + if ((i == srclen - 1) || (source[i+1] == '\\')) end_of_string = true; else end_of_string = false; diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index d5457015801d..bc906fcf3f6d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -229,7 +229,7 @@ cifs_statfs(struct dentry *dentry, struct kstatfs *buf) rc = server->ops->queryfs(xid, tcon, buf); free_xid(xid); - return 0; + return rc; } static long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len) diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 6335ca143292..6285085195c1 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -777,6 +777,8 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) list_del_init(&server->tcp_ses_list); spin_unlock(&cifs_tcp_ses_lock); + cancel_delayed_work_sync(&server->echo); + spin_lock(&GlobalMid_Lock); server->tcpStatus = CifsExiting; spin_unlock(&GlobalMid_Lock); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index f6e3c0089825..c7e162c9383d 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -840,6 +840,7 @@ static int cifs_d_revalidate(struct dentry *direntry, unsigned int flags) { struct inode *inode; + int rc; if (flags & LOOKUP_RCU) return -ECHILD; @@ -849,8 +850,25 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags) if ((flags & LOOKUP_REVAL) && !CIFS_CACHE_READ(CIFS_I(inode))) CIFS_I(inode)->time = 0; /* force reval */ - if (cifs_revalidate_dentry(direntry)) - return 0; + rc = cifs_revalidate_dentry(direntry); + if (rc) { + cifs_dbg(FYI, "cifs_revalidate_dentry failed with rc=%d", rc); + switch (rc) { + case -ENOENT: + case -ESTALE: + /* + * Those errors mean the dentry is invalid + * (file was deleted or recreated) + */ + return 0; + default: + /* + * Otherwise some unexpected error happened + * report it as-is to VFS layer + */ + return rc; + } + } else { /* * If the inode wasn't known to be a dfs entry when diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5cb15649adb0..7b482489bd22 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -163,6 +163,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode, goto posix_open_ret; } } else { + cifs_revalidate_mapping(*pinode); cifs_fattr_to_inode(*pinode, &fattr); } diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 7d875a47d022..7177720e822e 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -738,8 +738,8 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) } } spin_unlock(&cifs_tcp_ses_lock); - cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n"); - return false; + cifs_dbg(FYI, "No file id matched, oplock break ignored\n"); + return true; } void diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index e20d170d13f6..faafa9a557c2 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -366,7 +366,8 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, goto out; } - if (bytes_left || p->Next) + /* Azure rounds the buffer size up 8, to a 16 byte boundary */ + if ((bytes_left > 8) || p->Next) cifs_dbg(VFS, "%s: incomplete interface info\n", __func__); diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 379ac8caa29a..ee824131c02e 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -406,8 +406,8 @@ build_preauth_ctxt(struct smb2_preauth_neg_context *pneg_ctxt) pneg_ctxt->ContextType = SMB2_PREAUTH_INTEGRITY_CAPABILITIES; pneg_ctxt->DataLength = cpu_to_le16(38); pneg_ctxt->HashAlgorithmCount = cpu_to_le16(1); - pneg_ctxt->SaltLength = cpu_to_le16(SMB311_SALT_SIZE); - get_random_bytes(pneg_ctxt->Salt, SMB311_SALT_SIZE); + pneg_ctxt->SaltLength = cpu_to_le16(SMB311_LINUX_CLIENT_SALT_SIZE); + get_random_bytes(pneg_ctxt->Salt, SMB311_LINUX_CLIENT_SALT_SIZE); pneg_ctxt->HashAlgorithms = SMB2_PREAUTH_INTEGRITY_SHA512; } @@ -461,6 +461,9 @@ static void decode_preauth_context(struct smb2_preauth_neg_context *ctxt) if (len < MIN_PREAUTH_CTXT_DATA_LEN) { printk_once(KERN_WARNING "server sent bad preauth context\n"); return; + } else if (len < MIN_PREAUTH_CTXT_DATA_LEN + le16_to_cpu(ctxt->SaltLength)) { + pr_warn_once("server sent invalid SaltLength\n"); + return; } if (le16_to_cpu(ctxt->HashAlgorithmCount) != 1) printk_once(KERN_WARNING "illegal SMB3 hash algorithm count\n"); diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 44501f8cbd75..8a44d59947b7 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h @@ -222,7 +222,7 @@ struct smb2_negotiate_req { __le32 NegotiateContextOffset; /* SMB3.1.1 only. MBZ earlier */ __le16 NegotiateContextCount; /* SMB3.1.1 only. MBZ earlier */ __le16 Reserved2; - __le16 Dialects[1]; /* One dialect (vers=) at a time for now */ + __le16 Dialects[4]; /* BB expand this if autonegotiate > 4 dialects */ } __packed; /* Dialects */ @@ -257,12 +257,20 @@ struct smb2_neg_context { /* Followed by array of data */ } __packed; -#define SMB311_SALT_SIZE 32 +#define SMB311_LINUX_CLIENT_SALT_SIZE 32 /* Hash Algorithm Types */ #define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001) #define SMB2_PREAUTH_HASH_SIZE 64 -#define MIN_PREAUTH_CTXT_DATA_LEN (SMB311_SALT_SIZE + 6) +/* + * SaltLength that the server send can be zero, so the only three required + * fields (all __le16) end up six bytes total, so the minimum context data len + * in the response is six bytes which accounts for + * + * HashAlgorithmCount, SaltLength, and 1 HashAlgorithm. + */ +#define MIN_PREAUTH_CTXT_DATA_LEN 6 + struct smb2_preauth_neg_context { __le16 ContextType; /* 1 */ __le16 DataLength; @@ -270,7 +278,7 @@ struct smb2_preauth_neg_context { __le16 HashAlgorithmCount; /* 1 */ __le16 SaltLength; __le16 HashAlgorithms; /* HashAlgorithms[0] since only one defined */ - __u8 Salt[SMB311_SALT_SIZE]; + __u8 Salt[SMB311_LINUX_CLIENT_SALT_SIZE]; } __packed; /* Encryption Algorithms Ciphers */ diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 70412944b267..59643acb6d67 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -891,9 +891,12 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, /* * Compounding is never used during session establish. */ - if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) + if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) { + mutex_lock(&ses->server->srv_mutex); smb311_update_preauth_hash(ses, rqst[0].rq_iov, rqst[0].rq_nvec); + mutex_unlock(&ses->server->srv_mutex); + } if (timeout == CIFS_ASYNC_OP) goto out; @@ -964,7 +967,9 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses, .iov_base = resp_iov[0].iov_base, .iov_len = resp_iov[0].iov_len }; + mutex_lock(&ses->server->srv_mutex); smb311_update_preauth_hash(ses, &iov, 1); + mutex_unlock(&ses->server->srv_mutex); } out: diff --git a/fs/configfs/file.c b/fs/configfs/file.c index bb0a427517e9..50b7c4c4310e 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -392,7 +392,7 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type attr = to_attr(dentry); if (!attr) - goto out_put_item; + goto out_free_buffer; if (type & CONFIGFS_ITEM_BIN_ATTR) { buffer->bin_attr = to_bin_attr(dentry); @@ -405,7 +405,7 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type /* Grab the module reference for this attribute if we have one */ error = -ENODEV; if (!try_module_get(buffer->owner)) - goto out_put_item; + goto out_free_buffer; error = -EACCES; if (!buffer->item->ci_type) @@ -449,8 +449,6 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type out_put_module: module_put(buffer->owner); -out_put_item: - config_item_put(buffer->item); out_free_buffer: up_read(&frag->frag_sem); kfree(buffer); diff --git a/fs/d_path.c b/fs/d_path.c index 3af92cc4bdae..4c28e0b38275 100644 --- a/fs/d_path.c +++ b/fs/d_path.c @@ -46,12 +46,7 @@ static int prepend_name(char **buffer, int *buflen, const struct qstr *name) return -ENAMETOOLONG; p = *buffer -= dlen + 1; *p++ = '/'; - while (dlen--) { - char c = *dname++; - if (!c) - break; - *p++ = c; - } + memcpy(p, dname, dlen); return 0; } @@ -254,9 +249,9 @@ static void get_fs_root_rcu(struct fs_struct *fs, struct path *root) * * "buflen" should be positive. */ -char *d_path(const struct path *path, char *buf, int buflen) +char *d_path_outlen(const struct path *path, char *buf, int *buflen) { - char *res = buf + buflen; + char *res = buf + *buflen; struct path root; int error; @@ -273,17 +268,22 @@ char *d_path(const struct path *path, char *buf, int buflen) */ if (path->dentry->d_op && path->dentry->d_op->d_dname && (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root)) - return path->dentry->d_op->d_dname(path->dentry, buf, buflen); + return path->dentry->d_op->d_dname(path->dentry, buf, *buflen); rcu_read_lock(); get_fs_root_rcu(current->fs, &root); - error = path_with_deleted(path, &root, &res, &buflen); + error = path_with_deleted(path, &root, &res, buflen); rcu_read_unlock(); if (error < 0) res = ERR_PTR(error); return res; } + +char *d_path(const struct path *path, char *buf, int buflen) +{ + return d_path_outlen(path, buf, &buflen); +} EXPORT_SYMBOL(d_path); /* diff --git a/fs/direct-io.c b/fs/direct-io.c index 715e699af7b5..bc3a2bf94339 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -869,6 +869,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, struct buffer_head *map_bh) { int ret = 0; + int boundary = sdio->boundary; /* dio_send_cur_page may clear it */ if (dio->op == REQ_OP_WRITE) { /* @@ -907,10 +908,10 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, sdio->cur_page_fs_offset = sdio->block_in_file << sdio->blkbits; out: /* - * If sdio->boundary then we want to schedule the IO now to + * If boundary then we want to schedule the IO now to * avoid metadata seeks. */ - if (sdio->boundary) { + if (boundary) { ret = dio_send_cur_page(dio, sdio, map_bh); if (sdio->bio) dio_bio_submit(dio, sdio); diff --git a/fs/drop_caches.c b/fs/drop_caches.c index dc1a1d5d825b..0c58efeb90f8 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -46,6 +46,18 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused) iput(toput_inode); } +void mm_drop_caches(int val) +{ + if (val & 1) { + iterate_supers(drop_pagecache_sb, NULL); + count_vm_event(DROP_PAGECACHE); + } + if (val & 2) { + drop_slab(); + count_vm_event(DROP_SLAB); + } +} + int drop_caches_sysctl_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { @@ -57,14 +69,8 @@ int drop_caches_sysctl_handler(struct ctl_table *table, int write, if (write) { static int stfu; - if (sysctl_drop_caches & 1) { - iterate_supers(drop_pagecache_sb, NULL); - count_vm_event(DROP_PAGECACHE); - } - if (sysctl_drop_caches & 2) { - drop_slab(); - count_vm_event(DROP_SLAB); - } + mm_drop_caches(sysctl_drop_caches); + if (!stfu) { pr_info("%s (%d): drop_caches: %d\n", current->comm, task_pid_nr(current), diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c index 8c6ab6c95727..7f40343b39b0 100644 --- a/fs/efivarfs/inode.c +++ b/fs/efivarfs/inode.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -106,6 +107,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, var->var.VariableName[i] = '\0'; inode->i_private = var; + kmemleak_ignore(var); err = efivar_entry_add(var, &efivarfs_list); if (err) diff --git a/fs/exec.c b/fs/exec.c index f9d5406bd70b..07ebf57ff7ee 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -78,6 +78,25 @@ int suid_dumpable = 0; static LIST_HEAD(formats); static DEFINE_RWLOCK(binfmt_lock); +#define HWCOMPOSER_BIN_PREFIX "/vendor/bin/hw/vendor.qti.hardware.display.composer-service" +#define ZYGOTE32_BIN "/system/bin/app_process32" +#define ZYGOTE64_BIN "/system/bin/app_process64" +static struct signal_struct *zygote32_sig; +static struct signal_struct *zygote64_sig; +static atomic_t zygote32_pid; +static atomic_t zygote64_pid; + +bool is_zygote_pid(pid_t pid) +{ + return atomic_read(&zygote32_pid) == pid || + atomic_read(&zygote64_pid) == pid; +} + +bool task_is_zygote(struct task_struct *p) +{ + return p->signal == zygote32_sig || p->signal == zygote64_sig; +} + void __register_binfmt(struct linux_binfmt * fmt, int insert) { BUG_ON(!fmt); @@ -1012,7 +1031,7 @@ static int exec_mmap(struct mm_struct *mm) /* Notify parent that we're no longer interested in the old VM */ tsk = current; old_mm = current->mm; - mm_release(tsk, old_mm); + exec_mm_release(tsk, old_mm); if (old_mm) { sync_mm_rss(old_mm); @@ -1443,7 +1462,6 @@ static void free_bprm(struct linux_binprm *bprm) /* If a binfmt changed the interp, free it. */ if (bprm->interp != bprm->filename) kfree(bprm->interp); - kfree(bprm); } int bprm_change_interp(const char *interp, struct linux_binprm *bprm) @@ -1729,7 +1747,7 @@ static int __do_execve_file(int fd, struct filename *filename, int flags, struct file *file) { char *pathbuf = NULL; - struct linux_binprm *bprm; + struct linux_binprm bprm; struct files_struct *displaced; int retval; @@ -1756,16 +1774,13 @@ static int __do_execve_file(int fd, struct filename *filename, if (retval) goto out_ret; - retval = -ENOMEM; - bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); - if (!bprm) - goto out_files; + memset(&bprm, 0, sizeof(bprm)); - retval = prepare_bprm_creds(bprm); + retval = prepare_bprm_creds(&bprm); if (retval) goto out_free; - check_unsafe_exec(bprm); + check_unsafe_exec(&bprm); current->in_execve = 1; if (!file) @@ -1776,11 +1791,11 @@ static int __do_execve_file(int fd, struct filename *filename, sched_exec(); - bprm->file = file; + bprm.file = file; if (!filename) { - bprm->filename = "none"; + bprm.filename = "none"; } else if (fd == AT_FDCWD || filename->name[0] == '/') { - bprm->filename = filename->name; + bprm.filename = filename->name; } else { if (filename->name[0] == '\0') pathbuf = kasprintf(GFP_KERNEL, "/dev/fd/%d", fd); @@ -1797,44 +1812,64 @@ static int __do_execve_file(int fd, struct filename *filename, * current->files (due to unshare_files above). */ if (close_on_exec(fd, rcu_dereference_raw(current->files->fdt))) - bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; - bprm->filename = pathbuf; + bprm.interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; + bprm.filename = pathbuf; } - bprm->interp = bprm->filename; + bprm.interp = bprm.filename; - retval = bprm_mm_init(bprm); + retval = bprm_mm_init(&bprm); if (retval) goto out_unmark; - bprm->argc = count(argv, MAX_ARG_STRINGS); - if ((retval = bprm->argc) < 0) + bprm.argc = count(argv, MAX_ARG_STRINGS); + if ((retval = bprm.argc) < 0) goto out; - bprm->envc = count(envp, MAX_ARG_STRINGS); - if ((retval = bprm->envc) < 0) + bprm.envc = count(envp, MAX_ARG_STRINGS); + if ((retval = bprm.envc) < 0) goto out; - retval = prepare_binprm(bprm); + retval = prepare_binprm(&bprm); if (retval < 0) goto out; - retval = copy_strings_kernel(1, &bprm->filename, bprm); + retval = copy_strings_kernel(1, &bprm.filename, &bprm); if (retval < 0) goto out; - bprm->exec = bprm->p; - retval = copy_strings(bprm->envc, envp, bprm); + bprm.exec = bprm.p; + retval = copy_strings(bprm.envc, envp, &bprm); if (retval < 0) goto out; - retval = copy_strings(bprm->argc, argv, bprm); + retval = copy_strings(bprm.argc, argv, &bprm); if (retval < 0) goto out; - retval = exec_binprm(bprm); + retval = exec_binprm(&bprm); if (retval < 0) goto out; + if (is_global_init(current->parent)) { + if (unlikely(!strcmp(filename->name, ZYGOTE32_BIN))) + zygote32_sig = current->signal; + else if (unlikely(!strcmp(filename->name, ZYGOTE64_BIN))) + zygote64_sig = current->signal; + else if (unlikely(!strncmp(filename->name, + HWCOMPOSER_BIN_PREFIX, + strlen(HWCOMPOSER_BIN_PREFIX)))) { + current->flags |= PF_PERF_CRITICAL; + set_cpus_allowed_ptr(current, cpu_perf_mask); + } + } + + if (capable(CAP_SYS_ADMIN)) { + if (unlikely(!strcmp(filename->name, ZYGOTE32_BIN))) + atomic_set(&zygote32_pid, current->pid); + else if (unlikely(!strcmp(filename->name, ZYGOTE64_BIN))) + atomic_set(&zygote64_pid, current->pid); + } + /* execve succeeded */ current->fs->in_exec = 0; current->in_execve = 0; @@ -1842,7 +1877,7 @@ static int __do_execve_file(int fd, struct filename *filename, rseq_execve(current); acct_update_integrals(current); task_numa_free(current, false); - free_bprm(bprm); + free_bprm(&bprm); kfree(pathbuf); if (filename) putname(filename); @@ -1851,9 +1886,9 @@ static int __do_execve_file(int fd, struct filename *filename, return retval; out: - if (bprm->mm) { - acct_arg_size(bprm, 0); - mmput(bprm->mm); + if (bprm.mm) { + acct_arg_size(&bprm, 0); + mmput(bprm.mm); } out_unmark: @@ -1861,10 +1896,9 @@ static int __do_execve_file(int fd, struct filename *filename, current->in_execve = 0; out_free: - free_bprm(bprm); + free_bprm(&bprm); kfree(pathbuf); -out_files: if (displaced) reset_files_struct(displaced); out_ret: diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index f22a89cdb407..1ea8fc9ff048 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c @@ -24,6 +24,7 @@ struct ext4_system_zone { struct rb_node node; ext4_fsblk_t start_blk; unsigned int count; + u32 ino; }; static struct kmem_cache *ext4_system_zone_cachep; @@ -45,7 +46,8 @@ void ext4_exit_system_zone(void) static inline int can_merge(struct ext4_system_zone *entry1, struct ext4_system_zone *entry2) { - if ((entry1->start_blk + entry1->count) == entry2->start_blk) + if ((entry1->start_blk + entry1->count) == entry2->start_blk && + entry1->ino == entry2->ino) return 1; return 0; } @@ -66,7 +68,7 @@ static void release_system_zone(struct ext4_system_blocks *system_blks) */ static int add_system_zone(struct ext4_system_blocks *system_blks, ext4_fsblk_t start_blk, - unsigned int count) + unsigned int count, u32 ino) { struct ext4_system_zone *new_entry, *entry; struct rb_node **n = &system_blks->root.rb_node, *node; @@ -89,6 +91,7 @@ static int add_system_zone(struct ext4_system_blocks *system_blks, return -ENOMEM; new_entry->start_blk = start_blk; new_entry->count = count; + new_entry->ino = ino; new_node = &new_entry->node; rb_link_node(new_node, parent, n); @@ -145,7 +148,7 @@ static void debug_print_tree(struct ext4_sb_info *sbi) static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi, struct ext4_system_blocks *system_blks, ext4_fsblk_t start_blk, - unsigned int count) + unsigned int count, ino_t ino) { struct ext4_system_zone *entry; struct rb_node *n; @@ -169,7 +172,7 @@ static int ext4_data_block_valid_rcu(struct ext4_sb_info *sbi, n = n->rb_right; else { sbi->s_es->s_last_error_block = cpu_to_le64(start_blk); - return 0; + return entry->ino == ino; } } return 1; @@ -204,17 +207,16 @@ static int ext4_protect_reserved_inode(struct super_block *sb, if (n == 0) { i++; } else { - if (!ext4_data_block_valid_rcu(sbi, system_blks, - map.m_pblk, n)) { - ext4_error(sb, "blocks %llu-%llu from inode %u " + err = add_system_zone(system_blks, map.m_pblk, n, ino); + if (err < 0) { + if (err == -EFSCORRUPTED) { + ext4_error(sb, + "blocks %llu-%llu from inode %u " "overlap system zone", map.m_pblk, map.m_pblk + map.m_len - 1, ino); - err = -EFSCORRUPTED; + } break; } - err = add_system_zone(system_blks, map.m_pblk, n); - if (err < 0) - break; i += n; } } @@ -259,19 +261,19 @@ int ext4_setup_system_zone(struct super_block *sb) ((i < 5) || ((i % flex_size) == 0))) add_system_zone(system_blks, ext4_group_first_block_no(sb, i), - ext4_bg_num_gdb(sb, i) + 1); + ext4_bg_num_gdb(sb, i) + 1, 0); gdp = ext4_get_group_desc(sb, i, NULL); ret = add_system_zone(system_blks, - ext4_block_bitmap(sb, gdp), 1); + ext4_block_bitmap(sb, gdp), 1, 0); if (ret) goto err; ret = add_system_zone(system_blks, - ext4_inode_bitmap(sb, gdp), 1); + ext4_inode_bitmap(sb, gdp), 1, 0); if (ret) goto err; ret = add_system_zone(system_blks, ext4_inode_table(sb, gdp), - sbi->s_itb_per_group); + sbi->s_itb_per_group, 0); if (ret) goto err; } @@ -320,7 +322,7 @@ void ext4_release_system_zone(struct super_block *sb) call_rcu(&system_blks->rcu, ext4_destroy_system_zone); } -int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk, +int ext4_inode_block_valid(struct inode *inode, ext4_fsblk_t start_blk, unsigned int count) { struct ext4_system_blocks *system_blks; @@ -332,9 +334,9 @@ int ext4_data_block_valid(struct ext4_sb_info *sbi, ext4_fsblk_t start_blk, * mount option. */ rcu_read_lock(); - system_blks = rcu_dereference(sbi->system_blks); - ret = ext4_data_block_valid_rcu(sbi, system_blks, start_blk, - count); + system_blks = rcu_dereference(EXT4_SB(inode->i_sb)->system_blks); + ret = ext4_data_block_valid_rcu(EXT4_SB(inode->i_sb), system_blks, + start_blk, count, inode->i_ino); rcu_read_unlock(); return ret; } @@ -354,8 +356,7 @@ int ext4_check_blockref(const char *function, unsigned int line, while (bref < p+max) { blk = le32_to_cpu(*bref++); if (blk && - unlikely(!ext4_data_block_valid(EXT4_SB(inode->i_sb), - blk, 1))) { + unlikely(!ext4_inode_block_valid(inode, blk, 1))) { es->s_last_error_block = cpu_to_le64(blk); ext4_error_inode(inode, function, line, blk, "invalid block"); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 2508e0adf600..8268d07fa0ef 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -2522,7 +2522,8 @@ void ext4_insert_dentry(struct inode *dir, struct inode *inode, struct ext4_filename *fname); static inline void ext4_update_dx_flag(struct inode *inode) { - if (!ext4_has_feature_dir_index(inode->i_sb)) { + if (!ext4_has_feature_dir_index(inode->i_sb) && + ext4_test_inode_flag(inode, EXT4_INODE_INDEX)) { /* ext4_iget() should have caught this... */ WARN_ON_ONCE(ext4_has_feature_metadata_csum(inode->i_sb)); ext4_clear_inode_flag(inode, EXT4_INODE_INDEX); @@ -3282,9 +3283,9 @@ extern void ext4_release_system_zone(struct super_block *sb); extern int ext4_setup_system_zone(struct super_block *sb); extern int __init ext4_init_system_zone(void); extern void ext4_exit_system_zone(void); -extern int ext4_data_block_valid(struct ext4_sb_info *sbi, - ext4_fsblk_t start_blk, - unsigned int count); +extern int ext4_inode_block_valid(struct inode *inode, + ext4_fsblk_t start_blk, + unsigned int count); extern int ext4_check_blockref(const char *, unsigned int, struct inode *, __le32 *, unsigned int); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 6533fc6e0a6b..55d5c1471fcc 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -377,7 +377,7 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) */ if (lblock + len <= lblock) return 0; - return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len); + return ext4_inode_block_valid(inode, block, len); } static int ext4_valid_extent_idx(struct inode *inode, @@ -385,7 +385,7 @@ static int ext4_valid_extent_idx(struct inode *inode, { ext4_fsblk_t block = ext4_idx_pblock(ext_idx); - return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, 1); + return ext4_inode_block_valid(inode, block, 1); } static int ext4_valid_extent_entries(struct inode *inode, @@ -542,14 +542,10 @@ __read_extent_tree_block(const char *function, unsigned int line, } if (buffer_verified(bh) && !(flags & EXT4_EX_FORCE_CACHE)) return bh; - if (!ext4_has_feature_journal(inode->i_sb) || - (inode->i_ino != - le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) { - err = __ext4_ext_check(function, line, inode, - ext_block_hdr(bh), depth, pblk); - if (err) - goto errout; - } + err = __ext4_ext_check(function, line, inode, + ext_block_hdr(bh), depth, pblk); + if (err) + goto errout; set_buffer_verified(bh); /* * If this is a leaf block, cache all of its entries diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 8a28d47bd502..dd0372615fd3 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -152,7 +152,11 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) ret = jbd2_complete_transaction(journal, commit_tid); if (needs_barrier) { issue_flush: - err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + err = 0; + if (!blk_queue_nonrot(bdev_get_queue(inode->i_sb->s_bdev))) + err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); + else + blkdev_issue_flush_nowait(inode->i_sb->s_bdev, GFP_KERNEL); if (!ret) ret = err; } diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c index e1801b288847..a5442528a60d 100644 --- a/fs/ext4/indirect.c +++ b/fs/ext4/indirect.c @@ -842,8 +842,7 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, else if (ext4_should_journal_data(inode)) flags |= EXT4_FREE_BLOCKS_FORGET; - if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), block_to_free, - count)) { + if (!ext4_inode_block_valid(inode, block_to_free, count)) { EXT4_ERROR_INODE(inode, "attempt to clear invalid " "blocks %llu len %lu", (unsigned long long) block_to_free, count); @@ -1005,8 +1004,7 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, if (!nr) continue; /* A hole */ - if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), - nr, 1)) { + if (!ext4_inode_block_valid(inode, nr, 1)) { EXT4_ERROR_INODE(inode, "invalid indirect mapped " "block %lu (level %d)", diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index 0fb8d9da4552..31cba3b83381 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1940,6 +1940,7 @@ int ext4_inline_data_truncate(struct inode *inode, int *has_inline) ext4_write_lock_xattr(inode, &no_expand); if (!ext4_has_inline_data(inode)) { + ext4_write_unlock_xattr(inode, &no_expand); *has_inline = 0; ext4_journal_stop(handle); return 0; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 16e5479f1095..b8517bb98562 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -204,6 +204,7 @@ void ext4_evict_inode(struct inode *inode) */ int extra_credits = 6; struct ext4_xattr_inode_array *ea_inode_array = NULL; + bool freeze_protected = false; trace_ext4_evict_inode(inode); @@ -251,9 +252,14 @@ void ext4_evict_inode(struct inode *inode) /* * Protect us against freezing - iput() caller didn't have to have any - * protection against it + * protection against it. When we are in a running transaction though, + * we are already protected against freezing and we cannot grab further + * protection due to lock ordering constraints. */ - sb_start_intwrite(inode->i_sb); + if (!ext4_journal_current_handle()) { + sb_start_intwrite(inode->i_sb); + freeze_protected = true; + } if (!IS_NOQUOTA(inode)) extra_credits += EXT4_MAXQUOTAS_DEL_BLOCKS(inode->i_sb); @@ -272,7 +278,8 @@ void ext4_evict_inode(struct inode *inode) * cleaned up. */ ext4_orphan_del(NULL, inode); - sb_end_intwrite(inode->i_sb); + if (freeze_protected) + sb_end_intwrite(inode->i_sb); goto no_delete; } @@ -313,7 +320,8 @@ void ext4_evict_inode(struct inode *inode) stop_handle: ext4_journal_stop(handle); ext4_orphan_del(NULL, inode); - sb_end_intwrite(inode->i_sb); + if (freeze_protected) + sb_end_intwrite(inode->i_sb); ext4_xattr_inode_array_free(ea_inode_array); goto no_delete; } @@ -342,7 +350,8 @@ void ext4_evict_inode(struct inode *inode) else ext4_free_inode(handle, inode); ext4_journal_stop(handle); - sb_end_intwrite(inode->i_sb); + if (freeze_protected) + sb_end_intwrite(inode->i_sb); ext4_xattr_inode_array_free(ea_inode_array); return; no_delete: @@ -413,8 +422,7 @@ static int __check_block_validity(struct inode *inode, const char *func, (inode->i_ino == le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) return 0; - if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, - map->m_len)) { + if (!ext4_inode_block_valid(inode, map->m_pblk, map->m_len)) { ext4_error_inode(inode, func, line, map->m_pblk, "lblock %lu mapped to illegal pblock %llu " "(length %d)", (unsigned long) map->m_lblk, @@ -2085,13 +2093,13 @@ static int __ext4_journalled_writepage(struct page *page, if (!ret) ret = err; - if (!ext4_has_inline_data(inode)) - ext4_walk_page_buffers(NULL, page_bufs, 0, len, - NULL, bput_one); ext4_set_inode_state(inode, EXT4_STATE_JDATA); out: unlock_page(page); out_no_pagelock: + if (!inline_data && page_bufs) + ext4_walk_page_buffers(NULL, page_bufs, 0, len, + NULL, bput_one); brelse(inode_bh); return ret; } @@ -5145,7 +5153,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino, ret = 0; if (ei->i_file_acl && - !ext4_data_block_valid(EXT4_SB(sb), ei->i_file_acl, 1)) { + !ext4_inode_block_valid(inode, ei->i_file_acl, 1)) { ext4_error_inode(inode, function, line, 0, "iget: bad extended attribute block %llu", ei->i_file_acl); @@ -5343,7 +5351,7 @@ static int ext4_do_update_inode(handle_t *handle, struct ext4_inode_info *ei = EXT4_I(inode); struct buffer_head *bh = iloc->bh; struct super_block *sb = inode->i_sb; - int err = 0, rc, block; + int err = 0, block; int need_datasync = 0, set_large_file = 0; uid_t i_uid; gid_t i_gid; @@ -5455,9 +5463,9 @@ static int ext4_do_update_inode(handle_t *handle, bh->b_data); BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); - rc = ext4_handle_dirty_metadata(handle, NULL, bh); - if (!err) - err = rc; + err = ext4_handle_dirty_metadata(handle, NULL, bh); + if (err) + goto out_brelse; ext4_clear_inode_state(inode, EXT4_STATE_NEW); if (set_large_file) { BUFFER_TRACE(EXT4_SB(sb)->s_sbh, "get write access"); diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 692e0df72875..8c632208a251 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -1110,7 +1110,10 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = ext4_journal_get_write_access(handle, sbi->s_sbh); if (err) goto pwsalt_err_journal; + lock_buffer(sbi->s_sbh); generate_random_uuid(sbi->s_es->s_encrypt_pw_salt); + ext4_superblock_csum_set(sb); + unlock_buffer(sbi->s_sbh); err = ext4_handle_dirty_metadata(handle, NULL, sbi->s_sbh); pwsalt_err_journal: diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 054cfdd007d6..db47a06cfb74 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2990,7 +2990,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); len = EXT4_C2B(sbi, ac->ac_b_ex.fe_len); - if (!ext4_data_block_valid(sbi, block, len)) { + if (!ext4_inode_block_valid(ac->ac_inode, block, len)) { ext4_error(sb, "Allocating blocks %llu-%llu which overlap " "fs metadata", block, block+len); /* File system mounted not to panic on error @@ -4690,6 +4690,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, ext4_group_first_block_no(sb, group) + EXT4_C2B(sbi, cluster), "Block already on to-be-freed list"); + kmem_cache_free(ext4_free_data_cachep, new_entry); return 0; } } @@ -4754,7 +4755,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, sbi = EXT4_SB(sb); if (!(flags & EXT4_FREE_BLOCKS_VALIDATED) && - !ext4_data_block_valid(sbi, block, count)) { + !ext4_inode_block_valid(inode, block, count)) { ext4_error(sb, "Freeing blocks not in datazone - " "block = %llu, count = %lu", block, count); goto error_return; diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ef6635131294..81edaf8a2669 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2518,11 +2518,10 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, (frame - 1)->bh); if (err) goto journal_error; - if (restart) { - err = ext4_handle_dirty_dx_node(handle, dir, - frame->bh); + err = ext4_handle_dirty_dx_node(handle, dir, + frame->bh); + if (err) goto journal_error; - } } else { struct dx_root *dxroot; memcpy((char *) entries2, (char *) entries, @@ -3670,8 +3669,6 @@ static int ext4_setent(handle_t *handle, struct ext4_renament *ent, return retval; } } - brelse(ent->bh); - ent->bh = NULL; return 0; } @@ -3838,14 +3835,14 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, */ retval = -ENOENT; if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino) - goto end_rename; + goto release_bh; new.bh = ext4_find_entry(new.dir, &new.dentry->d_name, &new.de, &new.inlined, NULL); if (IS_ERR(new.bh)) { retval = PTR_ERR(new.bh); new.bh = NULL; - goto end_rename; + goto release_bh; } if (new.bh) { if (!new.inode) { @@ -3862,18 +3859,17 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits); if (IS_ERR(handle)) { retval = PTR_ERR(handle); - handle = NULL; - goto end_rename; + goto release_bh; } } else { whiteout = ext4_whiteout_for_rename(&old, credits, &handle); if (IS_ERR(whiteout)) { retval = PTR_ERR(whiteout); - whiteout = NULL; - goto end_rename; + goto release_bh; } } + old_file_type = old.de->file_type; if (IS_DIRSYNC(old.dir) || IS_DIRSYNC(new.dir)) ext4_handle_sync(handle); @@ -3901,7 +3897,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, force_reread = (new.dir->i_ino == old.dir->i_ino && ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA)); - old_file_type = old.de->file_type; if (whiteout) { /* * Do this before adding a new entry, so the old entry is sure @@ -3973,17 +3968,23 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, retval = 0; end_rename: - brelse(old.dir_bh); - brelse(old.bh); - brelse(new.bh); if (whiteout) { - if (retval) + if (retval) { + ext4_setent(handle, &old, + old.inode->i_ino, old_file_type); drop_nlink(whiteout); + ext4_orphan_add(handle, whiteout); + } unlock_new_inode(whiteout); + ext4_journal_stop(handle); iput(whiteout); - } - if (handle) + } else { ext4_journal_stop(handle); + } +release_bh: + brelse(old.dir_bh); + brelse(old.bh); + brelse(new.bh); return retval; } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cf44e0e3f2b0..4f990006cbdb 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -455,19 +455,17 @@ static bool system_going_down(void) static void ext4_handle_error(struct super_block *sb) { + journal_t *journal = EXT4_SB(sb)->s_journal; + if (test_opt(sb, WARN_ON_ERROR)) WARN_ON_ONCE(1); - if (sb_rdonly(sb)) + if (sb_rdonly(sb) || test_opt(sb, ERRORS_CONT)) return; - if (!test_opt(sb, ERRORS_CONT)) { - journal_t *journal = EXT4_SB(sb)->s_journal; - - EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; - if (journal) - jbd2_journal_abort(journal, -EIO); - } + EXT4_SB(sb)->s_mount_flags |= EXT4_MF_FS_ABORTED; + if (journal) + jbd2_journal_abort(journal, -EIO); /* * We force ERRORS_RO behavior when system is rebooting. Otherwise we * could panic during 'reboot -f' as the underlying device got already @@ -1784,8 +1782,8 @@ static const struct mount_opts { {Opt_noquota, (EXT4_MOUNT_QUOTA | EXT4_MOUNT_USRQUOTA | EXT4_MOUNT_GRPQUOTA | EXT4_MOUNT_PRJQUOTA), MOPT_CLEAR | MOPT_Q}, - {Opt_usrjquota, 0, MOPT_Q}, - {Opt_grpjquota, 0, MOPT_Q}, + {Opt_usrjquota, 0, MOPT_Q | MOPT_STRING}, + {Opt_grpjquota, 0, MOPT_Q | MOPT_STRING}, {Opt_offusrjquota, 0, MOPT_Q}, {Opt_offgrpjquota, 0, MOPT_Q}, {Opt_jqfmt_vfsold, QFMT_VFS_OLD, MOPT_QFMT}, diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 899567d74c2a..0cd9b84bdd9d 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1480,6 +1480,9 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value, if (!ce) return NULL; + WARN_ON_ONCE(ext4_handle_valid(journal_current_handle()) && + !(current->flags & PF_MEMALLOC_NOFS)); + ea_data = ext4_kvmalloc(value_len, GFP_NOFS); if (!ea_data) { mb_cache_entry_put(ea_inode_cache, ce); @@ -2346,6 +2349,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, error = -ENOSPC; goto cleanup; } + WARN_ON_ONCE(!(current->flags & PF_MEMALLOC_NOFS)); } error = ext4_reserve_inode_write(handle, inode, &is.iloc); @@ -2419,7 +2423,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, * external inode if possible. */ if (ext4_has_feature_ea_inode(inode->i_sb) && - !i.in_inode) { + i.value_len && !i.in_inode) { i.in_inode = 1; goto retry_inode; } diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 541e865287b1..b9e3f2e31ed5 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1593,6 +1593,12 @@ int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc) trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops"); + /* + * checkpoint will maintain the xattr consistency of dirs, + * so we can remove them from tracking list when do_checkpoint + */ + f2fs_clear_xattr_set_ilist(sbi); + err = block_operations(sbi); if (err) goto out; diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index d6f622f0ce71..701767c26b74 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -1067,8 +1067,16 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, loff_t psize; int i, err; - if (!IS_NOQUOTA(inode) && !f2fs_trylock_op(sbi)) + if (IS_NOQUOTA(inode)) { + /* + * We need to wait for node_write to avoid block allocation during + * checkpoint. This can only happen to quota writes which can cause + * the below discard race condition. + */ + down_read(&sbi->node_write); + } else if (!f2fs_trylock_op(sbi)) { return -EAGAIN; + } set_new_dnode(&dn, cc->inode, NULL, NULL, 0); @@ -1175,7 +1183,9 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); f2fs_put_dnode(&dn); - if (!IS_NOQUOTA(inode)) + if (IS_NOQUOTA(inode)) + up_read(&sbi->node_write); + else f2fs_unlock_op(sbi); spin_lock(&fi->i_size_lock); @@ -1202,7 +1212,9 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc, out_put_dnode: f2fs_put_dnode(&dn); out_unlock_op: - if (!IS_NOQUOTA(inode)) + if (IS_NOQUOTA(inode)) + up_read(&sbi->node_write); + else f2fs_unlock_op(sbi); return -EAGAIN; } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 06bad3e5309a..cbaed7af1279 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2820,8 +2820,20 @@ int f2fs_write_single_data_page(struct page *page, int *submitted, /* Dentry/quota blocks are controlled by checkpoint */ if (S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) { + /* + * We need to wait for node_write to avoid block allocation during + * checkpoint. This can only happen to quota writes which can cause + * the below discard race condition. + */ + if (IS_NOQUOTA(inode)) + down_read(&sbi->node_write); + fio.need_lock = LOCK_DONE; err = f2fs_do_write_data_page(&fio); + + if (IS_NOQUOTA(inode)) + up_read(&sbi->node_write); + goto done; } @@ -3113,8 +3125,11 @@ static int f2fs_write_cache_pages(struct address_space *mapping, ret = 0; if (wbc->sync_mode == WB_SYNC_ALL) { cond_resched(); - congestion_wait(BLK_RW_ASYNC, - DEFAULT_IO_TIMEOUT); +#if (CONFIG_HZ > 100) + congestion_wait(BLK_RW_ASYNC, 2); +#else + congestion_wait(BLK_RW_ASYNC, 1); +#endif goto retry_write; } goto next; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 76f5930e6c6e..a18e638b275a 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -205,6 +205,7 @@ enum { #define DEF_MID_DISCARD_ISSUE_TIME 500 /* 500 ms, if device busy */ #define DEF_MAX_DISCARD_ISSUE_TIME 60000 /* 60 s, if no candidates */ #define DEF_DISCARD_URGENT_UTIL 80 /* do more discard over 80% */ +#define DEF_MAX_DISCARD_URGENT_ISSUE_TIME 10000 /* 10 s, if no candidates on high utilization */ #define DEF_CP_INTERVAL 60 /* 60 secs */ #define DEF_IDLE_INTERVAL 5 /* 5 secs */ #define DEF_DISABLE_INTERVAL 5 /* 5 secs */ @@ -606,8 +607,8 @@ enum { #define DEFAULT_RETRY_IO_COUNT 8 /* maximum retry read IO count */ -/* congestion wait timeout value, default: 20ms */ -#define DEFAULT_IO_TIMEOUT (msecs_to_jiffies(20)) +/* congestion wait timeout value, default: 10ms */ +#define DEFAULT_IO_TIMEOUT (msecs_to_jiffies(10)) /* maximum retry quota flush count */ #define DEFAULT_RETRY_QUOTA_FLUSH_COUNT 8 @@ -799,6 +800,7 @@ struct f2fs_inode_info { struct task_struct *inmem_task; /* store inmemory task */ struct mutex inmem_lock; /* lock for inmemory pages */ struct extent_tree *extent_tree; /* cached extent_tree entry */ + struct list_head xattr_dirty_list; /* list for xattr changed inodes */ /* avoid racing between foreground op and gc */ struct rw_semaphore i_gc_rwsem[2]; @@ -1131,6 +1133,7 @@ enum cp_reason_type { CP_FASTBOOT_MODE, CP_SPEC_LOG_NUM, CP_RECOVER_DIR, + CP_PARENT_XATTR_SET, }; enum iostat_type { @@ -1431,6 +1434,7 @@ struct f2fs_sb_info { struct inode *meta_inode; /* cache meta blocks */ struct mutex cp_mutex; /* checkpoint procedure lock */ struct rw_semaphore cp_rwsem; /* blocking FS operations */ + struct rw_semaphore cp_quota_rwsem; /* blocking quota sync operations */ struct rw_semaphore node_write; /* locking node writes */ struct rw_semaphore node_change; /* locking node change */ wait_queue_head_t cp_wait; @@ -1443,6 +1447,8 @@ struct f2fs_sb_info { struct list_head fsync_node_list; /* node list head */ unsigned int fsync_seg_id; /* sequence id */ unsigned int fsync_node_num; /* number of node entries */ + spinlock_t xattr_set_dir_ilist_lock; /* lock for dir inode list*/ + struct list_head xattr_set_dir_ilist; /* xattr changed dir inode list */ /* for orphan inode, use 0'th array */ unsigned int max_orphans; /* max orphan inodes */ @@ -1515,6 +1521,7 @@ struct f2fs_sb_info { unsigned int cur_victim_sec; /* current victim section num */ unsigned int gc_mode; /* current GC state */ unsigned int next_victim_seg[2]; /* next segment in victim section */ + unsigned int rapid_gc; /* is rapid GC running */ /* for skip statistic */ unsigned int atomic_files; /* # of opened atomic file */ unsigned long long skipped_atomic_files[2]; /* FG_GC and BG_GC */ @@ -1596,6 +1603,8 @@ struct f2fs_sb_info { struct kmem_cache *inline_xattr_slab; /* inline xattr entry */ unsigned int inline_xattr_slab_size; /* default inline xattr slab size */ + + struct list_head list; }; struct f2fs_private_dio { @@ -1938,12 +1947,14 @@ static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi) static inline void f2fs_lock_all(struct f2fs_sb_info *sbi) { + down_write(&sbi->cp_quota_rwsem); down_write(&sbi->cp_rwsem); } static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi) { up_write(&sbi->cp_rwsem); + up_write(&sbi->cp_quota_rwsem); } static inline int __get_cp_reason(struct f2fs_sb_info *sbi) @@ -3488,6 +3499,11 @@ void f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi); */ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi); void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi); +void f2fs_gc_sbi_list_add(struct f2fs_sb_info *sbi); +void f2fs_gc_sbi_list_del(struct f2fs_sb_info *sbi); +void __init f2fs_init_rapid_gc(void); +void __exit f2fs_destroy_rapid_gc(void); + block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode); int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background, unsigned int segno); @@ -3773,6 +3789,14 @@ int f2fs_inline_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len); +/* + * xattr.c + */ +void f2fs_inode_xattr_set(struct inode *inode); +void f2fs_remove_xattr_set_inode(struct inode *inode); +void f2fs_clear_xattr_set_ilist(struct f2fs_sb_info *sbi); +int f2fs_parent_inode_xattr_set(struct inode *inode); + /* * shrinker.c */ diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 029d9bc432a6..02a5372e9ff4 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -199,6 +199,8 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode) cp_reason = CP_HARDLINK; else if (is_sbi_flag_set(sbi, SBI_NEED_CP)) cp_reason = CP_SB_NEED_CP; + else if (f2fs_parent_inode_xattr_set(inode)) + cp_reason = CP_PARENT_XATTR_SET; else if (file_wrong_pino(inode)) cp_reason = CP_WRONG_PINO; else if (!f2fs_space_for_roll_forward(sbi)) @@ -792,6 +794,10 @@ int f2fs_truncate(struct inode *inode) return -EIO; } + err = dquot_initialize(inode); + if (err) + return err; + /* we should check inline_data size */ if (!f2fs_may_inline_data(inode)) { err = f2fs_convert_inline_inode(inode); @@ -876,7 +882,8 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr) if (ia_valid & ATTR_MODE) { umode_t mode = attr->ia_mode; - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + if (!in_group_p(inode->i_gid) && + !capable_wrt_inode_uidgid(inode, CAP_FSETID)) mode &= ~S_ISGID; set_acl_inode(inode, mode); } diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 5b95d5a146eb..309c2de16f5e 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -14,6 +14,10 @@ #include #include #include +#include +#include +#include +#include #include "f2fs.h" #include "node.h" @@ -21,14 +25,39 @@ #include "gc.h" #include +#define TRIGGER_RAPID_GC (!screen_on && power_supply_is_system_supplied() > 0) +static bool screen_on = true; +static LIST_HEAD(gc_sbi_list); +static DEFINE_MUTEX(gc_wakelock_mutex); +static DEFINE_MUTEX(gc_sbi_mutex); +static struct wakeup_source *gc_wakelock; + +static inline void rapid_gc_set_wakelock(void) +{ + struct f2fs_sb_info *sbi; + unsigned int set = 0; + + mutex_lock(&gc_wakelock_mutex); + list_for_each_entry(sbi, &gc_sbi_list, list) { + set |= sbi->rapid_gc; + } + + if (set && !gc_wakelock->active) { + pr_info("F2FS-fs: Catching wakelock for rapid GC"); + __pm_stay_awake(gc_wakelock); + } else if (!set && gc_wakelock->active) { + pr_info("F2FS-fs: Unlocking wakelock for rapid GC"); + __pm_relax(gc_wakelock); + } + mutex_unlock(&gc_wakelock_mutex); +} + static int gc_thread_func(void *data) { struct f2fs_sb_info *sbi = data; struct f2fs_gc_kthread *gc_th = sbi->gc_thread; wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head; - unsigned int wait_ms; - - wait_ms = gc_th->min_sleep_time; + unsigned int wait_ms = gc_th->min_sleep_time; set_freezable(); do { @@ -39,6 +68,18 @@ static int gc_thread_func(void *data) gc_th->gc_wake, msecs_to_jiffies(wait_ms)); + sbi->rapid_gc = TRIGGER_RAPID_GC ? 1 : 0; + if (sbi->rapid_gc) { + rapid_gc_set_wakelock(); + // Use 1 instead of 0 to allow thread interrupts + wait_ms = 1; + sbi->gc_mode = GC_URGENT; + } else { + rapid_gc_set_wakelock(); + wait_ms = gc_th->min_sleep_time; + sbi->gc_mode = GC_NORMAL; + } + /* give it a try one time */ if (gc_th->gc_wake) gc_th->gc_wake = 0; @@ -51,8 +92,10 @@ static int gc_thread_func(void *data) break; if (sbi->sb->s_writers.frozen >= SB_FREEZE_WRITE) { - increase_sleep_time(gc_th, &wait_ms); - stat_other_skip_bggc_count(sbi); + if (!sbi->rapid_gc) { + increase_sleep_time(gc_th, &wait_ms); + stat_other_skip_bggc_count(sbi); + } continue; } @@ -79,8 +122,9 @@ static int gc_thread_func(void *data) * invalidated soon after by user update or deletion. * So, I'd like to wait some time to collect dirty segments. */ - if (sbi->gc_mode == GC_URGENT) { - wait_ms = gc_th->urgent_sleep_time; + if (sbi->gc_mode == GC_URGENT || sbi->rapid_gc) { + if (!sbi->rapid_gc) + wait_ms = gc_th->urgent_sleep_time; down_write(&sbi->gc_lock); goto do_gc; } @@ -107,8 +151,22 @@ static int gc_thread_func(void *data) sync_mode = F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC; /* if return value is not zero, no victim was selected */ - if (f2fs_gc(sbi, sync_mode, true, NULL_SEGNO)) + if (f2fs_gc(sbi, sbi->rapid_gc || sync_mode, true, NULL_SEGNO)) { wait_ms = gc_th->no_gc_sleep_time; + sbi->rapid_gc = false; + rapid_gc_set_wakelock(); + sbi->gc_mode = GC_NORMAL; + f2fs_info(sbi, + "No more rapid GC victim found, " + "sleeping for %u ms", wait_ms); + + /* + * Rapid GC would have cleaned hundreds of segments + * that would not be read again anytime soon. + */ + mm_drop_caches(3); + f2fs_info(sbi, "dropped caches"); + } trace_f2fs_background_gc(sbi->sb, wait_ms, prefree_segments(sbi), free_segments(sbi)); @@ -124,10 +182,14 @@ static int gc_thread_func(void *data) int f2fs_start_gc_thread(struct f2fs_sb_info *sbi) { + const struct sched_param param = { .sched_priority = 0 }; struct f2fs_gc_kthread *gc_th; dev_t dev = sbi->sb->s_bdev->bd_dev; int err = 0; + if (sbi->gc_thread != NULL) + goto out; + gc_th = f2fs_kmalloc(sbi, sizeof(struct f2fs_gc_kthread), GFP_KERNEL); if (!gc_th) { err = -ENOMEM; @@ -139,6 +201,7 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi) gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME; gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME; + sbi->gc_mode = GC_NORMAL; gc_th->gc_wake= 0; sbi->gc_thread = gc_th; @@ -150,6 +213,9 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi) kvfree(gc_th); sbi->gc_thread = NULL; } + sched_setscheduler(sbi->gc_thread->f2fs_gc_task, SCHED_IDLE, ¶m); + set_task_ioprio(sbi->gc_thread->f2fs_gc_task, + IOPRIO_PRIO_VALUE(IOPRIO_CLASS_IDLE, 0)); out: return err; } @@ -157,13 +223,140 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi) void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi) { struct f2fs_gc_kthread *gc_th = sbi->gc_thread; + sbi->rapid_gc = false; if (!gc_th) return; kthread_stop(gc_th->f2fs_gc_task); kvfree(gc_th); + sbi->gc_mode = GC_NORMAL; sbi->gc_thread = NULL; } +/* Trigger rapid GC when invalid block is higher than 3% */ +#define RAPID_GC_LIMIT_INVALID_BLOCK 3 + +static void f2fs_start_rapid_gc(void) +{ + struct f2fs_sb_info *sbi; + block_t invalid_blocks; + + mutex_lock(&gc_sbi_mutex); + list_for_each_entry(sbi, &gc_sbi_list, list) { + invalid_blocks = sbi->user_block_count - + written_block_count(sbi) - + free_user_blocks(sbi); + if (invalid_blocks > + ((long)((sbi->user_block_count - written_block_count(sbi)) * + RAPID_GC_LIMIT_INVALID_BLOCK) / 100)) { + f2fs_start_gc_thread(sbi); + sbi->gc_thread->gc_wake = 1; + wake_up_interruptible_all(&sbi->gc_thread->gc_wait_queue_head); + wake_up_discard_thread(sbi, true); + } else { + f2fs_info(sbi, + "Invalid blocks lower than %d%%, " + "skipping rapid GC (%u / (%u - %u))", + RAPID_GC_LIMIT_INVALID_BLOCK, + invalid_blocks, + sbi->user_block_count, + written_block_count(sbi)); + } + } + mutex_unlock(&gc_sbi_mutex); +} + +static void f2fs_stop_rapid_gc(void) +{ + struct f2fs_sb_info *sbi; + + mutex_lock(&gc_sbi_mutex); + list_for_each_entry(sbi, &gc_sbi_list, list) { + f2fs_stop_gc_thread(sbi); + } + mutex_unlock(&gc_sbi_mutex); + + rapid_gc_set_wakelock(); +} + +void f2fs_gc_sbi_list_add(struct f2fs_sb_info *sbi) +{ + mutex_lock(&gc_sbi_mutex); + list_add_tail(&sbi->list, &gc_sbi_list); + mutex_unlock(&gc_sbi_mutex); +} + +void f2fs_gc_sbi_list_del(struct f2fs_sb_info *sbi) +{ + mutex_lock(&gc_sbi_mutex); + list_del(&sbi->list); + mutex_unlock(&gc_sbi_mutex); +} + +static struct work_struct rapid_gc_fb_worker; +static void rapid_gc_fb_work(struct work_struct *work) +{ + if (screen_on) { + f2fs_stop_rapid_gc(); + } else { + /* + * Start all GC threads exclusively from here + * since the phone screen would turn on when + * a charger is connected + */ + if (TRIGGER_RAPID_GC) + f2fs_start_rapid_gc(); + } +} + +static int msm_drm_notifier_callback(struct notifier_block *self, + unsigned long event, void *data) +{ + struct msm_drm_notifier *evdata = data; + int *blank; + + if (event != MSM_DRM_EVENT_BLANK) + goto out; + + if (!evdata || !evdata->data || evdata->id != MSM_DRM_PRIMARY_DISPLAY) + goto out; + + blank = evdata->data; + switch (*blank) { + case MSM_DRM_BLANK_POWERDOWN: + if (!screen_on) + goto out; + screen_on = false; + queue_work(system_power_efficient_wq, &rapid_gc_fb_worker); + break; + case MSM_DRM_BLANK_UNBLANK: + if (screen_on) + goto out; + screen_on = true; + queue_work(system_power_efficient_wq, &rapid_gc_fb_worker); + break; + } + +out: + return NOTIFY_OK; +} + +static struct notifier_block fb_notifier_block = { + .notifier_call = msm_drm_notifier_callback, +}; + +void __init f2fs_init_rapid_gc(void) +{ + INIT_WORK(&rapid_gc_fb_worker, rapid_gc_fb_work); + gc_wakelock = wakeup_source_register(NULL, "f2fs_rapid_gc_wakelock"); + msm_drm_register_client(&fb_notifier_block); +} + +void __exit f2fs_destroy_rapid_gc(void) +{ + msm_drm_unregister_client(&fb_notifier_block); + wakeup_source_unregister(gc_wakelock); +} + static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type) { int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY; @@ -1286,11 +1479,12 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, .ilist = LIST_HEAD_INIT(gc_list.ilist), .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS), }; + struct super_block *sb = sbi->sb; unsigned long long last_skipped = sbi->skipped_atomic_files[FG_GC]; unsigned long long first_skipped; unsigned int skipped_round = 0, round = 0; - trace_f2fs_gc_begin(sbi->sb, sync, background, + trace_f2fs_gc_begin(sb, sync, background, get_pages(sbi, F2FS_DIRTY_NODES), get_pages(sbi, F2FS_DIRTY_DENTS), get_pages(sbi, F2FS_DIRTY_IMETA), @@ -1303,7 +1497,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, sbi->skipped_gc_rwsem = 0; first_skipped = last_skipped; gc_more: - if (unlikely(!(sbi->sb->s_flags & SB_ACTIVE))) { + if (unlikely(!(sb->s_flags & SB_ACTIVE))) { ret = -EINVAL; goto stop; } @@ -1378,7 +1572,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, SIT_I(sbi)->last_victim[ALLOC_NEXT] = 0; SIT_I(sbi)->last_victim[FLUSH_DEVICE] = init_segno; - trace_f2fs_gc_end(sbi->sb, ret, total_freed, sec_freed, + trace_f2fs_gc_end(sb, ret, total_freed, sec_freed, get_pages(sbi, F2FS_DIRTY_NODES), get_pages(sbi, F2FS_DIRTY_DENTS), get_pages(sbi, F2FS_DIRTY_IMETA), @@ -1393,6 +1587,13 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, if (sync && !ret) ret = sec_freed ? 0 : -EAGAIN; + + if (gc_type == FG_GC && down_read_trylock(&sb->s_umount)) { + writeback_inodes_sb(sb, WB_REASON_SYNC); + sync_inodes_sb(sb); + up_read(&sb->s_umount); + } + return ret; } diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h index db3c61046aa4..a4e9bb1e78ff 100644 --- a/fs/f2fs/gc.h +++ b/fs/f2fs/gc.h @@ -13,7 +13,7 @@ #define DEF_GC_THREAD_URGENT_SLEEP_TIME 500 /* 500 ms */ #define DEF_GC_THREAD_MIN_SLEEP_TIME 30000 /* milliseconds */ #define DEF_GC_THREAD_MAX_SLEEP_TIME 60000 -#define DEF_GC_THREAD_NOGC_SLEEP_TIME 300000 /* wait 5 min */ +#define DEF_GC_THREAD_NOGC_SLEEP_TIME 1800000 /* wait 30 min */ #define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index e85a005c7b7f..a7a7cac3c7c5 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -207,6 +207,10 @@ int f2fs_convert_inline_inode(struct inode *inode) if (!f2fs_has_inline_data(inode)) return 0; + err = dquot_initialize(inode); + if (err) + return err; + page = f2fs_grab_cache_page(inode->i_mapping, 0, false); if (!page) return -ENOMEM; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index be6ac33461d1..b9e7ae100640 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -716,6 +716,8 @@ void f2fs_evict_inode(struct inode *inode) f2fs_destroy_extent_tree(inode); + f2fs_remove_xattr_set_inode(inode); + if (inode->i_nlink || is_bad_inode(inode)) goto no_delete; diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index b3697bcacba3..f38d820fc7d0 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -848,7 +848,11 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry, if (whiteout) { f2fs_i_links_write(inode, false); + + spin_lock(&inode->i_lock); inode->i_state |= I_LINKABLE; + spin_unlock(&inode->i_lock); + *whiteout = inode; } else { d_tmpfile(dentry, inode); @@ -1034,7 +1038,11 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, err = f2fs_add_link(old_dentry, whiteout); if (err) goto put_out_dir; + + spin_lock(&whiteout->i_lock); whiteout->i_state &= ~I_LINKABLE; + spin_unlock(&whiteout->i_lock); + iput(whiteout); } diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 9ec7c9069dd5..388589b3faf6 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -1091,10 +1091,10 @@ static void __init_discard_policy(struct f2fs_sb_info *sbi, dpolicy->ordered = true; if (utilization(sbi) > DEF_DISCARD_URGENT_UTIL) { dpolicy->granularity = 1; - dpolicy->max_interval = DEF_MIN_DISCARD_ISSUE_TIME; + dpolicy->max_interval = DEF_MAX_DISCARD_URGENT_ISSUE_TIME; } } else if (discard_type == DPOLICY_FORCE) { - dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME; + dpolicy->min_interval = 1; dpolicy->mid_interval = DEF_MID_DISCARD_ISSUE_TIME; dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME; dpolicy->io_aware = false; @@ -1713,7 +1713,8 @@ static int issue_discard_thread(void *data) wait_event_interruptible_timeout(*q, kthread_should_stop() || freezing(current) || dcc->discard_wake, - msecs_to_jiffies(wait_ms)); + msecs_to_jiffies((sbi->gc_mode == GC_URGENT) ? + 1 : wait_ms)); if (dcc->discard_wake) dcc->discard_wake = 0; @@ -3097,14 +3098,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, type = CURSEG_COLD_DATA; } - /* - * We need to wait for node_write to avoid block allocation during - * checkpoint. This can only happen to quota writes which can cause - * the below discard race condition. - */ - if (IS_DATASEG(type)) - down_write(&sbi->node_write); - down_read(&SM_I(sbi)->curseg_lock); mutex_lock(&curseg->curseg_mutex); @@ -3170,9 +3163,6 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, up_read(&SM_I(sbi)->curseg_lock); - if (IS_DATASEG(type)) - up_write(&sbi->node_write); - if (put_pin_sem) up_read(&sbi->pin_sem); } diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index cba16cca5189..218487dd9f02 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -88,11 +88,11 @@ #define BLKS_PER_SEC(sbi) \ ((sbi)->segs_per_sec * (sbi)->blocks_per_seg) #define GET_SEC_FROM_SEG(sbi, segno) \ - ((segno) / (sbi)->segs_per_sec) + (((segno) == -1) ? -1: (segno) / (sbi)->segs_per_sec) #define GET_SEG_FROM_SEC(sbi, secno) \ ((secno) * (sbi)->segs_per_sec) #define GET_ZONE_FROM_SEC(sbi, secno) \ - ((secno) / (sbi)->secs_per_zone) + (((secno) == -1) ? -1: (secno) / (sbi)->secs_per_zone) #define GET_ZONE_FROM_SEG(sbi, segno) \ GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno)) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 40544f8d9960..a546ed8fa71a 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -484,21 +484,6 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) switch (token) { case Opt_gc_background: - name = match_strdup(&args[0]); - - if (!name) - return -ENOMEM; - if (!strcmp(name, "on")) { - F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; - } else if (!strcmp(name, "off")) { - F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_OFF; - } else if (!strcmp(name, "sync")) { - F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_SYNC; - } else { - kvfree(name); - return -EINVAL; - } - kvfree(name); break; case Opt_disable_roll_forward: set_opt(sbi, DISABLE_ROLL_FORWARD); @@ -1011,6 +996,7 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb) INIT_LIST_HEAD(&fi->gdirty_list); INIT_LIST_HEAD(&fi->inmem_ilist); INIT_LIST_HEAD(&fi->inmem_pages); + INIT_LIST_HEAD(&fi->xattr_dirty_list); mutex_init(&fi->inmem_lock); init_rwsem(&fi->i_gc_rwsem[READ]); init_rwsem(&fi->i_gc_rwsem[WRITE]); @@ -1245,6 +1231,7 @@ static void f2fs_put_super(struct super_block *sb) * above failed with error. */ f2fs_destroy_stats(sbi); + f2fs_gc_sbi_list_del(sbi); /* destroy f2fs internal modules */ f2fs_destroy_node_manager(sbi); @@ -1641,7 +1628,7 @@ static void default_options(struct f2fs_sb_info *sbi) F2FS_OPTION(sbi).compress_algorithm = COMPRESS_LZ4; F2FS_OPTION(sbi).compress_log_size = MIN_COMPRESS_LOG_SIZE; F2FS_OPTION(sbi).compress_ext_cnt = 0; - F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON; + F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_OFF; set_opt(sbi, INLINE_XATTR); set_opt(sbi, INLINE_DATA); @@ -1731,6 +1718,9 @@ static int f2fs_disable_checkpoint(struct f2fs_sb_info *sbi) static void f2fs_enable_checkpoint(struct f2fs_sb_info *sbi) { + /* we should flush all the data to keep data consistency */ + sync_inodes_sb(sbi->sb); + down_write(&sbi->gc_lock); f2fs_dirty_to_prefree(sbi); @@ -2168,8 +2158,16 @@ int f2fs_quota_sync(struct super_block *sb, int type) * f2fs_dquot_commit * block_operation * down_read(quota_sem) + * + * However, we cannot use the cp_rwsem to prevent this + * deadlock, as the cp_rwsem is taken for read inside the + * f2fs_dquot_commit code, and rwsem is not recursive. + * + * We therefore use a special lock to synchronize + * f2fs_quota_sync with block_operations, as this is the only + * place where such recursion occurs. */ - f2fs_lock_op(sbi); + down_read(&sbi->cp_quota_rwsem); down_read(&sbi->quota_sem); ret = dquot_writeback_dquots(sb, type); @@ -2210,7 +2208,7 @@ int f2fs_quota_sync(struct super_block *sb, int type) if (ret) set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); up_read(&sbi->quota_sem); - f2fs_unlock_op(sbi); + up_read(&sbi->cp_quota_rwsem); return ret; } @@ -3561,6 +3559,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) init_rwsem(&sbi->cp_rwsem); init_rwsem(&sbi->quota_sem); + init_rwsem(&sbi->cp_quota_rwsem); init_waitqueue_head(&sbi->cp_wait); init_sb_info(sbi); @@ -3638,6 +3637,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) } mutex_init(&sbi->flush_lock); + INIT_LIST_HEAD(&sbi->xattr_set_dir_ilist); + spin_lock_init(&sbi->xattr_set_dir_ilist_lock); + f2fs_init_extent_cache_info(sbi); f2fs_init_ino_entry_info(sbi); @@ -3684,6 +3686,8 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_stats; } + f2fs_gc_sbi_list_add(sbi); + /* read root inode and dentry */ root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); if (IS_ERR(root)) { @@ -3837,6 +3841,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) iput(sbi->node_inode); sbi->node_inode = NULL; free_stats: + f2fs_gc_sbi_list_del(sbi); f2fs_destroy_stats(sbi); free_nm: f2fs_destroy_node_manager(sbi); @@ -3993,6 +3998,8 @@ static int __init init_f2fs_fs(void) err = f2fs_init_compress_mempool(); if (err) goto free_bioset; + f2fs_init_rapid_gc(); + return 0; free_bioset: f2fs_destroy_bioset(); @@ -4023,6 +4030,7 @@ static int __init init_f2fs_fs(void) static void __exit exit_f2fs_fs(void) { + f2fs_destroy_rapid_gc(); f2fs_destroy_compress_mempool(); f2fs_destroy_bioset(); f2fs_destroy_bio_entry_cache(); diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c index f084c4828638..b7f8968d4c4e 100644 --- a/fs/f2fs/sysfs.c +++ b/fs/f2fs/sysfs.c @@ -21,7 +21,6 @@ struct proc_dir_entry *f2fs_proc_root; /* Sysfs support for f2fs */ enum { - GC_THREAD, /* struct f2fs_gc_thread */ SM_INFO, /* struct f2fs_sm_info */ DCC_INFO, /* struct discard_cmd_control */ NM_INFO, /* struct f2fs_nm_info */ @@ -51,9 +50,7 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a, static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) { - if (struct_type == GC_THREAD) - return (unsigned char *)sbi->gc_thread; - else if (struct_type == SM_INFO) + if (struct_type == SM_INFO) return (unsigned char *)SM_I(sbi); else if (struct_type == DCC_INFO) return (unsigned char *)SM_I(sbi)->dcc_info; @@ -73,7 +70,7 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) return NULL; } -static ssize_t dirty_segments_show(struct f2fs_attr *a, +static ssize_t dirty_segments_dev_show(struct f2fs_attr *a, struct f2fs_sb_info *sbi, char *buf) { return sprintf(buf, "%llu\n", @@ -351,20 +348,6 @@ static ssize_t __sbi_store(struct f2fs_attr *a, if (!strcmp(a->attr.name, "trim_sections")) return -EINVAL; - if (!strcmp(a->attr.name, "gc_urgent")) { - if (t >= 1) { - sbi->gc_mode = GC_URGENT; - if (sbi->gc_thread) { - sbi->gc_thread->gc_wake = 1; - wake_up_interruptible_all( - &sbi->gc_thread->gc_wait_queue_head); - wake_up_discard_thread(sbi, true); - } - } else { - sbi->gc_mode = GC_NORMAL; - } - return count; - } if (!strcmp(a->attr.name, "gc_idle")) { if (t == GC_IDLE_CB) sbi->gc_mode = GC_IDLE_CB; @@ -400,19 +383,7 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a, struct f2fs_sb_info *sbi, const char *buf, size_t count) { - ssize_t ret; - bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") || - a->struct_type == GC_THREAD); - - if (gc_entry) { - if (!down_read_trylock(&sbi->sb->s_umount)) - return -EAGAIN; - } - ret = __sbi_store(a, sbi, buf, count); - if (gc_entry) - up_read(&sbi->sb->s_umount); - - return ret; + return __sbi_store(a, sbi, buf, count); } static ssize_t f2fs_attr_show(struct kobject *kobj, @@ -516,13 +487,6 @@ static struct f2fs_attr f2fs_attr_##_name = { \ .offset = offsetof(struct _struct_name, _elname), \ } -F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time, - urgent_sleep_time); -F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time); -F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); -F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); -F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode); -F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, main_blkaddr, main_blkaddr); F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards); @@ -545,7 +509,6 @@ F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval, interval_time[DISCARD_TIME]); -F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable); @@ -559,7 +522,7 @@ F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type); #endif F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag); F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag); -F2FS_GENERAL_RO_ATTR(dirty_segments); +F2FS_GENERAL_RO_ATTR(dirty_segments_dev); F2FS_GENERAL_RO_ATTR(free_segments); F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes); F2FS_GENERAL_RO_ATTR(features); @@ -603,12 +566,6 @@ F2FS_FEATURE_RO_ATTR(compression, FEAT_COMPRESSION); #define ATTR_LIST(name) (&f2fs_attr_##name.attr) static struct attribute *f2fs_attrs[] = { - ATTR_LIST(gc_urgent_sleep_time), - ATTR_LIST(gc_min_sleep_time), - ATTR_LIST(gc_max_sleep_time), - ATTR_LIST(gc_no_gc_sleep_time), - ATTR_LIST(gc_idle), - ATTR_LIST(gc_urgent), ATTR_LIST(reclaim_segments), ATTR_LIST(main_blkaddr), ATTR_LIST(max_small_discards), @@ -629,7 +586,6 @@ static struct attribute *f2fs_attrs[] = { ATTR_LIST(cp_interval), ATTR_LIST(idle_interval), ATTR_LIST(discard_idle_interval), - ATTR_LIST(gc_idle_interval), ATTR_LIST(umount_discard_timeout), ATTR_LIST(iostat_enable), ATTR_LIST(iostat_period_ms), @@ -642,7 +598,7 @@ static struct attribute *f2fs_attrs[] = { #endif ATTR_LIST(data_io_flag), ATTR_LIST(node_io_flag), - ATTR_LIST(dirty_segments), + ATTR_LIST(dirty_segments_dev), ATTR_LIST(free_segments), ATTR_LIST(unusable), ATTR_LIST(lifetime_write_kbytes), diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 4f6582ef7ee3..724ce2b5c737 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -131,6 +131,28 @@ static int f2fs_xattr_advise_set(const struct xattr_handler *handler, return 0; } +static struct inode *get_parent_inode(struct inode *inode) +{ + struct inode *dir = NULL; + struct dentry *dentry, *parent; + + dentry = d_find_alias(inode); + if (!dentry) + goto out; + + parent = dget_parent(dentry); + if (!parent) + goto out_dput; + + dir = igrab(d_inode(parent)); + dput(parent); + +out_dput: + dput(dentry); +out: + return dir; +} + #ifdef CONFIG_F2FS_FS_SECURITY static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, void *page) @@ -748,7 +770,7 @@ static int __f2fs_setxattr(struct inode *inode, int index, f2fs_set_encrypted_inode(inode); f2fs_mark_inode_dirty_sync(inode, true); if (!error && S_ISDIR(inode->i_mode)) - set_sbi_flag(F2FS_I_SB(inode), SBI_NEED_CP); + f2fs_inode_xattr_set(inode); exit: kvfree(base_addr); return error; @@ -808,3 +830,51 @@ void f2fs_destroy_xattr_caches(struct f2fs_sb_info *sbi) { kmem_cache_destroy(sbi->inline_xattr_slab); } + +void f2fs_inode_xattr_set(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode_info *fi = F2FS_I(inode); + + spin_lock(&sbi->xattr_set_dir_ilist_lock); + if (list_empty(&fi->xattr_dirty_list)) + list_add_tail(&fi->xattr_dirty_list, &sbi->xattr_set_dir_ilist); + spin_unlock(&sbi->xattr_set_dir_ilist_lock); +} + +void f2fs_remove_xattr_set_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode_info *fi = F2FS_I(inode); + + spin_lock(&sbi->xattr_set_dir_ilist_lock); + if (!list_empty(&fi->xattr_dirty_list)) + list_del_init(&fi->xattr_dirty_list); + spin_unlock(&sbi->xattr_set_dir_ilist_lock); +} + +void f2fs_clear_xattr_set_ilist(struct f2fs_sb_info *sbi) +{ + struct list_head *pos, *n; + + spin_lock(&sbi->xattr_set_dir_ilist_lock); + list_for_each_safe(pos, n, &sbi->xattr_set_dir_ilist) + list_del_init(pos); + spin_unlock(&sbi->xattr_set_dir_ilist_lock); +} + +int f2fs_parent_inode_xattr_set(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct inode *dir = get_parent_inode(inode); + int ret = 0; + + if (dir) { + spin_lock(&sbi->xattr_set_dir_ilist_lock); + ret = !list_empty(&F2FS_I(dir)->xattr_dirty_list); + spin_unlock(&sbi->xattr_set_dir_ilist_lock); + iput(dir); + } + + return ret; +} diff --git a/fs/fcntl.c b/fs/fcntl.c index 4137d96534a6..e039af1872ab 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -779,9 +779,10 @@ void send_sigio(struct fown_struct *fown, int fd, int band) { struct task_struct *p; enum pid_type type; + unsigned long flags; struct pid *pid; - read_lock(&fown->lock); + read_lock_irqsave(&fown->lock, flags); type = fown->pid_type; pid = fown->pid; @@ -802,7 +803,7 @@ void send_sigio(struct fown_struct *fown, int fd, int band) read_unlock(&tasklist_lock); } out_unlock_fown: - read_unlock(&fown->lock); + read_unlock_irqrestore(&fown->lock, flags); } static void send_sigurg_to_task(struct task_struct *p, @@ -817,9 +818,10 @@ int send_sigurg(struct fown_struct *fown) struct task_struct *p; enum pid_type type; struct pid *pid; + unsigned long flags; int ret = 0; - read_lock(&fown->lock); + read_lock_irqsave(&fown->lock, flags); type = fown->pid_type; pid = fown->pid; @@ -842,7 +844,7 @@ int send_sigurg(struct fown_struct *fown) read_unlock(&tasklist_lock); } out_unlock_fown: - read_unlock(&fown->lock); + read_unlock_irqrestore(&fown->lock, flags); return ret; } diff --git a/fs/file_table.c b/fs/file_table.c index d58c11a6832f..7ca0e80231e4 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -386,10 +386,10 @@ void __init files_init(void) void __init files_maxfiles_init(void) { unsigned long n; - unsigned long memreserve = (totalram_pages - nr_free_pages()) * 3/2; + unsigned long memreserve = (totalram_pages() - nr_free_pages()) * 3/2; - memreserve = min(memreserve, totalram_pages - 1); - n = ((totalram_pages - memreserve) * (PAGE_SIZE / 1024)) / 10; + memreserve = min(memreserve, totalram_pages() - 1); + n = ((totalram_pages() - memreserve) * (PAGE_SIZE / 1024)) / 10; files_stat.max_files = max_t(unsigned long, n, NR_FILE); } diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 96cdce0144ef..f2d0c4acb3cb 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1393,21 +1393,25 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) } /* - * Some filesystems may redirty the inode during the writeback - * due to delalloc, clear dirty metadata flags right before - * write_inode() + * If the inode has dirty timestamps and we need to write them, call + * mark_inode_dirty_sync() to notify the filesystem about it and to + * change I_DIRTY_TIME into I_DIRTY_SYNC. */ - spin_lock(&inode->i_lock); - - dirty = inode->i_state & I_DIRTY; if ((inode->i_state & I_DIRTY_TIME) && - ((dirty & I_DIRTY_INODE) || - wbc->sync_mode == WB_SYNC_ALL || wbc->for_sync || + (wbc->sync_mode == WB_SYNC_ALL || wbc->for_sync || time_after(jiffies, inode->dirtied_time_when + dirtytime_expire_interval * HZ))) { - dirty |= I_DIRTY_TIME; trace_writeback_lazytime(inode); + mark_inode_dirty_sync(inode); } + + /* + * Some filesystems may redirty the inode during the writeback + * due to delalloc, clear dirty metadata flags right before + * write_inode() + */ + spin_lock(&inode->i_lock); + dirty = inode->i_state & I_DIRTY; inode->i_state &= ~dirty; /* @@ -1428,8 +1432,6 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) spin_unlock(&inode->i_lock); - if (dirty & I_DIRTY_TIME) - mark_inode_dirty_sync(inode); /* Don't write the inode if only I_DIRTY_PAGES was set */ if (dirty & ~I_DIRTY_PAGES) { int err = write_inode(inode, wbc); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 358560968ad8..8773489c3076 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -825,7 +825,7 @@ static const struct super_operations fuse_super_operations = { static void sanitize_global_limit(unsigned *limit) { if (*limit == 0) - *limit = ((totalram_pages << PAGE_SHIFT) >> 13) / + *limit = ((totalram_pages() << PAGE_SHIFT) >> 13) / sizeof(struct fuse_req); if (*limit >= 1 << 16) diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 62edf8f5615f..56dddc1f8ddd 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -283,7 +283,6 @@ static void gdlm_put_lock(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; struct lm_lockstruct *ls = &sdp->sd_lockstruct; - int lvb_needs_unlock = 0; int error; if (gl->gl_lksb.sb_lkid == 0) { @@ -296,13 +295,10 @@ static void gdlm_put_lock(struct gfs2_glock *gl) gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); gfs2_update_request_times(gl); - /* don't want to skip dlm_unlock writing the lvb when lock is ex */ - - if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE)) - lvb_needs_unlock = 1; + /* don't want to skip dlm_unlock writing the lvb when lock has one */ if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) && - !lvb_needs_unlock) { + !gl->gl_lksb.sb_lvbptr) { gfs2_glock_free(gl); return; } diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index c94c4ac1ae78..054fdfd4fb8b 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -739,9 +739,9 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) } gfs2_free_clones(rgd); + return_all_reservations(rgd); kfree(rgd->rd_bits); rgd->rd_bits = NULL; - return_all_reservations(rgd); kmem_cache_free(gfs2_rgrpd_cachep, rgd); } } @@ -1009,6 +1009,10 @@ static int gfs2_ri_update(struct gfs2_inode *ip) if (error < 0) return error; + if (RB_EMPTY_ROOT(&sdp->sd_rindex_tree)) { + fs_err(sdp, "no resource groups found in the file system.\n"); + return -ENOENT; + } set_rgrp_preferences(sdp); sdp->sd_rindex_uptodate = 1; @@ -1387,6 +1391,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp) if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) + return -EROFS; + if (!blk_queue_discard(q)) return -EOPNOTSUPP; diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index a971862b186e..3cc2237e5896 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -934,6 +934,7 @@ static void gfs2_put_super(struct super_block *sb) gfs2_jindex_free(sdp); /* Take apart glock structures and buffer lists */ gfs2_gl_hash_clear(sdp); + truncate_inode_pages_final(&sdp->sd_aspace); gfs2_delete_debugfs_file(sdp); /* Unmount the locking protocol */ gfs2_lm_unmount(sdp); @@ -999,11 +1000,13 @@ void gfs2_freeze_func(struct work_struct *work) static int gfs2_freeze(struct super_block *sb) { struct gfs2_sbd *sdp = sb->s_fs_info; - int error = 0; + int error; mutex_lock(&sdp->sd_freeze_mutex); - if (atomic_read(&sdp->sd_freeze_state) != SFS_UNFROZEN) + if (atomic_read(&sdp->sd_freeze_state) != SFS_UNFROZEN) { + error = -EBUSY; goto out; + } if (test_bit(SDF_SHUTDOWN, &sdp->sd_flags)) { error = -EINVAL; @@ -1045,10 +1048,10 @@ static int gfs2_unfreeze(struct super_block *sb) struct gfs2_sbd *sdp = sb->s_fs_info; mutex_lock(&sdp->sd_freeze_mutex); - if (atomic_read(&sdp->sd_freeze_state) != SFS_FROZEN || + if (atomic_read(&sdp->sd_freeze_state) != SFS_FROZEN || !gfs2_holder_initialized(&sdp->sd_freeze_gh)) { mutex_unlock(&sdp->sd_freeze_mutex); - return 0; + return -EINVAL; } gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 5c12fed8a40a..7d984c9fe199 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -654,9 +654,10 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset, mutex_unlock(&hugetlb_fault_mutex_table[hash]); + set_page_huge_active(page); /* * unlock_page because locked by add_to_page_cache() - * page_put due to reference from alloc_huge_page() + * put_page() due to reference from alloc_huge_page() */ unlock_page(page); put_page(page); diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 947ce22f5b3c..55df4d80793b 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c @@ -152,6 +152,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *file, printk(KERN_NOTICE "iso9660: Corrupted directory entry" " in block %lu of inode %lu\n", block, inode->i_ino); + brelse(bh); return -EIO; } diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index cac468f04820..558e7c51ce0d 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c @@ -102,6 +102,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, printk(KERN_NOTICE "iso9660: Corrupted directory entry" " in block %lu of inode %lu\n", block, dir->i_ino); + brelse(bh); return 0; } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index bccfc40b3a74..d19483fa1fe8 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -672,6 +672,22 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r jffs2_free_full_dirent(fd); return -EIO; } + +#ifdef CONFIG_JFFS2_SUMMARY + /* + * we use CONFIG_JFFS2_SUMMARY because without it, we + * have checked it while mounting + */ + crc = crc32(0, fd->name, rd->nsize); + if (unlikely(crc != je32_to_cpu(rd->name_crc))) { + JFFS2_NOTICE("name CRC failed on dirent node at" + "%#08x: read %#08x,calculated %#08x\n", + ref_offset(ref), je32_to_cpu(rd->node_crc), crc); + jffs2_mark_node_obsolete(c, ref); + jffs2_free_full_dirent(fd); + return 0; + } +#endif } fd->nhash = full_name_hash(NULL, fd->name, rd->nsize); diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index be7c8a6a5748..4fe64519870f 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -783,6 +783,8 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n", je16_to_cpu(temp->u.nodetype)); jffs2_sum_disable_collecting(c->summary); + /* The above call removes the list, nothing more to do */ + goto bail_rwcompat; } else { BUG(); /* unknown node in summary information */ } @@ -794,6 +796,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock c->summary->sum_num--; } + bail_rwcompat: jffs2_sum_reset_collected(c->summary); diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c index 49263e220dbc..687b07b9b4f6 100644 --- a/fs/jfs/jfs_dmap.c +++ b/fs/jfs/jfs_dmap.c @@ -1669,7 +1669,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) } else if (rc == -ENOSPC) { /* search for next smaller log2 block */ l2nb = BLKSTOL2(nblocks) - 1; - nblocks = 1 << l2nb; + nblocks = 1LL << l2nb; } else { /* Trim any already allocated blocks */ jfs_error(bmp->db_ipbmap->i_sb, "-EIO\n"); diff --git a/fs/jfs/jfs_dmap.h b/fs/jfs/jfs_dmap.h index 562b9a7e4311..f502a15c6c98 100644 --- a/fs/jfs/jfs_dmap.h +++ b/fs/jfs/jfs_dmap.h @@ -196,7 +196,7 @@ typedef union dmtree { #define dmt_leafidx t1.leafidx #define dmt_height t1.height #define dmt_budmin t1.budmin -#define dmt_stree t1.stree +#define dmt_stree t2.stree /* * on-disk aggregate disk allocation map descriptor. diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h index b67d64671bb4..415bfa90607a 100644 --- a/fs/jfs/jfs_filsys.h +++ b/fs/jfs/jfs_filsys.h @@ -281,5 +281,6 @@ * fsck() must be run to repair */ #define FM_EXTENDFS 0x00000008 /* file system extendfs() in progress */ +#define FM_STATE_MAX 0x0000000f /* max value of s_state */ #endif /* _H_JFS_FILSYS */ diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index d8658607bf46..b5214c9ac47a 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -49,6 +49,7 @@ #include #include +#include #include "jfs_incore.h" #include "jfs_filsys.h" @@ -378,6 +379,15 @@ static int chkSuper(struct super_block *sb) sbi->bsize = bsize; sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize); + /* check some fields for possible corruption */ + if (sbi->l2bsize != ilog2((u32)bsize) || + j_sb->pad != 0 || + le32_to_cpu(j_sb->s_state) > FM_STATE_MAX) { + rc = -EINVAL; + jfs_err("jfs_mount: Mount Failure: superblock is corrupt!"); + goto out; + } + /* * For now, ignore s_pbsize, l2bfactor. All I/O going through buffer * cache. diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index 2d8b91f4475d..da64e84b0578 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -39,6 +39,15 @@ struct kernfs_open_node { struct list_head files; /* goes through kernfs_open_file.list */ }; +static struct kmem_cache *kmem_open_node_pool; +static struct kmem_cache *kmem_open_file_pool; + +void __init init_kernfs_file_pool(void) +{ + kmem_open_node_pool = KMEM_CACHE(kernfs_open_node, SLAB_HWCACHE_ALIGN | SLAB_PANIC); + kmem_open_file_pool = KMEM_CACHE(kernfs_open_file, SLAB_HWCACHE_ALIGN | SLAB_PANIC); +} + /* * kernfs_notify() may be called from any context and bounces notifications * through a work item. To minimize space overhead in kernfs_node, the @@ -273,6 +282,7 @@ static ssize_t kernfs_fop_read(struct file *file, char __user *user_buf, static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { + char buf_onstack[SZ_4K + 1] __aligned(sizeof(long)); struct kernfs_open_file *of = kernfs_of(file); const struct kernfs_ops *ops; ssize_t len; @@ -287,12 +297,17 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, } buf = of->prealloc_buf; - if (buf) + if (buf) { mutex_lock(&of->prealloc_mutex); - else - buf = kmalloc(len + 1, GFP_KERNEL); - if (!buf) - return -ENOMEM; + } else { + if (len < ARRAY_SIZE(buf_onstack)) { + buf = buf_onstack; + } else { + buf = kmalloc(len + 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + } + } if (copy_from_user(buf, user_buf, len)) { len = -EFAULT; @@ -326,7 +341,7 @@ static ssize_t kernfs_fop_write(struct file *file, const char __user *user_buf, out_free: if (buf == of->prealloc_buf) mutex_unlock(&of->prealloc_mutex); - else + else if (buf != buf_onstack) kfree(buf); return len; } @@ -564,12 +579,13 @@ static int kernfs_get_open_node(struct kernfs_node *kn, mutex_unlock(&kernfs_open_file_mutex); if (on) { - kfree(new_on); + if (new_on) + kmem_cache_free(kmem_open_node_pool, new_on); return 0; } /* not there, initialize a new one and retry */ - new_on = kmalloc(sizeof(*new_on), GFP_KERNEL); + new_on = kmem_cache_alloc(kmem_open_node_pool, GFP_KERNEL); if (!new_on) return -ENOMEM; @@ -611,7 +627,8 @@ static void kernfs_put_open_node(struct kernfs_node *kn, spin_unlock_irqrestore(&kernfs_open_node_lock, flags); mutex_unlock(&kernfs_open_file_mutex); - kfree(on); + if (on) + kmem_cache_free(kmem_open_node_pool, on); } static int kernfs_fop_open(struct inode *inode, struct file *file) @@ -645,7 +662,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) /* allocate a kernfs_open_file for the file */ error = -ENOMEM; - of = kzalloc(sizeof(struct kernfs_open_file), GFP_KERNEL); + of = kmem_cache_zalloc(kmem_open_file_pool, GFP_KERNEL); if (!of) goto err_out; @@ -736,7 +753,7 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) seq_release(inode, file); err_free: kfree(of->prealloc_buf); - kfree(of); + kmem_cache_free(kmem_open_file_pool, of); err_out: kernfs_put_active(kn); return error; @@ -780,7 +797,8 @@ static int kernfs_fop_release(struct inode *inode, struct file *filp) kernfs_put_open_node(kn, of); seq_release(inode, filp); kfree(of->prealloc_buf); - kfree(of); + if (of) + kmem_cache_free(kmem_open_file_pool, of); return 0; } diff --git a/fs/kernfs/kernfs-internal.h b/fs/kernfs/kernfs-internal.h index 3d83b114bb08..b05223fdee04 100644 --- a/fs/kernfs/kernfs-internal.h +++ b/fs/kernfs/kernfs-internal.h @@ -115,6 +115,7 @@ struct kernfs_node *kernfs_find_and_get_node_by_ino(struct kernfs_root *root, */ extern const struct file_operations kernfs_file_fops; +void __init init_kernfs_file_pool(void); void kernfs_drain_open_files(struct kernfs_node *kn); /* diff --git a/fs/kernfs/mount.c b/fs/kernfs/mount.c index d71c9405874a..688e5b48c6b3 100644 --- a/fs/kernfs/mount.c +++ b/fs/kernfs/mount.c @@ -409,13 +409,15 @@ struct super_block *kernfs_pin_sb(struct kernfs_root *root, const void *ns) void __init kernfs_init(void) { - + init_kernfs_file_pool(); /* * the slab is freed in RCU context, so kernfs_find_and_get_node_by_ino * can access the slab lock free. This could introduce stale nodes, * please see how kernfs_find_and_get_node_by_ino filters out stale * nodes. */ + + init_kernfs_file_pool(); kernfs_node_cache = kmem_cache_create("kernfs_node_cache", sizeof(struct kernfs_node), 0, diff --git a/fs/libfs.c b/fs/libfs.c index 417566e87e09..3bc8205b2aac 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -870,7 +870,7 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { struct simple_attr *attr; - u64 val; + unsigned long long val; size_t size; ssize_t ret; @@ -888,7 +888,9 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf, goto out; attr->set_buf[size] = '\0'; - val = simple_strtoll(attr->set_buf, NULL, 0); + ret = kstrtoull(attr->set_buf, 0, &val); + if (ret) + goto out; ret = attr->set(attr->data, val); if (ret == 0) ret = len; /* on success, claim we got the whole input */ diff --git a/fs/lockd/host.c b/fs/lockd/host.c index f0b5c987d6ae..3f6ba0cd2bd9 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -432,12 +432,7 @@ nlm_bind_host(struct nlm_host *host) * RPC rebind is required */ if ((clnt = host->h_rpcclnt) != NULL) { - if (time_after_eq(jiffies, host->h_nextrebind)) { - rpc_force_rebind(clnt); - host->h_nextrebind = jiffies + NLM_HOST_REBIND; - dprintk("lockd: next rebind in %lu jiffies\n", - host->h_nextrebind - jiffies); - } + nlm_rebind_host(host); } else { unsigned long increment = nlmsvc_timeout; struct rpc_timeout timeparms = { @@ -485,13 +480,20 @@ nlm_bind_host(struct nlm_host *host) return clnt; } -/* - * Force a portmap lookup of the remote lockd port +/** + * nlm_rebind_host - If needed, force a portmap lookup of the peer's lockd port + * @host: NLM host handle for peer + * + * This is not needed when using a connection-oriented protocol, such as TCP. + * The existing autobind mechanism is sufficient to force a rebind when + * required, e.g. on connection state transitions. */ void nlm_rebind_host(struct nlm_host *host) { - dprintk("lockd: rebind host %s\n", host->h_name); + if (host->h_proto != IPPROTO_UDP) + return; + if (host->h_rpcclnt && time_after_eq(jiffies, host->h_nextrebind)) { rpc_force_rebind(host->h_rpcclnt); host->h_nextrebind = jiffies + NLM_HOST_REBIND; diff --git a/fs/mbcache.c b/fs/mbcache.c index 081ccf0caee3..2879d80ee6ac 100644 --- a/fs/mbcache.c +++ b/fs/mbcache.c @@ -26,7 +26,7 @@ struct mb_cache { /* Hash table of entries */ - struct hlist_bl_head *c_hash; + struct mb_bucket *c_bucket; /* log2 of hash table size */ int c_bucket_bits; /* Maximum entries in cache to avoid degrading hash too much */ @@ -41,6 +41,17 @@ struct mb_cache { struct work_struct c_shrink_work; }; +struct mb_bucket { + struct hlist_bl_head hash; + struct list_head req_list; +}; + +struct mb_cache_req { + struct list_head lnode; + u32 e_key; + u64 e_value; +}; + static struct kmem_cache *mb_entry_cache; static unsigned long mb_cache_shrink(struct mb_cache *cache, @@ -49,7 +60,7 @@ static unsigned long mb_cache_shrink(struct mb_cache *cache, static inline struct hlist_bl_head *mb_cache_entry_head(struct mb_cache *cache, u32 key) { - return &cache->c_hash[hash_32(key, cache->c_bucket_bits)]; + return &cache->c_bucket[hash_32(key, cache->c_bucket_bits)].hash; } /* @@ -76,6 +87,11 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key, struct mb_cache_entry *entry, *dup; struct hlist_bl_node *dup_node; struct hlist_bl_head *head; + struct mb_cache_req *tmp_req, req = { + .e_key = key, + .e_value = value + }; + struct mb_bucket *bucket; /* Schedule background reclaim if there are too many entries */ if (cache->c_entry_count >= cache->c_max_entries) @@ -84,33 +100,48 @@ int mb_cache_entry_create(struct mb_cache *cache, gfp_t mask, u32 key, if (cache->c_entry_count >= 2*cache->c_max_entries) mb_cache_shrink(cache, SYNC_SHRINK_BATCH); - entry = kmem_cache_alloc(mb_entry_cache, mask); - if (!entry) - return -ENOMEM; - - INIT_LIST_HEAD(&entry->e_list); - /* One ref for hash, one ref returned */ - atomic_set(&entry->e_refcnt, 1); - entry->e_key = key; - entry->e_value = value; - entry->e_reusable = reusable; - entry->e_referenced = 0; - head = mb_cache_entry_head(cache, key); + bucket = &cache->c_bucket[hash_32(key, cache->c_bucket_bits)]; + head = &bucket->hash; hlist_bl_lock(head); + list_for_each_entry(tmp_req, &bucket->req_list, lnode) { + if (tmp_req->e_key == key && tmp_req->e_value == value) { + hlist_bl_unlock(head); + return -EBUSY; + } + } hlist_bl_for_each_entry(dup, dup_node, head, e_hash_list) { if (dup->e_key == key && dup->e_value == value) { hlist_bl_unlock(head); - kmem_cache_free(mb_entry_cache, entry); return -EBUSY; } } + list_add(&req.lnode, &bucket->req_list); + hlist_bl_unlock(head); + + entry = kmem_cache_alloc(mb_entry_cache, mask); + if (!entry) { + hlist_bl_lock(head); + list_del(&req.lnode); + hlist_bl_unlock(head); + return -ENOMEM; + } + + *entry = (typeof(*entry)){ + .e_list = LIST_HEAD_INIT(entry->e_list), + /* One ref for hash, one ref returned */ + .e_refcnt = ATOMIC_INIT(2), + .e_key = key, + .e_value = value, + .e_reusable = reusable + }; + + hlist_bl_lock(head); + list_del(&req.lnode); hlist_bl_add_head(&entry->e_hash_list, head); hlist_bl_unlock(head); spin_lock(&cache->c_list_lock); list_add_tail(&entry->e_list, &cache->c_list); - /* Grab ref for LRU list */ - atomic_inc(&entry->e_refcnt); cache->c_entry_count++; spin_unlock(&cache->c_list_lock); @@ -353,21 +384,22 @@ struct mb_cache *mb_cache_create(int bucket_bits) cache->c_max_entries = bucket_count << 4; INIT_LIST_HEAD(&cache->c_list); spin_lock_init(&cache->c_list_lock); - cache->c_hash = kmalloc_array(bucket_count, - sizeof(struct hlist_bl_head), - GFP_KERNEL); - if (!cache->c_hash) { + cache->c_bucket = kmalloc_array(bucket_count, sizeof(*cache->c_bucket), + GFP_KERNEL); + if (!cache->c_bucket) { kfree(cache); goto err_out; } - for (i = 0; i < bucket_count; i++) - INIT_HLIST_BL_HEAD(&cache->c_hash[i]); + for (i = 0; i < bucket_count; i++) { + INIT_HLIST_BL_HEAD(&cache->c_bucket[i].hash); + INIT_LIST_HEAD(&cache->c_bucket[i].req_list); + } cache->c_shrink.count_objects = mb_cache_count; cache->c_shrink.scan_objects = mb_cache_scan; cache->c_shrink.seeks = DEFAULT_SEEKS; if (register_shrinker(&cache->c_shrink)) { - kfree(cache->c_hash); + kfree(cache->c_bucket); kfree(cache); goto err_out; } @@ -408,7 +440,7 @@ void mb_cache_destroy(struct mb_cache *cache) WARN_ON(atomic_read(&entry->e_refcnt) != 1); mb_cache_entry_put(cache, entry); } - kfree(cache->c_hash); + kfree(cache->c_bucket); kfree(cache); } EXPORT_SYMBOL(mb_cache_destroy); diff --git a/fs/namespace.c b/fs/namespace.c index e876362ac9c3..128783513bbe 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1378,7 +1378,7 @@ static void namespace_unlock(void) if (likely(hlist_empty(&head))) return; - synchronize_rcu(); + synchronize_rcu_expedited(); group_pin_kill(&head); } @@ -2774,9 +2774,9 @@ long do_mount(const char *dev_name, const char __user *dir_name, if (retval) goto dput_out; - /* Default to relatime unless overriden */ - if (!(flags & MS_NOATIME)) - mnt_flags |= MNT_RELATIME; + /* Default to noatime unless overriden */ + if (!(flags & MS_RELATIME)) + mnt_flags |= MNT_NOATIME; /* Separate the per-mountpoint flags */ if (flags & MS_NOSUID) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index ac3e06367cb6..e55f86713948 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -127,7 +127,7 @@ config PNFS_BLOCK config PNFS_FLEXFILE_LAYOUT tristate depends on NFS_V4_1 && NFS_V3 - default m + default NFS_V4 config NFS_V4_1_IMPLEMENTATION_ID_DOMAIN string "NFSv4.1 Implementation ID Domain" diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e4cd3a2fe698..aee66d8f1330 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -2142,7 +2142,7 @@ static int nfsiod_start(void) { struct workqueue_struct *wq; dprintk("RPC: creating workqueue nfsiod\n"); - wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM, 0); + wq = alloc_workqueue("nfsiod", WQ_MEM_RECLAIM | WQ_UNBOUND, 0); if (wq == NULL) return -ENOMEM; nfsiod_workqueue = wq; diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8357ff69962f..cc07189a501f 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -575,12 +575,14 @@ extern int nfs4_test_session_trunk(struct rpc_clnt *, static inline struct inode *nfs_igrab_and_active(struct inode *inode) { - inode = igrab(inode); - if (inode != NULL && !nfs_sb_active(inode->i_sb)) { - iput(inode); - inode = NULL; + struct super_block *sb = inode->i_sb; + + if (sb && nfs_sb_active(sb)) { + if (igrab(inode)) + return inode; + nfs_sb_deactive(sb); } - return inode; + return NULL; } static inline void nfs_iput_and_deactive(struct inode *inode) diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 9956453aa6ff..0ed419bb02b0 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c @@ -34,6 +34,7 @@ */ #define NFS3_fhandle_sz (1+16) #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */ +#define NFS3_post_op_fh_sz (1+NFS3_fh_sz) #define NFS3_sattr_sz (15) #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) @@ -71,7 +72,7 @@ #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) -#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) +#define NFS3_createres_sz (1+NFS3_post_op_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index fe7b42c277ac..bcad052db065 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4687,12 +4687,12 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page **pages, unsigned int count, bool plus) { struct inode *dir = d_inode(dentry); + struct nfs_server *server = NFS_SERVER(dir); struct nfs4_readdir_arg args = { .fh = NFS_FH(dir), .pages = pages, .pgbase = 0, .count = count, - .bitmask = NFS_SERVER(d_inode(dentry))->attr_bitmask, .plus = plus, }; struct nfs4_readdir_res res; @@ -4707,9 +4707,15 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, dprintk("%s: dentry = %pd2, cookie = %Lu\n", __func__, dentry, (unsigned long long)cookie); + if (!(server->caps & NFS_CAP_SECURITY_LABEL)) + args.bitmask = server->attr_bitmask_nl; + else + args.bitmask = server->attr_bitmask; + nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); res.pgbase = args.pgbase; - status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); + status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, + &res.seq_res, 0); if (status >= 0) { memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; @@ -5529,6 +5535,9 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE); int ret, i; + /* You can't remove system.nfs4_acl: */ + if (buflen == 0) + return -EINVAL; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; if (npages > ARRAY_SIZE(pages)) @@ -5605,7 +5614,7 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf, return ret; if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) return -ENOENT; - return 0; + return label.len; } static int nfs4_get_security_label(struct inode *inode, void *buf, @@ -6715,9 +6724,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f data->arg.new_lock_owner, ret); } else data->cancelled = true; + trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret); rpc_put_task(task); dprintk("%s: done, ret = %d!\n", __func__, ret); - trace_nfs4_set_lock(fl, state, &data->res.stateid, cmd, ret); return ret; } diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 6fb7cb6b3f4b..e7a10f5f5405 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -95,7 +95,7 @@ static void nfs4_evict_inode(struct inode *inode) nfs_inode_return_delegation_noreclaim(inode); /* Note that above delegreturn would trigger pnfs return-on-close */ pnfs_return_layout(inode); - pnfs_destroy_layout(NFS_I(inode)); + pnfs_destroy_layout_final(NFS_I(inode)); /* First call standard NFS clear_inode() code */ nfs_clear_inode(inode); } diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 2b9e139a2997..55965e8e9a2e 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -294,6 +294,7 @@ void pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) { struct inode *inode; + unsigned long i_state; if (!lo) return; @@ -304,8 +305,12 @@ pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) if (!list_empty(&lo->plh_segs)) WARN_ONCE(1, "NFS: BUG unfreed layout segments.\n"); pnfs_detach_layout_hdr(lo); + i_state = inode->i_state; spin_unlock(&inode->i_lock); pnfs_free_layout_hdr(lo); + /* Notify pnfs_destroy_layout_final() that we're done */ + if (i_state & (I_FREEING | I_CLEAR)) + wake_up_var(lo); } } @@ -713,8 +718,7 @@ pnfs_free_lseg_list(struct list_head *free_me) } } -void -pnfs_destroy_layout(struct nfs_inode *nfsi) +static struct pnfs_layout_hdr *__pnfs_destroy_layout(struct nfs_inode *nfsi) { struct pnfs_layout_hdr *lo; LIST_HEAD(tmp_list); @@ -732,9 +736,34 @@ pnfs_destroy_layout(struct nfs_inode *nfsi) pnfs_put_layout_hdr(lo); } else spin_unlock(&nfsi->vfs_inode.i_lock); + return lo; +} + +void pnfs_destroy_layout(struct nfs_inode *nfsi) +{ + __pnfs_destroy_layout(nfsi); } EXPORT_SYMBOL_GPL(pnfs_destroy_layout); +static bool pnfs_layout_removed(struct nfs_inode *nfsi, + struct pnfs_layout_hdr *lo) +{ + bool ret; + + spin_lock(&nfsi->vfs_inode.i_lock); + ret = nfsi->layout != lo; + spin_unlock(&nfsi->vfs_inode.i_lock); + return ret; +} + +void pnfs_destroy_layout_final(struct nfs_inode *nfsi) +{ + struct pnfs_layout_hdr *lo = __pnfs_destroy_layout(nfsi); + + if (lo) + wait_var_event(lo, pnfs_layout_removed(nfsi, lo)); +} + static bool pnfs_layout_add_bulk_destroy_list(struct inode *inode, struct list_head *layout_list) @@ -1431,12 +1460,18 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args, int ret) { struct pnfs_layout_hdr *lo = args->layout; + struct inode *inode = args->inode; const nfs4_stateid *arg_stateid = NULL; const nfs4_stateid *res_stateid = NULL; struct nfs4_xdr_opaque_data *ld_private = args->ld_private; switch (ret) { case -NFS4ERR_NOMATCHING_LAYOUT: + spin_lock(&inode->i_lock); + if (pnfs_layout_is_valid(lo) && + nfs4_stateid_match_other(&args->stateid, &lo->plh_stateid)) + pnfs_set_plh_return_info(lo, args->range.iomode, 0); + spin_unlock(&inode->i_lock); break; case 0: if (res->lrs_present) @@ -2112,6 +2147,7 @@ static void _lgopen_prepare_attached(struct nfs4_opendata *data, &rng, GFP_KERNEL); if (!lgp) { pnfs_clear_first_layoutget(lo); + nfs_layoutget_end(lo); pnfs_put_layout_hdr(lo); return; } @@ -2265,7 +2301,13 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) * We got an entirely new state ID. Mark all segments for the * inode invalid, and retry the layoutget */ - pnfs_mark_layout_stateid_invalid(lo, &free_me); + struct pnfs_layout_range range = { + .iomode = IOMODE_ANY, + .length = NFS4_MAX_UINT64, + }; + pnfs_set_plh_return_info(lo, IOMODE_ANY, 0); + pnfs_mark_matching_lsegs_return(lo, &lo->plh_return_segs, + &range, 0); goto out_forget; } @@ -2284,6 +2326,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) spin_unlock(&ino->i_lock); lseg->pls_layout = lo; NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg); + pnfs_free_lseg_list(&free_me); return ERR_PTR(-EAGAIN); } diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 3ba44819a88a..80fafa29e567 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -254,6 +254,7 @@ struct pnfs_layout_segment *pnfs_layout_process(struct nfs4_layoutget *lgp); void pnfs_layoutget_free(struct nfs4_layoutget *lgp); void pnfs_free_lseg_list(struct list_head *tmp_list); void pnfs_destroy_layout(struct nfs_inode *); +void pnfs_destroy_layout_final(struct nfs_inode *); void pnfs_destroy_all_layouts(struct nfs_client *); int pnfs_destroy_layouts_byfsid(struct nfs_client *clp, struct nfs_fsid *fsid, @@ -645,6 +646,10 @@ static inline void pnfs_destroy_layout(struct nfs_inode *nfsi) { } +static inline void pnfs_destroy_layout_final(struct nfs_inode *nfsi) +{ +} + static inline struct pnfs_layout_segment * pnfs_get_lseg(struct pnfs_layout_segment *lseg) { diff --git a/fs/nfs/write.c b/fs/nfs/write.c index d419d89b91f7..f0dbaa865208 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -2148,7 +2148,7 @@ int __init nfs_init_writepagecache(void) * This allows larger machines to have larger/more transfers. * Limit the default to 256M */ - nfs_congestion_kb = (16*int_sqrt(totalram_pages)) << (PAGE_SHIFT-10); + nfs_congestion_kb = (16*int_sqrt(totalram_pages())) << (PAGE_SHIFT-10); if (nfs_congestion_kb > 256*1024) nfs_congestion_kb = 256*1024; diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c index 5be08f02a76b..4f90c444907f 100644 --- a/fs/nfs_common/grace.c +++ b/fs/nfs_common/grace.c @@ -68,10 +68,14 @@ __state_in_grace(struct net *net, bool open) if (!open) return !list_empty(grace_list); + spin_lock(&grace_lock); list_for_each_entry(lm, grace_list, list) { - if (lm->block_opens) + if (lm->block_opens) { + spin_unlock(&grace_lock); return true; + } } + spin_unlock(&grace_lock); return false; } diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 83919116d5cb..b90bea1c434e 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -844,9 +844,14 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, if (isdotent(name, namlen)) { if (namlen == 2) { dchild = dget_parent(dparent); - /* filesystem root - cannot return filehandle for ".." */ + /* + * Don't return filehandle for ".." if we're at + * the filesystem or export root: + */ if (dchild == dparent) goto out; + if (dparent == exp->ex_path.dentry) + goto out; } else dchild = dget(dparent); } else diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index dbdeb9d6af03..ca2274910ea7 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -98,7 +98,7 @@ static unsigned int nfsd_cache_size_limit(void) { unsigned int limit; - unsigned long low_pages = totalram_pages - totalhigh_pages; + unsigned long low_pages = totalram_pages() - totalhigh_pages(); limit = (16 * int_sqrt(low_pages)) << (PAGE_SHIFT-10); return min_t(unsigned int, limit, 256*1024); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 89cb484f1cfb..ad38633392a0 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -417,8 +417,7 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net) return; nfsd_shutdown_net(net); - printk(KERN_WARNING "nfsd: last server has exited, flushing export " - "cache\n"); + pr_info("nfsd: last server has exited, flushing export cache\n"); nfsd_export_flush(net); } diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index 0d4b5b9843b6..a2fb866ff76e 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -654,6 +654,12 @@ static int ntfs_read_locked_inode(struct inode *vi) } a = ctx->attr; /* Get the standard information attribute value. */ + if ((u8 *)a + le16_to_cpu(a->data.resident.value_offset) + + le32_to_cpu(a->data.resident.value_length) > + (u8 *)ctx->mrec + vol->mft_record_size) { + ntfs_error(vi->i_sb, "Corrupt standard information attribute in inode."); + goto unm_err_out; + } si = (STANDARD_INFORMATION*)((u8*)a + le16_to_cpu(a->data.resident.value_offset)); diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h index ab172e5f51d9..5becc8acc8f4 100644 --- a/fs/ntfs/malloc.h +++ b/fs/ntfs/malloc.h @@ -47,7 +47,7 @@ static inline void *__ntfs_malloc(unsigned long size, gfp_t gfp_mask) return kmalloc(PAGE_SIZE, gfp_mask & ~__GFP_HIGHMEM); /* return (void *)__get_free_page(gfp_mask); */ } - if (likely((size >> PAGE_SHIFT) < totalram_pages)) + if (likely((size >> PAGE_SHIFT) < totalram_pages())) return __vmalloc(size, gfp_mask, PAGE_KERNEL); return NULL; } diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 543efa3e5655..b6948813eb06 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -2311,7 +2311,7 @@ static int ocfs2_dio_end_io_write(struct inode *inode, struct ocfs2_alloc_context *meta_ac = NULL; handle_t *handle = NULL; loff_t end = offset + bytes; - int ret = 0, credits = 0, locked = 0; + int ret = 0, credits = 0; ocfs2_init_dealloc_ctxt(&dealloc); @@ -2322,13 +2322,6 @@ static int ocfs2_dio_end_io_write(struct inode *inode, !dwc->dw_orphaned) goto out; - /* ocfs2_file_write_iter will get i_mutex, so we need not lock if we - * are in that context. */ - if (dwc->dw_writer_pid != task_pid_nr(current)) { - inode_lock(inode); - locked = 1; - } - ret = ocfs2_inode_lock(inode, &di_bh, 1); if (ret < 0) { mlog_errno(ret); @@ -2409,8 +2402,6 @@ static int ocfs2_dio_end_io_write(struct inode *inode, if (meta_ac) ocfs2_free_alloc_context(meta_ac); ocfs2_run_deallocs(osb, &dealloc); - if (locked) - inode_unlock(inode); ocfs2_dio_free_write_ctx(inode, dwc); return ret; diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 9b2ed62dd638..19b0d358a0d6 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -2154,7 +2154,7 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g o2hb_nego_timeout_handler, reg, NULL, ®->hr_handler_list); if (ret) - goto free; + goto remove_item; ret = o2net_register_handler(O2HB_NEGO_APPROVE_MSG, reg->hr_key, sizeof(struct o2hb_nego_msg), @@ -2173,6 +2173,12 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g unregister_handler: o2net_unregister_handler_list(®->hr_handler_list); +remove_item: + spin_lock(&o2hb_live_lock); + list_del(®->hr_all_item); + if (o2hb_global_heartbeat_active()) + clear_bit(reg->hr_region_num, o2hb_region_bitmap); + spin_unlock(&o2hb_live_lock); free: kfree(reg); return ERR_PTR(ret); diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index fbd70111a2f1..5c507569ef70 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1252,22 +1252,24 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) goto bail_unlock; } } + down_write(&OCFS2_I(inode)->ip_alloc_sem); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS + 2 * ocfs2_quota_trans_credits(sb)); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); - goto bail_unlock; + goto bail_unlock_alloc; } status = __dquot_transfer(inode, transfer_to); if (status < 0) goto bail_commit; } else { + down_write(&OCFS2_I(inode)->ip_alloc_sem); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); - goto bail_unlock; + goto bail_unlock_alloc; } } @@ -1280,6 +1282,8 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) bail_commit: ocfs2_commit_trans(osb, handle); +bail_unlock_alloc: + up_write(&OCFS2_I(inode)->ip_alloc_sem); bail_unlock: if (status && inode_locked) { ocfs2_inode_unlock_tracker(inode, 1, &oh, had_lock); diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 2658d91c1f7b..09bc2cf5f61c 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1747,6 +1747,7 @@ static void ocfs2_inode_init_once(void *data) oi->ip_blkno = 0ULL; oi->ip_clusters = 0; + oi->ip_next_orphan = NULL; ocfs2_resv_init_once(&oi->ip_la_data_resv); diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 53041ea78053..6c8af146e2c1 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -79,6 +79,14 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) if (ovl_is_private_xattr(name)) continue; + + error = security_inode_copy_up_xattr(name); + if (error < 0 && error != -EOPNOTSUPP) + break; + if (error == 1) { + error = 0; + continue; /* Discard */ + } retry: size = vfs_getxattr(old, name, value, value_size); if (size == -ERANGE) @@ -102,13 +110,6 @@ int ovl_copy_xattr(struct dentry *old, struct dentry *new) goto retry; } - error = security_inode_copy_up_xattr(name); - if (error < 0 && error != -EOPNOTSUPP) - break; - if (error == 1) { - error = 0; - continue; /* Discard */ - } error = vfs_setxattr(new, name, value, size, 0); if (error) break; diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index 7b5357a4606b..218e3a362dee 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -949,8 +949,8 @@ static char *ovl_get_redirect(struct dentry *dentry, bool abs_redirect) buflen -= thislen; memcpy(&buf[buflen], name, thislen); - tmp = dget_dlock(d->d_parent); spin_unlock(&d->d_lock); + tmp = dget_parent(d); dput(d); d = tmp; diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 7fe9bbb2045d..7f3787a6b445 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -340,7 +340,9 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, goto out; if (!value && !upperdentry) { + old_cred = ovl_override_creds(dentry->d_sb); err = vfs_getxattr(realdentry, name, NULL, 0); + revert_creds(old_cred); if (err < 0) goto out_drop_write; } diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 7dffe70c51fc..117975df78e6 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -87,7 +87,7 @@ static void ovl_dentry_release(struct dentry *dentry) static struct dentry *ovl_d_real(struct dentry *dentry, const struct inode *inode) { - struct dentry *real; + struct dentry *real = NULL, *lower; /* It's an overlay file */ if (inode && d_inode(dentry) == inode) @@ -106,9 +106,10 @@ static struct dentry *ovl_d_real(struct dentry *dentry, if (real && !inode && ovl_has_upperdata(d_inode(dentry))) return real; - real = ovl_dentry_lowerdata(dentry); - if (!real) + lower = ovl_dentry_lowerdata(dentry); + if (!lower) goto bug; + real = lower; /* Handle recursion */ real = d_real(real, inode); @@ -116,8 +117,10 @@ static struct dentry *ovl_d_real(struct dentry *dentry, if (!inode || inode == d_inode(real)) return real; bug: - WARN(1, "ovl_d_real(%pd4, %s:%lu): real dentry not found\n", dentry, - inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); + WARN(1, "%s(%pd4, %s:%lu): real dentry (%p/%lu) not found\n", + __func__, dentry, inode ? inode->i_sb->s_id : "NULL", + inode ? inode->i_ino : 0, real, + real && d_inode(real) ? d_inode(real)->i_ino : 0); return dentry; } diff --git a/fs/proc/base.c b/fs/proc/base.c index 67c3b5fd4701..faee9b2c0d0e 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -553,7 +553,7 @@ static const struct file_operations proc_lstats_operations = { static int proc_oom_score(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task) { - unsigned long totalpages = totalram_pages + total_swap_pages; + unsigned long totalpages = totalram_pages() + total_swap_pages; unsigned long points = 0; points = oom_badness(task, NULL, NULL, totalpages, false) * diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c index fa762c5fbcb2..2450352e51c8 100644 --- a/fs/proc/cmdline.c +++ b/fs/proc/cmdline.c @@ -3,16 +3,51 @@ #include #include #include +#include + +static char new_command_line[COMMAND_LINE_SIZE]; static int cmdline_proc_show(struct seq_file *m, void *v) { - seq_puts(m, saved_command_line); + seq_puts(m, new_command_line); seq_putc(m, '\n'); return 0; } +static void patch_flag(char *cmd, const char *flag, const char *val) +{ + size_t flag_len, val_len; + char *start, *end; + + start = strstr(cmd, flag); + if (!start) + return; + + flag_len = strlen(flag); + val_len = strlen(val); + end = start + flag_len + strcspn(start + flag_len, " "); + memmove(start + flag_len + val_len, end, strlen(end) + 1); + memcpy(start + flag_len, val, val_len); +} + +static void patch_safetynet_flags(char *cmd) +{ + patch_flag(cmd, "androidboot.flash.locked=", "1"); + patch_flag(cmd, "androidboot.verifiedbootstate=", "green"); + patch_flag(cmd, "androidboot.veritymode=", "enforcing"); + patch_flag(cmd, "androidboot.vbmeta.device_state=", "locked"); +} + static int __init proc_cmdline_init(void) { + strcpy(new_command_line, saved_command_line); + + /* + * Patch various flags from command line seen by userspace in order to + * pass SafetyNet checks. + */ + patch_safetynet_flags(new_command_line); + proc_create_single("cmdline", 0, NULL, cmdline_proc_show); return 0; } diff --git a/fs/proc/generic.c b/fs/proc/generic.c index e39bac94dead..bab10368a04d 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -137,8 +137,12 @@ static int proc_getattr(const struct path *path, struct kstat *stat, { struct inode *inode = d_inode(path->dentry); struct proc_dir_entry *de = PDE(inode); - if (de && de->nlink) - set_nlink(inode, de->nlink); + if (de) { + nlink_t nlink = READ_ONCE(de->nlink); + if (nlink > 0) { + set_nlink(inode, nlink); + } + } generic_fillattr(inode, stat); return 0; @@ -337,6 +341,16 @@ static const struct file_operations proc_dir_operations = { .iterate_shared = proc_readdir, }; +static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags) +{ + return 0; +} + +const struct dentry_operations proc_net_dentry_ops = { + .d_revalidate = proc_net_d_revalidate, + .d_delete = always_delete_dentry, +}; + /* * proc directories can do almost nothing.. */ @@ -361,6 +375,7 @@ struct proc_dir_entry *proc_register(struct proc_dir_entry *dir, write_unlock(&proc_subdir_lock); goto out_free_inum; } + dir->nlink++; write_unlock(&proc_subdir_lock); return dp; @@ -458,8 +473,8 @@ struct proc_dir_entry *proc_symlink(const char *name, } EXPORT_SYMBOL(proc_symlink); -struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, - struct proc_dir_entry *parent, void *data) +struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode, + struct proc_dir_entry *parent, void *data, bool force_lookup) { struct proc_dir_entry *ent; @@ -471,13 +486,20 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, ent->data = data; ent->proc_fops = &proc_dir_operations; ent->proc_iops = &proc_dir_inode_operations; - parent->nlink++; + if (force_lookup) { + pde_force_lookup(ent); + } ent = proc_register(parent, ent); - if (!ent) - parent->nlink--; } return ent; } +EXPORT_SYMBOL_GPL(_proc_mkdir); + +struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, + struct proc_dir_entry *parent, void *data) +{ + return _proc_mkdir(name, mode, parent, data, false); +} EXPORT_SYMBOL_GPL(proc_mkdir_data); struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode, @@ -504,10 +526,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name) ent->data = NULL; ent->proc_fops = NULL; ent->proc_iops = NULL; - parent->nlink++; ent = proc_register(parent, ent); - if (!ent) - parent->nlink--; } return ent; } @@ -665,8 +684,12 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) len = strlen(fn); de = pde_subdir_find(parent, fn, len); - if (de) + if (de) { rb_erase(&de->subdir_node, &parent->subdir); + if (S_ISDIR(de->mode)) { + parent->nlink--; + } + } write_unlock(&proc_subdir_lock); if (!de) { WARN(1, "name '%s'\n", name); @@ -675,9 +698,6 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) proc_entry_rundown(de); - if (S_ISDIR(de->mode)) - parent->nlink--; - de->nlink = 0; WARN(pde_subdir_first(de), "%s: removing non-empty directory '%s/%s', leaking at least '%s'\n", __func__, de->parent->name, de->name, pde_subdir_first(de)->name); @@ -713,13 +733,12 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) de = next; continue; } - write_unlock(&proc_subdir_lock); - - proc_entry_rundown(de); next = de->parent; if (S_ISDIR(de->mode)) next->nlink--; - de->nlink = 0; + write_unlock(&proc_subdir_lock); + + proc_entry_rundown(de); if (de == root) break; pde_put(de); diff --git a/fs/proc/internal.h b/fs/proc/internal.h index db189d59ce1e..041af21ebc0b 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -298,6 +298,7 @@ struct proc_maps_private { #ifdef CONFIG_NUMA struct mempolicy *task_mempolicy; #endif + unsigned long old_cpus_allowed; } __randomize_layout; struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode); @@ -314,3 +315,10 @@ extern unsigned long task_statm(struct mm_struct *, unsigned long *, unsigned long *, unsigned long *, unsigned long *); extern void task_mem(struct seq_file *, struct mm_struct *); + +extern const struct dentry_operations proc_net_dentry_ops; +static inline void pde_force_lookup(struct proc_dir_entry *pde) +{ + /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */ + pde->proc_dops = &proc_net_dentry_ops; +} diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index a7b12435519e..096bcc1e7a8a 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -38,22 +38,6 @@ static struct net *get_proc_net(const struct inode *inode) return maybe_get_net(PDE_NET(PDE(inode))); } -static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags) -{ - return 0; -} - -static const struct dentry_operations proc_net_dentry_ops = { - .d_revalidate = proc_net_d_revalidate, - .d_delete = always_delete_dentry, -}; - -static void pde_force_lookup(struct proc_dir_entry *pde) -{ - /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */ - pde->proc_dops = &proc_net_dentry_ops; -} - static int seq_open_net(struct inode *inode, struct file *file) { unsigned int state_size = PDE(inode)->state_size; diff --git a/fs/proc/self.c b/fs/proc/self.c index cc6d4253399d..7922edf70ce1 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c @@ -16,6 +16,13 @@ static const char *proc_self_get_link(struct dentry *dentry, pid_t tgid = task_tgid_nr_ns(current, ns); char *name; + /* + * Not currently supported. Once we can inherit all of struct pid, + * we can allow this. + */ + if (current->flags & PF_KTHREAD) + return ERR_PTR(-EOPNOTSUPP); + if (!tgid) return ERR_PTR(-ENOENT); /* max length of unsigned int in decimal + NULL term */ diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 6cc098e86c34..67a148c01dce 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -140,7 +140,7 @@ static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) page_offset = (unsigned long)name - page_start_vaddr; num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE); - seq_puts(m, "[anon:"); + seq_write(m, "[anon:", 6); for (i = 0; i < num_pages; i++) { int len; @@ -152,7 +152,7 @@ static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) pages_pinned = get_user_pages_remote(current, mm, page_start_vaddr, 1, 0, &page, NULL, NULL); if (pages_pinned < 1) { - seq_puts(m, "]"); + seq_write(m, "]\n", 9); return; } @@ -172,7 +172,7 @@ static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) page_start_vaddr += PAGE_SIZE; } - seq_putc(m, ']'); + seq_write(m, "]\n", 2); } static void vma_stop(struct proc_maps_private *priv) @@ -182,6 +182,9 @@ static void vma_stop(struct proc_maps_private *priv) release_task_mempolicy(priv); up_read(&mm->mmap_sem); mmput(mm); + + sched_migrate_to_cpumask_end(to_cpumask(&priv->old_cpus_allowed), + cpu_lp_mask); } static struct vm_area_struct * @@ -223,6 +226,9 @@ static void *m_start(struct seq_file *m, loff_t *ppos) return ERR_PTR(-EINTR); } + sched_migrate_to_cpumask_start(to_cpumask(&priv->old_cpus_allowed), + cpu_lp_mask); + hold_task_mempolicy(priv); priv->tail_vma = get_gate_vma(mm); @@ -328,24 +334,117 @@ static int is_stack(struct vm_area_struct *vma) vma->vm_end >= vma->vm_mm->start_stack; } -static void show_vma_header_prefix(struct seq_file *m, - unsigned long start, unsigned long end, - vm_flags_t flags, unsigned long long pgoff, - dev_t dev, unsigned long ino) -{ - seq_setwidth(m, 25 + sizeof(void *) * 6 - 1); - seq_put_hex_ll(m, NULL, start, 8); - seq_put_hex_ll(m, "-", end, 8); - seq_putc(m, ' '); - seq_putc(m, flags & VM_READ ? 'r' : '-'); - seq_putc(m, flags & VM_WRITE ? 'w' : '-'); - seq_putc(m, flags & VM_EXEC ? 'x' : '-'); - seq_putc(m, flags & VM_MAYSHARE ? 's' : 'p'); - seq_put_hex_ll(m, " ", pgoff, 8); - seq_put_hex_ll(m, " ", MAJOR(dev), 2); - seq_put_hex_ll(m, ":", MINOR(dev), 2); - seq_put_decimal_ull(m, " ", ino); - seq_putc(m, ' '); +#define print_vma_hex10(out, val, clz_fn) \ +({ \ + const typeof(val) __val = val; \ + char *const __out = out; \ + size_t __len; \ + \ + if (__val) { \ + __len = (sizeof(__val) * 8 - clz_fn(__val) + 3) / 4; \ + switch (__len) { \ + case 10: \ + __out[9] = hex_asc[(__val >> 0) & 0xf]; \ + __out[8] = hex_asc[(__val >> 4) & 0xf]; \ + __out[7] = hex_asc[(__val >> 8) & 0xf]; \ + __out[6] = hex_asc[(__val >> 12) & 0xf]; \ + __out[5] = hex_asc[(__val >> 16) & 0xf]; \ + __out[4] = hex_asc[(__val >> 20) & 0xf]; \ + __out[3] = hex_asc[(__val >> 24) & 0xf]; \ + __out[2] = hex_asc[(__val >> 28) & 0xf]; \ + __out[1] = hex_asc[(__val >> 32) & 0xf]; \ + __out[0] = hex_asc[(__val >> 36) & 0xf]; \ + break; \ + case 9: \ + __out[8] = hex_asc[(__val >> 0) & 0xf]; \ + __out[7] = hex_asc[(__val >> 4) & 0xf]; \ + __out[6] = hex_asc[(__val >> 8) & 0xf]; \ + __out[5] = hex_asc[(__val >> 12) & 0xf]; \ + __out[4] = hex_asc[(__val >> 16) & 0xf]; \ + __out[3] = hex_asc[(__val >> 20) & 0xf]; \ + __out[2] = hex_asc[(__val >> 24) & 0xf]; \ + __out[1] = hex_asc[(__val >> 28) & 0xf]; \ + __out[0] = hex_asc[(__val >> 32) & 0xf]; \ + break; \ + default: \ + __out[7] = hex_asc[(__val >> 0) & 0xf]; \ + __out[6] = hex_asc[(__val >> 4) & 0xf]; \ + __out[5] = hex_asc[(__val >> 8) & 0xf]; \ + __out[4] = hex_asc[(__val >> 12) & 0xf]; \ + __out[3] = hex_asc[(__val >> 16) & 0xf]; \ + __out[2] = hex_asc[(__val >> 20) & 0xf]; \ + __out[1] = hex_asc[(__val >> 24) & 0xf]; \ + __out[0] = hex_asc[(__val >> 28) & 0xf]; \ + __len = 8; \ + break; \ + } \ + } else { \ + *(u64 *)__out = U64_C(0x3030303030303030); \ + __len = 8; \ + } \ + \ + __len; \ +}) + +#define print_vma_hex2(out, val) \ +({ \ + const typeof(val) __val = val; \ + char *const __out = out; \ + \ + __out[1] = hex_asc[(__val >> 0) & 0xf]; \ + __out[0] = hex_asc[(__val >> 4) & 0xf]; \ + \ + 2; \ +}) + +static int show_vma_header_prefix(struct seq_file *m, unsigned long start, + unsigned long end, vm_flags_t flags, + unsigned long long pgoff, dev_t dev, + unsigned long ino) +{ + size_t len; + char *out; + + /* Set the overflow status to get more memory if there's no space */ + if (seq_get_buf(m, &out) < 65) { + seq_commit(m, -1); + return -ENOMEM; + } + + /* Supports printing up to 40 bits per virtual address */ + BUILD_BUG_ON(CONFIG_ARM64_VA_BITS > 40); + + len = print_vma_hex10(out, start, __builtin_clzl); + + out[len++] = '-'; + + len += print_vma_hex10(out + len, end, __builtin_clzl); + + out[len++] = ' '; + out[len++] = "-r"[!!(flags & VM_READ)]; + out[len++] = "-w"[!!(flags & VM_WRITE)]; + out[len++] = "-x"[!!(flags & VM_EXEC)]; + out[len++] = "ps"[!!(flags & VM_MAYSHARE)]; + out[len++] = ' '; + + len += print_vma_hex10(out + len, pgoff, __builtin_clzll); + + out[len++] = ' '; + + len += print_vma_hex2(out + len, MAJOR(dev)); + + out[len++] = ':'; + + len += print_vma_hex2(out + len, MINOR(dev)); + + out[len++] = ' '; + + len += num_to_str(&out[len], 20, ino, 0); + + out[len++] = ' '; + + m->count += len; + return 0; } static void @@ -369,16 +468,44 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) start = vma->vm_start; end = vma->vm_end; - show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino); + if (show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino)) + return; /* * Print the dentry name for named mappings, and a * special [heap] marker for the heap: */ if (file) { - seq_pad(m, ' '); - seq_file_path(m, file, "\n"); - goto done; + char *buf; + size_t size = seq_get_buf(m, &buf); + + /* + * This won't escape newline characters from the path. If a + * program uses newlines in its paths then it can kick rocks. + */ + if (size > 1) { + const int inlen = size - 1; + int outlen = inlen; + char *p; + + p = d_path_outlen(&file->f_path, buf, &outlen); + if (!IS_ERR(p)) { + size_t len; + + if (outlen != inlen) + len = inlen - outlen - 1; + else + len = strlen(p); + memmove(buf, p, len); + buf[len] = '\n'; + seq_commit(m, len + 1); + return; + } + } + + /* Set the overflow status to get more memory */ + seq_commit(m, -1); + return; } if (vma->vm_ops && vma->vm_ops->name) { @@ -390,32 +517,30 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) name = arch_vma_name(vma); if (!name) { if (!mm) { - name = "[vdso]"; - goto done; + seq_write(m, "[vdso]\n", 7); + return; } if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { - name = "[heap]"; - goto done; + seq_write(m, "[heap]\n", 7); + return; } if (is_stack(vma)) { - name = "[stack]"; - goto done; + seq_write(m, "[stack]\n", 8); + return; } if (vma_get_anon_name(vma)) { - seq_pad(m, ' '); seq_print_vma_name(m, vma); + return; } } done: - if (name) { - seq_pad(m, ' '); + if (name) seq_puts(m, name); - } seq_putc(m, '\n'); } @@ -854,7 +979,6 @@ static int show_smap(struct seq_file *m, void *v) if (vma_get_anon_name(vma)) { seq_puts(m, "Name: "); seq_print_vma_name(m, vma); - seq_putc(m, '\n'); } SEQ_PUT_DEC("Size: ", vma->vm_end - vma->vm_start); @@ -909,7 +1033,6 @@ static int show_smaps_rollup(struct seq_file *m, void *v) show_vma_header_prefix(m, priv->mm->mmap->vm_start, last_vma_end, 0, 0, 0, 0); - seq_pad(m, ' '); seq_puts(m, "[rollup]\n"); __show_smap(m, &mss); diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 2197bf68f278..904c2a60f5ba 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -250,7 +250,7 @@ static int pstore_compress(const void *in, void *out, { int ret; - if (!IS_ENABLED(CONFIG_PSTORE_COMPRESSION)) + if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS)) return -EINVAL; ret = crypto_comp_compress(tfm, in, inlen, out, &outlen); @@ -650,7 +650,7 @@ static void decompress_record(struct pstore_record *record) int unzipped_len; char *decompressed; - if (!IS_ENABLED(CONFIG_PSTORE_COMPRESSION) || !record->compressed) + if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed) return; /* Only PSTORE_TYPE_DMESG support compression. */ diff --git a/fs/quota/quota_tree.c b/fs/quota/quota_tree.c index bb3f59bcfcf5..7557fa00e366 100644 --- a/fs/quota/quota_tree.c +++ b/fs/quota/quota_tree.c @@ -46,14 +46,37 @@ static int qtree_dqstr_in_blk(struct qtree_mem_dqinfo *info) / info->dqi_entry_size; } -static char *getdqbuf(size_t size) -{ - char *buf = kmalloc(size, GFP_NOFS); - if (!buf) - printk(KERN_WARNING - "VFS: Not enough memory for quota buffers.\n"); - return buf; -} +#define STACK_ALLOC_SIZE (SZ_512 + SZ_256) +#define GETDQBUF_NORET(size) \ + char *buf; \ + char buf_onstack[STACK_ALLOC_SIZE] __aligned(8); \ + if (unlikely(size > STACK_ALLOC_SIZE)) { \ + buf = kmalloc(size, GFP_NOFS); \ + if (!buf) \ + printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n"); \ + } else { \ + buf = buf_onstack; \ + } + +#define __GETDQBUF(size) \ + if (unlikely(size > STACK_ALLOC_SIZE)) { \ + buf = kmalloc(size, GFP_NOFS); \ + if (!buf) { \ + printk(KERN_WARNING "VFS: Not enough memory for quota buffers.\n"); \ + return -ENOMEM; \ + } \ + } else { \ + buf = buf_onstack; \ + } + +#define GETDQBUF(size) \ + char *buf; \ + char buf_onstack[STACK_ALLOC_SIZE] __aligned(8); \ + __GETDQBUF(size); + +#define FREEDQBUF() \ + if (unlikely(buf != buf_onstack)) \ + kfree(buf); static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) { @@ -61,7 +84,7 @@ static ssize_t read_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) memset(buf, 0, info->dqi_usable_bs); return sb->s_op->quota_read(sb, info->dqi_type, buf, - info->dqi_usable_bs, blk << info->dqi_blocksize_bits); + info->dqi_usable_bs, (loff_t)blk << info->dqi_blocksize_bits); } static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) @@ -70,7 +93,7 @@ static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) ssize_t ret; ret = sb->s_op->quota_write(sb, info->dqi_type, buf, - info->dqi_usable_bs, blk << info->dqi_blocksize_bits); + info->dqi_usable_bs, (loff_t)blk << info->dqi_blocksize_bits); if (ret != info->dqi_usable_bs) { quota_error(sb, "dquota write failed"); if (ret >= 0) @@ -82,12 +105,12 @@ static ssize_t write_blk(struct qtree_mem_dqinfo *info, uint blk, char *buf) /* Remove empty block from list and return it */ static int get_free_dqblk(struct qtree_mem_dqinfo *info) { - char *buf = getdqbuf(info->dqi_usable_bs); - struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + struct qt_disk_dqdbheader *dh; int ret, blk; + GETDQBUF(info->dqi_usable_bs); + + dh = (struct qt_disk_dqdbheader *)buf; - if (!buf) - return -ENOMEM; if (info->dqi_free_blk) { blk = info->dqi_free_blk; ret = read_blk(info, blk, buf); @@ -106,7 +129,7 @@ static int get_free_dqblk(struct qtree_mem_dqinfo *info) mark_info_dirty(info->dqi_sb, info->dqi_type); ret = blk; out_buf: - kfree(buf); + FREEDQBUF(); return ret; } @@ -128,83 +151,79 @@ static int put_free_dqblk(struct qtree_mem_dqinfo *info, char *buf, uint blk) } /* Remove given block from the list of blocks with free entries */ -static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, +static int remove_free_dqentry(struct qtree_mem_dqinfo *info, char *pbuf, uint blk) { - char *tmpbuf = getdqbuf(info->dqi_usable_bs); - struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)pbuf; uint nextblk = le32_to_cpu(dh->dqdh_next_free); uint prevblk = le32_to_cpu(dh->dqdh_prev_free); int err; + GETDQBUF(info->dqi_usable_bs); - if (!tmpbuf) - return -ENOMEM; if (nextblk) { - err = read_blk(info, nextblk, tmpbuf); + err = read_blk(info, nextblk, buf); if (err < 0) goto out_buf; - ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = + ((struct qt_disk_dqdbheader *)buf)->dqdh_prev_free = dh->dqdh_prev_free; - err = write_blk(info, nextblk, tmpbuf); + err = write_blk(info, nextblk, buf); if (err < 0) goto out_buf; } if (prevblk) { - err = read_blk(info, prevblk, tmpbuf); + err = read_blk(info, prevblk, buf); if (err < 0) goto out_buf; - ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_next_free = + ((struct qt_disk_dqdbheader *)buf)->dqdh_next_free = dh->dqdh_next_free; - err = write_blk(info, prevblk, tmpbuf); + err = write_blk(info, prevblk, buf); if (err < 0) goto out_buf; } else { info->dqi_free_entry = nextblk; mark_info_dirty(info->dqi_sb, info->dqi_type); } - kfree(tmpbuf); + FREEDQBUF(); dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0); /* No matter whether write succeeds block is out of list */ - if (write_blk(info, blk, buf) < 0) + if (write_blk(info, blk, pbuf) < 0) quota_error(info->dqi_sb, "Can't write block (%u) " "with free entries", blk); return 0; out_buf: - kfree(tmpbuf); + FREEDQBUF(); return err; } /* Insert given block to the beginning of list with free entries */ -static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *buf, +static int insert_free_dqentry(struct qtree_mem_dqinfo *info, char *pbuf, uint blk) { - char *tmpbuf = getdqbuf(info->dqi_usable_bs); - struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)buf; + struct qt_disk_dqdbheader *dh = (struct qt_disk_dqdbheader *)pbuf; int err; + GETDQBUF(info->dqi_usable_bs); - if (!tmpbuf) - return -ENOMEM; dh->dqdh_next_free = cpu_to_le32(info->dqi_free_entry); dh->dqdh_prev_free = cpu_to_le32(0); - err = write_blk(info, blk, buf); + err = write_blk(info, blk, pbuf); if (err < 0) goto out_buf; if (info->dqi_free_entry) { - err = read_blk(info, info->dqi_free_entry, tmpbuf); + err = read_blk(info, info->dqi_free_entry, buf); if (err < 0) goto out_buf; - ((struct qt_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = + ((struct qt_disk_dqdbheader *)buf)->dqdh_prev_free = cpu_to_le32(blk); - err = write_blk(info, info->dqi_free_entry, tmpbuf); + err = write_blk(info, info->dqi_free_entry, buf); if (err < 0) goto out_buf; } - kfree(tmpbuf); + FREEDQBUF(); info->dqi_free_entry = blk; mark_info_dirty(info->dqi_sb, info->dqi_type); return 0; out_buf: - kfree(tmpbuf); + FREEDQBUF(); return err; } @@ -226,11 +245,11 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, { uint blk, i; struct qt_disk_dqdbheader *dh; - char *buf = getdqbuf(info->dqi_usable_bs); char *ddquot; + GETDQBUF_NORET(info->dqi_usable_bs); *err = 0; - if (!buf) { + if (unlikely((buf != buf_onstack) && !buf)) { *err = -ENOMEM; return 0; } @@ -244,7 +263,7 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, blk = get_free_dqblk(info); if ((int)blk < 0) { *err = blk; - kfree(buf); + FREEDQBUF(); return 0; } memset(buf, 0, info->dqi_usable_bs); @@ -283,13 +302,13 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, blk); goto out_buf; } - dquot->dq_off = (blk << info->dqi_blocksize_bits) + + dquot->dq_off = ((loff_t)blk << info->dqi_blocksize_bits) + sizeof(struct qt_disk_dqdbheader) + i * info->dqi_entry_size; - kfree(buf); + FREEDQBUF(); return blk; out_buf: - kfree(buf); + FREEDQBUF(); return 0; } @@ -297,13 +316,11 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info, static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint *treeblk, int depth) { - char *buf = getdqbuf(info->dqi_usable_bs); int ret = 0, newson = 0, newact = 0; __le32 *ref; uint newblk; + GETDQBUF(info->dqi_usable_bs); - if (!buf) - return -ENOMEM; if (!*treeblk) { ret = get_free_dqblk(info); if (ret < 0) @@ -346,7 +363,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, put_free_dqblk(info, buf, *treeblk); } out_buf: - kfree(buf); + FREEDQBUF(); return ret; } @@ -374,10 +391,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) int type = dquot->dq_id.type; struct super_block *sb = dquot->dq_sb; ssize_t ret; - char *ddquot = getdqbuf(info->dqi_entry_size); - - if (!ddquot) - return -ENOMEM; + GETDQBUF(info->dqi_entry_size); /* dq_off is guarded by dqio_sem */ if (!dquot->dq_off) { @@ -385,14 +399,14 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) if (ret < 0) { quota_error(sb, "Error %zd occurred while creating " "quota", ret); - kfree(ddquot); + FREEDQBUF(); return ret; } } spin_lock(&dquot->dq_dqb_lock); - info->dqi_ops->mem2disk_dqblk(ddquot, dquot); + info->dqi_ops->mem2disk_dqblk(buf, dquot); spin_unlock(&dquot->dq_dqb_lock); - ret = sb->s_op->quota_write(sb, type, ddquot, info->dqi_entry_size, + ret = sb->s_op->quota_write(sb, type, buf, info->dqi_entry_size, dquot->dq_off); if (ret != info->dqi_entry_size) { quota_error(sb, "dquota write failed"); @@ -402,7 +416,7 @@ int qtree_write_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) ret = 0; } dqstats_inc(DQST_WRITES); - kfree(ddquot); + FREEDQBUF(); return ret; } @@ -413,11 +427,9 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint blk) { struct qt_disk_dqdbheader *dh; - char *buf = getdqbuf(info->dqi_usable_bs); int ret = 0; + GETDQBUF(info->dqi_usable_bs); - if (!buf) - return -ENOMEM; if (dquot->dq_off >> info->dqi_blocksize_bits != blk) { quota_error(dquot->dq_sb, "Quota structure has offset to " "other block (%u) than it should (%u)", blk, @@ -465,7 +477,7 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, } dquot->dq_off = 0; /* Quota is now unattached */ out_buf: - kfree(buf); + FREEDQBUF(); return ret; } @@ -473,13 +485,12 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint *blk, int depth) { - char *buf = getdqbuf(info->dqi_usable_bs); int ret = 0; uint newblk; - __le32 *ref = (__le32 *)buf; + __le32 *ref; + GETDQBUF(info->dqi_usable_bs); + ref = (__le32 *)buf; - if (!buf) - return -ENOMEM; ret = read_blk(info, *blk, buf); if (ret < 0) { quota_error(dquot->dq_sb, "Can't read quota data block %u", @@ -513,7 +524,7 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, } } out_buf: - kfree(buf); + FREEDQBUF(); return ret; } @@ -532,13 +543,11 @@ EXPORT_SYMBOL(qtree_delete_dquot); static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint blk) { - char *buf = getdqbuf(info->dqi_usable_bs); loff_t ret = 0; int i; char *ddquot; + GETDQBUF(info->dqi_usable_bs); - if (!buf) - return -ENOMEM; ret = read_blk(info, blk, buf); if (ret < 0) { quota_error(dquot->dq_sb, "Can't read quota tree " @@ -558,11 +567,11 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, ret = -EIO; goto out_buf; } else { - ret = (blk << info->dqi_blocksize_bits) + sizeof(struct + ret = ((loff_t)blk << info->dqi_blocksize_bits) + sizeof(struct qt_disk_dqdbheader) + i * info->dqi_entry_size; } out_buf: - kfree(buf); + FREEDQBUF(); return ret; } @@ -570,12 +579,11 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info, static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot, uint blk, int depth) { - char *buf = getdqbuf(info->dqi_usable_bs); loff_t ret = 0; - __le32 *ref = (__le32 *)buf; + __le32 *ref; + GETDQBUF(info->dqi_usable_bs); + ref = (__le32 *)buf; - if (!buf) - return -ENOMEM; ret = read_blk(info, blk, buf); if (ret < 0) { quota_error(dquot->dq_sb, "Can't read quota tree block %u", @@ -591,7 +599,7 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info, else ret = find_block_dqentry(info, dquot, blk); out_buf: - kfree(buf); + FREEDQBUF(); return ret; } @@ -607,8 +615,9 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) int type = dquot->dq_id.type; struct super_block *sb = dquot->dq_sb; loff_t offset; - char *ddquot; int ret = 0; + char *buf; + char buf_onstack[STACK_ALLOC_SIZE] __aligned(8); #ifdef __QUOTA_QT_PARANOIA /* Invalidated quota? */ @@ -634,10 +643,8 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) } dquot->dq_off = offset; } - ddquot = getdqbuf(info->dqi_entry_size); - if (!ddquot) - return -ENOMEM; - ret = sb->s_op->quota_read(sb, type, ddquot, info->dqi_entry_size, + __GETDQBUF(info->dqi_entry_size); + ret = sb->s_op->quota_read(sb, type, buf, info->dqi_entry_size, dquot->dq_off); if (ret != info->dqi_entry_size) { if (ret >= 0) @@ -646,18 +653,18 @@ int qtree_read_dquot(struct qtree_mem_dqinfo *info, struct dquot *dquot) from_kqid(&init_user_ns, dquot->dq_id)); set_bit(DQ_FAKE_B, &dquot->dq_flags); memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk)); - kfree(ddquot); + FREEDQBUF(); goto out; } spin_lock(&dquot->dq_dqb_lock); - info->dqi_ops->disk2mem_dqblk(dquot, ddquot); + info->dqi_ops->disk2mem_dqblk(dquot, buf); if (!dquot->dq_dqb.dqb_bhardlimit && !dquot->dq_dqb.dqb_bsoftlimit && !dquot->dq_dqb.dqb_ihardlimit && !dquot->dq_dqb.dqb_isoftlimit) set_bit(DQ_FAKE_B, &dquot->dq_flags); spin_unlock(&dquot->dq_dqb_lock); - kfree(ddquot); + FREEDQBUF(); out: dqstats_inc(DQST_READS); return ret; @@ -678,15 +685,13 @@ EXPORT_SYMBOL(qtree_release_dquot); static int find_next_id(struct qtree_mem_dqinfo *info, qid_t *id, unsigned int blk, int depth) { - char *buf = getdqbuf(info->dqi_usable_bs); - __le32 *ref = (__le32 *)buf; + __le32 *ref; ssize_t ret; unsigned int epb = info->dqi_usable_bs >> 2; unsigned int level_inc = 1; int i; - - if (!buf) - return -ENOMEM; + GETDQBUF(info->dqi_usable_bs); + ref = (__le32 *)buf; for (i = depth; i < info->dqi_qtree_depth - 1; i++) level_inc *= epb; @@ -715,7 +720,7 @@ static int find_next_id(struct qtree_mem_dqinfo *info, qid_t *id, goto out_buf; } out_buf: - kfree(buf); + FREEDQBUF(); return ret; } diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c index 5d4dc0f84f20..addfaae8decf 100644 --- a/fs/quota/quota_v2.c +++ b/fs/quota/quota_v2.c @@ -158,7 +158,31 @@ static int v2_read_file_info(struct super_block *sb, int type) qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk); qinfo->dqi_ops = &v2r1_qtree_ops; } + ret = -EUCLEAN; + /* Some sanity checks of the read headers... */ + if ((loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits > + i_size_read(sb_dqopt(sb)->files[type])) { + quota_error(sb, "Number of blocks too big for quota file size (%llu > %llu).", + (loff_t)qinfo->dqi_blocks << qinfo->dqi_blocksize_bits, + i_size_read(sb_dqopt(sb)->files[type])); + goto out_free; + } + if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) { + quota_error(sb, "Free block number too big (%u >= %u).", + qinfo->dqi_free_blk, qinfo->dqi_blocks); + goto out_free; + } + if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) { + quota_error(sb, "Block with free entry too big (%u >= %u).", + qinfo->dqi_free_entry, qinfo->dqi_blocks); + goto out_free; + } ret = 0; +out_free: + if (ret) { + kfree(info->dqi_priv); + info->dqi_priv = NULL; + } out: up_read(&dqopt->dqio_sem); return ret; diff --git a/fs/readdir.c b/fs/readdir.c index 443270f635f4..3c5ce8a0ddc9 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -132,6 +132,9 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen, if (buf->result) return -EINVAL; + buf->result = verify_dirent_name(name, namlen); + if (buf->result < 0) + return buf->result; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->result = -EOVERFLOW; @@ -398,6 +401,9 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name, if (buf->result) return -EINVAL; + buf->result = verify_dirent_name(name, namlen); + if (buf->result < 0) + return buf->result; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->result = -EOVERFLOW; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 2946713cb00d..5229038852ca 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -454,6 +454,12 @@ static int is_leaf(char *buf, int blocksize, struct buffer_head *bh) "(second one): %h", ih); return 0; } + if (is_direntry_le_ih(ih) && (ih_item_len(ih) < (ih_entry_count(ih) * IH_SIZE))) { + reiserfs_warning(NULL, "reiserfs-5093", + "item entry count seems wrong %h", + ih); + return 0; + } prev_location = ih_location(ih); } diff --git a/fs/reiserfs/xattr.h b/fs/reiserfs/xattr.h index c764352447ba..81bec2c80b25 100644 --- a/fs/reiserfs/xattr.h +++ b/fs/reiserfs/xattr.h @@ -43,7 +43,7 @@ void reiserfs_security_free(struct reiserfs_security_handle *sec); static inline int reiserfs_xattrs_initialized(struct super_block *sb) { - return REISERFS_SB(sb)->priv_root != NULL; + return REISERFS_SB(sb)->priv_root && REISERFS_SB(sb)->xattr_root; } #define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header)) diff --git a/fs/sdcardfs/file.c b/fs/sdcardfs/file.c index 271c4c4cb760..70134f3f296c 100644 --- a/fs/sdcardfs/file.c +++ b/fs/sdcardfs/file.c @@ -23,6 +23,8 @@ #include #endif +struct kmem_cache *kmem_file_info_pool; + static ssize_t sdcardfs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { @@ -256,7 +258,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) } file->private_data = - kzalloc(sizeof(struct sdcardfs_file_info), GFP_KERNEL); + kmem_cache_zalloc(kmem_file_info_pool, GFP_KERNEL); if (!SDCARDFS_F(file)) { err = -ENOMEM; goto out_revert_cred; @@ -278,7 +280,7 @@ static int sdcardfs_open(struct inode *inode, struct file *file) } if (err) - kfree(SDCARDFS_F(file)); + kmem_cache_free(kmem_file_info_pool, SDCARDFS_F(file)); else sdcardfs_copy_and_fix_attrs(inode, sdcardfs_lower_inode(inode)); @@ -314,7 +316,7 @@ static int sdcardfs_file_release(struct inode *inode, struct file *file) fput(lower_file); } - kfree(SDCARDFS_F(file)); + kmem_cache_free(kmem_file_info_pool, SDCARDFS_F(file)); return 0; } diff --git a/fs/sdcardfs/lookup.c b/fs/sdcardfs/lookup.c index d2dfdf1028c6..0abbd09c5b79 100644 --- a/fs/sdcardfs/lookup.c +++ b/fs/sdcardfs/lookup.c @@ -234,9 +234,12 @@ static int sdcardfs_name_match(struct dir_context *ctx, const char *name, struct qstr candidate = QSTR_INIT(name, namelen); if (qstr_case_eq(buf->to_find, &candidate)) { - memcpy(buf->name, name, namelen); - buf->name[namelen] = 0; buf->found = true; + buf->name = kmalloc(namelen + 1, GFP_KERNEL); + if (buf->name) { + memcpy(buf->name, name, namelen); + buf->name[namelen] = '\0'; + } return 1; } return 0; @@ -284,33 +287,34 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry, struct sdcardfs_name_data buffer = { .ctx.actor = sdcardfs_name_match, .to_find = name, - .name = __getname(), .found = false, }; - if (!buffer.name) { - err = -ENOMEM; - goto out; - } file = dentry_open(lower_parent_path, O_RDONLY, cred); if (IS_ERR(file)) { err = PTR_ERR(file); - goto put_name; + goto err; } + err = iterate_dir(file, &buffer.ctx); fput(file); if (err) - goto put_name; + goto err; + + if (buffer.found) { + if (!buffer.name) { + err = -ENOMEM; + goto out; + } - if (buffer.found) err = vfs_path_lookup(lower_dir_dentry, lower_dir_mnt, buffer.name, 0, &lower_path); - else + kfree(buffer.name); + } else { err = -ENOENT; -put_name: - __putname(buffer.name); + } } /* no error: handle positive dentries */ @@ -359,6 +363,7 @@ static struct dentry *__sdcardfs_lookup(struct dentry *dentry, * We don't consider ENOENT an error, and we want to return a * negative dentry. */ +err: if (err && err != -ENOENT) goto out; diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index cb668f72ee23..8f7ca3fa7111 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -476,6 +476,12 @@ static int __init init_sdcardfs_fs(void) pr_info("Registering sdcardfs " SDCARDFS_VERSION "\n"); + kmem_file_info_pool = KMEM_CACHE(sdcardfs_file_info, SLAB_HWCACHE_ALIGN); + if (!kmem_file_info_pool) { + err = -ENOMEM; + goto err; + } + err = sdcardfs_init_inode_cache(); if (err) goto out; @@ -492,6 +498,7 @@ static int __init init_sdcardfs_fs(void) sdcardfs_destroy_dentry_cache(); packagelist_exit(); } +err: return err; } @@ -501,6 +508,7 @@ static void __exit exit_sdcardfs_fs(void) sdcardfs_destroy_dentry_cache(); packagelist_exit(); unregister_filesystem(&sdcardfs_fs_type); + kmem_cache_destroy(kmem_file_info_pool); pr_info("Completed sdcardfs module unload\n"); } diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 401445e9121d..f429dc0bd49f 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -655,4 +655,6 @@ static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2) #define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1) +extern struct kmem_cache *kmem_file_info_pool; + #endif /* not _SDCARDFS_H_ */ diff --git a/fs/select.c b/fs/select.c index 4a6b6e4b21cb..11a7051075b4 100644 --- a/fs/select.c +++ b/fs/select.c @@ -1003,10 +1003,9 @@ static long do_restart_poll(struct restart_block *restart_block) ret = do_sys_poll(ufds, nfds, to); - if (ret == -EINTR) { - restart_block->fn = do_restart_poll; - ret = -ERESTART_RESTARTBLOCK; - } + if (ret == -EINTR) + ret = set_restart_fn(restart_block, do_restart_poll); + return ret; } @@ -1028,7 +1027,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, struct restart_block *restart_block; restart_block = ¤t->restart_block; - restart_block->fn = do_restart_poll; restart_block->poll.ufds = ufds; restart_block->poll.nfds = nfds; @@ -1039,7 +1037,7 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds, } else restart_block->poll.has_timeout = 0; - ret = -ERESTART_RESTARTBLOCK; + ret = set_restart_fn(restart_block, do_restart_poll); } return ret; } diff --git a/fs/squashfs/export.c b/fs/squashfs/export.c index 8073b6532cf0..1d406a2094a5 100644 --- a/fs/squashfs/export.c +++ b/fs/squashfs/export.c @@ -54,12 +54,17 @@ static long long squashfs_inode_lookup(struct super_block *sb, int ino_num) struct squashfs_sb_info *msblk = sb->s_fs_info; int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1); int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1); - u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]); + u64 start; __le64 ino; int err; TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num); + if (ino_num == 0 || (ino_num - 1) >= msblk->inodes) + return -EINVAL; + + start = le64_to_cpu(msblk->inode_lookup_table[blk]); + err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino)); if (err < 0) return err; @@ -124,7 +129,10 @@ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb, u64 lookup_table_start, u64 next_table, unsigned int inodes) { unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes); + unsigned int indexes = SQUASHFS_LOOKUP_BLOCKS(inodes); + int n; __le64 *table; + u64 start, end; TRACE("In read_inode_lookup_table, length %d\n", length); @@ -134,20 +142,41 @@ __le64 *squashfs_read_inode_lookup_table(struct super_block *sb, if (inodes == 0) return ERR_PTR(-EINVAL); - /* length bytes should not extend into the next table - this check - * also traps instances where lookup_table_start is incorrectly larger - * than the next table start + /* + * The computed size of the lookup table (length bytes) should exactly + * match the table start and end points */ - if (lookup_table_start + length > next_table) + if (length != (next_table - lookup_table_start)) return ERR_PTR(-EINVAL); table = squashfs_read_table(sb, lookup_table_start, length); + if (IS_ERR(table)) + return table; /* - * table[0] points to the first inode lookup table metadata block, - * this should be less than lookup_table_start + * table0], table[1], ... table[indexes - 1] store the locations + * of the compressed inode lookup blocks. Each entry should be + * less than the next (i.e. table[0] < table[1]), and the difference + * between them should be SQUASHFS_METADATA_SIZE or less. + * table[indexes - 1] should be less than lookup_table_start, and + * again the difference should be SQUASHFS_METADATA_SIZE or less */ - if (!IS_ERR(table) && le64_to_cpu(table[0]) >= lookup_table_start) { + for (n = 0; n < (indexes - 1); n++) { + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + + if (start >= end + || (end - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); + if (start >= lookup_table_start || + (lookup_table_start - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } diff --git a/fs/squashfs/id.c b/fs/squashfs/id.c index d38ea3dab951..d2e15baab537 100644 --- a/fs/squashfs/id.c +++ b/fs/squashfs/id.c @@ -48,10 +48,15 @@ int squashfs_get_id(struct super_block *sb, unsigned int index, struct squashfs_sb_info *msblk = sb->s_fs_info; int block = SQUASHFS_ID_BLOCK(index); int offset = SQUASHFS_ID_BLOCK_OFFSET(index); - u64 start_block = le64_to_cpu(msblk->id_table[block]); + u64 start_block; __le32 disk_id; int err; + if (index >= msblk->ids) + return -EINVAL; + + start_block = le64_to_cpu(msblk->id_table[block]); + err = squashfs_read_metadata(sb, &disk_id, &start_block, &offset, sizeof(disk_id)); if (err < 0) @@ -69,7 +74,10 @@ __le64 *squashfs_read_id_index_table(struct super_block *sb, u64 id_table_start, u64 next_table, unsigned short no_ids) { unsigned int length = SQUASHFS_ID_BLOCK_BYTES(no_ids); + unsigned int indexes = SQUASHFS_ID_BLOCKS(no_ids); + int n; __le64 *table; + u64 start, end; TRACE("In read_id_index_table, length %d\n", length); @@ -80,20 +88,38 @@ __le64 *squashfs_read_id_index_table(struct super_block *sb, return ERR_PTR(-EINVAL); /* - * length bytes should not extend into the next table - this check - * also traps instances where id_table_start is incorrectly larger - * than the next table start + * The computed size of the index table (length bytes) should exactly + * match the table start and end points */ - if (id_table_start + length > next_table) + if (length != (next_table - id_table_start)) return ERR_PTR(-EINVAL); table = squashfs_read_table(sb, id_table_start, length); + if (IS_ERR(table)) + return table; /* - * table[0] points to the first id lookup table metadata block, this - * should be less than id_table_start + * table[0], table[1], ... table[indexes - 1] store the locations + * of the compressed id blocks. Each entry should be less than + * the next (i.e. table[0] < table[1]), and the difference between them + * should be SQUASHFS_METADATA_SIZE or less. table[indexes - 1] + * should be less than id_table_start, and again the difference + * should be SQUASHFS_METADATA_SIZE or less */ - if (!IS_ERR(table) && le64_to_cpu(table[0]) >= id_table_start) { + for (n = 0; n < (indexes - 1); n++) { + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + + if (start >= end || (end - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); + if (start >= id_table_start || (id_table_start - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { kfree(table); return ERR_PTR(-EINVAL); } diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index 4e6853f084d0..10e93345b615 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h @@ -30,6 +30,7 @@ /* size of metadata (inode and directory) blocks */ #define SQUASHFS_METADATA_SIZE 8192 +#define SQUASHFS_BLOCK_OFFSET 2 /* default size of block device I/O */ #ifdef CONFIG_SQUASHFS_4K_DEVBLK_SIZE diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h index ef69c31947bf..5234c19a0eab 100644 --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h @@ -77,5 +77,6 @@ struct squashfs_sb_info { unsigned int inodes; unsigned int fragments; int xattr_ids; + unsigned int ids; }; #endif diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 40e657386fa5..728b2d72f3f0 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -176,6 +176,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) msblk->directory_table = le64_to_cpu(sblk->directory_table_start); msblk->inodes = le32_to_cpu(sblk->inodes); msblk->fragments = le32_to_cpu(sblk->fragments); + msblk->ids = le16_to_cpu(sblk->no_ids); flags = le16_to_cpu(sblk->flags); TRACE("Found valid superblock on %pg\n", sb->s_bdev); @@ -187,7 +188,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) TRACE("Block size %d\n", msblk->block_size); TRACE("Number of inodes %d\n", msblk->inodes); TRACE("Number of fragments %d\n", msblk->fragments); - TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids)); + TRACE("Number of ids %d\n", msblk->ids); TRACE("sblk->inode_table_start %llx\n", msblk->inode_table); TRACE("sblk->directory_table_start %llx\n", msblk->directory_table); TRACE("sblk->fragment_table_start %llx\n", @@ -244,8 +245,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) allocate_id_index_table: /* Allocate and read id index table */ msblk->id_table = squashfs_read_id_index_table(sb, - le64_to_cpu(sblk->id_table_start), next_table, - le16_to_cpu(sblk->no_ids)); + le64_to_cpu(sblk->id_table_start), next_table, msblk->ids); if (IS_ERR(msblk->id_table)) { ERROR("unable to read id index table\n"); err = PTR_ERR(msblk->id_table); diff --git a/fs/squashfs/xattr.h b/fs/squashfs/xattr.h index afe70f815e3d..86b0a0073e51 100644 --- a/fs/squashfs/xattr.h +++ b/fs/squashfs/xattr.h @@ -30,8 +30,16 @@ extern int squashfs_xattr_lookup(struct super_block *, unsigned int, int *, static inline __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, u64 *xattr_table_start, int *xattr_ids) { + struct squashfs_xattr_id_table *id_table; + + id_table = squashfs_read_table(sb, start, sizeof(*id_table)); + if (IS_ERR(id_table)) + return (__le64 *) id_table; + + *xattr_table_start = le64_to_cpu(id_table->xattr_table_start); + kfree(id_table); + ERROR("Xattrs in filesystem, these will be ignored\n"); - *xattr_table_start = start; return ERR_PTR(-ENOTSUPP); } diff --git a/fs/squashfs/xattr_id.c b/fs/squashfs/xattr_id.c index c89607d690c4..7f718d2bf357 100644 --- a/fs/squashfs/xattr_id.c +++ b/fs/squashfs/xattr_id.c @@ -44,10 +44,15 @@ int squashfs_xattr_lookup(struct super_block *sb, unsigned int index, struct squashfs_sb_info *msblk = sb->s_fs_info; int block = SQUASHFS_XATTR_BLOCK(index); int offset = SQUASHFS_XATTR_BLOCK_OFFSET(index); - u64 start_block = le64_to_cpu(msblk->xattr_id_table[block]); + u64 start_block; struct squashfs_xattr_id id; int err; + if (index >= msblk->xattr_ids) + return -EINVAL; + + start_block = le64_to_cpu(msblk->xattr_id_table[block]); + err = squashfs_read_metadata(sb, &id, &start_block, &offset, sizeof(id)); if (err < 0) @@ -63,13 +68,17 @@ int squashfs_xattr_lookup(struct super_block *sb, unsigned int index, /* * Read uncompressed xattr id lookup table indexes from disk into memory */ -__le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, +__le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 table_start, u64 *xattr_table_start, int *xattr_ids) { - unsigned int len; + struct squashfs_sb_info *msblk = sb->s_fs_info; + unsigned int len, indexes; struct squashfs_xattr_id_table *id_table; + __le64 *table; + u64 start, end; + int n; - id_table = squashfs_read_table(sb, start, sizeof(*id_table)); + id_table = squashfs_read_table(sb, table_start, sizeof(*id_table)); if (IS_ERR(id_table)) return (__le64 *) id_table; @@ -83,13 +92,54 @@ __le64 *squashfs_read_xattr_id_table(struct super_block *sb, u64 start, if (*xattr_ids == 0) return ERR_PTR(-EINVAL); - /* xattr_table should be less than start */ - if (*xattr_table_start >= start) + len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); + indexes = SQUASHFS_XATTR_BLOCKS(*xattr_ids); + + /* + * The computed size of the index table (len bytes) should exactly + * match the table start and end points + */ + start = table_start + sizeof(*id_table); + end = msblk->bytes_used; + + if (len != (end - start)) return ERR_PTR(-EINVAL); - len = SQUASHFS_XATTR_BLOCK_BYTES(*xattr_ids); + table = squashfs_read_table(sb, start, len); + if (IS_ERR(table)) + return table; + + /* table[0], table[1], ... table[indexes - 1] store the locations + * of the compressed xattr id blocks. Each entry should be less than + * the next (i.e. table[0] < table[1]), and the difference between them + * should be SQUASHFS_METADATA_SIZE or less. table[indexes - 1] + * should be less than table_start, and again the difference + * shouls be SQUASHFS_METADATA_SIZE or less. + * + * Finally xattr_table_start should be less than table[0]. + */ + for (n = 0; n < (indexes - 1); n++) { + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + + if (start >= end || (end - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); + if (start >= table_start || (table_start - start) > + (SQUASHFS_METADATA_SIZE + SQUASHFS_BLOCK_OFFSET)) { + kfree(table); + return ERR_PTR(-EINVAL); + } - TRACE("In read_xattr_index_table, length %d\n", len); + if (*xattr_table_start >= le64_to_cpu(table[0])) { + kfree(table); + return ERR_PTR(-EINVAL); + } - return squashfs_read_table(sb, start + sizeof(*id_table), len); + return table; } diff --git a/fs/super.c b/fs/super.c index 7fa6fe5f16b7..4c3ae56ca99f 100644 --- a/fs/super.c +++ b/fs/super.c @@ -1380,36 +1380,11 @@ EXPORT_SYMBOL(__sb_end_write); */ int __sb_start_write(struct super_block *sb, int level, bool wait) { - bool force_trylock = false; - int ret = 1; + if (!wait) + return percpu_down_read_trylock(sb->s_writers.rw_sem + level-1); -#ifdef CONFIG_LOCKDEP - /* - * We want lockdep to tell us about possible deadlocks with freezing - * but it's it bit tricky to properly instrument it. Getting a freeze - * protection works as getting a read lock but there are subtle - * problems. XFS for example gets freeze protection on internal level - * twice in some cases, which is OK only because we already hold a - * freeze protection also on higher level. Due to these cases we have - * to use wait == F (trylock mode) which must not fail. - */ - if (wait) { - int i; - - for (i = 0; i < level - 1; i++) - if (percpu_rwsem_is_held(sb->s_writers.rw_sem + i)) { - force_trylock = true; - break; - } - } -#endif - if (wait && !force_trylock) - percpu_down_read(sb->s_writers.rw_sem + level-1); - else - ret = percpu_down_read_trylock(sb->s_writers.rw_sem + level-1); - - WARN_ON(force_trylock && !ret); - return ret; + percpu_down_read(sb->s_writers.rw_sem + level-1); + return 1; } EXPORT_SYMBOL(__sb_start_write); diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 0a7252aecfa5..5166eb40917d 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sysfs.h" #include "../kernfs/kernfs-internal.h" @@ -556,3 +557,57 @@ void sysfs_remove_bin_file(struct kobject *kobj, kernfs_remove_by_name(kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); + +/** + * sysfs_emit - scnprintf equivalent, aware of PAGE_SIZE buffer. + * @buf: start of PAGE_SIZE buffer. + * @fmt: format + * @...: optional arguments to @format + * + * + * Returns number of characters written to @buf. + */ +int sysfs_emit(char *buf, const char *fmt, ...) +{ + va_list args; + int len; + + if (WARN(!buf || offset_in_page(buf), + "invalid sysfs_emit: buf:%p\n", buf)) + return 0; + + va_start(args, fmt); + len = vscnprintf(buf, PAGE_SIZE, fmt, args); + va_end(args); + + return len; +} +EXPORT_SYMBOL_GPL(sysfs_emit); + +/** + * sysfs_emit_at - scnprintf equivalent, aware of PAGE_SIZE buffer. + * @buf: start of PAGE_SIZE buffer. + * @at: offset in @buf to start write in bytes + * @at must be >= 0 && < PAGE_SIZE + * @fmt: format + * @...: optional arguments to @fmt + * + * + * Returns number of characters written starting at &@buf[@at]. + */ +int sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + va_list args; + int len; + + if (WARN(!buf || offset_in_page(buf) || at < 0 || at >= PAGE_SIZE, + "invalid sysfs_emit_at: buf:%p at:%d\n", buf, at)) + return 0; + + va_start(args, fmt); + len = vscnprintf(buf + at, PAGE_SIZE - at, fmt, args); + va_end(args); + + return len; +} +EXPORT_SYMBOL_GPL(sysfs_emit_at); diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 1a7c5c0754d4..cc2f10ec3839 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -290,6 +290,15 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry, return d_splice_alias(inode, dentry); } +static int ubifs_prepare_create(struct inode *dir, struct dentry *dentry, + struct fscrypt_name *nm) +{ + if (fscrypt_is_nokey_name(dentry)) + return -ENOKEY; + + return fscrypt_setup_filename(dir, &dentry->d_name, 0, nm); +} + static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { @@ -313,7 +322,7 @@ static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, if (err) return err; - err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm); + err = ubifs_prepare_create(dir, dentry, &nm); if (err) goto out_budg; @@ -977,7 +986,7 @@ static int ubifs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) if (err) return err; - err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm); + err = ubifs_prepare_create(dir, dentry, &nm); if (err) goto out_budg; @@ -1062,7 +1071,7 @@ static int ubifs_mknod(struct inode *dir, struct dentry *dentry, return err; } - err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm); + err = ubifs_prepare_create(dir, dentry, &nm); if (err) { kfree(dev); goto out_budg; @@ -1146,7 +1155,7 @@ static int ubifs_symlink(struct inode *dir, struct dentry *dentry, if (err) return err; - err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm); + err = ubifs_prepare_create(dir, dentry, &nm); if (err) goto out_budg; diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index fab29f899f91..9542ebf643a5 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -331,7 +331,7 @@ void ubifs_pad(const struct ubifs_info *c, void *buf, int pad) { uint32_t crc; - ubifs_assert(c, pad >= 0 && !(pad & 7)); + ubifs_assert(c, pad >= 0); if (pad >= UBIFS_PAD_NODE_SZ) { struct ubifs_ch *ch = buf; @@ -728,6 +728,10 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) * write-buffer. */ memcpy(wbuf->buf + wbuf->used, buf, len); + if (aligned_len > len) { + ubifs_assert(c, aligned_len - len < 8); + ubifs_pad(c, wbuf->buf + wbuf->used + len, aligned_len - len); + } if (aligned_len == wbuf->avail) { dbg_io("flush jhead %s wbuf to LEB %d:%d", @@ -820,13 +824,18 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len) } spin_lock(&wbuf->lock); - if (aligned_len) + if (aligned_len) { /* * And now we have what's left and what does not take whole * max. write unit, so write it to the write-buffer and we are * done. */ memcpy(wbuf->buf, buf + written, len); + if (aligned_len > len) { + ubifs_assert(c, aligned_len - len < 8); + ubifs_pad(c, wbuf->buf + len, aligned_len - len); + } + } if (c->leb_size - wbuf->offs >= c->max_write_size) wbuf->size = c->max_write_size; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 3bf89a633836..f5500d2a3879 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -540,11 +540,14 @@ static int udf_do_extend_file(struct inode *inode, udf_write_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); + /* - * We've rewritten the last extent but there may be empty - * indirect extent after it - enter it. + * We've rewritten the last extent. If we are going to add + * more extents, we may need to enter possible following + * empty indirect extent. */ - udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0); + if (new_block_bytes || prealloc_len) + udf_next_aext(inode, last_pos, &tmploc, &tmplen, 0); } /* Managed to do everything necessary? */ diff --git a/fs/xattr.c b/fs/xattr.c index e1f041e9b3b0..314caca12eaf 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -598,6 +598,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, ssize_t error; void *kvalue = NULL; char kname[XATTR_NAME_MAX + 1]; + char kvalue_onstack[255]; error = strncpy_from_user(kname, name, sizeof(kname)); if (error == 0 || error == sizeof(kname)) @@ -606,11 +607,15 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, return error; if (size) { - if (size > XATTR_SIZE_MAX) - size = XATTR_SIZE_MAX; - kvalue = kvzalloc(size, GFP_KERNEL); - if (!kvalue) - return -ENOMEM; + if (size <= ARRAY_SIZE(kvalue_onstack)) { + kvalue = kvalue_onstack; + } else { + if (size > XATTR_SIZE_MAX) + size = XATTR_SIZE_MAX; + kvalue = kvzalloc(size, GFP_KERNEL); + if (!kvalue) + return -ENOMEM; + } } error = vfs_getxattr(d, kname, kvalue, size); @@ -626,7 +631,8 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, error = -E2BIG; } - kvfree(kvalue); + if (kvalue != kvalue_onstack) + kvfree(kvalue); return error; } diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 1eb7933dac83..b3a9043b0c9e 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2213,6 +2213,7 @@ xfs_defer_agfl_block( new->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno); new->xefi_blockcount = 1; new->xefi_oinfo = *oinfo; + new->xefi_skip_discard = false; trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1); diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 488dc8860fd7..50242ba3cdb7 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -52,9 +52,9 @@ struct xfs_extent_free_item { xfs_fsblock_t xefi_startblock;/* starting fs block number */ xfs_extlen_t xefi_blockcount;/* number of blocks in extent */ + bool xefi_skip_discard; struct list_head xefi_list; struct xfs_owner_info xefi_oinfo; /* extent owner */ - bool xefi_skip_discard; }; #define XFS_BMAP_MAX_NMAP 4 diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 245af452840e..ab3e72e702f0 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -1387,7 +1387,7 @@ xfs_rmap_convert_shared( * record for our insertion point. This will also give us the record for * start block contiguity tests. */ - error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, + error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, oldext, &PREV, &i); if (error) goto done; diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index f84a58e523bc..cf005e18d618 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -120,6 +120,8 @@ xchk_bmap_get_rmap( if (info->whichfork == XFS_ATTR_FORK) rflags |= XFS_RMAP_ATTR_FORK; + if (irec->br_state == XFS_EXT_UNWRITTEN) + rflags |= XFS_RMAP_UNWRITTEN; /* * CoW staging extents are owned (on disk) by the refcountbt, so @@ -223,13 +225,13 @@ xchk_bmap_xref_rmap( * which doesn't track unwritten state. */ if (owner != XFS_RMAP_OWN_COW && - irec->br_state == XFS_EXT_UNWRITTEN && - !(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) + !!(irec->br_state == XFS_EXT_UNWRITTEN) != + !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN)) xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, irec->br_startoff); - if (info->whichfork == XFS_ATTR_FORK && - !(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) + if (!!(info->whichfork == XFS_ATTR_FORK) != + !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK)) xchk_fblock_xref_set_corrupt(info->sc, info->whichfork, irec->br_startoff); if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK) diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c index 4ae959f7ad2c..c924fe3cdad6 100644 --- a/fs/xfs/scrub/btree.c +++ b/fs/xfs/scrub/btree.c @@ -450,32 +450,41 @@ xchk_btree_check_minrecs( int level, struct xfs_btree_block *block) { - unsigned int numrecs; - int ok_level; - - numrecs = be16_to_cpu(block->bb_numrecs); + struct xfs_btree_cur *cur = bs->cur; + unsigned int root_level = cur->bc_nlevels - 1; + unsigned int numrecs = be16_to_cpu(block->bb_numrecs); /* More records than minrecs means the block is ok. */ - if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level)) + if (numrecs >= cur->bc_ops->get_minrecs(cur, level)) return; /* - * Certain btree blocks /can/ have fewer than minrecs records. Any - * level greater than or equal to the level of the highest dedicated - * btree block are allowed to violate this constraint. - * - * For a btree rooted in a block, the btree root can have fewer than - * minrecs records. If the btree is rooted in an inode and does not - * store records in the root, the direct children of the root and the - * root itself can have fewer than minrecs records. + * For btrees rooted in the inode, it's possible that the root block + * contents spilled into a regular ondisk block because there wasn't + * enough space in the inode root. The number of records in that + * child block might be less than the standard minrecs, but that's ok + * provided that there's only one direct child of the root. */ - ok_level = bs->cur->bc_nlevels - 1; - if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) - ok_level--; - if (level >= ok_level) + if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && + level == cur->bc_nlevels - 2) { + struct xfs_btree_block *root_block; + struct xfs_buf *root_bp; + int root_maxrecs; + + root_block = xfs_btree_get_block(cur, root_level, &root_bp); + root_maxrecs = cur->bc_ops->get_dmaxrecs(cur, root_level); + if (be16_to_cpu(root_block->bb_numrecs) != 1 || + numrecs <= root_maxrecs) + xchk_btree_set_corrupt(bs->sc, cur, level); return; + } - xchk_btree_set_corrupt(bs->sc, bs->cur, level); + /* + * Otherwise, only the root level is allowed to have fewer than minrecs + * records or keyptrs. + */ + if (level < root_level) + xchk_btree_set_corrupt(bs->sc, cur, level); } /* diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c index e386c9b0b4ab..8d45d60832db 100644 --- a/fs/xfs/scrub/inode.c +++ b/fs/xfs/scrub/inode.c @@ -131,8 +131,7 @@ xchk_inode_flags( goto bad; /* rt flags require rt device */ - if ((flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT)) && - !mp->m_rtdev_targp) + if ((flags & XFS_DIFLAG_REALTIME) && !mp->m_rtdev_targp) goto bad; /* new rt bitmap flag only valid for rbmino */ diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c index e8c82b026083..76e4f16a9fab 100644 --- a/fs/xfs/scrub/refcount.c +++ b/fs/xfs/scrub/refcount.c @@ -180,7 +180,6 @@ xchk_refcountbt_process_rmap_fragments( */ INIT_LIST_HEAD(&worklist); rbno = NULLAGBLOCK; - nr = 1; /* Make sure the fragments actually /are/ in agbno order. */ bno = 0; @@ -194,15 +193,14 @@ xchk_refcountbt_process_rmap_fragments( * Find all the rmaps that start at or before the refc extent, * and put them on the worklist. */ + nr = 0; list_for_each_entry_safe(frag, n, &refchk->fragments, list) { - if (frag->rm.rm_startblock > refchk->bno) - goto done; + if (frag->rm.rm_startblock > refchk->bno || nr > target_nr) + break; bno = frag->rm.rm_startblock + frag->rm.rm_blockcount; if (bno < rbno) rbno = bno; list_move_tail(&frag->list, &worklist); - if (nr == target_nr) - break; nr++; } diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index e427ad097e2e..6011086b51de 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -849,7 +849,7 @@ xfs_setattr_size( ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); ASSERT(S_ISREG(inode->i_mode)); ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| - ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); + ATTR_MTIME_SET|ATTR_TIMES_SET)) == 0); oldsize = inode->i_size; newsize = iattr->ia_size; @@ -895,6 +895,16 @@ xfs_setattr_size( error = iomap_zero_range(inode, oldsize, newsize - oldsize, &did_zeroing, &xfs_iomap_ops); } else { + /* + * iomap won't detect a dirty page over an unwritten block (or a + * cow block over a hole) and subsequently skips zeroing the + * newly post-EOF portion of the page. Flush the new EOF to + * convert the block before the pagecache truncate. + */ + error = filemap_write_and_wait_range(inode->i_mapping, newsize, + newsize); + if (error) + return error; error = iomap_truncate_page(inode, newsize, &did_zeroing, &xfs_iomap_ops); } diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index f44c3599527d..1c9bced3e860 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -141,7 +141,7 @@ xfs_fs_map_blocks( goto out_unlock; error = invalidate_inode_pages2(inode->i_mapping); if (WARN_ON_ONCE(error)) - return error; + goto out_unlock; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + length); offset_fsb = XFS_B_TO_FSBT(mp, offset); diff --git a/gen_headers_arm.bp b/gen_headers_arm.bp index b5a546f124ac..e8678343488b 100644 --- a/gen_headers_arm.bp +++ b/gen_headers_arm.bp @@ -148,6 +148,7 @@ gen_headers_out_arm = [ "linux/b1lli.h", "linux/batadv_packet.h", "linux/batman_adv.h", + "linux/batterydata-interface.h", "linux/baycom.h", "linux/bcache.h", "linux/bcm933xx_hcs.h", @@ -623,6 +624,7 @@ gen_headers_out_arm = [ "linux/virtio_scsi.h", "linux/virtio_types.h", "linux/virtio_vsock.h", + "linux/vm_bms.h", "linux/vm_sockets.h", "linux/vm_sockets_diag.h", "linux/vmcore.h", diff --git a/gen_headers_arm64.bp b/gen_headers_arm64.bp index 17616f395cf2..8b884b3ed6ad 100644 --- a/gen_headers_arm64.bp +++ b/gen_headers_arm64.bp @@ -143,6 +143,7 @@ gen_headers_out_arm64 = [ "linux/b1lli.h", "linux/batadv_packet.h", "linux/batman_adv.h", + "linux/batterydata-interface.h", "linux/baycom.h", "linux/bcache.h", "linux/bcm933xx_hcs.h", @@ -617,6 +618,7 @@ gen_headers_out_arm64 = [ "linux/virtio_scsi.h", "linux/virtio_types.h", "linux/virtio_vsock.h", + "linux/vm_bms.h", "linux/vm_sockets.h", "linux/vm_sockets_diag.h", "linux/vmcore.h", diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 856c56ef0143..878b8e26c6c5 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -59,11 +59,11 @@ struct acpi_exception_info { #define AE_OK (acpi_status) 0x0000 -#define ACPI_ENV_EXCEPTION(status) (status & AE_CODE_ENVIRONMENTAL) -#define ACPI_AML_EXCEPTION(status) (status & AE_CODE_AML) -#define ACPI_PROG_EXCEPTION(status) (status & AE_CODE_PROGRAMMER) -#define ACPI_TABLE_EXCEPTION(status) (status & AE_CODE_ACPI_TABLES) -#define ACPI_CNTL_EXCEPTION(status) (status & AE_CODE_CONTROL) +#define ACPI_ENV_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_ENVIRONMENTAL) +#define ACPI_AML_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_AML) +#define ACPI_PROG_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_PROGRAMMER) +#define ACPI_TABLE_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_ACPI_TABLES) +#define ACPI_CNTL_EXCEPTION(status) (((status) & AE_CODE_MASK) == AE_CODE_CONTROL) /* * Environmental exceptions diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ba4dd54f2c82..8b19618bad0a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -248,6 +248,7 @@ struct acpi_pnp_type { struct acpi_device_pnp { acpi_bus_id bus_id; /* Object name */ + int instance_no; /* Instance number of this object */ struct acpi_pnp_type type; /* ID type */ acpi_bus_address bus_address; /* _ADR */ char *unique_id; /* _UID */ @@ -622,7 +623,6 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev); bool acpi_pm_device_can_wakeup(struct device *dev); int acpi_pm_device_sleep_state(struct device *, int *, int); int acpi_pm_set_device_wakeup(struct device *dev, bool enable); -int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable); #else static inline void acpi_pm_wakeup_event(struct device *dev) { @@ -653,10 +653,6 @@ static inline int acpi_pm_set_device_wakeup(struct device *dev, bool enable) { return -ENODEV; } -static inline int acpi_pm_set_bridge_wakeup(struct device *dev, bool enable) -{ - return -ENODEV; -} #endif #ifdef CONFIG_ACPI_SLEEP diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index eff86b973109..67559d107ceb 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -69,11 +69,11 @@ #if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG) #define TEXT_MAIN .text .text.[0-9a-zA-Z_]* #define TEXT_CFI_MAIN .text.[0-9a-zA-Z_]*.cfi -#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..LPBX* -#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]* -#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* -#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* -#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]* +#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..LPBX* .data..compoundliteral* +#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]* .sdata..compoundliteral* +#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* .rodata..compoundliteral* +#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..compoundliteral* +#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]* .sbss..compoundliteral* #else #define TEXT_MAIN .text #define TEXT_CFI_MAIN .text.cfi @@ -365,7 +365,7 @@ } \ \ /* Built-in firmware blobs */ \ - .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) { \ + .builtin_fw : AT(ADDR(.builtin_fw) - LOAD_OFFSET) ALIGN(8) { \ __start_builtin_fw = .; \ KEEP(*(.builtin_fw)) \ __end_builtin_fw = .; \ @@ -702,8 +702,13 @@ /* DWARF 4 */ \ .debug_types 0 : { *(.debug_types) } \ /* DWARF 5 */ \ + .debug_addr 0 : { *(.debug_addr) } \ + .debug_line_str 0 : { *(.debug_line_str) } \ + .debug_loclists 0 : { *(.debug_loclists) } \ .debug_macro 0 : { *(.debug_macro) } \ - .debug_addr 0 : { *(.debug_addr) } + .debug_names 0 : { *(.debug_names) } \ + .debug_rnglists 0 : { *(.debug_rnglists) } \ + .debug_str_offsets 0 : { *(.debug_str_offsets) } /* Stabs debugging sections. */ #define STABS_DEBUG \ diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index a3c02470cc39..e72ca1c96b2b 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -82,6 +82,53 @@ enum drm_connector_status { connector_status_unknown = 3, }; +/** + * enum drm_connector_registration_status - userspace registration status for + * a &drm_connector + * + * This enum is used to track the status of initializing a connector and + * registering it with userspace, so that DRM can prevent bogus modesets on + * connectors that no longer exist. + */ +enum drm_connector_registration_state { + /** + * @DRM_CONNECTOR_INITIALIZING: The connector has just been created, + * but has yet to be exposed to userspace. There should be no + * additional restrictions to how the state of this connector may be + * modified. + */ + DRM_CONNECTOR_INITIALIZING = 0, + + /** + * @DRM_CONNECTOR_REGISTERED: The connector has been fully initialized + * and registered with sysfs, as such it has been exposed to + * userspace. There should be no additional restrictions to how the + * state of this connector may be modified. + */ + DRM_CONNECTOR_REGISTERED = 1, + + /** + * @DRM_CONNECTOR_UNREGISTERED: The connector has either been exposed + * to userspace and has since been unregistered and removed from + * userspace, or the connector was unregistered before it had a chance + * to be exposed to userspace (e.g. still in the + * @DRM_CONNECTOR_INITIALIZING state). When a connector is + * unregistered, there are additional restrictions to how its state + * may be modified: + * + * - An unregistered connector may only have its DPMS changed from + * On->Off. Once DPMS is changed to Off, it may not be switched back + * to On. + * - Modesets are not allowed on unregistered connectors, unless they + * would result in disabling its assigned CRTCs. This means + * disabling a CRTC on an unregistered connector is OK, but enabling + * one is not. + * - Removing a CRTC from an unregistered connector is OK, but new + * CRTCs may never be assigned to an unregistered connector. + */ + DRM_CONNECTOR_UNREGISTERED = 2, +}; + enum subpixel_order { SubPixelUnknown = 0, SubPixelHorizontalRGB, @@ -894,10 +941,12 @@ struct drm_connector { bool ycbcr_420_allowed; /** - * @registered: Is this connector exposed (registered) with userspace? + * @registration_state: Is this connector initializing, exposed + * (registered) with userspace, or unregistered? + * * Protected by @mutex. */ - bool registered; + enum drm_connector_registration_state registration_state; /** * @modes: @@ -1276,6 +1325,24 @@ static inline void drm_connector_unreference(struct drm_connector *connector) drm_connector_put(connector); } +/** + * drm_connector_is_unregistered - has the connector been unregistered from + * userspace? + * @connector: DRM connector + * + * Checks whether or not @connector has been unregistered from userspace. + * + * Returns: + * True if the connector was unregistered, false if the connector is + * registered or has not yet been registered with userspace. + */ +static inline bool +drm_connector_is_unregistered(struct drm_connector *connector) +{ + return READ_ONCE(connector->registration_state) == + DRM_CONNECTOR_UNREGISTERED; +} + const char *drm_get_connector_status_name(enum drm_connector_status status); const char *drm_get_subpixel_order_name(enum subpixel_order order); const char *drm_get_dpms_name(int val); diff --git a/include/drm/drm_refresh_rate.h b/include/drm/drm_refresh_rate.h new file mode 100644 index 000000000000..b0c6cfe634e2 --- /dev/null +++ b/include/drm/drm_refresh_rate.h @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sultan Alsawaf . + */ + +unsigned int dsi_panel_get_refresh_rate(void); diff --git a/include/dt-bindings/clock/mdss-28nm-pll-clk-legacy.h b/include/dt-bindings/clock/mdss-28nm-pll-clk-legacy.h new file mode 100644 index 000000000000..7a0a274386bb --- /dev/null +++ b/include/dt-bindings/clock/mdss-28nm-pll-clk-legacy.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016-2019, 2021 The Linux Foundation. All rights reserved. + */ + +#ifndef __MDSS_28NM_PLL_CLK_LEGACY_H +#define __MDSS_28NM_PLL_CLK_LEGACY_H + +/* DSI PLL clocks */ +#define VCOCLK_0 0 +#define ANALOG_POSTDIV_0_CLK 1 +#define INDIRECT_PATH_SRC_0_CLK 2 +#define BYTECLK_SRC_MUX_0_CLK 3 +#define BYTECLK_SRC_0_CLK 4 +#define PCLK_SRC_0_CLK 5 +#define VCOCLK_1 6 +#define ANALOG_POSTDIV_1_CLK 7 +#define INDIRECT_PATH_SRC_1_CLK 8 +#define BYTECLK_SRC_MUX_1_CLK 9 +#define BYTECLK_SRC_1_CLK 10 +#define PCLK_SRC_1_CLK 11 + +/* HDMI PLL clocks */ +#define HDMI_VCO_CLK 0 +#define HDMI_VCO_DIVIDED_1_CLK_SRC 1 +#define HDMI_VCO_DIVIDED_TWO_CLK_SRC 2 +#define HDMI_VCO_DIVIDED_FOUR_CLK_SRC 3 +#define HDMI_VCO_DIVIDED_SIX_CLK_SRC 4 +#define HDMI_PCLK_SRC_MUX 5 +#define HDMI_PCLK_SRC 6 +#endif diff --git a/include/linux/acpi.h b/include/linux/acpi.h index cd412817654f..019468f072b7 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -812,6 +812,13 @@ static inline int acpi_device_modalias(struct device *dev, return -ENODEV; } +static inline struct platform_device * +acpi_create_platform_device(struct acpi_device *adev, + struct property_entry *properties) +{ + return NULL; +} + static inline bool acpi_dma_supported(struct acpi_device *adev) { return false; diff --git a/include/linux/android_kabi.h b/include/linux/android_kabi.h index efa52953fe35..d1ad017acf3b 100644 --- a/include/linux/android_kabi.h +++ b/include/linux/android_kabi.h @@ -59,17 +59,11 @@ #else #define _ANDROID_KABI_REPLACE(_orig, _new) \ - union { \ - _new; \ - struct { \ - _orig; \ - } __UNIQUE_ID(android_kabi_hide); \ - __ANDROID_KABI_CHECK_SIZE_ALIGN(_orig, _new); \ - } + _new #endif /* __GENKSYMS__ */ -#define _ANDROID_KABI_RESERVE(n) u64 android_kabi_reserved##n +#define _ANDROID_KABI_RESERVE(n) /* diff --git a/include/linux/audit.h b/include/linux/audit.h index 9334fbef7bae..2858d233ac39 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -205,6 +205,10 @@ static inline int audit_log_task_context(struct audit_buffer *ab) static inline void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) { } +static inline int audit_update_lsm_rules(void) +{ + return 0; +} #define audit_enabled AUDIT_OFF #endif /* CONFIG_AUDIT */ diff --git a/include/linux/batterydata-interface.h b/include/linux/batterydata-interface.h new file mode 100644 index 000000000000..aa3acd268ddd --- /dev/null +++ b/include/linux/batterydata-interface.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2014-2015, 2018, 2021, The Linux Foundation. All rights reserved. + */ + +#include + +int config_battery_data(struct bms_battery_data *profile); diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index c05f24fac4f6..24ed10b0b1ea 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -142,6 +142,7 @@ extern int prepare_bprm_creds(struct linux_binprm *bprm); extern void install_exec_creds(struct linux_binprm *bprm); extern void set_binfmt(struct linux_binfmt *new); extern ssize_t read_code(struct file *, unsigned long, loff_t, size_t); +extern bool is_zygote_pid(pid_t pid); extern int do_execve(struct filename *, const char __user * const __user *, diff --git a/include/linux/bio.h b/include/linux/bio.h index 1c8491a8d36e..08b76d9dbc13 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -469,6 +469,7 @@ struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); extern int submit_bio_wait(struct bio *bio); +extern void submit_bio_nowait(struct bio *bio); extern void bio_advance(struct bio *, unsigned); extern void bio_init(struct bio *bio, struct bio_vec *table, diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 26f0a62c303c..d8ecfb5b5580 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -708,12 +708,10 @@ struct request_queue { #define QUEUE_FLAG_SCSI_PASSTHROUGH 27 /* queue supports SCSI commands */ #define QUEUE_FLAG_QUIESCED 28 /* queue has been quiesced */ -#define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ - (1 << QUEUE_FLAG_SAME_COMP) | \ +#define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_SAME_COMP) | \ (1 << QUEUE_FLAG_ADD_RANDOM)) -#define QUEUE_FLAG_MQ_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ - (1 << QUEUE_FLAG_SAME_COMP) | \ +#define QUEUE_FLAG_MQ_DEFAULT ((1 << QUEUE_FLAG_SAME_COMP) | \ (1 << QUEUE_FLAG_POLL)) void blk_queue_flag_set(unsigned int flag, struct request_queue *q); @@ -746,6 +744,7 @@ bool blk_queue_flag_test_and_clear(unsigned int flag, struct request_queue *q); #define blk_queue_quiesced(q) test_bit(QUEUE_FLAG_QUIESCED, &(q)->queue_flags) #define blk_queue_pm_only(q) atomic_read(&(q)->pm_only) #define blk_queue_fua(q) test_bit(QUEUE_FLAG_FUA, &(q)->queue_flags) +#define blk_queue_registered(q) test_bit(QUEUE_FLAG_REGISTERED, &(q)->queue_flags) extern void blk_set_pm_only(struct request_queue *q); extern void blk_clear_pm_only(struct request_queue *q); @@ -1390,6 +1389,7 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, } extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); +extern void blkdev_issue_flush_nowait(struct block_device *, gfp_t); extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct page *page); @@ -2102,6 +2102,10 @@ static inline int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, return 0; } +static inline void blkdev_issue_flush_nowait(struct block_device *bdev, gfp_t gfp_mask) +{ +} + #endif /* CONFIG_BLOCK */ #endif diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 16f6beef5cad..e38efb3b0dcd 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -382,7 +382,7 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, struct bpf_prog *include_prog, struct bpf_prog_array **new_array); -#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null) \ +#define __BPF_PROG_RUN_ARRAY(array, ctx, func, check_non_null, set_cg_storage) \ ({ \ struct bpf_prog_array_item *_item; \ struct bpf_prog *_prog; \ @@ -395,7 +395,8 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, goto _out; \ _item = &_array->items[0]; \ while ((_prog = READ_ONCE(_item->prog))) { \ - bpf_cgroup_storage_set(_item->cgroup_storage); \ + if (set_cg_storage) \ + bpf_cgroup_storage_set(_item->cgroup_storage); \ _ret &= func(_prog, ctx); \ _item++; \ } \ @@ -406,10 +407,10 @@ _out: \ }) #define BPF_PROG_RUN_ARRAY(array, ctx, func) \ - __BPF_PROG_RUN_ARRAY(array, ctx, func, false) + __BPF_PROG_RUN_ARRAY(array, ctx, func, false, true) #define BPF_PROG_RUN_ARRAY_CHECK(array, ctx, func) \ - __BPF_PROG_RUN_ARRAY(array, ctx, func, true) + __BPF_PROG_RUN_ARRAY(array, ctx, func, true, false) #ifdef CONFIG_BPF_SYSCALL DECLARE_PER_CPU(int, bpf_prog_active); @@ -813,6 +814,7 @@ extern const struct bpf_func_proto bpf_get_smp_processor_id_proto; extern const struct bpf_func_proto bpf_get_numa_node_id_proto; extern const struct bpf_func_proto bpf_tail_call_proto; extern const struct bpf_func_proto bpf_ktime_get_ns_proto; +extern const struct bpf_func_proto bpf_ktime_get_boot_ns_proto; extern const struct bpf_func_proto bpf_get_current_pid_tgid_proto; extern const struct bpf_func_proto bpf_get_current_uid_gid_proto; extern const struct bpf_func_proto bpf_get_current_comm_proto; diff --git a/include/linux/build_bug.h b/include/linux/build_bug.h index 43d1fd50d433..6099f754aad7 100644 --- a/include/linux/build_bug.h +++ b/include/linux/build_bug.h @@ -80,4 +80,9 @@ #endif /* __CHECKER__ */ +#ifdef __GENKSYMS__ +/* genksyms gets confused by _Static_assert */ +#define _Static_assert(expr, ...) +#endif + #endif /* _LINUX_BUILD_BUG_H */ diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index b3379a97245c..fd1ae7907250 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -49,8 +49,12 @@ static inline void can_skb_reserve(struct sk_buff *skb) static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) { - if (sk) { - sock_hold(sk); + /* If the socket has already been closed by user space, the + * refcount may already be 0 (and the socket will be freed + * after the last TX skb has been freed). So only increase + * socket refcount if the refcount is > 0. + */ + if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { skb->destructor = sock_efree; skb->sk = sk; } @@ -61,21 +65,17 @@ static inline void can_skb_set_owner(struct sk_buff *skb, struct sock *sk) */ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb) { - if (skb_shared(skb)) { - struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC); + struct sk_buff *nskb; - if (likely(nskb)) { - can_skb_set_owner(nskb, skb->sk); - consume_skb(skb); - return nskb; - } else { - kfree_skb(skb); - return NULL; - } + nskb = skb_clone(skb, GFP_ATOMIC); + if (unlikely(!nskb)) { + kfree_skb(skb); + return NULL; } - /* we can assume to have an unshared skb with proper owner */ - return skb; + can_skb_set_owner(nskb, skb->sk); + consume_skb(skb); + return nskb; } #endif /* !_CAN_SKB_H */ diff --git a/include/linux/compat.h b/include/linux/compat.h index de0c13bdcd2c..189d0e111d57 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -445,8 +445,6 @@ struct compat_kexec_segment; struct compat_mq_attr; struct compat_msgbuf; -extern void compat_exit_robust_list(struct task_struct *curr); - #define BITS_PER_COMPAT_LONG (8*sizeof(compat_long_t)) #define BITS_TO_COMPAT_LONGS(bits) DIV_ROUND_UP(bits, BITS_PER_COMPAT_LONG) diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index 6f80c8da9f94..a89045d3c403 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -44,7 +44,6 @@ * and may be redefined here because they should not be shared with other * compilers, like ICC. */ -#define barrier() __asm__ __volatile__("" : : : "memory") #define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) #define __assume_aligned(a, ...) \ __attribute__((__assume_aligned__(a, ## __VA_ARGS__))) diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index ca37bdd0f5eb..15aca9a97f60 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -12,26 +12,13 @@ #if GCC_VERSION < 40600 # error Sorry, your compiler is too old - please upgrade it. -#endif - -/* Optimization barrier */ - -/* The "volatile" is due to gcc bugs */ -#define barrier() __asm__ __volatile__("": : :"memory") +#elif defined(CONFIG_ARM64) && GCC_VERSION < 50100 /* - * This version is i.e. to prevent dead stores elimination on @ptr - * where gcc and llvm may behave differently when otherwise using - * normal barrier(): while gcc behavior gets along with a normal - * barrier(), llvm needs an explicit input variable to be assumed - * clobbered. The issue is as follows: while the inline asm might - * access any memory it wants, the compiler could have fit all of - * @ptr into memory registers instead, and since @ptr never escaped - * from that, it proved that the inline asm wasn't touching any of - * it. This version works well with both compilers, i.e. we're telling - * the compiler that the inline asm absolutely may see the contents - * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495 + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63293 + * https://lore.kernel.org/r/20210107111841.GN1551@shell.armlinux.org.uk */ -#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory") +# error Sorry, your version of GCC is too old - please use 5.1 or newer. +#endif /* * This macro obfuscates arithmetic on a variable address so that gcc diff --git a/include/linux/compiler.h b/include/linux/compiler.h index acd8c2649073..030f152b602a 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -79,11 +79,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val, /* Optimization barrier */ #ifndef barrier -# define barrier() __memory_barrier() +/* The "volatile" is due to gcc bugs */ +# define barrier() __asm__ __volatile__("": : :"memory") #endif #ifndef barrier_data -# define barrier_data(ptr) barrier() +/* + * This version is i.e. to prevent dead stores elimination on @ptr + * where gcc and llvm may behave differently when otherwise using + * normal barrier(): while gcc behavior gets along with a normal + * barrier(), llvm needs an explicit input variable to be assumed + * clobbered. The issue is as follows: while the inline asm might + * access any memory it wants, the compiler could have fit all of + * @ptr into memory registers instead, and since @ptr never escaped + * from that, it proved that the inline asm wasn't touching any of + * it. This version works well with both compilers, i.e. we're telling + * the compiler that the inline asm absolutely may see the contents + * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495 + */ +# define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory") #endif /* workaround for GCC PR82365 if needed */ diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 39707f71f912..39d26fae53d3 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -931,7 +931,7 @@ static inline bool policy_has_boost_freq(struct cpufreq_policy *policy) } #endif -#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) + #if defined(CONFIG_ENERGY_MODEL) && ((defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) || defined(CONFIG_CPU_FREQ_GOV_SCHEDHORIZON))) void sched_cpufreq_governor_change(struct cpufreq_policy *policy, struct cpufreq_governor *old_gov); #else diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 8ccffba863ea..3aa3ec1253dd 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -291,4 +291,12 @@ static inline int cpuidle_register_governor(struct cpuidle_governor *gov) #define CPU_PM_CPU_IDLE_ENTER_RETENTION(low_level_idle_enter, idx) \ __CPU_PM_CPU_IDLE_ENTER(low_level_idle_enter, idx, 1) +#ifdef CONFIG_SMP +void cpuidle_set_idle_cpu(unsigned int cpu); +void cpuidle_clear_idle_cpu(unsigned int cpu); +#else +static inline void cpuidle_set_idle_cpu(unsigned int cpu) { } +static inline void cpuidle_clear_idle_cpu(unsigned int cpu) { } +#endif + #endif /* _LINUX_CPUIDLE_H */ diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index e5d963c571ae..bab130115875 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -55,6 +55,9 @@ extern unsigned int nr_cpu_ids; * cpu_online_mask - has bit 'cpu' set iff cpu available to scheduler * cpu_active_mask - has bit 'cpu' set iff cpu available to migration * cpu_isolated_mask- has bit 'cpu' set iff cpu isolated + * cpu_lp_mask - has bit 'cpu' set iff cpu is part of little cluster + * cpu_perf_mask - has bit 'cpu' set iff cpu is part of big cluster + * cpu_prime_mask - has bit 'cpu' set iff cpu is part of prime cluster * * If !CONFIG_HOTPLUG_CPU, present == possible, and active == online. * @@ -97,6 +100,9 @@ extern struct cpumask __cpu_isolated_mask; #define cpu_present_mask ((const struct cpumask *)&__cpu_present_mask) #define cpu_active_mask ((const struct cpumask *)&__cpu_active_mask) #define cpu_isolated_mask ((const struct cpumask *)&__cpu_isolated_mask) +extern const struct cpumask *const cpu_lp_mask; +extern const struct cpumask *const cpu_perf_mask; +extern const struct cpumask *const cpu_prime_mask; #if NR_CPUS > 1 #define num_online_cpus() cpumask_weight(cpu_online_mask) diff --git a/include/linux/dcache.h b/include/linux/dcache.h index ee2d177dc0e8..5651e6b4036b 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -75,7 +75,7 @@ extern struct dentry_stat_t dentry_stat; * large memory footprint increase). */ #ifdef CONFIG_64BIT -# define DNAME_INLINE_LEN 32 /* 192 bytes */ +# define DNAME_INLINE_LEN 32 + 192 /* 384 bytes */ #else # ifdef CONFIG_SMP # define DNAME_INLINE_LEN 36 /* 128 bytes */ @@ -306,6 +306,7 @@ extern char *simple_dname(struct dentry *, char *, int); extern char *__d_path(const struct path *, const struct path *, char *, int); extern char *d_absolute_path(const struct path *, char *, int); extern char *d_path(const struct path *, char *, int); +extern char *d_path_outlen(const struct path *, char *, int *); extern char *dentry_path_raw(struct dentry *, char *, int); extern char *dentry_path(struct dentry *, char *, int); diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 2151a0649b0f..b8a740c242be 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -167,6 +167,8 @@ struct devfreq { unsigned long scaling_min_freq; unsigned long scaling_max_freq; bool stop_polling; + bool is_boost_device; + bool max_boost; /* information for device frequency transition */ unsigned int total_trans; @@ -285,6 +287,9 @@ struct devfreq_passive_data { }; #endif +/* Caution: devfreq->lock must be locked before calling update_devfreq */ +extern int update_devfreq(struct devfreq *devfreq); + #else /* !CONFIG_PM_DEVFREQ */ static inline struct devfreq *devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile, @@ -390,6 +395,11 @@ static inline int devfreq_update_stats(struct devfreq *df) { return -EINVAL; } + +static inline int update_devfreq(struct devfreq *devfreq) +{ + return -EINVAL; +} #endif /* CONFIG_PM_DEVFREQ */ #endif /* __LINUX_DEVFREQ_H__ */ diff --git a/include/linux/devfreq_boost.h b/include/linux/devfreq_boost.h new file mode 100644 index 000000000000..3d17f41ba4a4 --- /dev/null +++ b/include/linux/devfreq_boost.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2018-2019 Sultan Alsawaf . + */ +#ifndef _DEVFREQ_BOOST_H_ +#define _DEVFREQ_BOOST_H_ + +#include + +enum df_device { + DEVFREQ_MSM_LLCCBW_DDR, + DEVFREQ_MSM_CPU_LLCCBW, + DEVFREQ_MAX +}; + +#ifdef CONFIG_DEVFREQ_BOOST +void devfreq_boost_kick(enum df_device device); +void devfreq_boost_kick_max(enum df_device device, unsigned int duration_ms); +void devfreq_register_boost_device(enum df_device device, struct devfreq *df); +#else +static inline +void devfreq_boost_kick(enum df_device device) +{ +} +static inline +void devfreq_boost_kick_max(enum df_device device, unsigned int duration_ms) +{ +} +static inline +void devfreq_register_boost_device(enum df_device device, struct devfreq *df) +{ +} +#endif + +#endif /* _DEVFREQ_BOOST_H_ */ diff --git a/include/linux/dm-bufio.h b/include/linux/dm-bufio.h index 3c8b7d274bd9..45ba37aaf6b7 100644 --- a/include/linux/dm-bufio.h +++ b/include/linux/dm-bufio.h @@ -138,6 +138,7 @@ void dm_bufio_set_minimum_buffers(struct dm_bufio_client *c, unsigned n); unsigned dm_bufio_get_block_size(struct dm_bufio_client *c); sector_t dm_bufio_get_device_size(struct dm_bufio_client *c); +struct dm_io_client *dm_bufio_get_dm_io_client(struct dm_bufio_client *c); sector_t dm_bufio_get_block_number(struct dm_buffer *b); void *dm_bufio_get_block_data(struct dm_buffer *b); void *dm_bufio_get_aux_data(struct dm_buffer *b); diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 077d75354ac5..f9c1b91a4c69 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -463,6 +463,8 @@ struct dma_buf { dma_buf_destructor dtor; void *dtor_data; atomic_t dent_count; + + bool from_kmem; }; /** diff --git a/include/linux/eeprom_93xx46.h b/include/linux/eeprom_93xx46.h index eec7928ff8fe..99580c22f91a 100644 --- a/include/linux/eeprom_93xx46.h +++ b/include/linux/eeprom_93xx46.h @@ -16,6 +16,8 @@ struct eeprom_93xx46_platform_data { #define EEPROM_93XX46_QUIRK_SINGLE_WORD_READ (1 << 0) /* Instructions such as EWEN are (addrlen + 2) in length. */ #define EEPROM_93XX46_QUIRK_INSTRUCTION_LENGTH (1 << 1) +/* Add extra cycle after address during a read */ +#define EEPROM_93XX46_QUIRK_EXTRA_READ_CYCLE BIT(2) /* * optional hooks to control additional logic diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h index 4cad0e784b28..b81f9e1d74b0 100644 --- a/include/linux/elfcore.h +++ b/include/linux/elfcore.h @@ -58,6 +58,7 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregse } #endif +#if defined(CONFIG_UM) || defined(CONFIG_IA64) /* * These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out * extra segments containing the gate DSO contents. Dumping its @@ -72,5 +73,26 @@ elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset); extern int elf_core_write_extra_data(struct coredump_params *cprm); extern size_t elf_core_extra_data_size(void); +#else +static inline Elf_Half elf_core_extra_phdrs(void) +{ + return 0; +} + +static inline int elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset) +{ + return 1; +} + +static inline int elf_core_write_extra_data(struct coredump_params *cprm) +{ + return 1; +} + +static inline size_t elf_core_extra_data_size(void) +{ + return 0; +} +#endif #endif /* _LINUX_ELFCORE_H */ diff --git a/include/linux/extcon.h b/include/linux/extcon.h index c34c50faaec4..4438af8fe431 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -312,6 +312,29 @@ static inline void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb) { } +static inline int extcon_register_notifier_all(struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline int extcon_unregister_notifier_all(struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline int devm_extcon_register_notifier_all(struct device *dev, + struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline void devm_extcon_unregister_notifier_all(struct device *dev, + struct extcon_dev *edev, + struct notifier_block *nb) { } + static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) { return ERR_PTR(-ENODEV); diff --git a/include/linux/filter.h b/include/linux/filter.h index 01923c9f3208..497172007603 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -806,7 +806,7 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp); u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5); #define __bpf_call_base_args \ ((u64 (*)(u64, u64, u64, u64, u64, const struct bpf_insn *)) \ - __bpf_call_base) + (void *)__bpf_call_base) struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog); void bpf_jit_compile(struct bpf_prog *prog); diff --git a/include/linux/fs.h b/include/linux/fs.h index 0a1073862bd3..33211a2ac522 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2162,7 +2162,6 @@ static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) #define I_DIO_WAKEUP (1 << __I_DIO_WAKEUP) #define I_LINKABLE (1 << 10) #define I_DIRTY_TIME (1 << 11) -#define I_DIRTY_TIME_EXPIRED (1 << 12) #define I_WB_SWITCH (1 << 13) #define I_OVL_INUSE (1 << 14) #define I_CREATING (1 << 15) diff --git a/include/linux/futex.h b/include/linux/futex.h index a61bf436dcf3..d141df679863 100644 --- a/include/linux/futex.h +++ b/include/linux/futex.h @@ -2,7 +2,9 @@ #ifndef _LINUX_FUTEX_H #define _LINUX_FUTEX_H +#include #include + #include struct inode; @@ -51,28 +53,64 @@ union futex_key { #define FUTEX_KEY_INIT (union futex_key) { .both = { .ptr = 0ULL } } #ifdef CONFIG_FUTEX -extern void exit_robust_list(struct task_struct *curr); +enum { + FUTEX_STATE_OK, + FUTEX_STATE_DEAD, +}; -long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, - u32 __user *uaddr2, u32 val2, u32 val3); -#else -static inline void exit_robust_list(struct task_struct *curr) +static inline void futex_init_task(struct task_struct *tsk) { + tsk->robust_list = NULL; +#ifdef CONFIG_COMPAT + tsk->compat_robust_list = NULL; +#endif + INIT_LIST_HEAD(&tsk->pi_state_list); + tsk->pi_state_cache = NULL; + tsk->futex_state = FUTEX_STATE_OK; } -static inline long do_futex(u32 __user *uaddr, int op, u32 val, - ktime_t *timeout, u32 __user *uaddr2, - u32 val2, u32 val3) +/** + * futex_exit_done - Sets the tasks futex state to FUTEX_STATE_DEAD + * @tsk: task to set the state on + * + * Set the futex exit state of the task lockless. The futex waiter code + * observes that state when a task is exiting and loops until the task has + * actually finished the futex cleanup. The worst case for this is that the + * waiter runs through the wait loop until the state becomes visible. + * + * This has two callers: + * + * - futex_mm_release() after the futex exit cleanup has been done + * + * - do_exit() from the recursive fault handling path. + * + * In case of a recursive fault this is best effort. Either the futex exit + * code has run already or not. If the OWNER_DIED bit has been set on the + * futex then the waiter can take it over. If not, the problem is pushed + * back to user space. If the futex exit code did not run yet, then an + * already queued waiter might block forever, but there is nothing which + * can be done about that. + */ +static inline void futex_exit_done(struct task_struct *tsk) { - return -EINVAL; + tsk->futex_state = FUTEX_STATE_DEAD; } -#endif -#ifdef CONFIG_FUTEX_PI -extern void exit_pi_state_list(struct task_struct *curr); +void futex_exit_release(struct task_struct *tsk); +void futex_exec_release(struct task_struct *tsk); + +long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, + u32 __user *uaddr2, u32 val2, u32 val3); #else -static inline void exit_pi_state_list(struct task_struct *curr) +static inline void futex_init_task(struct task_struct *tsk) { } +static inline void futex_exit_done(struct task_struct *tsk) { } +static inline void futex_exit_release(struct task_struct *tsk) { } +static inline void futex_exec_release(struct task_struct *tsk) { } +static inline long do_futex(u32 __user *uaddr, int op, u32 val, + ktime_t *timeout, u32 __user *uaddr2, + u32 val2, u32 val3) { + return -EINVAL; } #endif diff --git a/include/linux/highmem.h b/include/linux/highmem.h index e6cf2af62187..e6abd3ed70a0 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -36,7 +36,31 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size) /* declarations for linux/mm/highmem.c */ unsigned int nr_free_highpages(void); -extern unsigned long totalhigh_pages; +extern atomic_long_t _totalhigh_pages; +static inline unsigned long totalhigh_pages(void) +{ + return (unsigned long)atomic_long_read(&_totalhigh_pages); +} + +static inline void totalhigh_pages_inc(void) +{ + atomic_long_inc(&_totalhigh_pages); +} + +static inline void totalhigh_pages_dec(void) +{ + atomic_long_dec(&_totalhigh_pages); +} + +static inline void totalhigh_pages_add(long count) +{ + atomic_long_add(count, &_totalhigh_pages); +} + +static inline void totalhigh_pages_set(long val) +{ + atomic_long_set(&_totalhigh_pages, val); +} void kmap_flush_unused(void); @@ -57,7 +81,7 @@ static inline struct page *kmap_to_page(void *addr) return virt_to_page(addr); } -#define totalhigh_pages 0UL +static inline unsigned long totalhigh_pages(void) { return 0UL; } #ifndef ARCH_HAS_KMAP static inline void *kmap(struct page *page) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index d34112fb3d52..cae7fd680448 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -541,6 +541,9 @@ static inline void set_huge_swap_pte_at(struct mm_struct *mm, unsigned long addr set_huge_pte_at(mm, addr, ptep, pte); } #endif + +void set_page_huge_active(struct page *page); + #else /* CONFIG_HUGETLB_PAGE */ struct hstate {}; #define alloc_huge_page(v, a, r) NULL diff --git a/include/linux/i2c-qcom-geni.h b/include/linux/i2c-qcom-geni.h new file mode 100644 index 000000000000..6be6d77d6aa6 --- /dev/null +++ b/include/linux/i2c-qcom-geni.h @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2020 Sultan Alsawaf . + */ + +int geni_i2c_get_adap_irq(struct i2c_client *client); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 7e748648c7d3..baa610b8e413 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -770,6 +770,7 @@ i2c_unlock_bus(struct i2c_adapter *adapter, unsigned int flags) #define I2C_CLIENT_SLAVE 0x20 /* we are the slave */ #define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */ #define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */ +#define I2C_CLIENT_ASYNC_SUSPEND 0x100 /* async suspend is supported */ #define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ /* Must match I2C_M_STOP|IGNORE_NAK */ diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index 024b7a4cd98e..60d5e5a807f5 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -13,12 +13,32 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) #include #if IS_ENABLED(CONFIG_IPV6) -extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); typedef void ip6_icmp_send_t(struct sk_buff *skb, u8 type, u8 code, __u32 info, const struct in6_addr *force_saddr); +void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct in6_addr *force_saddr); +#if IS_BUILTIN(CONFIG_IPV6) +static inline void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) +{ + icmp6_send(skb, type, code, info, NULL); +} +static inline int inet6_register_icmp_sender(ip6_icmp_send_t *fn) +{ + BUILD_BUG_ON(fn != icmp6_send); + return 0; +} +static inline int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn) +{ + BUILD_BUG_ON(fn != icmp6_send); + return 0; +} +#else +extern void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info); extern int inet6_register_icmp_sender(ip6_icmp_send_t *fn); extern int inet6_unregister_icmp_sender(ip6_icmp_send_t *fn); +#endif + int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type, unsigned int data_len); @@ -41,6 +61,12 @@ static inline void icmpv6_ndo_send(struct sk_buff *skb, } #endif +#if IS_ENABLED(CONFIG_NF_NAT) +void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info); +#else +#define icmpv6_ndo_send icmpv6_send +#endif + extern int icmpv6_init(void); extern int icmpv6_err_convert(u8 type, u8 code, int *err); diff --git a/include/linux/if_macvlan.h b/include/linux/if_macvlan.h index 2e55e4cdbd8a..1261559d70b4 100644 --- a/include/linux/if_macvlan.h +++ b/include/linux/if_macvlan.h @@ -43,13 +43,14 @@ static inline void macvlan_count_rx(const struct macvlan_dev *vlan, if (likely(success)) { struct vlan_pcpu_stats *pcpu_stats; - pcpu_stats = this_cpu_ptr(vlan->pcpu_stats); + pcpu_stats = get_cpu_ptr(vlan->pcpu_stats); u64_stats_update_begin(&pcpu_stats->syncp); pcpu_stats->rx_packets++; pcpu_stats->rx_bytes += len; if (multicast) pcpu_stats->rx_multicast++; u64_stats_update_end(&pcpu_stats->syncp); + put_cpu_ptr(vlan->pcpu_stats); } else { this_cpu_inc(vlan->pcpu_stats->rx_errors); } diff --git a/include/linux/init.h b/include/linux/init.h index bc719c7da735..586dd187e22f 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -322,8 +322,6 @@ void __init parse_early_options(char *cmdline); /* Data marked not to be saved by software suspend */ #define __nosavedata __section(.data..nosave) -#define __rticdata __attribute__((section(".bss.rtic"))) - #ifdef MODULE #define __exit_p(x) x #else diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 539f4a84412f..786df33c0020 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -472,6 +472,8 @@ struct intel_iommu { struct iommu_device iommu; /* IOMMU core code handle */ int node; u32 flags; /* Software defined flags */ + + struct dmar_drhd_unit *drhd; }; /* PCI domain-device relationship */ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 15e6882e8df0..2fa1875822fb 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -61,6 +61,10 @@ * interrupt handler after suspending interrupts. For system * wakeup devices users need to implement wakeup detection in * their interrupt handlers. + * IRQF_PERF_AFFINE - Interrupt is critical to the overall performance of the + * system and should be processed on a big CPU. + * IRQF_PRIME_AFFINE - Interrupt is critical to the overall performance of the + * system and should be processed on a prime CPU. */ #define IRQF_SHARED 0x00000080 #define IRQF_PROBE_SHARED 0x00000100 @@ -74,6 +78,8 @@ #define IRQF_NO_THREAD 0x00010000 #define IRQF_EARLY_RESUME 0x00020000 #define IRQF_COND_SUSPEND 0x00040000 +#define IRQF_PERF_AFFINE 0x00080000 +#define IRQF_PRIME_AFFINE 0x00100000 #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND | IRQF_NO_THREAD) @@ -216,10 +222,13 @@ extern void enable_irq(unsigned int irq); extern void enable_percpu_irq(unsigned int irq, unsigned int type); extern bool irq_percpu_is_enabled(unsigned int irq); extern void irq_wake_thread(unsigned int irq, void *dev_id); +extern void irq_set_perf_affinity(unsigned int irq, unsigned int perf_flag); /* The following three functions are for the core kernel use only. */ extern void suspend_device_irqs(void); extern void resume_device_irqs(void); +extern void unaffine_perf_irqs(void); +extern void reaffine_perf_irqs(bool from_hotplug); /** * struct irq_affinity_notify - context for notification of IRQ affinity changes diff --git a/include/linux/irq.h b/include/linux/irq.h index 62aa2877d7f3..46296d908ed5 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -212,6 +212,7 @@ struct irq_data { * required * IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call * irq_chip::irq_set_affinity() when deactivated. + * IRQD_PERF_CRITICAL - IRQ is performance-critical */ enum { IRQD_TRIGGER_MASK = 0xf, @@ -235,6 +236,7 @@ enum { IRQD_DEFAULT_TRIGGER_SET = (1 << 25), IRQD_CAN_RESERVE = (1 << 26), IRQD_MSI_NOMASK_QUIRK = (1 << 27), + IRQD_PERF_CRITICAL = (1 << 28), IRQD_AFFINITY_ON_ACTIVATE = (1 << 29), }; diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h index 4c3e77687d4e..3e113a1fa0f1 100644 --- a/include/linux/jump_label.h +++ b/include/linux/jump_label.h @@ -115,6 +115,68 @@ struct static_key { #ifdef CONFIG_JUMP_LABEL #include + +#ifndef __ASSEMBLY__ +#ifdef CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE + +struct jump_entry { + s32 code; + s32 target; + long key; // key may be far away from the core kernel under KASLR +}; + +static inline unsigned long jump_entry_code(const struct jump_entry *entry) +{ + return (unsigned long)&entry->code + entry->code; +} + +static inline unsigned long jump_entry_target(const struct jump_entry *entry) +{ + return (unsigned long)&entry->target + entry->target; +} + +static inline struct static_key *jump_entry_key(const struct jump_entry *entry) +{ + long offset = entry->key & ~3L; + + return (struct static_key *)((unsigned long)&entry->key + offset); +} + +#else + +static inline unsigned long jump_entry_code(const struct jump_entry *entry) +{ + return entry->code; +} + +static inline unsigned long jump_entry_target(const struct jump_entry *entry) +{ + return entry->target; +} + +static inline struct static_key *jump_entry_key(const struct jump_entry *entry) +{ + return (struct static_key *)((unsigned long)entry->key & ~3UL); +} + +#endif + +static inline bool jump_entry_is_branch(const struct jump_entry *entry) +{ + return (unsigned long)entry->key & 1UL; +} + +static inline bool jump_entry_is_init(const struct jump_entry *entry) +{ + return (unsigned long)entry->key & 2UL; +} + +static inline void jump_entry_set_init(struct jump_entry *entry) +{ + entry->key |= 2; +} + +#endif #endif #ifndef __ASSEMBLY__ @@ -147,7 +209,6 @@ extern struct jump_entry __start___jump_table[]; extern struct jump_entry __stop___jump_table[]; extern void jump_label_init(void); -extern void jump_label_invalidate_initmem(void); extern void jump_label_lock(void); extern void jump_label_unlock(void); extern void arch_jump_label_transform(struct jump_entry *entry, @@ -195,8 +256,6 @@ static __always_inline void jump_label_init(void) static_key_initialized = true; } -static inline void jump_label_invalidate_initmem(void) {} - static __always_inline bool static_key_false(struct static_key *key) { if (unlikely(static_key_count(key) > 0)) diff --git a/include/linux/jump_label_ratelimit.h b/include/linux/jump_label_ratelimit.h index a49f2b45b3f0..42710d5949ba 100644 --- a/include/linux/jump_label_ratelimit.h +++ b/include/linux/jump_label_ratelimit.h @@ -12,21 +12,79 @@ struct static_key_deferred { struct delayed_work work; }; -extern void static_key_slow_dec_deferred(struct static_key_deferred *key); -extern void static_key_deferred_flush(struct static_key_deferred *key); +struct static_key_true_deferred { + struct static_key_true key; + unsigned long timeout; + struct delayed_work work; +}; + +struct static_key_false_deferred { + struct static_key_false key; + unsigned long timeout; + struct delayed_work work; +}; + +#define static_key_slow_dec_deferred(x) \ + __static_key_slow_dec_deferred(&(x)->key, &(x)->work, (x)->timeout) +#define static_branch_slow_dec_deferred(x) \ + __static_key_slow_dec_deferred(&(x)->key.key, &(x)->work, (x)->timeout) + +#define static_key_deferred_flush(x) \ + __static_key_deferred_flush((x), &(x)->work) + +extern void +__static_key_slow_dec_deferred(struct static_key *key, + struct delayed_work *work, + unsigned long timeout); +extern void __static_key_deferred_flush(void *key, struct delayed_work *work); extern void jump_label_rate_limit(struct static_key_deferred *key, unsigned long rl); +extern void jump_label_update_timeout(struct work_struct *work); + +#define DEFINE_STATIC_KEY_DEFERRED_TRUE(name, rl) \ + struct static_key_true_deferred name = { \ + .key = { STATIC_KEY_INIT_TRUE }, \ + .timeout = (rl), \ + .work = __DELAYED_WORK_INITIALIZER((name).work, \ + jump_label_update_timeout, \ + 0), \ + } + +#define DEFINE_STATIC_KEY_DEFERRED_FALSE(name, rl) \ + struct static_key_false_deferred name = { \ + .key = { STATIC_KEY_INIT_FALSE }, \ + .timeout = (rl), \ + .work = __DELAYED_WORK_INITIALIZER((name).work, \ + jump_label_update_timeout, \ + 0), \ + } + +#define static_branch_deferred_inc(x) static_branch_inc(&(x)->key) + #else /* !CONFIG_JUMP_LABEL */ struct static_key_deferred { struct static_key key; }; +struct static_key_true_deferred { + struct static_key_true key; +}; +struct static_key_false_deferred { + struct static_key_false key; +}; +#define DEFINE_STATIC_KEY_DEFERRED_TRUE(name, rl) \ + struct static_key_true_deferred name = { STATIC_KEY_TRUE_INIT } +#define DEFINE_STATIC_KEY_DEFERRED_FALSE(name, rl) \ + struct static_key_false_deferred name = { STATIC_KEY_FALSE_INIT } + +#define static_branch_slow_dec_deferred(x) static_branch_dec(&(x)->key) + static inline void static_key_slow_dec_deferred(struct static_key_deferred *key) { STATIC_KEY_CHECK_USE(key); static_key_slow_dec(&key->key); } -static inline void static_key_deferred_flush(struct static_key_deferred *key) +static inline void static_key_deferred_flush(void *key) { STATIC_KEY_CHECK_USE(key); } diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 1f96ce2b47df..8e570dfe0ee4 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -14,7 +14,7 @@ #include -#define KSYM_NAME_LEN 128 +#define KSYM_NAME_LEN 256 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s]") + (KSYM_NAME_LEN - 1) + \ 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + 1) diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h index 85b5151911cf..4856706fbfeb 100644 --- a/include/linux/kdev_t.h +++ b/include/linux/kdev_t.h @@ -21,61 +21,61 @@ }) /* acceptable for old filesystems */ -static inline bool old_valid_dev(dev_t dev) +static __always_inline bool old_valid_dev(dev_t dev) { return MAJOR(dev) < 256 && MINOR(dev) < 256; } -static inline u16 old_encode_dev(dev_t dev) +static __always_inline u16 old_encode_dev(dev_t dev) { return (MAJOR(dev) << 8) | MINOR(dev); } -static inline dev_t old_decode_dev(u16 val) +static __always_inline dev_t old_decode_dev(u16 val) { return MKDEV((val >> 8) & 255, val & 255); } -static inline u32 new_encode_dev(dev_t dev) +static __always_inline u32 new_encode_dev(dev_t dev) { unsigned major = MAJOR(dev); unsigned minor = MINOR(dev); return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12); } -static inline dev_t new_decode_dev(u32 dev) +static __always_inline dev_t new_decode_dev(u32 dev) { unsigned major = (dev & 0xfff00) >> 8; unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00); return MKDEV(major, minor); } -static inline u64 huge_encode_dev(dev_t dev) +static __always_inline u64 huge_encode_dev(dev_t dev) { return new_encode_dev(dev); } -static inline dev_t huge_decode_dev(u64 dev) +static __always_inline dev_t huge_decode_dev(u64 dev) { return new_decode_dev(dev); } -static inline int sysv_valid_dev(dev_t dev) +static __always_inline int sysv_valid_dev(dev_t dev) { return MAJOR(dev) < (1<<14) && MINOR(dev) < (1<<18); } -static inline u32 sysv_encode_dev(dev_t dev) +static __always_inline u32 sysv_encode_dev(dev_t dev) { return MINOR(dev) | (MAJOR(dev) << 18); } -static inline unsigned sysv_major(u32 dev) +static __always_inline unsigned sysv_major(u32 dev) { return (dev >> 18) & 0x3fff; } -static inline unsigned sysv_minor(u32 dev) +static __always_inline unsigned sysv_minor(u32 dev) { return dev & 0x3ffff; } diff --git a/include/linux/kernel.h b/include/linux/kernel.h index ba809b1009b7..a0e3ba359b27 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -687,6 +687,9 @@ do { \ * let gcc optimize the rest. */ +#ifdef CONFIG_DISABLE_TRACE_PRINTK +#define trace_printk pr_debug +#else #define trace_printk(fmt, ...) \ do { \ char _______STR[] = __stringify((__VA_ARGS__)); \ @@ -709,6 +712,7 @@ do { \ else \ __trace_printk(_THIS_IP_, fmt, ##args); \ } while (0) +#endif extern __printf(2, 3) int __trace_bprintk(unsigned long ip, const char *fmt, ...); diff --git a/include/linux/kexec.h b/include/linux/kexec.h index 9e4e638fb505..fe9f6f2dd811 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -260,6 +260,11 @@ struct kimage { /* Information for loading purgatory */ struct purgatory_info purgatory_info; #endif + +#ifdef CONFIG_IMA_KEXEC + /* Virtual address of IMA measurement buffer for kexec syscall */ + void *ima_buffer; +#endif }; /* kexec interface functions */ diff --git a/include/linux/key.h b/include/linux/key.h index 804e3afbcc3c..883def7ff564 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -249,6 +249,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_BUILT_IN 0x0004 /* Key is built into kernel */ #define KEY_ALLOC_BYPASS_RESTRICTION 0x0008 /* Override the check on restricted keyrings */ #define KEY_ALLOC_UID_KEYRING 0x0010 /* allocating a user or user session keyring */ +#define KEY_ALLOC_SET_KEEP 0x0020 /* Set the KEEP flag on the key/keyring */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 9f22652d69bb..c28204e22b54 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -245,7 +245,7 @@ extern void kprobes_inc_nmissed_count(struct kprobe *p); extern bool arch_within_kprobe_blacklist(unsigned long addr); extern int arch_populate_kprobe_blacklist(void); extern bool arch_kprobe_on_func_entry(unsigned long offset); -extern bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); +extern int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); extern bool within_kprobe_blacklist(unsigned long addr); extern int kprobe_add_ksym_blacklist(unsigned long entry); diff --git a/include/linux/kthread.h b/include/linux/kthread.h index edf8f8636ee9..128e1af60e82 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -31,6 +31,9 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), unsigned int cpu, const char *namefmt); +void kthread_set_per_cpu(struct task_struct *k, int cpu); +bool kthread_is_per_cpu(struct task_struct *k); + /** * kthread_run - create and wake a thread. * @threadfn: the function to run until signal_pending(current). @@ -49,6 +52,26 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), __k; \ }) +/** + * kthread_run_perf_critical - create and wake a performance-critical thread. + * + * Same as kthread_create(), but takes a perf cpumask to affine to. + */ +#define kthread_run_perf_critical(perfmask, threadfn, data, namefmt, ...) \ +({ \ + struct task_struct *__k \ + = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \ + if (!IS_ERR(__k)) { \ + __k->flags |= PF_PERF_CRITICAL; \ + BUILD_BUG_ON(perfmask != cpu_lp_mask && \ + perfmask != cpu_perf_mask && \ + perfmask != cpu_prime_mask); \ + kthread_bind_mask(__k, perfmask); \ + wake_up_process(__k); \ + } \ + __k; \ +}) + void free_kthread_struct(struct task_struct *k); void kthread_bind(struct task_struct *k, unsigned int cpu); void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask); diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index 915330abf6e5..7ae9dcf89578 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h @@ -117,8 +117,16 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb, int ipv6_skb_to_auditdata(struct sk_buff *skb, struct common_audit_data *ad, u8 *proto); +#ifdef CONFIG_AUDIT void common_lsm_audit(struct common_audit_data *a, void (*pre_audit)(struct audit_buffer *, void *), void (*post_audit)(struct audit_buffer *, void *)); +#else +static inline void common_lsm_audit(struct common_audit_data *a, + void (*pre_audit)(struct audit_buffer *, void *), + void (*post_audit)(struct audit_buffer *, void *)) +{ +} +#endif #endif diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index 1eb6f244588d..9a488497ebc2 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -21,11 +21,12 @@ #define MARVELL_PHY_ID_88E1545 0x01410ea0 #define MARVELL_PHY_ID_88E3016 0x01410e60 -/* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do +/* These Ethernet switch families contain embedded PHYs, but they do * not have a model ID. So the switch driver traps reads to the ID2 * register and returns the switch family ID */ -#define MARVELL_PHY_ID_88E6390 0x01410f90 +#define MARVELL_PHY_ID_88E6341_FAMILY 0x01410f41 +#define MARVELL_PHY_ID_88E6390_FAMILY 0x01410f90 #define MARVELL_PHY_FAMILY_ID(id) ((id) >> 4) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index b87b1569d15b..5f711b2983db 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -357,11 +357,11 @@ struct mlx5_ifc_flow_table_prop_layout_bits { u8 reserved_at_60[0x18]; u8 log_max_ft_num[0x8]; - u8 reserved_at_80[0x18]; + u8 reserved_at_80[0x10]; + u8 log_max_flow_counter[0x8]; u8 log_max_destination[0x8]; - u8 log_max_flow_counter[0x8]; - u8 reserved_at_a8[0x10]; + u8 reserved_at_a0[0x18]; u8 log_max_flow[0x8]; u8 reserved_at_c0[0x40]; @@ -8929,7 +8929,7 @@ struct mlx5_ifc_pbmc_reg_bits { struct mlx5_ifc_bufferx_reg_bits buffer[10]; - u8 reserved_at_2e0[0x40]; + u8 reserved_at_2e0[0x80]; }; struct mlx5_ifc_qtct_reg_bits { diff --git a/include/linux/mm.h b/include/linux/mm.h index b5c12e5a0ff3..3d776c6e7e56 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -49,7 +49,32 @@ static inline void set_max_mapnr(unsigned long limit) static inline void set_max_mapnr(unsigned long limit) { } #endif -extern unsigned long totalram_pages; +extern atomic_long_t _totalram_pages; +static inline unsigned long totalram_pages(void) +{ + return (unsigned long)atomic_long_read(&_totalram_pages); +} + +static inline void totalram_pages_inc(void) +{ + atomic_long_inc(&_totalram_pages); +} + +static inline void totalram_pages_dec(void) +{ + atomic_long_dec(&_totalram_pages); +} + +static inline void totalram_pages_add(long count) +{ + atomic_long_add(count, &_totalram_pages); +} + +static inline void totalram_pages_set(long val) +{ + atomic_long_set(&_totalram_pages, val); +} + extern void * high_memory; extern int page_cluster; @@ -2578,7 +2603,7 @@ int __must_check write_one_page(struct page *page); void task_dirty_inc(struct task_struct *tsk); /* readahead.c */ -#define VM_MAX_READAHEAD 512 /* kbytes */ +#define VM_MAX_READAHEAD 128 /* kbytes */ #define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, @@ -2895,6 +2920,7 @@ extern int sysctl_drop_caches; int drop_caches_sysctl_handler(struct ctl_table *, int, void __user *, size_t *, loff_t *); #endif +void mm_drop_caches(int val); void drop_slab(void); void drop_slab_node(int nid); diff --git a/include/linux/msi.h b/include/linux/msi.h index be8ec813dbfb..5dd171849a27 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -118,6 +118,12 @@ struct msi_desc { list_for_each_entry((desc), dev_to_msi_list((dev)), list) #define for_each_msi_entry_safe(desc, tmp, dev) \ list_for_each_entry_safe((desc), (tmp), dev_to_msi_list((dev)), list) +#define for_each_msi_vector(desc, __irq, dev) \ + for_each_msi_entry((desc), (dev)) \ + if ((desc)->irq) \ + for (__irq = (desc)->irq; \ + __irq < ((desc)->irq + (desc)->nvec_used); \ + __irq++) #ifdef CONFIG_PCI_MSI #define first_pci_msi_entry(pdev) first_msi_entry(&(pdev)->dev) diff --git a/include/linux/msm_drm_notify.h b/include/linux/msm_drm_notify.h new file mode 100644 index 000000000000..93926fddbc4f --- /dev/null +++ b/include/linux/msm_drm_notify.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + */ +#ifndef _MSM_DRM_NOTIFY_H_ +#define _MSM_DRM_NOTIFY_H_ + +#include + +/* A hardware display blank change occurred */ +#define MSM_DRM_EVENT_BLANK 0x01 +/* A hardware display blank early change occurred */ +#define MSM_DRM_EARLY_EVENT_BLANK 0x02 + +enum { + /* panel: power on */ + MSM_DRM_BLANK_UNBLANK, + /* panel: power off */ + MSM_DRM_BLANK_POWERDOWN, + /* panel power on for tp */ + MSM_DRM_BLANK_UNBLANK_CUST, + /* panel:lcd doze mode */ + MSM_DRM_BLANK_NORMAL, + /* panel power off */ + MSM_DRM_BLANK_POWERDOWN_CUST, + /*panel 60HZ */ + MSM_DRM_DYNAMICFPS_60 = 60, + /*panel 90HZ */ + MSM_DRM_DYNAMICFPS_90 = 90, +}; + +enum msm_drm_display_id { + /* primary display */ + MSM_DRM_PRIMARY_DISPLAY, + /* external display */ + MSM_DRM_EXTERNAL_DISPLAY, + MSM_DRM_DISPLAY_MAX +}; + +struct msm_drm_notifier { + enum msm_drm_display_id id; + void *data; +}; + +int dsi_panel_backlight_get(void); + +#ifdef CONFIG_DRM_MSM +int msm_drm_register_client(struct notifier_block *nb); +int msm_drm_unregister_client(struct notifier_block *nb); +#else +static inline int msm_drm_register_client(struct notifier_block *nb) +{ + return 0; +} + +static inline int msm_drm_unregister_client(struct notifier_block *nb) +{ + return 0; +} +#endif +#endif + diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h index 177e1abdd543..94fa5d42f6bb 100644 --- a/include/linux/msm_gsi.h +++ b/include/linux/msm_gsi.h @@ -1275,7 +1275,7 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, * @Return gsi_status */ int gsi_write_channel_scratch(unsigned long chan_hdl, - union __packed gsi_channel_scratch val); + union gsi_channel_scratch val); /** * gsi_write_channel_scratch3_reg - Peripheral should call this function to @@ -1314,7 +1314,7 @@ int gsi_write_channel_scratch2_reg(unsigned long chan_hdl, * @Return gsi_status */ int gsi_read_channel_scratch(unsigned long chan_hdl, - union __packed gsi_channel_scratch *val); + union gsi_channel_scratch *val); /** * gsi_pending_irq_type - Peripheral should call this function to @@ -1778,7 +1778,7 @@ static inline int gsi_alloc_channel(struct gsi_chan_props *props, } static inline int gsi_write_channel_scratch(unsigned long chan_hdl, - union __packed gsi_channel_scratch val) + union gsi_channel_scratch val) { return -GSI_STATUS_UNSUPPORTED_OP; } @@ -1795,7 +1795,7 @@ static inline int gsi_write_channel_scratch2_reg(unsigned long chan_hdl, } static inline int gsi_read_channel_scratch(unsigned long chan_hdl, - union __packed gsi_channel_scratch *val) + union gsi_channel_scratch *val) { return -GSI_STATUS_UNSUPPORTED_OP; } diff --git a/include/linux/mutex.h b/include/linux/mutex.h index 3093dd162424..8f7cdf83f359 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -184,7 +184,7 @@ extern void mutex_lock_io(struct mutex *lock); # define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock) # define mutex_lock_killable_nested(lock, subclass) mutex_lock_killable(lock) # define mutex_lock_nest_lock(lock, nest_lock) mutex_lock(lock) -# define mutex_lock_io_nested(lock, subclass) mutex_lock(lock) +# define mutex_lock_io_nested(lock, subclass) mutex_lock_io(lock) #endif /* diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 06cb69ab2664..2aadaafaf3a1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -4020,6 +4020,7 @@ static inline void netif_tx_disable(struct net_device *dev) local_bh_disable(); cpu = smp_processor_id(); + spin_lock(&dev->tx_global_lock); for (i = 0; i < dev->num_tx_queues; i++) { struct netdev_queue *txq = netdev_get_tx_queue(dev, i); @@ -4027,6 +4028,7 @@ static inline void netif_tx_disable(struct net_device *dev) netif_tx_stop_queue(txq); __netif_tx_unlock(txq); } + spin_unlock(&dev->tx_global_lock); local_bh_enable(); } diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index 72cb19c3db6a..9460a5635c90 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -300,7 +300,7 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, INIT_LIST_HEAD(&sublist); list_for_each_entry_safe(skb, next, head, list) { - list_del(&skb->list); + skb_list_del_init(skb); if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1) list_add_tail(&skb->list, &sublist); } diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h index 95ab5cc64422..45ff1330b339 100644 --- a/include/linux/netfilter_ipv4.h +++ b/include/linux/netfilter_ipv4.h @@ -16,7 +16,7 @@ struct ip_rt_info { u_int32_t mark; }; -int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type); +int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, unsigned addr_type); struct nf_queue_entry; diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h index c0dc4dd78887..47a2de582f57 100644 --- a/include/linux/netfilter_ipv6.h +++ b/include/linux/netfilter_ipv6.h @@ -36,7 +36,7 @@ struct nf_ipv6_ops { }; #ifdef CONFIG_NETFILTER -int ip6_route_me_harder(struct net *net, struct sk_buff *skb); +int ip6_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb); __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, unsigned int dataoff, u_int8_t protocol); diff --git a/include/linux/of.h b/include/linux/of.h index d4f14b0302b6..6429f00341d1 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1258,6 +1258,7 @@ static inline int of_get_available_child_count(const struct device_node *np) #define _OF_DECLARE(table, name, compat, fn, fn_type) \ static const struct of_device_id __of_table_##name \ __used __section(__##table##_of_table) \ + __aligned(__alignof__(struct of_device_id)) \ = { .compatible = compat, \ .data = (fn == (fn_type)NULL) ? fn : fn } #else diff --git a/include/linux/oom.h b/include/linux/oom.h index 67093d6f6630..de3140bd90e4 100644 --- a/include/linux/oom.h +++ b/include/linux/oom.h @@ -70,7 +70,11 @@ static inline bool oom_task_origin(const struct task_struct *p) static inline bool tsk_is_oom_victim(struct task_struct * tsk) { +#ifdef CONFIG_ANDROID_SIMPLE_LMK + return test_ti_thread_flag(task_thread_info(tsk), TIF_MEMDIE); +#else return tsk->signal->oom_mm; +#endif } /* diff --git a/include/linux/pm_qos.h b/include/linux/pm_qos.h index e22de69dcd98..13a9e912840a 100644 --- a/include/linux/pm_qos.h +++ b/include/linux/pm_qos.h @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -56,7 +55,7 @@ enum pm_qos_req_type { struct pm_qos_request { enum pm_qos_req_type type; - struct cpumask cpus_affine; + atomic_t cpus_affine; #ifdef CONFIG_SMP uint32_t irq; /* Internal structure members */ @@ -64,7 +63,6 @@ struct pm_qos_request { #endif struct plist_node node; int pm_qos_class; - struct delayed_work work; /* for pm_qos_update_request_timeout */ }; struct pm_qos_flags_request { @@ -144,8 +142,6 @@ void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class, s32 value); void pm_qos_update_request(struct pm_qos_request *req, s32 new_value); -void pm_qos_update_request_timeout(struct pm_qos_request *req, - s32 new_value, unsigned long timeout_us); void pm_qos_remove_request(struct pm_qos_request *req); int pm_qos_request(int pm_qos_class); diff --git a/include/linux/prandom.h b/include/linux/prandom.h index aa16e6468f91..cc1e71334e53 100644 --- a/include/linux/prandom.h +++ b/include/linux/prandom.h @@ -16,12 +16,44 @@ void prandom_bytes(void *buf, size_t nbytes); void prandom_seed(u32 seed); void prandom_reseed_late(void); +#if BITS_PER_LONG == 64 +/* + * The core SipHash round function. Each line can be executed in + * parallel given enough CPU resources. + */ +#define PRND_SIPROUND(v0, v1, v2, v3) ( \ + v0 += v1, v1 = rol64(v1, 13), v2 += v3, v3 = rol64(v3, 16), \ + v1 ^= v0, v0 = rol64(v0, 32), v3 ^= v2, \ + v0 += v3, v3 = rol64(v3, 21), v2 += v1, v1 = rol64(v1, 17), \ + v3 ^= v0, v1 ^= v2, v2 = rol64(v2, 32) \ +) + +#define PRND_K0 (0x736f6d6570736575 ^ 0x6c7967656e657261) +#define PRND_K1 (0x646f72616e646f6d ^ 0x7465646279746573) + +#elif BITS_PER_LONG == 32 +/* + * On 32-bit machines, we use HSipHash, a reduced-width version of SipHash. + * This is weaker, but 32-bit machines are not used for high-traffic + * applications, so there is less output for an attacker to analyze. + */ +#define PRND_SIPROUND(v0, v1, v2, v3) ( \ + v0 += v1, v1 = rol32(v1, 5), v2 += v3, v3 = rol32(v3, 8), \ + v1 ^= v0, v0 = rol32(v0, 16), v3 ^= v2, \ + v0 += v3, v3 = rol32(v3, 7), v2 += v1, v1 = rol32(v1, 13), \ + v3 ^= v0, v1 ^= v2, v2 = rol32(v2, 16) \ +) +#define PRND_K0 0x6c796765 +#define PRND_K1 0x74656462 + +#else +#error Unsupported BITS_PER_LONG +#endif + struct rnd_state { __u32 s1, s2, s3, s4; }; -DECLARE_PER_CPU(struct rnd_state, net_rand_state); - u32 prandom_u32_state(struct rnd_state *state); void prandom_bytes_state(struct rnd_state *state, void *buf, size_t nbytes); void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state); diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 0853d72a995e..c609d993511b 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -21,6 +21,7 @@ extern void proc_flush_task(struct task_struct *); extern struct proc_dir_entry *proc_symlink(const char *, struct proc_dir_entry *, const char *); +struct proc_dir_entry *_proc_mkdir(const char *, umode_t, struct proc_dir_entry *, void *, bool); extern struct proc_dir_entry *proc_mkdir(const char *, struct proc_dir_entry *); extern struct proc_dir_entry *proc_mkdir_data(const char *, umode_t, struct proc_dir_entry *, void *); @@ -90,6 +91,11 @@ static inline struct proc_dir_entry *proc_symlink(const char *name, static inline struct proc_dir_entry *proc_mkdir(const char *name, struct proc_dir_entry *parent) {return NULL;} static inline struct proc_dir_entry *proc_create_mount_point(const char *name) { return NULL; } +static inline struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode, + struct proc_dir_entry *parent, void *data, bool force_lookup) +{ + return NULL; +} static inline struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode, struct proc_dir_entry *parent, void *data) { return NULL; } static inline struct proc_dir_entry *proc_mkdir_mode(const char *name, @@ -133,7 +139,7 @@ struct net; static inline struct proc_dir_entry *proc_net_mkdir( struct net *net, const char *name, struct proc_dir_entry *parent) { - return proc_mkdir_data(name, 0, parent, net); + return _proc_mkdir(name, 0, parent, net, true); } struct ns_common; diff --git a/include/linux/rmap.h b/include/linux/rmap.h index 7268a54b8956..942718da2c16 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -228,7 +228,8 @@ struct page_vma_mapped_walk { static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw) { - if (pvmw->pte) + /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */ + if (pvmw->pte && !PageHuge(pvmw->page)) pte_unmap(pvmw->pte); if (pvmw->ptl) spin_unlock(pvmw->ptl); diff --git a/include/linux/sched.h b/include/linux/sched.h index 7f0f34e44786..650f292518ac 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -586,7 +586,6 @@ extern u32 sched_get_init_task_load(struct task_struct *p); extern void sched_update_cpu_freq_min_max(const cpumask_t *cpus, u32 fmin, u32 fmax); extern int sched_set_boost(int enable); -extern void free_task_load_ptrs(struct task_struct *p); extern void sched_set_refresh_rate(enum fps fps); #define RAVG_HIST_SIZE_MAX 5 @@ -631,7 +630,7 @@ struct ravg { u32 sum, demand; u32 coloc_demand; u32 sum_history[RAVG_HIST_SIZE_MAX]; - u32 *curr_window_cpu, *prev_window_cpu; + u32 curr_window_cpu[CONFIG_NR_CPUS], prev_window_cpu[CONFIG_NR_CPUS]; u32 curr_window, prev_window; u32 pred_demand; u8 busy_buckets[NUM_BUSY_BUCKETS]; @@ -653,8 +652,6 @@ static inline int sched_set_boost(int enable) { return -EINVAL; } -static inline void free_task_load_ptrs(struct task_struct *p) { } - static inline void sched_update_cpu_freq_min_max(const cpumask_t *cpus, u32 fmin, u32 fmax) { } @@ -1266,6 +1263,7 @@ struct task_struct { #endif struct list_head pi_state_list; struct futex_pi_state *pi_state_cache; + unsigned int futex_state; #endif #ifdef CONFIG_PERF_EVENTS struct perf_event_context *perf_event_ctxp[perf_nr_task_contexts]; @@ -1491,6 +1489,16 @@ struct task_struct { /* task is frozen/stopped (used by the cgroup freezer) */ ANDROID_KABI_USE(1, unsigned frozen:1); + struct { + struct work_struct work; + atomic_t running; + bool free_stack; + } async_free; + +#ifdef CONFIG_ANDROID_SIMPLE_LMK + struct task_struct *simple_lmk_next; +#endif + /* * New fields for task_struct should be added above here, so that * they are included in the randomized portion of task_struct. @@ -1667,7 +1675,6 @@ extern struct pid *cad_pid; */ #define PF_IDLE 0x00000002 /* I am an IDLE thread */ #define PF_EXITING 0x00000004 /* Getting shut down */ -#define PF_EXITPIDONE 0x00000008 /* PI exit done on shut down */ #define PF_VCPU 0x00000010 /* I'm a virtual CPU */ #define PF_WQ_WORKER 0x00000020 /* I'm a workqueue worker */ #define PF_FORKNOEXEC 0x00000040 /* Forked but didn't exec */ @@ -1689,6 +1696,7 @@ extern struct pid *cad_pid; #define PF_RANDOMIZE 0x00400000 /* Randomize virtual address space */ #define PF_SWAPWRITE 0x00800000 /* Allowed to write to swap */ #define PF_MEMSTALL 0x01000000 /* Stalled due to lack of memory */ +#define PF_PERF_CRITICAL 0x02000000 /* Thread is performance-critical */ #define PF_NO_SETAFFINITY 0x04000000 /* Userland is not allowed to meddle with cpus_allowed */ #define PF_MCE_EARLY 0x08000000 /* Early kill for mce process policy */ #define PF_WAKE_UP_IDLE 0x10000000 /* TTWU on an idle CPU */ @@ -1809,6 +1817,11 @@ static inline bool cpupri_check_rt(void) } #endif +void sched_migrate_to_cpumask_start(struct cpumask *old_mask, + const struct cpumask *dest); +void sched_migrate_to_cpumask_end(const struct cpumask *old_mask, + const struct cpumask *dest); + #ifndef cpu_relax_yield #define cpu_relax_yield() cpu_relax() #endif diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h index 766bbe813861..ef54f4b3f1e4 100644 --- a/include/linux/sched/mm.h +++ b/include/linux/sched/mm.h @@ -119,8 +119,10 @@ extern struct mm_struct *get_task_mm(struct task_struct *task); * succeeds. */ extern struct mm_struct *mm_access(struct task_struct *task, unsigned int mode); -/* Remove the current tasks stale references to the old mm_struct */ -extern void mm_release(struct task_struct *, struct mm_struct *); +/* Remove the current tasks stale references to the old mm_struct on exit() */ +extern void exit_mm_release(struct task_struct *, struct mm_struct *); +/* Remove the current tasks stale references to the old mm_struct on exec() */ +extern void exec_mm_release(struct task_struct *, struct mm_struct *); #ifdef CONFIG_MEMCG extern void mm_update_next_owner(struct mm_struct *mm); @@ -165,7 +167,8 @@ static inline bool in_vfork(struct task_struct *tsk) * another oom-unkillable task does this it should blame itself. */ rcu_read_lock(); - ret = tsk->vfork_done && tsk->real_parent->mm == tsk->mm; + ret = tsk->vfork_done && + rcu_dereference(tsk->real_parent)->mm == tsk->mm; rcu_read_unlock(); return ret; diff --git a/include/linux/sched/rt.h b/include/linux/sched/rt.h index e5af028c08b4..80014831b48c 100644 --- a/include/linux/sched/rt.h +++ b/include/linux/sched/rt.h @@ -59,9 +59,9 @@ extern void normalize_rt_tasks(void); /* - * default timeslice is 100 msecs (used only for SCHED_RR tasks). + * default timeslice is 1 jiffy (used only for SCHED_RR tasks). * Timeslices get refilled after they expire. */ -#define RR_TIMESLICE (100 * HZ / 1000) +#define RR_TIMESLICE (1) #endif /* _LINUX_SCHED_RT_H */ diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index e39f5d0e8cbb..05d8b1778fa6 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -167,7 +167,7 @@ extern char sched_lib_name[LIB_PATH_LENGTH]; extern unsigned int sched_lib_mask_force; extern bool is_sched_lib_based_app(pid_t pid); -#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) + #if defined(CONFIG_ENERGY_MODEL) && ((defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) || defined(CONFIG_CPU_FREQ_GOV_SCHEDHORIZON))) extern unsigned int sysctl_sched_energy_aware; extern int sched_energy_aware_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, diff --git a/include/linux/security.h b/include/linux/security.h index 71ad1841c59d..ef2079c60ed1 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -787,7 +787,7 @@ static inline int security_inode_killpriv(struct dentry *dentry) static inline int security_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc) { - return -EOPNOTSUPP; + return cap_inode_getsecurity(inode, name, buffer, alloc); } static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) diff --git a/include/linux/seq_buf.h b/include/linux/seq_buf.h index aa5deb041c25..7cc952282e8b 100644 --- a/include/linux/seq_buf.h +++ b/include/linux/seq_buf.h @@ -30,7 +30,7 @@ static inline void seq_buf_clear(struct seq_buf *s) } static inline void -seq_buf_init(struct seq_buf *s, unsigned char *buf, unsigned int size) +seq_buf_init(struct seq_buf *s, char *buf, unsigned int size) { s->buffer = buf; s->size = size; diff --git a/include/linux/simple_lmk.h b/include/linux/simple_lmk.h new file mode 100644 index 000000000000..b02d1bec9731 --- /dev/null +++ b/include/linux/simple_lmk.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2019-2020 Sultan Alsawaf . + */ +#ifndef _SIMPLE_LMK_H_ +#define _SIMPLE_LMK_H_ + +struct mm_struct; + +#ifdef CONFIG_ANDROID_SIMPLE_LMK +void simple_lmk_mm_freed(struct mm_struct *mm); +#else +static inline void simple_lmk_mm_freed(struct mm_struct *mm) +{ +} +#endif + +#endif /* _SIMPLE_LMK_H_ */ diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index a64235e05321..8ceba9b8e51e 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h @@ -634,6 +634,25 @@ static inline struct spi_controller *spi_alloc_slave(struct device *host, return __spi_alloc_controller(host, size, true); } +struct spi_controller *__devm_spi_alloc_controller(struct device *dev, + unsigned int size, + bool slave); + +static inline struct spi_controller *devm_spi_alloc_master(struct device *dev, + unsigned int size) +{ + return __devm_spi_alloc_controller(dev, size, false); +} + +static inline struct spi_controller *devm_spi_alloc_slave(struct device *dev, + unsigned int size) +{ + if (!IS_ENABLED(CONFIG_SPI_SLAVE)) + return NULL; + + return __devm_spi_alloc_controller(dev, size, true); +} + extern int spi_register_controller(struct spi_controller *ctlr); extern int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr); diff --git a/include/linux/stop_machine.h b/include/linux/stop_machine.h index 6d3635c86dbe..ccdaa8fd5657 100644 --- a/include/linux/stop_machine.h +++ b/include/linux/stop_machine.h @@ -138,7 +138,7 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus); #else /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */ -static inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, +static __always_inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus) { unsigned long flags; @@ -149,14 +149,15 @@ static inline int stop_machine_cpuslocked(cpu_stop_fn_t fn, void *data, return ret; } -static inline int stop_machine(cpu_stop_fn_t fn, void *data, - const struct cpumask *cpus) +static __always_inline int +stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus) { return stop_machine_cpuslocked(fn, data, cpus); } -static inline int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, - const struct cpumask *cpus) +static __always_inline int +stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data, + const struct cpumask *cpus) { return stop_machine(fn, data, cpus); } diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index 2bd68177a442..33580cc72a43 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -26,8 +26,7 @@ struct rpc_rqst; #define XDR_QUADLEN(l) (((l) + 3) >> 2) /* - * Generic opaque `network object.' At the kernel level, this type - * is used only by lockd. + * Generic opaque `network object.' */ #define XDR_MAX_NETOBJ 1024 struct xdr_netobj { diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index e7bbd82908b1..69fed13e633b 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -317,6 +317,7 @@ struct xprt_class { struct rpc_xprt * (*setup)(struct xprt_create *); struct module *owner; char name[32]; + const char * netid[]; }; /* diff --git a/include/linux/swap.h b/include/linux/swap.h index 83302aa822f7..894886fd3f8c 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -324,7 +324,6 @@ void workingset_update_node(struct radix_tree_node *node); }) /* linux/mm/page_alloc.c */ -extern unsigned long totalram_pages; extern unsigned long totalreserve_pages; extern unsigned long nr_free_buffer_pages(void); extern unsigned long nr_free_pagecache_pages(void); diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h index 790ca021203a..a022809009ac 100644 --- a/include/linux/sync_file.h +++ b/include/linux/sync_file.h @@ -34,14 +34,6 @@ */ struct sync_file { struct file *file; - /** - * @user_name: - * - * Name of the sync file provided by userspace, for merged fences. - * Otherwise generated through driver callbacks (in which case the - * entire array is 0). - */ - char user_name[32]; #ifdef CONFIG_DEBUG_FS struct list_head sync_file_list; #endif @@ -57,6 +49,5 @@ struct sync_file { struct sync_file *sync_file_create(struct dma_fence *fence); struct dma_fence *sync_file_get_fence(int fd); -char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len); #endif /* _LINUX_SYNC_H */ diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 987cefa337de..1cd7bad56075 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -299,6 +299,11 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) return kernfs_enable_ns(kn); } +__printf(2, 3) +int sysfs_emit(char *buf, const char *fmt, ...); +__printf(3, 4) +int sysfs_emit_at(char *buf, int at, const char *fmt, ...); + #else /* CONFIG_SYSFS */ static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) @@ -505,6 +510,17 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) { } +__printf(2, 3) +static inline int sysfs_emit(char *buf, const char *fmt, ...) +{ + return 0; +} + +__printf(3, 4) +static inline int sysfs_emit_at(char *buf, int at, const char *fmt, ...) +{ + return 0; +} #endif /* CONFIG_SYSFS */ static inline int __must_check sysfs_create_file(struct kobject *kobj, diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 8d8821b3689a..62dbecfe9132 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_THREAD_INFO_IN_TASK /* @@ -39,6 +40,18 @@ enum { #ifdef __KERNEL__ +#ifndef arch_set_restart_data +#define arch_set_restart_data(restart) do { } while (0) +#endif + +static inline long set_restart_fn(struct restart_block *restart, + long (*fn)(struct restart_block *)) +{ + restart->fn = fn; + arch_set_restart_data(restart); + return -ERESTART_RESTARTBLOCK; +} + #ifndef THREAD_ALIGN #define THREAD_ALIGN THREAD_SIZE #endif diff --git a/include/linux/time64.h b/include/linux/time64.h index 0333e106b5cf..6e27f3876a29 100644 --- a/include/linux/time64.h +++ b/include/linux/time64.h @@ -130,6 +130,10 @@ static inline bool timespec64_valid_settod(const struct timespec64 *ts) */ static inline s64 timespec64_to_ns(const struct timespec64 *ts) { + /* Prevent multiplication overflow */ + if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) + return KTIME_MAX; + return ((s64) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec; } diff --git a/include/linux/trace_seq.h b/include/linux/trace_seq.h index 6609b39a7232..6db257466af6 100644 --- a/include/linux/trace_seq.h +++ b/include/linux/trace_seq.h @@ -12,7 +12,7 @@ */ struct trace_seq { - unsigned char buffer[PAGE_SIZE]; + char buffer[PAGE_SIZE]; struct seq_buf seq; int full; }; @@ -51,7 +51,7 @@ static inline int trace_seq_used(struct trace_seq *s) * that is about to be written to and then return the result * of that write. */ -static inline unsigned char * +static inline char * trace_seq_buffer_ptr(struct trace_seq *s) { return s->buffer + seq_buf_used(&s->seq); diff --git a/include/linux/tty.h b/include/linux/tty.h index 83b2e68778c9..a75926ab316e 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -306,6 +306,10 @@ struct tty_struct { struct termiox *termiox; /* May be NULL for unsupported */ char name[64]; struct pid *pgrp; /* Protected by ctrl lock */ + /* + * Writes protected by both ctrl lock and legacy mutex, readers must use + * at least one of them. + */ struct pid *session; unsigned long flags; int count; diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h index a27604f99ed0..11096b561dab 100644 --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h @@ -69,12 +69,13 @@ struct u64_stats_sync { }; +#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) +#define u64_stats_init(syncp) seqcount_init(&(syncp)->seq) +#else static inline void u64_stats_init(struct u64_stats_sync *syncp) { -#if BITS_PER_LONG == 32 && defined(CONFIG_SMP) - seqcount_init(&syncp->seq); -#endif } +#endif static inline void u64_stats_update_begin(struct u64_stats_sync *syncp) { diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 000a5954b2e8..0a958c794832 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -84,6 +84,10 @@ /* Cannot handle REPORT_LUNS */ \ US_FLAG(ALWAYS_SYNC, 0x20000000) \ /* lies about caching, so always sync */ \ + US_FLAG(NO_SAME, 0x40000000) \ + /* Cannot handle WRITE_SAME */ \ + US_FLAG(SENSE_AFTER_SYNC, 0x80000000) \ + /* Do REQUEST_SENSE after SYNCHRONIZE_CACHE */ \ #define US_FLAG(name, value) US_FL_##name = value , enum { US_DO_ALL_FLAGS }; diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index f32fe7080d2e..36e6d19cd285 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -62,6 +62,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, return -EINVAL; } + skb_reset_mac_header(skb); + if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h index 1b8a21c3757a..31bffa69e864 100644 --- a/include/linux/vmpressure.h +++ b/include/linux/vmpressure.h @@ -16,6 +16,7 @@ struct vmpressure { unsigned long tree_scanned; unsigned long tree_reclaimed; + unsigned long stall; /* The lock is used to keep the scanned/reclaimed above in sync. */ struct spinlock sr_lock; @@ -32,7 +33,8 @@ struct mem_cgroup; extern int vmpressure_notifier_register(struct notifier_block *nb); extern int vmpressure_notifier_unregister(struct notifier_block *nb); extern void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed); + unsigned long scanned, unsigned long reclaimed, + int order); extern void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio); #ifdef CONFIG_MEMCG diff --git a/include/linux/wait.h b/include/linux/wait.h index 62aa6e0b3149..2861207821d4 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -150,6 +150,7 @@ static inline bool wq_has_sleeper(struct wait_queue_head *wq_head) extern void add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); extern void add_wait_queue_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); +extern void add_wait_queue_exclusive_lifo(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); extern void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); static inline void __add_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry) @@ -1110,6 +1111,7 @@ do { \ */ void prepare_to_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); void prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); +void prepare_to_wait_exclusive_lifo(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); long prepare_to_wait_event(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); void finish_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); long __sched wait_woken(struct wait_queue_entry *wq_entry, unsigned int mode, diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index 342f37479228..f3d74b92f35d 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -634,6 +634,15 @@ static inline bool schedule_delayed_work(struct delayed_work *dwork, return queue_delayed_work(system_wq, dwork, delay); } +/** + * delayed_work_busy - See work_busy() + * @dwork: the delayed work to be tested + */ +static inline unsigned int delayed_work_busy(struct delayed_work *dwork) +{ + return work_busy(&dwork->work); +} + #ifndef CONFIG_SMP static inline long work_on_cpu(int cpu, long (*fn)(void *), void *arg) { diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h index 3bf21608bec6..ed8dd5cb1d69 100644 --- a/include/media/radio-iris.h +++ b/include/media/radio-iris.h @@ -71,7 +71,7 @@ void radio_hci_event_packet(struct radio_hci_dev *hdev, struct sk_buff *skb); #undef FMDBG #ifdef FM_DEBUG -#define FMDBG(fmt, args...) pr_info("iris_radio: " fmt, ##args) +#define FMDBG(fmt, args...) pr_debug("iris_radio: " fmt, ##args) #else #define FMDBG(fmt, args...) #endif @@ -79,6 +79,8 @@ void radio_hci_event_packet(struct radio_hci_dev *hdev, struct sk_buff *skb); #undef FMDERR #define FMDERR(fmt, args...) pr_err("iris_radio: " fmt, ##args) +#define FM_INFO(fmt, args...) pr_info("iris_transport: " fmt, ##args) + /* HCI timeouts */ #define RADIO_HCI_TIMEOUT (10000) /* 10 seconds */ diff --git a/include/net/bonding.h b/include/net/bonding.h index 8116648873c3..c458f084f7bb 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -170,6 +170,11 @@ struct slave { struct rtnl_link_stats64 slave_stats; }; +static inline struct slave *to_slave(struct kobject *kobj) +{ + return container_of(kobj, struct slave, kobj); +} + struct bond_up_slave { unsigned int count; struct rcu_head rcu; @@ -733,6 +738,9 @@ extern struct bond_parm_tbl ad_select_tbl[]; /* exported from bond_netlink.c */ extern struct rtnl_link_ops bond_link_ops; +/* exported from bond_sysfs_slave.c */ +extern const struct sysfs_ops slave_sysfs_ops; + static inline void bond_tx_drop(struct net_device *dev, struct sk_buff *skb) { atomic_long_inc(&dev->tx_dropped); diff --git a/include/net/cnss2.h b/include/net/cnss2.h index d10ba56b9361..d3c242c0cb02 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ #ifndef _NET_CNSS2_H #define _NET_CNSS2_H @@ -8,6 +8,7 @@ #define CNSS_MAX_FILE_NAME 20 #define CNSS_MAX_TIMESTAMP_LEN 32 +#define CNSS_MAX_DEV_MEM_NUM 4 /* * Temporary change for compilation, will be removed @@ -52,6 +53,11 @@ struct cnss_device_version { u32 minor_version; }; +struct cnss_dev_mem_info { + u64 start; + u64 size; +}; + struct cnss_soc_info { void __iomem *va; phys_addr_t pa; @@ -62,6 +68,7 @@ struct cnss_soc_info { uint32_t fw_version; char fw_build_timestamp[CNSS_MAX_TIMESTAMP_LEN + 1]; struct cnss_device_version device_version; + struct cnss_dev_mem_info dev_mem_info[CNSS_MAX_DEV_MEM_NUM]; }; struct cnss_wlan_runtime_ops { diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index fc9d6e37552d..da8a582ab032 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -288,7 +288,7 @@ static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk) return inet_csk_reqsk_queue_len(sk) >= sk->sk_max_ack_backlog; } -void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req); +bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req); void inet_csk_reqsk_queue_drop_and_put(struct sock *sk, struct request_sock *req); void inet_csk_destroy_sock(struct sock *sk); diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 6f05af7eff0d..d5f62fb24cea 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -491,9 +491,11 @@ static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info, const void *from, int len, __be16 flags) { - memcpy(ip_tunnel_info_opts(info), from, len); info->options_len = len; - info->key.tun_flags |= flags; + if (len > 0) { + memcpy(ip_tunnel_info_opts(info), from, len); + info->key.tun_flags |= flags; + } } static inline struct ip_tunnel_info *lwt_tun_info(struct lwtunnel_state *lwtstate) @@ -539,7 +541,6 @@ static inline void ip_tunnel_info_opts_set(struct ip_tunnel_info *info, __be16 flags) { info->options_len = 0; - info->key.tun_flags |= flags; } #endif /* CONFIG_INET */ diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 9991e5ef52cc..fbfa59801454 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -70,7 +70,9 @@ struct netns_xfrm { #if IS_ENABLED(CONFIG_IPV6) struct dst_ops xfrm6_dst_ops; #endif - spinlock_t xfrm_state_lock; + spinlock_t xfrm_state_lock; + seqcount_t xfrm_state_hash_generation; + spinlock_t xfrm_policy_lock; struct mutex xfrm_cfg_mutex; }; diff --git a/include/net/red.h b/include/net/red.h index 9665582c4687..ff07a7cedf68 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -168,14 +168,24 @@ static inline void red_set_vars(struct red_vars *v) v->qcount = -1; } -static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog) +static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, + u8 Scell_log, u8 *stab) { - if (fls(qth_min) + Wlog > 32) + if (fls(qth_min) + Wlog >= 32) return false; - if (fls(qth_max) + Wlog > 32) + if (fls(qth_max) + Wlog >= 32) + return false; + if (Scell_log >= 32) return false; if (qth_max < qth_min) return false; + if (stab) { + int i; + + for (i = 0; i < RED_STAB_SIZE; i++) + if (stab[i] >= 32) + return false; + } return true; } diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 0bbaa5488423..3d961a3cf3c4 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -33,6 +33,7 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) * * @list: Used internally * @kind: Identifier + * @netns_refund: Physical device, move to init_net on netns exit * @maxtype: Highest device specific netlink attribute number * @policy: Netlink policy for device specific attribute validation * @validate: Optional validation function for netlink/changelink parameters @@ -64,6 +65,7 @@ struct rtnl_link_ops { size_t priv_size; void (*setup)(struct net_device *dev); + bool netns_refund; unsigned int maxtype; const struct nla_policy *policy; int (*validate)(struct nlattr *tb[], diff --git a/include/net/sock.h b/include/net/sock.h index 7100472cec0f..856056a584f8 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -237,6 +237,26 @@ struct sock_common { /* public: */ }; +struct sk_security_struct { +#ifdef CONFIG_NETLABEL + enum { /* NetLabel state */ + NLBL_UNSET = 0, + NLBL_REQUIRE, + NLBL_LABELED, + NLBL_REQSKB, + NLBL_CONNLABELED, + } nlbl_state; + struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */ +#endif + u32 sid; /* SID of this object */ + u32 peer_sid; /* SID of peer */ + u16 sclass; /* sock security class */ + enum { /* SCTP association state */ + SCTP_ASSOC_UNSET = 0, + SCTP_ASSOC_SET, + } sctp_assoc_state; +}; + /** * struct sock - network layer representation of sockets * @__sk_common: shared layout with inet_timewait_sock @@ -493,7 +513,7 @@ struct sock { struct socket *sk_socket; void *sk_user_data; #ifdef CONFIG_SECURITY - void *sk_security; + struct sk_security_struct sk_security[1]; #endif struct sock_cgroup_data sk_cgrp_data; struct mem_cgroup *sk_memcg; diff --git a/include/net/tcp.h b/include/net/tcp.h index 1607c917f6bb..10f72345ea95 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1396,8 +1396,13 @@ static inline int tcp_full_space(const struct sock *sk) */ static inline bool tcp_rmem_pressure(const struct sock *sk) { - int rcvbuf = READ_ONCE(sk->sk_rcvbuf); - int threshold = rcvbuf - (rcvbuf >> 3); + int rcvbuf, threshold; + + if (tcp_under_memory_pressure(sk)) + return true; + + rcvbuf = READ_ONCE(sk->sk_rcvbuf); + threshold = rcvbuf - (rcvbuf >> 3); return atomic_read(&sk->sk_rmem_alloc) > threshold; } @@ -1977,7 +1982,7 @@ void tcp_mark_skb_lost(struct sock *sk, struct sk_buff *skb); void tcp_newreno_mark_lost(struct sock *sk, bool snd_una_advanced); extern s32 tcp_rack_skb_timeout(struct tcp_sock *tp, struct sk_buff *skb, u32 reo_wnd); -extern void tcp_rack_mark_lost(struct sock *sk); +extern bool tcp_rack_mark_lost(struct sock *sk); extern void tcp_rack_advance(struct tcp_sock *tp, u8 sacked, u32 end_seq, u64 xmit_time); extern void tcp_rack_reo_timeout(struct sock *sk); diff --git a/include/net/tls.h b/include/net/tls.h index 98f5ad0319a2..9caef9bad075 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -163,6 +163,12 @@ enum { enum tls_context_flags { TLS_RX_SYNC_RUNNING = 0, + /* tls_dev_del was called for the RX side, device state was released, + * but tls_ctx->netdev might still be kept, because TX-side driver + * resources might not be released yet. Used to prevent the second + * tls_dev_del call in tls_device_down if it happens simultaneously. + */ + TLS_RX_DEV_CLOSED = 2, }; struct cipher_context { diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index c9bd935f4fd1..1ee0f30ae190 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -145,6 +145,9 @@ struct iscsi_task { void *dd_data; /* driver/transport data */ }; +/* invalid scsi_task pointer */ +#define INVALID_SCSI_TASK (struct iscsi_task *)-1l + static inline int iscsi_task_has_unsol_data(struct iscsi_task *task) { return task->unsol_r2t.data_length > task->unsol_r2t.sent; diff --git a/include/soc/qcom/scm.h b/include/soc/qcom/scm.h index 8f1a419bf8a0..ae4ec932d07f 100644 --- a/include/soc/qcom/scm.h +++ b/include/soc/qcom/scm.h @@ -108,6 +108,7 @@ extern int scm_get_feat_version(u32 feat); extern bool is_scm_armv8(void); extern struct mutex scm_lmh_lock; +extern bool under_scm_call(void); #else @@ -166,5 +167,9 @@ static inline bool scm_is_secure_device(void) return false; } +extern bool under_scm_call(void) +{ + return false; +} #endif #endif diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 51b6f50eabee..0deeff9b4496 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -69,6 +69,7 @@ int transport_backend_register(const struct target_backend_ops *); void target_backend_unregister(const struct target_backend_ops *); void target_complete_cmd(struct se_cmd *, u8); +void target_set_cmd_data_length(struct se_cmd *, int); void target_complete_cmd_with_length(struct se_cmd *, u8, int); void transport_copy_sense_to_cmd(struct se_cmd *, unsigned char *); diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index ccd2b382fff1..90d86c1432d2 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -152,7 +152,8 @@ TRACE_DEFINE_ENUM(CP_RESIZE); { CP_NODE_NEED_CP, "node needs cp" }, \ { CP_FASTBOOT_MODE, "fastboot mode" }, \ { CP_SPEC_LOG_NUM, "log type is 2" }, \ - { CP_RECOVER_DIR, "dir needs recovery" }) + { CP_RECOVER_DIR, "dir needs recovery" }, \ + { CP_PARENT_XATTR_SET, "parent xattr is set" }) #define show_shutdown_mode(type) \ __print_symbolic(type, \ diff --git a/include/uapi/linux/batterydata-interface.h b/include/uapi/linux/batterydata-interface.h new file mode 100644 index 000000000000..07cd900c0f4d --- /dev/null +++ b/include/uapi/linux/batterydata-interface.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +#ifndef __BATTERYDATA_LIB_H__ +#define __BATTERYDATA_LIB_H__ + +#include + +/** + * struct battery_params - Battery profile data to be exchanged. + * @soc: SOC (state of charge) of the battery + * @ocv_uv: OCV (open circuit voltage) of the battery + * @rbatt_sf: RBATT scaling factor + * @batt_temp: Battery temperature in deci-degree. + * @slope: Slope of the OCV-SOC curve. + * @fcc_mah: FCC (full charge capacity) of the battery. + */ +struct battery_params { + int soc; + int ocv_uv; + int rbatt_sf; + int batt_temp; + int slope; + int fcc_mah; +}; + +/* IOCTLs to query battery profile data */ +#define BPIOCXSOC _IOWR('B', 0x01, struct battery_params) /* SOC */ +#define BPIOCXRBATT _IOWR('B', 0x02, struct battery_params) /* RBATT SF */ +#define BPIOCXSLOPE _IOWR('B', 0x03, struct battery_params) /* SLOPE */ +#define BPIOCXFCC _IOWR('B', 0x04, struct battery_params) /* FCC */ + +#endif diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index a7884b930865..40aeda3c4df4 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -477,6 +477,8 @@ union bpf_attr { * u64 bpf_ktime_get_ns(void) * Description * Return the time elapsed since system boot, in nanoseconds. + * Does not include time the system was suspended. + * See: clock_gettime(CLOCK_MONOTONIC) * Return * Current *ktime*. * @@ -2157,6 +2159,14 @@ union bpf_attr { * request in the skb. * Return * 0 on success, or a negative error in case of failure. + * + * u64 bpf_ktime_get_boot_ns(void) + * Description + * Return the time elapsed since system boot, in nanoseconds. + * Does include the time the system was suspended. + * See: clock_gettime(CLOCK_BOOTTIME) + * Return + * Current *ktime*. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2243,7 +2253,49 @@ union bpf_attr { FN(get_current_cgroup_id), \ FN(get_local_storage), \ FN(sk_select_reuseport), \ - FN(skb_ancestor_cgroup_id), + FN(skb_ancestor_cgroup_id), \ + FN(sk_lookup_tcp), \ + FN(sk_lookup_udp), \ + FN(sk_release), \ + FN(map_push_elem), \ + FN(map_pop_elem), \ + FN(map_peek_elem), \ + FN(msg_push_data), \ + FN(msg_pop_data), \ + FN(rc_pointer_rel), \ + FN(spin_lock), \ + FN(spin_unlock), \ + FN(sk_fullsock), \ + FN(tcp_sock), \ + FN(skb_ecn_set_ce), \ + FN(get_listener_sock), \ + FN(skc_lookup_tcp), \ + FN(tcp_check_syncookie), \ + FN(sysctl_get_name), \ + FN(sysctl_get_current_value), \ + FN(sysctl_get_new_value), \ + FN(sysctl_set_new_value), \ + FN(strtol), \ + FN(strtoul), \ + FN(sk_storage_get), \ + FN(sk_storage_delete), \ + FN(send_signal), \ + FN(tcp_gen_syncookie), \ + FN(skb_output), \ + FN(probe_read_user), \ + FN(probe_read_kernel), \ + FN(probe_read_user_str), \ + FN(probe_read_kernel_str), \ + FN(tcp_send_ack), \ + FN(send_signal_thread), \ + FN(jiffies64), \ + FN(read_branch_records), \ + FN(get_ns_current_pid_tgid), \ + FN(xdp_output), \ + FN(get_netns_cookie), \ + FN(get_current_ancestor_cgroup_id), \ + FN(sk_assign), \ + FN(ktime_get_boot_ns), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/include/uapi/linux/const.h b/include/uapi/linux/const.h index 5ed721ad5b19..af2a44c08683 100644 --- a/include/uapi/linux/const.h +++ b/include/uapi/linux/const.h @@ -28,4 +28,9 @@ #define _BITUL(x) (_UL(1) << (x)) #define _BITULL(x) (_ULL(1) << (x)) +#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) +#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) + +#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + #endif /* _UAPI_LINUX_CONST_H */ diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index dc69391d2bba..fc21d3726b59 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -14,7 +14,7 @@ #ifndef _UAPI_LINUX_ETHTOOL_H #define _UAPI_LINUX_ETHTOOL_H -#include +#include #include #include diff --git a/include/uapi/linux/if_alg.h b/include/uapi/linux/if_alg.h index bc2bcdec377b..769050771423 100644 --- a/include/uapi/linux/if_alg.h +++ b/include/uapi/linux/if_alg.h @@ -24,6 +24,22 @@ struct sockaddr_alg { __u8 salg_name[64]; }; +/* + * Linux v4.12 and later removed the 64-byte limit on salg_name[]; it's now an + * arbitrary-length field. We had to keep the original struct above for source + * compatibility with existing userspace programs, though. Use the new struct + * below if support for very long algorithm names is needed. To do this, + * allocate 'sizeof(struct sockaddr_alg_new) + strlen(algname) + 1' bytes, and + * copy algname (including the null terminator) into salg_name. + */ +struct sockaddr_alg_new { + __u16 salg_family; + __u8 salg_type[14]; + __u32 salg_feat; + __u32 salg_mask; + __u8 salg_name[]; +}; + struct af_alg_iv { __u32 ivlen; __u8 iv[0]; diff --git a/include/uapi/linux/kernel.h b/include/uapi/linux/kernel.h index 0ff8f7477847..fadf2db71fe8 100644 --- a/include/uapi/linux/kernel.h +++ b/include/uapi/linux/kernel.h @@ -3,13 +3,6 @@ #define _UAPI_LINUX_KERNEL_H #include - -/* - * 'kernel.h' contains some often-used function prototypes etc - */ -#define __ALIGN_KERNEL(x, a) __ALIGN_KERNEL_MASK(x, (typeof(x))(a) - 1) -#define __ALIGN_KERNEL_MASK(x, mask) (((x) + (mask)) & ~(mask)) - -#define __KERNEL_DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +#include #endif /* _UAPI_LINUX_KERNEL_H */ diff --git a/include/uapi/linux/lightnvm.h b/include/uapi/linux/lightnvm.h index f9a1be7fc696..ead2e72e5c88 100644 --- a/include/uapi/linux/lightnvm.h +++ b/include/uapi/linux/lightnvm.h @@ -21,7 +21,7 @@ #define _UAPI_LINUX_LIGHTNVM_H #ifdef __KERNEL__ -#include +#include #include #else /* __KERNEL__ */ #include diff --git a/include/uapi/linux/mroute6.h b/include/uapi/linux/mroute6.h index 9999cc006390..1617eb9949a5 100644 --- a/include/uapi/linux/mroute6.h +++ b/include/uapi/linux/mroute6.h @@ -2,7 +2,7 @@ #ifndef _UAPI__LINUX_MROUTE6_H #define _UAPI__LINUX_MROUTE6_H -#include +#include #include #include #include /* For struct sockaddr_in6. */ diff --git a/include/uapi/linux/netfilter/nfnetlink_cthelper.h b/include/uapi/linux/netfilter/nfnetlink_cthelper.h index a13137afc429..70af02092d16 100644 --- a/include/uapi/linux/netfilter/nfnetlink_cthelper.h +++ b/include/uapi/linux/netfilter/nfnetlink_cthelper.h @@ -5,7 +5,7 @@ #define NFCT_HELPER_STATUS_DISABLED 0 #define NFCT_HELPER_STATUS_ENABLED 1 -enum nfnl_acct_msg_types { +enum nfnl_cthelper_msg_types { NFNL_MSG_CTHELPER_NEW, NFNL_MSG_CTHELPER_GET, NFNL_MSG_CTHELPER_DEL, diff --git a/include/uapi/linux/netfilter/x_tables.h b/include/uapi/linux/netfilter/x_tables.h index a8283f7dbc51..b8c6bb233ac1 100644 --- a/include/uapi/linux/netfilter/x_tables.h +++ b/include/uapi/linux/netfilter/x_tables.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _UAPI_X_TABLES_H #define _UAPI_X_TABLES_H -#include +#include #include #define XT_FUNCTION_MAXNAMELEN 30 diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index 5fa3fcc10128..d5ce61f86fd0 100644 --- a/include/uapi/linux/netlink.h +++ b/include/uapi/linux/netlink.h @@ -2,7 +2,7 @@ #ifndef _UAPI__LINUX_NETLINK_H #define _UAPI__LINUX_NETLINK_H -#include +#include #include /* for __kernel_sa_family_t */ #include diff --git a/include/uapi/linux/sysctl.h b/include/uapi/linux/sysctl.h index 4b9f32fb49c3..e5e038817292 100644 --- a/include/uapi/linux/sysctl.h +++ b/include/uapi/linux/sysctl.h @@ -23,7 +23,7 @@ #ifndef _UAPI_LINUX_SYSCTL_H #define _UAPI_LINUX_SYSCTL_H -#include +#include #include #include diff --git a/include/uapi/linux/vm_bms.h b/include/uapi/linux/vm_bms.h new file mode 100644 index 000000000000..db537f478f0c --- /dev/null +++ b/include/uapi/linux/vm_bms.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +#ifndef __VM_BMS_H__ +#define __VM_BMS_H__ + +#define VM_BMS_DEVICE "/dev/vm_bms" +#define MAX_FIFO_REGS 8 + +/** + * struct qpnp_vm_bms_data - vm-bms data (passed to usersapce) + * @data_type: type of data filled up + * @num_fifo: count of valid fifo averages + * @fifo_uv: array of fifo averages in uv + * @sample_interval sample interval of the fifo data in ms + * @sample_count total samples in one fifo + * @acc_uv averaged accumulator value in uv + * @acc_count num of accumulated samples + * @seq_num sequence number of the data + */ +struct qpnp_vm_bms_data { + unsigned int num_fifo; + unsigned int fifo_uv[MAX_FIFO_REGS]; + unsigned int sample_interval_ms; + unsigned int sample_count; + unsigned int acc_uv; + unsigned int acc_count; + unsigned int seq_num; +}; + +enum vmbms_power_usecase { + VMBMS_IGNORE_ALL_BIT = 1, + VMBMS_VOICE_CALL_BIT = (1 << 4), + VMBMS_STATIC_DISPLAY_BIT = (1 << 5), +}; + +#endif /* __VM_BMS_H__ */ diff --git a/include/uapi/linux/wireless.h b/include/uapi/linux/wireless.h index a2c006a364e0..24f3371ad826 100644 --- a/include/uapi/linux/wireless.h +++ b/include/uapi/linux/wireless.h @@ -74,7 +74,11 @@ #include /* for "struct sockaddr" et al */ #include /* for IFNAMSIZ and co... */ -#include /* for offsetof */ +#ifdef __KERNEL__ +# include /* for offsetof */ +#else +# include /* for offsetof */ +#endif /***************************** VERSION *****************************/ /* diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 9bc5bc07d4d3..a9978350b45b 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -157,6 +157,7 @@ gnttab_set_map_op(struct gnttab_map_grant_ref *map, phys_addr_t addr, map->flags = flags; map->ref = ref; map->dom = domid; + map->status = 1; /* arbitrary positive value */ } static inline void diff --git a/include/xen/xenbus.h b/include/xen/xenbus.h index 869c816d5f8c..14d47ed4114f 100644 --- a/include/xen/xenbus.h +++ b/include/xen/xenbus.h @@ -59,6 +59,15 @@ struct xenbus_watch /* Path being watched. */ const char *node; + unsigned int nr_pending; + + /* + * Called just before enqueing new event while a spinlock is held. + * The event will be discarded if this callback returns false. + */ + bool (*will_handle)(struct xenbus_watch *, + const char *path, const char *token); + /* Callback (executed in a process context with no locks held). */ void (*callback)(struct xenbus_watch *, const char *path, const char *token); @@ -178,8 +187,6 @@ void xs_suspend_cancel(void); struct work_struct; -void xenbus_probe(struct work_struct *); - #define XENBUS_IS_ERR_READ(str) ({ \ if (!IS_ERR(str) && strlen(str) == 0) { \ kfree(str); \ @@ -192,10 +199,14 @@ void xenbus_probe(struct work_struct *); int xenbus_watch_path(struct xenbus_device *dev, const char *path, struct xenbus_watch *watch, + bool (*will_handle)(struct xenbus_watch *, + const char *, const char *), void (*callback)(struct xenbus_watch *, const char *, const char *)); -__printf(4, 5) +__printf(5, 6) int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch, + bool (*will_handle)(struct xenbus_watch *, + const char *, const char *), void (*callback)(struct xenbus_watch *, const char *, const char *), const char *pathfmt, ...); diff --git a/init/Kconfig b/init/Kconfig index 98f695e0e808..1ec927fde3a8 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -72,8 +72,7 @@ config INIT_ENV_ARG_LIMIT config COMPILE_TEST bool "Compile also drivers which will not load" - depends on !UML - default n + depends on HAS_IOMEM help Some drivers can be compiled on a different platform than they are intended to be run on. Despite they cannot be loaded there (or even @@ -1303,9 +1302,6 @@ config LD_DEAD_CODE_DATA_ELIMINATION bool "Dead code and data elimination (EXPERIMENTAL)" depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION depends on EXPERT - depends on !(FUNCTION_TRACER && CC_IS_GCC && GCC_VERSION < 40800) - depends on $(cc-option,-ffunction-sections -fdata-sections) - depends on $(ld-option,--gc-sections) help Enable this if you want to do dead code and data elimination with the linker by compiling with -ffunction-sections -fdata-sections, @@ -1353,8 +1349,6 @@ config BPF menuconfig EXPERT bool "Configure standard kernel features (expert users)" - # Unhide debug options, to make the on-by-default options visible - select DEBUG_KERNEL help This option allows certain base kernel options and settings to be disabled or tweaked. This is for specialized diff --git a/init/init_task.c b/init/init_task.c index 9098cb0967e8..e268cfb56b1b 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -173,7 +173,8 @@ struct task_struct init_task .lockdep_recursion = 0, #endif #ifdef CONFIG_FUNCTION_GRAPH_TRACER - .ret_stack = NULL, + .ret_stack = NULL, + .tracing_graph_pause = ATOMIC_INIT(0), #endif #if defined(CONFIG_TRACING) && defined(CONFIG_PREEMPT) .trace_recursion = 0, diff --git a/init/main.c b/init/main.c index 0e7b6a871aa5..f73c29feef29 100644 --- a/init/main.c +++ b/init/main.c @@ -556,6 +556,8 @@ static void __init mm_init(void) pti_init(); } +void __init init_sync_kmem_pool(void); +void __init init_dma_buf_kmem_pool(void); asmlinkage __visible void __init start_kernel(void) { char *command_line; @@ -757,6 +759,8 @@ asmlinkage __visible void __init start_kernel(void) cgroup_init(); taskstats_init_early(); delayacct_init(); + init_sync_kmem_pool(); + init_dma_buf_kmem_pool(); check_bugs(); @@ -1099,7 +1103,6 @@ static int __ref kernel_init(void *unused) /* need to finish all async __init code before freeing the memory */ async_synchronize_full(); ftrace_free_init_mem(); - jump_label_invalidate_initmem(); free_initmem(); mark_readonly(); diff --git a/kernel/Makefile b/kernel/Makefile index 02f3b2d19b8d..ebebaa44208f 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -63,8 +63,8 @@ obj-$(CONFIG_SMP) += smp.o ifneq ($(CONFIG_SMP),y) obj-y += up.o endif +obj-y += module.o obj-$(CONFIG_UID16) += uid16.o -obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SIG) += module_signing.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o @@ -101,7 +101,6 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o obj-$(CONFIG_TRACEPOINTS) += tracepoint.o obj-$(CONFIG_LATENCYTOP) += latencytop.o -obj-$(CONFIG_ELFCORE) += elfcore.o obj-$(CONFIG_FUNCTION_TRACER) += trace/ obj-$(CONFIG_TRACING) += trace/ obj-$(CONFIG_TRACE_CLOCK) += trace/ @@ -129,7 +128,7 @@ obj-$(CONFIG_RSEQ) += rseq.o $(obj)/configs.o: $(obj)/config_data.h targets += config_data.gz -$(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE +$(obj)/config_data.gz: arch/arm64/configs/stock_defconfig FORCE $(call if_changed,gzip) filechk_ikconfiggz = (echo "static const char kernel_config_data[] __used = MAGIC_START"; cat $< | scripts/bin2c; echo "MAGIC_END;") diff --git a/kernel/bpf/bpf_lru_list.c b/kernel/bpf/bpf_lru_list.c index e6ef4401a138..9b5eeff72fd3 100644 --- a/kernel/bpf/bpf_lru_list.c +++ b/kernel/bpf/bpf_lru_list.c @@ -505,13 +505,14 @@ struct bpf_lru_node *bpf_lru_pop_free(struct bpf_lru *lru, u32 hash) static void bpf_common_lru_push_free(struct bpf_lru *lru, struct bpf_lru_node *node) { + u8 node_type = READ_ONCE(node->type); unsigned long flags; - if (WARN_ON_ONCE(node->type == BPF_LRU_LIST_T_FREE) || - WARN_ON_ONCE(node->type == BPF_LRU_LOCAL_LIST_T_FREE)) + if (WARN_ON_ONCE(node_type == BPF_LRU_LIST_T_FREE) || + WARN_ON_ONCE(node_type == BPF_LRU_LOCAL_LIST_T_FREE)) return; - if (node->type == BPF_LRU_LOCAL_LIST_T_PENDING) { + if (node_type == BPF_LRU_LOCAL_LIST_T_PENDING) { struct bpf_lru_locallist *loc_l; loc_l = per_cpu_ptr(lru->common_lru.local_list, node->cpu); diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index bdfb74d85e22..5bd904f10141 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -646,7 +646,11 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr, if (bpf_jit_charge_modmem(pages)) return NULL; +#ifdef CONFIG_MODULES hdr = module_alloc(size); +#else + hdr = vmalloc_exec(size); +#endif if (!hdr) { bpf_jit_uncharge_modmem(pages); return NULL; @@ -671,7 +675,11 @@ void bpf_jit_binary_free(struct bpf_binary_header *hdr) { u32 pages = hdr->pages; +#ifdef CONFIG_MODULES module_memfree(hdr); +#else + vfree(hdr); +#endif bpf_jit_uncharge_modmem(pages); } @@ -1869,6 +1877,7 @@ const struct bpf_func_proto bpf_get_prandom_u32_proto __weak; const struct bpf_func_proto bpf_get_smp_processor_id_proto __weak; const struct bpf_func_proto bpf_get_numa_node_id_proto __weak; const struct bpf_func_proto bpf_ktime_get_ns_proto __weak; +const struct bpf_func_proto bpf_ktime_get_boot_ns_proto __weak; const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak; const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak; diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index a3015dcbbb84..c54e3ac03389 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -116,6 +116,18 @@ const struct bpf_func_proto bpf_ktime_get_ns_proto = { .ret_type = RET_INTEGER, }; +BPF_CALL_0(bpf_ktime_get_boot_ns) +{ + /* NMI safe access to clock boottime */ + return ktime_get_boot_fast_ns(); +} + +const struct bpf_func_proto bpf_ktime_get_boot_ns_proto = { + .func = bpf_ktime_get_boot_ns, + .gpl_only = false, + .ret_type = RET_INTEGER, +}; + BPF_CALL_0(bpf_get_current_pid_tgid) { struct task_struct *task = current; diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 55fff5e6d983..a47d623f59fe 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -114,6 +114,8 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) /* hash table size must be power of 2 */ n_buckets = roundup_pow_of_two(attr->max_entries); + if (!n_buckets) + return ERR_PTR(-E2BIG); cost = n_buckets * sizeof(struct stack_map_bucket *) + sizeof(*smap); if (cost >= U32_MAX - PAGE_SIZE) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index ab3de0fac7e9..bc276eb0872f 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -662,6 +662,8 @@ static int map_lookup_elem(union bpf_attr *attr) int ufd = attr->map_fd; struct bpf_map *map; void *key, *value, *ptr; + u8 key_onstack[SZ_16] __aligned(sizeof(long)); + u8 value_onstack[SZ_64] __aligned(sizeof(long)); u32 value_size; struct fd f; int err; @@ -679,10 +681,18 @@ static int map_lookup_elem(union bpf_attr *attr) goto err_put; } - key = memdup_user(ukey, map->key_size); - if (IS_ERR(key)) { - err = PTR_ERR(key); - goto err_put; + if (map->key_size <= sizeof(key_onstack)) { + key = key_onstack; + if (copy_from_user(key, ukey, map->key_size)) { + err = -EFAULT; + goto err_put; + } + } else { + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto err_put; + } } if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || @@ -695,9 +705,13 @@ static int map_lookup_elem(union bpf_attr *attr) value_size = map->value_size; err = -ENOMEM; - value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); - if (!value) - goto free_key; + if (value_size <= sizeof(value_onstack)) { + value = value_onstack; + } else { + value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); + if (!value) + goto free_key; + } if (bpf_map_is_dev_bound(map)) { err = bpf_map_offload_lookup_elem(map, key, value); @@ -744,9 +758,11 @@ static int map_lookup_elem(union bpf_attr *attr) err = 0; free_value: - kfree(value); + if (value != value_onstack) + kfree(value); free_key: - kfree(key); + if (key != key_onstack) + kfree(key); err_put: fdput(f); return err; @@ -772,6 +788,8 @@ static int map_update_elem(union bpf_attr *attr) int ufd = attr->map_fd; struct bpf_map *map; void *key, *value; + u8 key_onstack[SZ_16] __aligned(sizeof(long)); + u8 value_onstack[SZ_64] __aligned(sizeof(long)); u32 value_size; struct fd f; int err; @@ -789,10 +807,18 @@ static int map_update_elem(union bpf_attr *attr) goto err_put; } - key = memdup_user(ukey, map->key_size); - if (IS_ERR(key)) { - err = PTR_ERR(key); - goto err_put; + if (map->key_size <= sizeof(key_onstack)) { + key = key_onstack; + if (copy_from_user(key, ukey, map->key_size)) { + err = -EFAULT; + goto err_put; + } + } else { + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto err_put; + } } if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH || @@ -802,10 +828,14 @@ static int map_update_elem(union bpf_attr *attr) else value_size = map->value_size; - err = -ENOMEM; - value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); - if (!value) - goto free_key; + if (value_size <= sizeof(value_onstack)) { + value = value_onstack; + } else { + err = -ENOMEM; + value = kmalloc(value_size, GFP_USER | __GFP_NOWARN); + if (!value) + goto free_key; + } err = -EFAULT; if (copy_from_user(value, uvalue, value_size) != 0) @@ -856,9 +886,11 @@ static int map_update_elem(union bpf_attr *attr) maybe_wait_bpf_programs(map); out: free_value: - kfree(value); + if (value != value_onstack) + kfree(value); free_key: - kfree(key); + if (key != key_onstack) + kfree(key); err_put: fdput(f); return err; @@ -873,6 +905,7 @@ static int map_delete_elem(union bpf_attr *attr) struct bpf_map *map; struct fd f; void *key; + u8 key_onstack[SZ_16] __aligned(sizeof(long)); int err; if (CHECK_ATTR(BPF_MAP_DELETE_ELEM)) @@ -888,10 +921,18 @@ static int map_delete_elem(union bpf_attr *attr) goto err_put; } - key = memdup_user(ukey, map->key_size); - if (IS_ERR(key)) { - err = PTR_ERR(key); - goto err_put; + if (map->key_size <= sizeof(key_onstack)) { + key = key_onstack; + if (copy_from_user(key, ukey, map->key_size)) { + err = -EFAULT; + goto err_put; + } + } else { + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto err_put; + } } if (bpf_map_is_dev_bound(map)) { @@ -908,7 +949,8 @@ static int map_delete_elem(union bpf_attr *attr) preempt_enable(); maybe_wait_bpf_programs(map); out: - kfree(key); + if (key != key_onstack) + kfree(key); err_put: fdput(f); return err; @@ -924,6 +966,8 @@ static int map_get_next_key(union bpf_attr *attr) int ufd = attr->map_fd; struct bpf_map *map; void *key, *next_key; + u8 key_onstack[SZ_16] __aligned(sizeof(long)); + u8 next_key_onstack[SZ_64] __aligned(sizeof(long)); struct fd f; int err; @@ -941,19 +985,31 @@ static int map_get_next_key(union bpf_attr *attr) } if (ukey) { - key = memdup_user(ukey, map->key_size); - if (IS_ERR(key)) { - err = PTR_ERR(key); - goto err_put; + if (map->key_size <= sizeof(key_onstack)) { + key = key_onstack; + if (copy_from_user(key, ukey, map->key_size)) { + err = -EFAULT; + goto err_put; + } + } else { + key = memdup_user(ukey, map->key_size); + if (IS_ERR(key)) { + err = PTR_ERR(key); + goto err_put; + } } } else { key = NULL; } err = -ENOMEM; - next_key = kmalloc(map->key_size, GFP_USER); - if (!next_key) - goto free_key; + if (map->key_size <= sizeof(next_key_onstack)) { + next_key = next_key_onstack; + } else { + next_key = kmalloc(map->key_size, GFP_USER); + if (!next_key) + goto free_key; + } if (bpf_map_is_dev_bound(map)) { err = bpf_map_offload_get_next_key(map, key, next_key); @@ -974,9 +1030,11 @@ static int map_get_next_key(union bpf_attr *attr) err = 0; free_next_key: - kfree(next_key); + if (next_key != next_key_onstack) + kfree(next_key); free_key: - kfree(key); + if (key != key_onstack) + kfree(key); err_put: fdput(f); return err; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index daf0a9637d73..a0cdb6c4a330 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -2734,24 +2734,29 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, { bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || (opcode == BPF_SUB && !off_is_neg); - u32 off; + u32 off, max; switch (ptr_reg->type) { case PTR_TO_STACK: + /* Offset 0 is out-of-bounds, but acceptable start for the + * left direction, see BPF_REG_FP. + */ + max = MAX_BPF_STACK + mask_to_left; off = ptr_reg->off + ptr_reg->var_off.value; if (mask_to_left) *ptr_limit = MAX_BPF_STACK + off; else - *ptr_limit = -off; - return 0; + *ptr_limit = -off - 1; + return *ptr_limit >= max ? -ERANGE : 0; case PTR_TO_MAP_VALUE: + max = ptr_reg->map_ptr->value_size; if (mask_to_left) { *ptr_limit = ptr_reg->umax_value + ptr_reg->off; } else { off = ptr_reg->smin_value + ptr_reg->off; - *ptr_limit = ptr_reg->map_ptr->value_size - off; + *ptr_limit = ptr_reg->map_ptr->value_size - off - 1; } - return 0; + return *ptr_limit >= max ? -ERANGE : 0; default: return -EINVAL; } @@ -2804,6 +2809,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env, u32 alu_state, alu_limit; struct bpf_reg_state tmp; bool ret; + int err; if (can_skip_alu_sanitation(env, insn)) return 0; @@ -2819,10 +2825,13 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env, alu_state |= ptr_is_dst_reg ? BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST; - if (retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg)) - return 0; - if (update_alu_sanitation_state(aux, alu_state, alu_limit)) - return -EACCES; + err = retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg); + if (err < 0) + return err; + + err = update_alu_sanitation_state(aux, alu_state, alu_limit); + if (err < 0) + return err; do_sim: /* Simulate and find potential out-of-bounds access under * speculative execution from truncation as a result of @@ -2920,7 +2929,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, case BPF_ADD: ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0); if (ret < 0) { - verbose(env, "R%d tried to add from different maps or paths\n", dst); + verbose(env, "R%d tried to add from different maps, paths, or prohibited types\n", dst); return ret; } /* We can take a fixed offset as long as it doesn't overflow @@ -2975,7 +2984,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, case BPF_SUB: ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0); if (ret < 0) { - verbose(env, "R%d tried to sub from different maps or paths\n", dst); + verbose(env, "R%d tried to sub from different maps, paths, or prohibited types\n", dst); return ret; } if (dst_reg == off_reg) { @@ -6085,7 +6094,7 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) off_reg = issrc ? insn->src_reg : insn->dst_reg; if (isneg) *patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1); - *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit - 1); + *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit); *patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg); *patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg); *patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0); diff --git a/kernel/cfi.c b/kernel/cfi.c index 5092eaa403c7..a9f698866596 100644 --- a/kernel/cfi.c +++ b/kernel/cfi.c @@ -194,7 +194,8 @@ static void update_shadow(struct module *mod, unsigned long min_addr, next->r.max_page = max_addr >> PAGE_SHIFT; spin_lock(&shadow_update_lock); - prev = rcu_dereference_protected(cfi_shadow, 1); + prev = rcu_dereference_protected(cfi_shadow, + mutex_is_locked(&shadow_update_lock)); prepare_next_shadow(prev, next); fn(next, mod); diff --git a/kernel/cgroup/cgroup-internal.h b/kernel/cgroup/cgroup-internal.h index 92717bb90059..b416af1fa115 100644 --- a/kernel/cgroup/cgroup-internal.h +++ b/kernel/cgroup/cgroup-internal.h @@ -212,9 +212,10 @@ int cgroup_migrate(struct task_struct *leader, bool threadgroup, int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader, bool threadgroup); -struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup) +struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup, + bool *locked) __acquires(&cgroup_threadgroup_rwsem); -void cgroup_procs_write_finish(struct task_struct *task) +void cgroup_procs_write_finish(struct task_struct *task, bool locked) __releases(&cgroup_threadgroup_rwsem); void cgroup_lock_and_drain_offline(struct cgroup *cgrp); diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index 262c96134c5c..0faec5e8a681 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include @@ -511,12 +513,13 @@ static ssize_t __cgroup1_procs_write(struct kernfs_open_file *of, struct task_struct *task; const struct cred *cred, *tcred; ssize_t ret; + bool locked; cgrp = cgroup_kn_lock_live(of->kn, false); if (!cgrp) return -ENODEV; - task = cgroup_procs_write_start(buf, threadgroup); + task = cgroup_procs_write_start(buf, threadgroup, &locked); ret = PTR_ERR_OR_ZERO(task); if (ret) goto out_unlock; @@ -538,8 +541,16 @@ static ssize_t __cgroup1_procs_write(struct kernfs_open_file *of, ret = cgroup_attach_task(cgrp, task, threadgroup); + /* This covers boosting for app launches and app transitions */ + if (!ret && !threadgroup && + !memcmp(of->kn->parent->name, "top-app", sizeof("top-app")) && + is_zygote_pid(task->parent->pid)) { + devfreq_boost_kick_max(DEVFREQ_MSM_LLCCBW_DDR, 500); + devfreq_boost_kick_max(DEVFREQ_MSM_CPU_LLCCBW, 500); + } + out_finish: - cgroup_procs_write_finish(task); + cgroup_procs_write_finish(task, locked); out_unlock: cgroup_kn_unlock(of->kn); diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 5e2d84a5947a..5d8d411bc7f6 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -695,6 +695,8 @@ EXPORT_SYMBOL_GPL(of_css); ; \ else +static struct kmem_cache *cgrp_cset_link_pool; + /* * The default css_set - used by init and its children prior to any * hierarchies being mounted. It contains a pointer to the root state @@ -923,7 +925,7 @@ void put_css_set_locked(struct css_set *cset) list_del(&link->cgrp_link); if (cgroup_parent(link->cgrp)) cgroup_put(link->cgrp); - kfree(link); + kmem_cache_free(cgrp_cset_link_pool, link); } if (css_set_threaded(cset)) { @@ -1073,7 +1075,7 @@ static void free_cgrp_cset_links(struct list_head *links_to_free) list_for_each_entry_safe(link, tmp_link, links_to_free, cset_link) { list_del(&link->cset_link); - kfree(link); + kmem_cache_free(cgrp_cset_link_pool, link); } } @@ -1093,7 +1095,7 @@ static int allocate_cgrp_cset_links(int count, struct list_head *tmp_links) INIT_LIST_HEAD(tmp_links); for (i = 0; i < count; i++) { - link = kzalloc(sizeof(*link), GFP_KERNEL); + link = kmem_cache_zalloc(cgrp_cset_link_pool, GFP_KERNEL); if (!link) { free_cgrp_cset_links(tmp_links); return -ENOMEM; @@ -1305,7 +1307,7 @@ static void cgroup_destroy_root(struct cgroup_root *root) list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) { list_del(&link->cset_link); list_del(&link->cgrp_link); - kfree(link); + kmem_cache_free(cgrp_cset_link_pool, link); } spin_unlock_irq(&css_set_lock); @@ -2696,7 +2698,8 @@ int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader, return ret; } -struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup) +struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup, + bool *locked) __acquires(&cgroup_threadgroup_rwsem) { struct task_struct *tsk; @@ -2705,7 +2708,21 @@ struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup) if (kstrtoint(strstrip(buf), 0, &pid) || pid < 0) return ERR_PTR(-EINVAL); - percpu_down_write(&cgroup_threadgroup_rwsem); + /* + * If we migrate a single thread, we don't care about threadgroup + * stability. If the thread is `current`, it won't exit(2) under our + * hands or change PID through exec(2). We exclude + * cgroup_update_dfl_csses and other cgroup_{proc,thread}s_write + * callers by cgroup_mutex. + * Therefore, we can skip the global lock. + */ + lockdep_assert_held(&cgroup_mutex); + if (pid || threadgroup) { + percpu_down_write(&cgroup_threadgroup_rwsem); + *locked = true; + } else { + *locked = false; + } rcu_read_lock(); if (pid) { @@ -2736,13 +2753,16 @@ struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup) goto out_unlock_rcu; out_unlock_threadgroup: - percpu_up_write(&cgroup_threadgroup_rwsem); + if (*locked) { + percpu_up_write(&cgroup_threadgroup_rwsem); + *locked = false; + } out_unlock_rcu: rcu_read_unlock(); return tsk; } -void cgroup_procs_write_finish(struct task_struct *task) +void cgroup_procs_write_finish(struct task_struct *task, bool locked) __releases(&cgroup_threadgroup_rwsem) { struct cgroup_subsys *ss; @@ -2751,7 +2771,8 @@ void cgroup_procs_write_finish(struct task_struct *task) /* release reference from cgroup_procs_write_start() */ put_task_struct(task); - percpu_up_write(&cgroup_threadgroup_rwsem); + if (locked) + percpu_up_write(&cgroup_threadgroup_rwsem); for_each_subsys(ss, ssid) if (ss->post_attach) ss->post_attach(); @@ -4629,12 +4650,13 @@ static ssize_t cgroup_procs_write(struct kernfs_open_file *of, struct cgroup *src_cgrp, *dst_cgrp; struct task_struct *task; ssize_t ret; + bool locked; dst_cgrp = cgroup_kn_lock_live(of->kn, false); if (!dst_cgrp) return -ENODEV; - task = cgroup_procs_write_start(buf, true); + task = cgroup_procs_write_start(buf, true, &locked); ret = PTR_ERR_OR_ZERO(task); if (ret) goto out_unlock; @@ -4652,7 +4674,7 @@ static ssize_t cgroup_procs_write(struct kernfs_open_file *of, ret = cgroup_attach_task(dst_cgrp, task, true); out_finish: - cgroup_procs_write_finish(task); + cgroup_procs_write_finish(task, locked); out_unlock: cgroup_kn_unlock(of->kn); @@ -4670,6 +4692,7 @@ static ssize_t cgroup_threads_write(struct kernfs_open_file *of, struct cgroup *src_cgrp, *dst_cgrp; struct task_struct *task; ssize_t ret; + bool locked; buf = strstrip(buf); @@ -4677,7 +4700,7 @@ static ssize_t cgroup_threads_write(struct kernfs_open_file *of, if (!dst_cgrp) return -ENODEV; - task = cgroup_procs_write_start(buf, false); + task = cgroup_procs_write_start(buf, false, &locked); ret = PTR_ERR_OR_ZERO(task); if (ret) goto out_unlock; @@ -4701,7 +4724,7 @@ static ssize_t cgroup_threads_write(struct kernfs_open_file *of, ret = cgroup_attach_task(dst_cgrp, task, false); out_finish: - cgroup_procs_write_finish(task); + cgroup_procs_write_finish(task, locked); out_unlock: cgroup_kn_unlock(of->kn); @@ -5595,6 +5618,8 @@ int __init cgroup_init(void) struct cgroup_subsys *ss; int ssid; + cgrp_cset_link_pool = KMEM_CACHE(cgrp_cset_link, SLAB_HWCACHE_ALIGN | SLAB_PANIC); + BUILD_BUG_ON(CGROUP_SUBSYS_COUNT > 16); BUG_ON(percpu_init_rwsem(&cgroup_threadgroup_rwsem)); BUG_ON(cgroup_init_cftypes(NULL, cgroup_base_files)); diff --git a/kernel/cpu.c b/kernel/cpu.c index fe26e17765df..fb2abd4a30f6 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -779,6 +779,10 @@ void __init cpuhp_threads_init(void) } #ifdef CONFIG_HOTPLUG_CPU +#ifndef arch_clear_mm_cpumask_cpu +#define arch_clear_mm_cpumask_cpu(cpu, mm) cpumask_clear_cpu(cpu, mm_cpumask(mm)) +#endif + /** * clear_tasks_mm_cpumask - Safely clear tasks' mm_cpumask for a CPU * @cpu: a CPU id @@ -814,7 +818,7 @@ void clear_tasks_mm_cpumask(int cpu) t = find_lock_task_mm(p); if (!t) continue; - cpumask_clear_cpu(cpu, mm_cpumask(t->mm)); + arch_clear_mm_cpumask_cpu(cpu, t->mm); task_unlock(t); } rcu_read_unlock(); @@ -1029,8 +1033,19 @@ static int cpu_down_maps_locked(unsigned int cpu, enum cpuhp_state target) static int do_cpu_down(unsigned int cpu, enum cpuhp_state target) { + struct cpumask newmask; int err; + preempt_disable(); + cpumask_andnot(&newmask, cpu_online_mask, cpumask_of(cpu)); + preempt_enable(); + + /* One big, LITTLE, and prime CPU must remain online */ + if (!cpumask_intersects(&newmask, cpu_lp_mask) || + !cpumask_intersects(&newmask, cpu_perf_mask) || + !cpumask_intersects(&newmask, cpu_prime_mask)) + return -EINVAL; + /* * When cpusets are enabled, the rebuilding of the scheduling * domains is deferred to a workqueue context. Make sure @@ -1261,6 +1276,7 @@ int freeze_secondary_cpus(int primary) int cpu, error = 0; cpu_maps_update_begin(); + unaffine_perf_irqs(); if (!cpu_online(primary)) primary = cpumask_first(cpu_online_mask); /* @@ -1350,6 +1366,7 @@ void enable_nonboot_cpus(void) arch_enable_nonboot_cpus_end(); cpumask_clear(frozen_cpus); + reaffine_perf_irqs(false); out: cpu_maps_update_done(); } @@ -2343,6 +2360,30 @@ EXPORT_SYMBOL(__cpu_active_mask); struct cpumask __cpu_isolated_mask __read_mostly; EXPORT_SYMBOL(__cpu_isolated_mask); +#if CONFIG_LITTLE_CPU_MASK +static const unsigned long lp_cpu_bits = CONFIG_LITTLE_CPU_MASK; +const struct cpumask *const cpu_lp_mask = to_cpumask(&lp_cpu_bits); +#else +const struct cpumask *const cpu_lp_mask = cpu_possible_mask; +#endif +EXPORT_SYMBOL(cpu_lp_mask); + +#if CONFIG_BIG_CPU_MASK +static const unsigned long perf_cpu_bits = CONFIG_BIG_CPU_MASK; +const struct cpumask *const cpu_perf_mask = to_cpumask(&perf_cpu_bits); +#else +const struct cpumask *const cpu_perf_mask = cpu_possible_mask; +#endif +EXPORT_SYMBOL(cpu_perf_mask); + +#if CONFIG_PRIME_CPU_MASK +static const unsigned long prime_cpu_bits = CONFIG_PRIME_CPU_MASK; +const struct cpumask *const cpu_prime_mask = to_cpumask(&prime_cpu_bits); +#else +const struct cpumask *const cpu_prime_mask = cpu_possible_mask; +#endif +EXPORT_SYMBOL(cpu_prime_mask); + void init_cpu_present(const struct cpumask *src) { cpumask_copy(&__cpu_present_mask, src); diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 2118d8258b7c..ad53b19734e9 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -233,7 +233,7 @@ extern struct task_struct *kdb_curr_task(int); #define kdb_do_each_thread(g, p) do_each_thread(g, p) #define kdb_while_each_thread(g, p) while_each_thread(g, p) -#define GFP_KDB (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) +#define GFP_KDB (in_dbg_master() ? GFP_ATOMIC : GFP_KERNEL) extern void *debug_kmalloc(size_t size, gfp_t flags); extern void debug_kfree(void *); diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index 1dc1ec0d9383..59bfd2fd135a 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -239,6 +239,7 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; } io_tlb_index = 0; + no_iotlb_memory = false; if (verbose) swiotlb_print_info(); @@ -270,9 +271,11 @@ swiotlb_init(int verbose) if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose)) return; - if (io_tlb_start) + if (io_tlb_start) { memblock_free_early(io_tlb_start, PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); + io_tlb_start = 0; + } pr_warn("Cannot allocate buffer"); no_iotlb_memory = true; } @@ -376,6 +379,7 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs) io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; } io_tlb_index = 0; + no_iotlb_memory = false; swiotlb_print_info(); diff --git a/kernel/elfcore.c b/kernel/elfcore.c deleted file mode 100644 index 57fb4dcff434..000000000000 --- a/kernel/elfcore.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include - -Elf_Half __weak elf_core_extra_phdrs(void) -{ - return 0; -} - -int __weak elf_core_write_extra_phdrs(struct coredump_params *cprm, loff_t offset) -{ - return 1; -} - -int __weak elf_core_write_extra_data(struct coredump_params *cprm) -{ - return 1; -} - -size_t __weak elf_core_extra_data_size(void) -{ - return 0; -} diff --git a/kernel/events/core.c b/kernel/events/core.c index 2c6b8409d56e..ccbba551a505 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5659,11 +5659,11 @@ static void perf_pmu_output_stop(struct perf_event *event); static void perf_mmap_close(struct vm_area_struct *vma) { struct perf_event *event = vma->vm_file->private_data; - struct ring_buffer *rb = ring_buffer_get(event); struct user_struct *mmap_user = rb->mmap_user; int mmap_locked = rb->mmap_locked; unsigned long size = perf_data_size(rb); + bool detach_rest = false; if (event->pmu->event_unmapped) event->pmu->event_unmapped(event, vma->vm_mm); @@ -5694,7 +5694,8 @@ static void perf_mmap_close(struct vm_area_struct *vma) mutex_unlock(&event->mmap_mutex); } - atomic_dec(&rb->mmap_count); + if (atomic_dec_and_test(&rb->mmap_count)) + detach_rest = true; if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) goto out_put; @@ -5703,7 +5704,7 @@ static void perf_mmap_close(struct vm_area_struct *vma) mutex_unlock(&event->mmap_mutex); /* If there's still other mmap()s of this buffer, we're done. */ - if (atomic_read(&rb->mmap_count)) + if (!detach_rest) goto out_put; /* diff --git a/kernel/events/internal.h b/kernel/events/internal.h index 6dc725a7e7bc..8fc0ddc38cb6 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -209,7 +209,7 @@ static inline int get_recursion_context(int *recursion) rctx = 3; else if (in_irq()) rctx = 2; - else if (in_softirq()) + else if (in_serving_softirq()) rctx = 1; else rctx = 0; diff --git a/kernel/exit.c b/kernel/exit.c index a94c6ac831b1..08d4d320c1a9 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -498,7 +498,7 @@ static void exit_mm(void) struct mm_struct *mm = current->mm; struct core_state *core_state; - mm_release(current, mm); + exit_mm_release(current, mm); if (!mm) return; sync_mm_rss(mm); @@ -517,7 +517,10 @@ static void exit_mm(void) up_read(&mm->mmap_sem); self.task = current; - self.next = xchg(&core_state->dumper.next, &self); + if (self.task->flags & PF_SIGNALED) + self.next = xchg(&core_state->dumper.next, &self); + else + self.task = NULL; /* * Implies mb(), the result of xchg() must be visible * to core_state->dumper. @@ -544,8 +547,12 @@ static void exit_mm(void) task_unlock(current); mm_update_next_owner(mm); mmput(mm); +#ifdef CONFIG_ANDROID_SIMPLE_LMK + clear_thread_flag(TIF_MEMDIE); +#else if (test_thread_flag(TIF_MEMDIE)) exit_oom_victim(); +#endif } static struct task_struct *find_alive_thread(struct task_struct *p) @@ -816,16 +823,7 @@ void __noreturn do_exit(long code) */ if (unlikely(tsk->flags & PF_EXITING)) { pr_alert("Fixing recursive fault but reboot is needed!\n"); - /* - * We can do this unlocked here. The futex code uses - * this flag just to verify whether the pi state - * cleanup has been done or not. In the worst case it - * loops once more. We pretend that the cleanup was - * done as there is no way to return. Either the - * OWNER_DIED bit is set by now or we push the blocked - * task into the wait for ever nirwana as well. - */ - tsk->flags |= PF_EXITPIDONE; + futex_exit_done(tsk); set_current_state(TASK_UNINTERRUPTIBLE); schedule(); } @@ -917,12 +915,6 @@ void __noreturn do_exit(long code) * Make sure we are holding no locks: */ debug_check_no_locks_held(); - /* - * We can do this unlocked here. The futex code uses this flag - * just to verify whether the pi state cleanup has been done - * or not. In the worst case it loops once more. - */ - tsk->flags |= PF_EXITPIDONE; if (tsk->io_context) exit_io_context(tsk); diff --git a/kernel/fail_function.c b/kernel/fail_function.c index bc80a4e268c0..a52151a2291f 100644 --- a/kernel/fail_function.c +++ b/kernel/fail_function.c @@ -261,7 +261,7 @@ static ssize_t fei_write(struct file *file, const char __user *buffer, if (copy_from_user(buf, buffer, count)) { ret = -EFAULT; - goto out; + goto out_free; } buf[count] = '\0'; sym = strstrip(buf); @@ -315,8 +315,9 @@ static ssize_t fei_write(struct file *file, const char __user *buffer, ret = count; } out: - kfree(buf); mutex_unlock(&fei_lock); +out_free: + kfree(buf); return ret; } diff --git a/kernel/fork.c b/kernel/fork.c index 56df97bf333f..ca919c1260ce 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -95,6 +95,8 @@ #include #include #include +#include +#include #include #include @@ -380,7 +382,7 @@ static void account_kernel_stack(struct task_struct *tsk, int account) } } -static void release_task_stack(struct task_struct *tsk) +void release_task_stack(struct task_struct *tsk) { if (WARN_ON(tsk->state != TASK_DEAD)) return; /* Better to leak the stack than to free prematurely */ @@ -747,10 +749,10 @@ static void set_max_threads(unsigned int max_threads_suggested) * The number of threads shall be limited such that the thread * structures may only consume a small part of the available memory. */ - if (fls64(totalram_pages) + fls64(PAGE_SIZE) > 64) + if (fls64(totalram_pages()) + fls64(PAGE_SIZE) > 64) threads = MAX_THREADS; else - threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, + threads = div64_u64((u64) totalram_pages() * (u64) PAGE_SIZE, (u64) THREAD_SIZE * 8UL); if (threads > max_threads_suggested) @@ -1061,6 +1063,7 @@ static inline void __mmput(struct mm_struct *mm) ksm_exit(mm); khugepaged_exit(mm); /* must run before exit_mmap */ exit_mmap(mm); + simple_lmk_mm_freed(mm); mm_put_huge_zero_page(mm); set_mm_exe_file(mm, NULL); if (!list_empty(&mm->mmlist)) { @@ -1267,24 +1270,8 @@ static int wait_for_vfork_done(struct task_struct *child, * restoring the old one. . . * Eric Biederman 10 January 1998 */ -void mm_release(struct task_struct *tsk, struct mm_struct *mm) +static void mm_release(struct task_struct *tsk, struct mm_struct *mm) { - /* Get rid of any futexes when releasing the mm */ -#ifdef CONFIG_FUTEX - if (unlikely(tsk->robust_list)) { - exit_robust_list(tsk); - tsk->robust_list = NULL; - } -#ifdef CONFIG_COMPAT - if (unlikely(tsk->compat_robust_list)) { - compat_exit_robust_list(tsk); - tsk->compat_robust_list = NULL; - } -#endif - if (unlikely(!list_empty(&tsk->pi_state_list))) - exit_pi_state_list(tsk); -#endif - uprobe_free_utask(tsk); /* Get rid of any cached register state */ @@ -1317,6 +1304,18 @@ void mm_release(struct task_struct *tsk, struct mm_struct *mm) complete_vfork_done(tsk); } +void exit_mm_release(struct task_struct *tsk, struct mm_struct *mm) +{ + futex_exit_release(tsk); + mm_release(tsk, mm); +} + +void exec_mm_release(struct task_struct *tsk, struct mm_struct *mm) +{ + futex_exec_release(tsk); + mm_release(tsk, mm); +} + /* * Allocate a new mm structure and copy contents from the * mm structure of the passed in task structure. @@ -2117,14 +2116,8 @@ static __latent_entropy struct task_struct *copy_process( #ifdef CONFIG_BLOCK p->plug = NULL; #endif -#ifdef CONFIG_FUTEX - p->robust_list = NULL; -#ifdef CONFIG_COMPAT - p->compat_robust_list = NULL; -#endif - INIT_LIST_HEAD(&p->pi_state_list); - p->pi_state_cache = NULL; -#endif + futex_init_task(p); + /* * sigaltstack should be cleared when sharing the same VM */ @@ -2330,7 +2323,6 @@ static __latent_entropy struct task_struct *copy_process( perf_event_free_task(p); bad_fork_cleanup_policy: lockdep_free_task(p); - free_task_load_ptrs(p); #ifdef CONFIG_NUMA mpol_put(p->mempolicy); bad_fork_cleanup_threadgroup_lock: @@ -2392,6 +2384,12 @@ long _do_fork(unsigned long clone_flags, int trace = 0; long nr; + /* Boost CPU to the max for 150 ms when userspace launches an app */ + if (is_zygote_pid(current->pid)) { + devfreq_boost_kick_max(DEVFREQ_MSM_LLCCBW_DDR, 150); + devfreq_boost_kick_max(DEVFREQ_MSM_CPU_LLCCBW, 150); + } + /* * Determine whether and which event to report to ptracer. When * called from kernel_thread or CLONE_UNTRACED is explicitly diff --git a/kernel/futex.c b/kernel/futex.c index 52f641c00a65..0cfc7c165940 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -341,6 +341,12 @@ static inline bool should_fail_futex(bool fshared) } #endif /* CONFIG_FAIL_FUTEX */ +#ifdef CONFIG_COMPAT +static void compat_exit_robust_list(struct task_struct *curr); +#else +static inline void compat_exit_robust_list(struct task_struct *curr) { } +#endif + static inline void futex_get_mm(union futex_key *key) { mmgrab(key->private.mm); @@ -833,6 +839,29 @@ static struct futex_pi_state *alloc_pi_state(void) return pi_state; } +static void pi_state_update_owner(struct futex_pi_state *pi_state, + struct task_struct *new_owner) +{ + struct task_struct *old_owner = pi_state->owner; + + lockdep_assert_held(&pi_state->pi_mutex.wait_lock); + + if (old_owner) { + raw_spin_lock(&old_owner->pi_lock); + WARN_ON(list_empty(&pi_state->list)); + list_del_init(&pi_state->list); + raw_spin_unlock(&old_owner->pi_lock); + } + + if (new_owner) { + raw_spin_lock(&new_owner->pi_lock); + WARN_ON(!list_empty(&pi_state->list)); + list_add(&pi_state->list, &new_owner->pi_state_list); + pi_state->owner = new_owner; + raw_spin_unlock(&new_owner->pi_lock); + } +} + static void get_pi_state(struct futex_pi_state *pi_state) { WARN_ON_ONCE(!atomic_inc_not_zero(&pi_state->refcount)); @@ -855,17 +884,12 @@ static void put_pi_state(struct futex_pi_state *pi_state) * and has cleaned up the pi_state already */ if (pi_state->owner) { - struct task_struct *owner; + unsigned long flags; - raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); - owner = pi_state->owner; - if (owner) { - raw_spin_lock(&owner->pi_lock); - list_del_init(&pi_state->list); - raw_spin_unlock(&owner->pi_lock); - } - rt_mutex_proxy_unlock(&pi_state->pi_mutex, owner); - raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); + raw_spin_lock_irqsave(&pi_state->pi_mutex.wait_lock, flags); + pi_state_update_owner(pi_state, NULL); + rt_mutex_proxy_unlock(&pi_state->pi_mutex); + raw_spin_unlock_irqrestore(&pi_state->pi_mutex.wait_lock, flags); } if (current->pi_state_cache) { @@ -889,7 +913,7 @@ static void put_pi_state(struct futex_pi_state *pi_state) * Kernel cleans up PI-state, but userspace is likely hosed. * (Robust-futex cleanup is separate and might save the day for userspace.) */ -void exit_pi_state_list(struct task_struct *curr) +static void exit_pi_state_list(struct task_struct *curr) { struct list_head *next, *head = &curr->pi_state_list; struct futex_pi_state *pi_state; @@ -959,7 +983,8 @@ void exit_pi_state_list(struct task_struct *curr) } raw_spin_unlock_irq(&curr->pi_lock); } - +#else +static inline void exit_pi_state_list(struct task_struct *curr) { } #endif /* @@ -1174,10 +1199,11 @@ static int handle_exit_race(u32 __user *uaddr, u32 uval, u32 uval2; /* - * If PF_EXITPIDONE is not yet set, then try again. + * If the futex exit state is not yet FUTEX_STATE_DEAD, tell the + * caller that the alleged owner is busy. */ - if (tsk && !(tsk->flags & PF_EXITPIDONE)) - return -EAGAIN; + if (tsk && tsk->futex_state != FUTEX_STATE_DEAD) + return -EBUSY; /* * Reread the user space value to handle the following situation: @@ -1195,8 +1221,9 @@ static int handle_exit_race(u32 __user *uaddr, u32 uval, * *uaddr = 0xC0000000; tsk = get_task(PID); * } if (!tsk->flags & PF_EXITING) { * ... attach(); - * tsk->flags |= PF_EXITPIDONE; } else { - * if (!(tsk->flags & PF_EXITPIDONE)) + * tsk->futex_state = } else { + * FUTEX_STATE_DEAD; if (tsk->futex_state != + * FUTEX_STATE_DEAD) * return -EAGAIN; * return -ESRCH; <--- FAIL * } @@ -1252,17 +1279,16 @@ static int attach_to_pi_owner(u32 __user *uaddr, u32 uval, union futex_key *key, } /* - * We need to look at the task state flags to figure out, - * whether the task is exiting. To protect against the do_exit - * change of the task flags, we do this protected by - * p->pi_lock: + * We need to look at the task state to figure out, whether the + * task is exiting. To protect against the change of the task state + * in futex_exit_release(), we do this protected by p->pi_lock: */ raw_spin_lock_irq(&p->pi_lock); - if (unlikely(p->flags & PF_EXITING)) { + if (unlikely(p->futex_state != FUTEX_STATE_OK)) { /* - * The task is on the way out. When PF_EXITPIDONE is - * set, we know that the task has finished the - * cleanup: + * The task is on the way out. When the futex state is + * FUTEX_STATE_DEAD, we know that the task has finished + * the cleanup: */ int ret = handle_exit_race(uaddr, uval, p); @@ -1536,26 +1562,15 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_pi_state *pi_ ret = -EINVAL; } - if (ret) - goto out_unlock; - - /* - * This is a point of no return; once we modify the uval there is no - * going back and subsequent operations must not fail. - */ - - raw_spin_lock(&pi_state->owner->pi_lock); - WARN_ON(list_empty(&pi_state->list)); - list_del_init(&pi_state->list); - raw_spin_unlock(&pi_state->owner->pi_lock); - - raw_spin_lock(&new_owner->pi_lock); - WARN_ON(!list_empty(&pi_state->list)); - list_add(&pi_state->list, &new_owner->pi_state_list); - pi_state->owner = new_owner; - raw_spin_unlock(&new_owner->pi_lock); - - postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q); + if (!ret) { + /* + * This is a point of no return; once we modified the uval + * there is no going back and subsequent operations must + * not fail. + */ + pi_state_update_owner(pi_state, new_owner); + postunlock = __rt_mutex_futex_unlock(&pi_state->pi_mutex, &wake_q); + } out_unlock: raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); @@ -2086,12 +2101,13 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, if (!ret) goto retry; goto out; + case -EBUSY: case -EAGAIN: /* * Two reasons for this: - * - Owner is exiting and we just wait for the + * - EBUSY: Owner is exiting and we just wait for the * exit to complete. - * - The user space value changed. + * - EAGAIN: The user space value changed. */ double_unlock_hb(hb1, hb2); hb_waiters_dec(hb2); @@ -2361,18 +2377,13 @@ static void unqueue_me_pi(struct futex_q *q) spin_unlock(q->lock_ptr); } -static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, - struct task_struct *argowner) +static int __fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + struct task_struct *argowner) { + u32 uval, uninitialized_var(curval), newval, newtid; struct futex_pi_state *pi_state = q->pi_state; - u32 uval, uninitialized_var(curval), newval; struct task_struct *oldowner, *newowner; - u32 newtid; - int ret, err = 0; - - lockdep_assert_held(q->lock_ptr); - - raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); + int err = 0; oldowner = pi_state->owner; @@ -2406,14 +2417,12 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ - ret = 0; - goto out_unlock; + return 0; } if (__rt_mutex_futex_trylock(&pi_state->pi_mutex)) { - /* We got the lock after all, nothing to fix. */ - ret = 0; - goto out_unlock; + /* We got the lock. pi_state is correct. Tell caller. */ + return 1; } /* @@ -2440,8 +2449,7 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We raced against a concurrent self; things are * already fixed up. Nothing to do. */ - ret = 0; - goto out_unlock; + return 1; } newowner = argowner; } @@ -2471,22 +2479,9 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, * We fixed up user space. Now we need to fix the pi_state * itself. */ - if (pi_state->owner != NULL) { - raw_spin_lock(&pi_state->owner->pi_lock); - WARN_ON(list_empty(&pi_state->list)); - list_del_init(&pi_state->list); - raw_spin_unlock(&pi_state->owner->pi_lock); - } + pi_state_update_owner(pi_state, newowner); - pi_state->owner = newowner; - - raw_spin_lock(&newowner->pi_lock); - WARN_ON(!list_empty(&pi_state->list)); - list_add(&pi_state->list, &newowner->pi_state_list); - raw_spin_unlock(&newowner->pi_lock); - raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); - - return 0; + return argowner == current; /* * In order to reschedule or handle a page fault, we need to drop the @@ -2507,17 +2502,16 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, switch (err) { case -EFAULT: - ret = fault_in_user_writeable(uaddr); + err = fault_in_user_writeable(uaddr); break; case -EAGAIN: cond_resched(); - ret = 0; + err = 0; break; default: WARN_ON_ONCE(1); - ret = err; break; } @@ -2527,17 +2521,26 @@ static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, /* * Check if someone else fixed it for us: */ - if (pi_state->owner != oldowner) { - ret = 0; - goto out_unlock; - } + if (pi_state->owner != oldowner) + return argowner == current; - if (ret) - goto out_unlock; + /* Retry if err was -EAGAIN or the fault in succeeded */ + if (!err) + goto retry; - goto retry; + return err; +} -out_unlock: +static int fixup_pi_state_owner(u32 __user *uaddr, struct futex_q *q, + struct task_struct *argowner) +{ + struct futex_pi_state *pi_state = q->pi_state; + int ret; + + lockdep_assert_held(q->lock_ptr); + + raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock); + ret = __fixup_pi_state_owner(uaddr, q, argowner); raw_spin_unlock_irq(&pi_state->pi_mutex.wait_lock); return ret; } @@ -2561,8 +2564,6 @@ static long futex_wait_restart(struct restart_block *restart); */ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) { - int ret = 0; - if (locked) { /* * Got the lock. We might not be the anticipated owner if we @@ -2573,8 +2574,8 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) * stable state, anything else needs more attention. */ if (q->pi_state->owner != current) - ret = fixup_pi_state_owner(uaddr, q, current); - goto out; + return fixup_pi_state_owner(uaddr, q, current); + return 1; } /* @@ -2585,24 +2586,17 @@ static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked) * Another speculative read; pi_state->owner == current is unstable * but needs our attention. */ - if (q->pi_state->owner == current) { - ret = fixup_pi_state_owner(uaddr, q, NULL); - goto out; - } + if (q->pi_state->owner == current) + return fixup_pi_state_owner(uaddr, q, NULL); /* * Paranoia check. If we did not take the lock, then we should not be - * the owner of the rt_mutex. + * the owner of the rt_mutex. Warn and establish consistent state. */ - if (rt_mutex_owner(&q->pi_state->pi_mutex) == current) { - printk(KERN_ERR "fixup_owner: ret = %d pi-mutex: %p " - "pi-state %p\n", ret, - q->pi_state->pi_mutex.owner, - q->pi_state->owner); - } + if (WARN_ON_ONCE(rt_mutex_owner(&q->pi_state->pi_mutex) == current)) + return fixup_pi_state_owner(uaddr, q, current); -out: - return ret ? ret : locked; + return 0; } /** @@ -2776,14 +2770,13 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val, goto out; restart = ¤t->restart_block; - restart->fn = futex_wait_restart; restart->futex.uaddr = uaddr; restart->futex.val = val; restart->futex.time = *abs_time; restart->futex.bitset = bitset; restart->futex.flags = flags | FLAGS_HAS_TIMEOUT; - ret = -ERESTART_RESTARTBLOCK; + ret = set_restart_fn(restart, futex_wait_restart); out: if (to) { @@ -2864,12 +2857,13 @@ static int futex_lock_pi(u32 __user *uaddr, unsigned int flags, goto out_unlock_put_key; case -EFAULT: goto uaddr_faulted; + case -EBUSY: case -EAGAIN: /* * Two reasons for this: - * - Task is exiting and we just wait for the + * - EBUSY: Task is exiting and we just wait for the * exit to complete. - * - The user space value changed. + * - EAGAIN: The user space value changed. */ queue_unlock(hb); put_futex_key(&q.key); @@ -3324,7 +3318,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, if (q.pi_state && (q.pi_state->owner != current)) { spin_lock(q.lock_ptr); ret = fixup_pi_state_owner(uaddr2, &q, current); - if (ret && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { + if (ret < 0 && rt_mutex_owner(&q.pi_state->pi_mutex) == current) { pi_state = q.pi_state; get_pi_state(pi_state); } @@ -3334,6 +3328,11 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, */ put_pi_state(q.pi_state); spin_unlock(q.lock_ptr); + /* + * Adjust the return value. It's either -EFAULT or + * success (1) but the caller expects 0 for success. + */ + ret = ret < 0 ? ret : 0; } } else { struct rt_mutex *pi_mutex; @@ -3624,7 +3623,7 @@ static inline int fetch_robust_entry(struct robust_list __user **entry, * * We silently return on any sign of list-walking problem. */ -void exit_robust_list(struct task_struct *curr) +static void exit_robust_list(struct task_struct *curr) { struct robust_list_head __user *head = curr->robust_list; struct robust_list __user *entry, *next_entry, *pending; @@ -3689,6 +3688,30 @@ void exit_robust_list(struct task_struct *curr) } } +void futex_exec_release(struct task_struct *tsk) +{ + if (unlikely(tsk->robust_list)) { + exit_robust_list(tsk); + tsk->robust_list = NULL; + } + +#ifdef CONFIG_COMPAT + if (unlikely(tsk->compat_robust_list)) { + compat_exit_robust_list(tsk); + tsk->compat_robust_list = NULL; + } +#endif + + if (unlikely(!list_empty(&tsk->pi_state_list))) + exit_pi_state_list(tsk); +} + +void futex_exit_release(struct task_struct *tsk) +{ + futex_exec_release(tsk); + futex_exit_done(tsk); +} + long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, u32 __user *uaddr2, u32 val2, u32 val3) { @@ -3816,7 +3839,7 @@ static void __user *futex_uaddr(struct robust_list __user *entry, * * We silently return on any sign of list-walking problem. */ -void compat_exit_robust_list(struct task_struct *curr) +static void compat_exit_robust_list(struct task_struct *curr) { struct compat_robust_list_head __user *head = curr->compat_robust_list; struct robust_list __user *entry, *next_entry, *pending; diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig index 5f3e2baefca9..d532bf0c5a67 100644 --- a/kernel/irq/Kconfig +++ b/kernel/irq/Kconfig @@ -80,6 +80,7 @@ config IRQ_FASTEOI_HIERARCHY_HANDLERS # Generic IRQ IPI support config GENERIC_IRQ_IPI bool + select IRQ_DOMAIN_HIERARCHY # Generic MSI interrupt support config GENERIC_MSI_IRQ diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index 698c81ef961c..d2203f09e8f6 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -267,7 +267,10 @@ int irq_startup(struct irq_desc *desc, bool resend, bool force) switch (__irq_startup_managed(desc, aff, force)) { case IRQ_STARTUP_NORMAL: ret = __irq_startup(desc); - irq_setup_affinity(desc); + if (irqd_has_set(&desc->irq_data, IRQD_PERF_CRITICAL)) + setup_perf_irq_locked(desc, desc->action->flags); + else + irq_setup_affinity(desc); break; case IRQ_STARTUP_MANAGED: irq_do_set_affinity(d, aff, false); diff --git a/kernel/irq/cpuhotplug.c b/kernel/irq/cpuhotplug.c index b19a65999bb3..96316ccdac53 100644 --- a/kernel/irq/cpuhotplug.c +++ b/kernel/irq/cpuhotplug.c @@ -70,6 +70,9 @@ static bool migrate_one_irq(struct irq_desc *desc) return false; } + if (irqd_has_set(d, IRQD_PERF_CRITICAL)) + return false; + /* * No move required, if: * - Interrupt is per cpu @@ -200,10 +203,13 @@ void irq_migrate_all_off_this_cpu(void) raw_spin_unlock(&desc->lock); if (affinity_broken) { - pr_info_ratelimited("IRQ %u: no longer affine to CPU%u\n", + pr_debug_ratelimited("IRQ %u: no longer affine to CPU%u\n", irq, smp_processor_id()); } } + + if (!cpumask_test_cpu(smp_processor_id(), cpu_lp_mask)) + reaffine_perf_irqs(true); } static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu) @@ -211,6 +217,9 @@ static void irq_restore_affinity_of_irq(struct irq_desc *desc, unsigned int cpu) struct irq_data *data = irq_desc_get_irq_data(desc); const struct cpumask *affinity = irq_data_get_affinity_mask(data); + if (irqd_has_set(data, IRQD_PERF_CRITICAL)) + return; + if (!irqd_affinity_is_managed(data) || !desc->action || !irq_data_get_irq_chip(data) || !cpumask_test_cpu(cpu, affinity)) return; @@ -247,5 +256,8 @@ int irq_affinity_online_cpu(unsigned int cpu) } irq_unlock_sparse(); + if (!cpumask_test_cpu(cpu, cpu_lp_mask)) + reaffine_perf_irqs(true); + return 0; } diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index 3f4618510d05..a766af7a080a 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -133,6 +133,7 @@ extern int irq_do_set_affinity(struct irq_data *data, #ifdef CONFIG_SMP extern int irq_setup_affinity(struct irq_desc *desc); +extern void setup_perf_irq_locked(struct irq_desc *desc, unsigned int perf_flag); #else static inline int irq_setup_affinity(struct irq_desc *desc) { return 0; } #endif diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 26814a14013c..7b572905d552 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -43,7 +43,7 @@ static void __init init_irq_default_affinity(void) if (!cpumask_available(irq_default_affinity)) zalloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT); if (cpumask_empty(irq_default_affinity)) - cpumask_setall(irq_default_affinity); + cpumask_set_cpu(0, irq_default_affinity); } #else static void __init init_irq_default_affinity(void) diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 585aa59f06f2..e3ac5a5a4887 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -1249,8 +1249,15 @@ static void irq_domain_free_irqs_hierarchy(struct irq_domain *domain, unsigned int irq_base, unsigned int nr_irqs) { - if (domain->ops->free) - domain->ops->free(domain, irq_base, nr_irqs); + unsigned int i; + + if (!domain->ops->free) + return; + + for (i = 0; i < nr_irqs; i++) { + if (irq_domain_get_irq_data(domain, irq_base + i)) + domain->ops->free(domain, irq_base + i, 1); + } } int irq_domain_alloc_irqs_hierarchy(struct irq_domain *domain, diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 39d858364333..a768e5addb61 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -20,9 +20,22 @@ #include #include #include +#include #include "internals.h" +struct irq_desc_list { + struct list_head list; + struct irq_desc *desc; + unsigned int perf_flag; +}; + +static LIST_HEAD(perf_crit_irqs); +static DEFINE_RAW_SPINLOCK(perf_irqs_lock); +static int perf_cpu_index = -1; +static int prime_cpu_index = -1; +static bool perf_crit_suspended; + #ifdef CONFIG_IRQ_FORCED_THREADING __read_mostly bool force_irqthreads; EXPORT_SYMBOL_GPL(force_irqthreads); @@ -173,7 +186,8 @@ bool irq_can_set_affinity_usr(unsigned int irq) struct irq_desc *desc = irq_to_desc(irq); return __irq_can_set_affinity(desc) && - !irqd_affinity_is_managed(&desc->irq_data); + !irqd_affinity_is_managed(&desc->irq_data) && + !irqd_has_set(&desc->irq_data, IRQD_PERF_CRITICAL); } /** @@ -227,6 +241,8 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, if (!chip || !chip->irq_set_affinity) return -EINVAL; + /* IRQs only run on the first CPU in the affinity mask; reflect that */ + mask = cpumask_of(cpumask_first(mask)); ret = chip->irq_set_affinity(data, mask, force); switch (ret) { case IRQ_SET_MASK_OK: @@ -988,11 +1004,15 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) irqreturn_t ret; local_bh_disable(); + if (!IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) + local_irq_disable(); ret = action->thread_fn(action->irq, action->dev_id); if (ret == IRQ_HANDLED) atomic_inc(&desc->threads_handled); irq_finalize_oneshot(desc, action); + if (!IS_ENABLED(CONFIG_PREEMPT_RT_BASE)) + local_irq_enable(); local_bh_enable(); return ret; } @@ -1229,6 +1249,144 @@ setup_irq_thread(struct irqaction *new, unsigned int irq, bool secondary) return 0; } +static void add_desc_to_perf_list(struct irq_desc *desc, unsigned int perf_flag) +{ + struct irq_desc_list *item; + + item = kmalloc(sizeof(*item), GFP_ATOMIC | __GFP_NOFAIL); + item->desc = desc; + item->perf_flag = perf_flag; + + raw_spin_lock(&perf_irqs_lock); + list_add(&item->list, &perf_crit_irqs); + raw_spin_unlock(&perf_irqs_lock); +} + +static void affine_one_perf_thread(struct irqaction *action) +{ + const struct cpumask *mask; + + if (!action->thread) + return; + + if (action->flags & IRQF_PERF_AFFINE) + mask = cpu_perf_mask; + else + mask = cpu_prime_mask; + + action->thread->flags |= PF_PERF_CRITICAL; + set_cpus_allowed_ptr(action->thread, mask); +} + +static void unaffine_one_perf_thread(struct irqaction *action) +{ + if (!action->thread) + return; + + action->thread->flags &= ~PF_PERF_CRITICAL; + set_cpus_allowed_ptr(action->thread, cpu_all_mask); +} + +static void affine_one_perf_irq(struct irq_desc *desc, unsigned int perf_flag) +{ + const struct cpumask *mask; + int *mask_index; + int cpu; + + if (perf_flag & IRQF_PERF_AFFINE) { + mask = cpu_perf_mask; + mask_index = &perf_cpu_index; + } else { + mask = cpu_prime_mask; + mask_index = &prime_cpu_index; + } + + if (!cpumask_intersects(mask, cpu_online_mask)) { + WARN(1, "requested perf CPU is offline for %s\n", desc->name); + irq_set_affinity_locked(&desc->irq_data, cpu_online_mask, true); + return; + } + + /* Balance the performance-critical IRQs across the given CPUs */ + while (1) { + cpu = cpumask_next_and(*mask_index, mask, cpu_online_mask); + if (cpu < nr_cpu_ids) + break; + *mask_index = -1; + } + irq_set_affinity_locked(&desc->irq_data, cpumask_of(cpu), true); + + *mask_index = cpu; +} + +void setup_perf_irq_locked(struct irq_desc *desc, unsigned int perf_flag) +{ + add_desc_to_perf_list(desc, perf_flag); + raw_spin_lock(&perf_irqs_lock); + affine_one_perf_irq(desc, perf_flag); + raw_spin_unlock(&perf_irqs_lock); +} + +void irq_set_perf_affinity(unsigned int irq, unsigned int perf_flag) +{ + struct irq_desc *desc = irq_to_desc(irq); + unsigned long flags; + + if (!desc) + return; + + raw_spin_lock_irqsave(&desc->lock, flags); + if (desc->action) { + desc->action->flags |= perf_flag; + irqd_set(&desc->irq_data, IRQD_PERF_CRITICAL); + setup_perf_irq_locked(desc, perf_flag); + } else { + WARN(1, "perf affine: action not set for IRQ%d\n", irq); + } + raw_spin_unlock_irqrestore(&desc->lock, flags); +} + +void unaffine_perf_irqs(void) +{ + struct irq_desc_list *data; + unsigned long flags; + + raw_spin_lock_irqsave(&perf_irqs_lock, flags); + perf_crit_suspended = true; + list_for_each_entry(data, &perf_crit_irqs, list) { + struct irq_desc *desc = data->desc; + + raw_spin_lock(&desc->lock); + irq_set_affinity_locked(&desc->irq_data, cpu_all_mask, true); + unaffine_one_perf_thread(desc->action); + raw_spin_unlock(&desc->lock); + } + raw_spin_unlock_irqrestore(&perf_irqs_lock, flags); +} + +void reaffine_perf_irqs(bool from_hotplug) +{ + struct irq_desc_list *data; + unsigned long flags; + + raw_spin_lock_irqsave(&perf_irqs_lock, flags); + /* Don't allow hotplug to reaffine IRQs when resuming from suspend */ + if (!from_hotplug || !perf_crit_suspended) { + perf_crit_suspended = false; + perf_cpu_index = -1; + prime_cpu_index = -1; + list_for_each_entry(data, &perf_crit_irqs, list) { + struct irq_desc *desc = data->desc; + + raw_spin_lock(&desc->lock); + affine_one_perf_irq(desc, data->perf_flag); + affine_one_perf_thread(desc->action); + raw_spin_unlock(&desc->lock); + } + } + raw_spin_unlock_irqrestore(&perf_irqs_lock, flags); +} + /* * Internal function to register an irqaction - typically used to * allocate special interrupts that are part of the architecture. @@ -1503,6 +1661,12 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) irqd_set(&desc->irq_data, IRQD_NO_BALANCING); } + if (new->flags & (IRQF_PERF_AFFINE | IRQF_PRIME_AFFINE)) { + affine_one_perf_thread(new); + irqd_set(&desc->irq_data, IRQD_PERF_CRITICAL); + *old_ptr = new; + } + if (irq_settings_can_autoenable(desc)) { irq_startup(desc, IRQ_RESEND, IRQ_START_COND); } else { @@ -1527,7 +1691,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) irq, omsk, nmsk); } - *old_ptr = new; + if (!irqd_has_set(&desc->irq_data, IRQD_PERF_CRITICAL)) + *old_ptr = new; irq_pm_install_action(desc, new); @@ -1668,6 +1833,20 @@ static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id) action_ptr = &action->next; } + if (irqd_has_set(&desc->irq_data, IRQD_PERF_CRITICAL)) { + struct irq_desc_list *data; + + raw_spin_lock(&perf_irqs_lock); + list_for_each_entry(data, &perf_crit_irqs, list) { + if (data->desc == desc) { + list_del(&data->list); + kfree(data); + break; + } + } + raw_spin_unlock(&perf_irqs_lock); + } + /* Found it - now remove it from the list of entries: */ *action_ptr = action->next; diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index dc1186ce3ecd..604974f2afb1 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -437,22 +437,22 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, can_reserve = msi_check_reservation_mode(domain, info, dev); - for_each_msi_entry(desc, dev) { - virq = desc->irq; - if (desc->nvec_used == 1) - dev_dbg(dev, "irq %d for MSI\n", virq); - else + /* + * This flag is set by the PCI layer as we need to activate + * the MSI entries before the PCI layer enables MSI in the + * card. Otherwise the card latches a random msi message. + */ + if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY)) + goto skip_activate; + + for_each_msi_vector(desc, i, dev) { + if (desc->irq == i) { + virq = desc->irq; dev_dbg(dev, "irq [%d-%d] for MSI\n", virq, virq + desc->nvec_used - 1); - /* - * This flag is set by the PCI layer as we need to activate - * the MSI entries before the PCI layer enables MSI in the - * card. Otherwise the card latches a random msi message. - */ - if (!(info->flags & MSI_FLAG_ACTIVATE_EARLY)) - continue; + } - irq_data = irq_domain_get_irq_data(domain, desc->irq); + irq_data = irq_domain_get_irq_data(domain, i); if (!can_reserve) { irqd_clr_can_reserve(irq_data); if (domain->flags & IRQ_DOMAIN_MSI_NOMASK_QUIRK) @@ -463,28 +463,24 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, goto cleanup; } +skip_activate: /* * If these interrupts use reservation mode, clear the activated bit * so request_irq() will assign the final vector. */ if (can_reserve) { - for_each_msi_entry(desc, dev) { - irq_data = irq_domain_get_irq_data(domain, desc->irq); + for_each_msi_vector(desc, i, dev) { + irq_data = irq_domain_get_irq_data(domain, i); irqd_clr_activated(irq_data); } } return 0; cleanup: - for_each_msi_entry(desc, dev) { - struct irq_data *irqd; - - if (desc->irq == virq) - break; - - irqd = irq_domain_get_irq_data(domain, desc->irq); - if (irqd_is_activated(irqd)) - irq_domain_deactivate_irq(irqd); + for_each_msi_vector(desc, i, dev) { + irq_data = irq_domain_get_irq_data(domain, i); + if (irqd_is_activated(irq_data)) + irq_domain_deactivate_irq(irq_data); } msi_domain_free_irqs(domain, dev); return ret; diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index d867d6ddafdd..2d067f2e7b57 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -426,7 +426,7 @@ void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret) desc->irqs_unhandled = 0; } -bool noirqdebug __read_mostly; +bool noirqdebug __read_mostly = true; int noirqdebug_setup(char *str) { diff --git a/kernel/jump_label.c b/kernel/jump_label.c index 7c8262635b29..73bbbaddbd9c 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -36,23 +36,43 @@ static int jump_label_cmp(const void *a, const void *b) const struct jump_entry *jea = a; const struct jump_entry *jeb = b; - if (jea->key < jeb->key) + if (jump_entry_key(jea) < jump_entry_key(jeb)) return -1; - if (jea->key > jeb->key) + if (jump_entry_key(jea) > jump_entry_key(jeb)) return 1; return 0; } +static void jump_label_swap(void *a, void *b, int size) +{ + long delta = (unsigned long)a - (unsigned long)b; + struct jump_entry *jea = a; + struct jump_entry *jeb = b; + struct jump_entry tmp = *jea; + + jea->code = jeb->code - delta; + jea->target = jeb->target - delta; + jea->key = jeb->key - delta; + + jeb->code = tmp.code + delta; + jeb->target = tmp.target + delta; + jeb->key = tmp.key + delta; +} + static void jump_label_sort_entries(struct jump_entry *start, struct jump_entry *stop) { unsigned long size; + void *swapfn = NULL; + + if (IS_ENABLED(CONFIG_HAVE_ARCH_JUMP_LABEL_RELATIVE)) + swapfn = jump_label_swap; size = (((unsigned long)stop - (unsigned long)start) / sizeof(struct jump_entry)); - sort(start, size, sizeof(struct jump_entry), jump_label_cmp, NULL); + sort(start, size, sizeof(struct jump_entry), jump_label_cmp, swapfn); } static void jump_label_update(struct static_key *key); @@ -83,6 +103,7 @@ void static_key_slow_inc_cpuslocked(struct static_key *key) int v, v1; STATIC_KEY_CHECK_USE(key); + lockdep_assert_cpus_held(); /* * Careful if we get concurrent static_key_slow_inc() calls; @@ -128,6 +149,7 @@ EXPORT_SYMBOL_GPL(static_key_slow_inc); void static_key_enable_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(key); + lockdep_assert_cpus_held(); if (atomic_read(&key->enabled) > 0) { WARN_ON_ONCE(atomic_read(&key->enabled) != 1); @@ -158,6 +180,7 @@ EXPORT_SYMBOL_GPL(static_key_enable); void static_key_disable_cpuslocked(struct static_key *key) { STATIC_KEY_CHECK_USE(key); + lockdep_assert_cpus_held(); if (atomic_read(&key->enabled) != 1) { WARN_ON_ONCE(atomic_read(&key->enabled) != 0); @@ -183,6 +206,10 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key, unsigned long rate_limit, struct delayed_work *work) { + int val; + + lockdep_assert_cpus_held(); + /* * The negative count check is valid even when a negative * key->enabled is in use by static_key_slow_inc(); a @@ -190,17 +217,20 @@ static void __static_key_slow_dec_cpuslocked(struct static_key *key, * returns is unbalanced, because all other static_key_slow_inc() * instances block while the update is in progress. */ - if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) { - WARN(atomic_read(&key->enabled) < 0, - "jump label: negative count!\n"); + val = atomic_fetch_add_unless(&key->enabled, -1, 1); + if (val != 1) { + WARN(val < 0, "jump label: negative count!\n"); return; } - if (rate_limit) { - atomic_inc(&key->enabled); - schedule_delayed_work(work, rate_limit); - } else { - jump_label_update(key); + jump_label_lock(); + if (atomic_dec_and_test(&key->enabled)) { + if (rate_limit) { + atomic_inc(&key->enabled); + schedule_delayed_work(work, rate_limit); + } else { + jump_label_update(key); + } } jump_label_unlock(); } @@ -214,12 +244,13 @@ static void __static_key_slow_dec(struct static_key *key, cpus_read_unlock(); } -static void jump_label_update_timeout(struct work_struct *work) +void jump_label_update_timeout(struct work_struct *work) { struct static_key_deferred *key = container_of(work, struct static_key_deferred, work.work); __static_key_slow_dec(&key->key, 0, NULL); } +EXPORT_SYMBOL_GPL(jump_label_update_timeout); void static_key_slow_dec(struct static_key *key) { @@ -234,19 +265,21 @@ void static_key_slow_dec_cpuslocked(struct static_key *key) __static_key_slow_dec_cpuslocked(key, 0, NULL); } -void static_key_slow_dec_deferred(struct static_key_deferred *key) +void __static_key_slow_dec_deferred(struct static_key *key, + struct delayed_work *work, + unsigned long timeout) { STATIC_KEY_CHECK_USE(key); - __static_key_slow_dec(&key->key, key->timeout, &key->work); + __static_key_slow_dec(key, timeout, work); } -EXPORT_SYMBOL_GPL(static_key_slow_dec_deferred); +EXPORT_SYMBOL_GPL(__static_key_slow_dec_deferred); -void static_key_deferred_flush(struct static_key_deferred *key) +void __static_key_deferred_flush(void *key, struct delayed_work *work) { STATIC_KEY_CHECK_USE(key); - flush_delayed_work(&key->work); + flush_delayed_work(work); } -EXPORT_SYMBOL_GPL(static_key_deferred_flush); +EXPORT_SYMBOL_GPL(__static_key_deferred_flush); void jump_label_rate_limit(struct static_key_deferred *key, unsigned long rl) @@ -259,8 +292,8 @@ EXPORT_SYMBOL_GPL(jump_label_rate_limit); static int addr_conflict(struct jump_entry *entry, void *start, void *end) { - if (entry->code <= (unsigned long)end && - entry->code + JUMP_LABEL_NOP_SIZE > (unsigned long)start) + if (jump_entry_code(entry) <= (unsigned long)end && + jump_entry_code(entry) + JUMP_LABEL_NOP_SIZE > (unsigned long)start) return 1; return 0; @@ -319,16 +352,6 @@ static inline void static_key_set_linked(struct static_key *key) key->type |= JUMP_TYPE_LINKED; } -static inline struct static_key *jump_entry_key(struct jump_entry *entry) -{ - return (struct static_key *)((unsigned long)entry->key & ~1UL); -} - -static bool jump_entry_branch(struct jump_entry *entry) -{ - return (unsigned long)entry->key & 1UL; -} - /*** * A 'struct static_key' uses a union such that it either points directly * to a table of 'struct jump_entry' or to a linked list of modules which in @@ -353,7 +376,7 @@ static enum jump_label_type jump_label_type(struct jump_entry *entry) { struct static_key *key = jump_entry_key(entry); bool enabled = static_key_enabled(key); - bool branch = jump_entry_branch(entry); + bool branch = jump_entry_is_branch(entry); /* See the comment in linux/jump_label.h */ return enabled ^ branch; @@ -361,19 +384,20 @@ static enum jump_label_type jump_label_type(struct jump_entry *entry) static void __jump_label_update(struct static_key *key, struct jump_entry *entry, - struct jump_entry *stop) + struct jump_entry *stop, + bool init) { for (; (entry < stop) && (jump_entry_key(entry) == key); entry++) { /* * An entry->code of 0 indicates an entry which has been * disabled because it was in an init text area. */ - if (entry->code) { - if (kernel_text_address(entry->code)) + if (init || !jump_entry_is_init(entry)) { + if (kernel_text_address(jump_entry_code(entry))) arch_jump_label_transform(entry, jump_label_type(entry)); else WARN_ONCE(1, "can't patch jump_label at %pS", - (void *)(unsigned long)entry->code); + (void *)jump_entry_code(entry)); } } } @@ -408,6 +432,9 @@ void __init jump_label_init(void) if (jump_label_type(iter) == JUMP_LABEL_NOP) arch_jump_label_transform_static(iter, JUMP_LABEL_NOP); + if (init_section_contains((void *)jump_entry_code(iter), 1)) + jump_entry_set_init(iter); + iterk = jump_entry_key(iter); if (iterk == key) continue; @@ -420,26 +447,13 @@ void __init jump_label_init(void) cpus_read_unlock(); } -/* Disable any jump label entries in __init/__exit code */ -void __init jump_label_invalidate_initmem(void) -{ - struct jump_entry *iter_start = __start___jump_table; - struct jump_entry *iter_stop = __stop___jump_table; - struct jump_entry *iter; - - for (iter = iter_start; iter < iter_stop; iter++) { - if (init_section_contains((void *)(unsigned long)iter->code, 1)) - iter->code = 0; - } -} - #ifdef CONFIG_MODULES static enum jump_label_type jump_label_init_type(struct jump_entry *entry) { struct static_key *key = jump_entry_key(entry); bool type = static_key_type(key); - bool branch = jump_entry_branch(entry); + bool branch = jump_entry_is_branch(entry); /* See the comment in linux/jump_label.h */ return type ^ branch; @@ -453,7 +467,7 @@ struct static_key_mod { static inline struct static_key_mod *static_key_mod(struct static_key *key) { - WARN_ON_ONCE(!(key->type & JUMP_TYPE_LINKED)); + WARN_ON_ONCE(!static_key_linked(key)); return (struct static_key_mod *)(key->type & ~JUMP_TYPE_MASK); } @@ -512,7 +526,8 @@ static void __jump_label_mod_update(struct static_key *key) stop = __stop___jump_table; else stop = m->jump_entries + m->num_jump_entries; - __jump_label_update(key, mod->entries, stop); + __jump_label_update(key, mod->entries, stop, + m && m->state == MODULE_STATE_COMING); } } @@ -558,12 +573,15 @@ static int jump_label_add_module(struct module *mod) for (iter = iter_start; iter < iter_stop; iter++) { struct static_key *iterk; + if (within_module_init(jump_entry_code(iter), mod)) + jump_entry_set_init(iter); + iterk = jump_entry_key(iter); if (iterk == key) continue; key = iterk; - if (within_module(iter->key, mod)) { + if (within_module((unsigned long)key, mod)) { static_key_set_entries(key, iter); continue; } @@ -593,7 +611,7 @@ static int jump_label_add_module(struct module *mod) /* Only update if we've changed from our initial state */ if (jump_label_type(iter) != jump_label_init_type(iter)) - __jump_label_update(key, iter, iter_stop); + __jump_label_update(key, iter, iter_stop, true); } return 0; @@ -613,7 +631,7 @@ static void jump_label_del_module(struct module *mod) key = jump_entry_key(iter); - if (within_module(iter->key, mod)) + if (within_module((unsigned long)key, mod)) continue; /* No memory during module load */ @@ -649,19 +667,6 @@ static void jump_label_del_module(struct module *mod) } } -/* Disable any jump label entries in module init code */ -static void jump_label_invalidate_module_init(struct module *mod) -{ - struct jump_entry *iter_start = mod->jump_entries; - struct jump_entry *iter_stop = iter_start + mod->num_jump_entries; - struct jump_entry *iter; - - for (iter = iter_start; iter < iter_stop; iter++) { - if (within_module_init(iter->code, mod)) - iter->code = 0; - } -} - static int jump_label_module_notify(struct notifier_block *self, unsigned long val, void *data) @@ -683,9 +688,6 @@ jump_label_module_notify(struct notifier_block *self, unsigned long val, case MODULE_STATE_GOING: jump_label_del_module(mod); break; - case MODULE_STATE_LIVE: - jump_label_invalidate_module_init(mod); - break; } jump_label_unlock(); @@ -755,7 +757,8 @@ static void jump_label_update(struct static_key *key) entry = static_key_entries(key); /* if there are no users, entry can be NULL */ if (entry) - __jump_label_update(key, entry, stop); + __jump_label_update(key, entry, stop, + system_state < SYSTEM_RUNNING); } #ifdef CONFIG_STATIC_KEYS_SELFTEST diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c index faeec8255e7e..9ed714a5a5af 100644 --- a/kernel/kexec_core.c +++ b/kernel/kexec_core.c @@ -217,13 +217,13 @@ int sanity_check_segment_list(struct kimage *image) * wasted allocating pages, which can cause a soft lockup. */ for (i = 0; i < nr_segments; i++) { - if (PAGE_COUNT(image->segment[i].memsz) > totalram_pages / 2) + if (PAGE_COUNT(image->segment[i].memsz) > totalram_pages() / 2) return -EINVAL; total_pages += PAGE_COUNT(image->segment[i].memsz); } - if (total_pages > totalram_pages / 2) + if (total_pages > totalram_pages() / 2) return -EINVAL; /* @@ -1130,7 +1130,6 @@ int kernel_kexec(void) #ifdef CONFIG_KEXEC_JUMP if (kexec_image->preserve_context) { - lock_system_sleep(); pm_prepare_console(); error = freeze_processes(); if (error) { @@ -1193,7 +1192,6 @@ int kernel_kexec(void) thaw_processes(); Restore_console: pm_restore_console(); - unlock_system_sleep(); } #endif diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index c6a3b6851372..2fbdb78d66c8 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -168,6 +168,11 @@ void kimage_file_post_load_cleanup(struct kimage *image) vfree(pi->sechdrs); pi->sechdrs = NULL; +#ifdef CONFIG_IMA_KEXEC + vfree(image->ima_buffer); + image->ima_buffer = NULL; +#endif /* CONFIG_IMA_KEXEC */ + /* See if architecture has anything to cleanup post load */ arch_kimage_file_post_load_cleanup(image); diff --git a/kernel/kmod.c b/kernel/kmod.c index a2de58de6ab6..130d564af308 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -31,7 +31,7 @@ /* * Assuming: * - * threads = div64_u64((u64) totalram_pages * (u64) PAGE_SIZE, + * threads = div64_u64((u64) totalram_pages() * (u64) PAGE_SIZE, * (u64) THREAD_SIZE * 8UL); * * If you need less than 50 threads would mean we're dealing with systems diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 2161f519d481..d4435fd6fc8b 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1921,28 +1921,48 @@ bool __weak arch_kprobe_on_func_entry(unsigned long offset) return !offset; } -bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) +/** + * kprobe_on_func_entry() -- check whether given address is function entry + * @addr: Target address + * @sym: Target symbol name + * @offset: The offset from the symbol or the address + * + * This checks whether the given @addr+@offset or @sym+@offset is on the + * function entry address or not. + * This returns 0 if it is the function entry, or -EINVAL if it is not. + * And also it returns -ENOENT if it fails the symbol or address lookup. + * Caller must pass @addr or @sym (either one must be NULL), or this + * returns -EINVAL. + */ +int kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) { kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset); if (IS_ERR(kp_addr)) - return false; + return PTR_ERR(kp_addr); - if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) || - !arch_kprobe_on_func_entry(offset)) - return false; + if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset)) + return -ENOENT; - return true; + if (!arch_kprobe_on_func_entry(offset)) + return -EINVAL; + + return 0; } int register_kretprobe(struct kretprobe *rp) { - int ret = 0; + int ret; struct kretprobe_instance *inst; int i; void *addr; - if (!kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset)) + ret = kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset); + if (ret) + return ret; + + /* If only rp->kp.addr is specified, check reregistering kprobes */ + if (rp->kp.addr && check_kprobe_rereg(&rp->kp)) return -EINVAL; if (kretprobe_blacklist_size) { diff --git a/kernel/kthread.c b/kernel/kthread.c index b7e2254e99a6..e709aa3e1f4e 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -302,18 +302,15 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), { DECLARE_COMPLETION_ONSTACK(done); struct task_struct *task; - struct kthread_create_info *create = kmalloc(sizeof(*create), - GFP_KERNEL); + struct kthread_create_info create; - if (!create) - return ERR_PTR(-ENOMEM); - create->threadfn = threadfn; - create->data = data; - create->node = node; - create->done = &done; + create.threadfn = threadfn; + create.data = data; + create.node = node; + create.done = &done; spin_lock(&kthread_create_lock); - list_add_tail(&create->list, &kthread_create_list); + list_add_tail(&create.list, &kthread_create_list); spin_unlock(&kthread_create_lock); wake_up_process(kthreadd_task); @@ -328,7 +325,7 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), * calls complete(), leave the cleanup of this structure to * that thread. */ - if (xchg(&create->done, NULL)) + if (xchg(&create.done, NULL)) return ERR_PTR(-EINTR); /* * kthreadd (or new kernel thread) will call complete() @@ -336,7 +333,7 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), */ wait_for_completion(&done); } - task = create->result; + task = create.result; if (!IS_ERR(task)) { static const struct sched_param param = { .sched_priority = 0 }; char name[TASK_COMM_LEN]; @@ -354,7 +351,6 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), sched_setscheduler_nocheck(task, SCHED_NORMAL, ¶m); set_cpus_allowed_ptr(task, cpu_all_mask); } - kfree(create); return task; } @@ -461,11 +457,36 @@ struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), return p; kthread_bind(p, cpu); /* CPU hotplug need to bind once again when unparking the thread. */ - set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags); to_kthread(p)->cpu = cpu; return p; } +void kthread_set_per_cpu(struct task_struct *k, int cpu) +{ + struct kthread *kthread = to_kthread(k); + if (!kthread) + return; + + WARN_ON_ONCE(!(k->flags & PF_NO_SETAFFINITY)); + + if (cpu < 0) { + clear_bit(KTHREAD_IS_PER_CPU, &kthread->flags); + return; + } + + kthread->cpu = cpu; + set_bit(KTHREAD_IS_PER_CPU, &kthread->flags); +} + +bool kthread_is_per_cpu(struct task_struct *k) +{ + struct kthread *kthread = to_kthread(k); + if (!kthread) + return false; + + return test_bit(KTHREAD_IS_PER_CPU, &kthread->flags); +} + /** * kthread_unpark - unpark a thread created by kthread_create(). * @k: thread created by kthread_create(). diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c index 202ef0d29fb6..eb54fc67f9cf 100644 --- a/kernel/locking/mutex.c +++ b/kernel/locking/mutex.c @@ -28,7 +28,6 @@ #include #include #include -#include #ifdef CONFIG_DEBUG_MUTEXES # include "mutex-debug.h" @@ -526,21 +525,31 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner, { bool ret = true; - rcu_read_lock(); - while (__mutex_owner(lock) == owner) { + for (;;) { + unsigned int cpu; + bool same_owner; + /* - * Ensure we emit the owner->on_cpu, dereference _after_ - * checking lock->owner still matches owner. If that fails, + * Ensure lock->owner still matches owner. If that fails, * owner might point to freed memory. If it still matches, * the rcu_read_lock() ensures the memory stays valid. */ - barrier(); + rcu_read_lock(); + same_owner = __mutex_owner(lock) == owner; + if (same_owner) { + ret = owner->on_cpu; + if (ret) + cpu = task_cpu(owner); + } + rcu_read_unlock(); + + if (!ret || !same_owner) + break; /* * Use vcpu_is_preempted to detect lock holder preemption issue. */ - if (!owner->on_cpu || need_resched() || - vcpu_is_preempted(task_cpu(owner))) { + if (need_resched() || vcpu_is_preempted(cpu)) { ret = false; break; } @@ -552,7 +561,6 @@ bool mutex_spin_on_owner(struct mutex *lock, struct task_struct *owner, cpu_relax(); } - rcu_read_unlock(); return ret; } @@ -610,7 +618,7 @@ static inline int mutex_can_spin_on_owner(struct mutex *lock) */ static __always_inline bool mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx, - const bool use_ww_ctx, struct mutex_waiter *waiter) + struct mutex_waiter *waiter) { if (!waiter) { /* @@ -654,17 +662,6 @@ mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx, * values at the cost of a few extra spins. */ cpu_relax(); - - /* - * On arm systems, we must slow down the waiter's repeated - * aquisition of spin_mlock and atomics on the lock count, or - * we risk starving out a thread attempting to release the - * mutex. The mutex slowpath release must take spin lock - * wait_lock. This spin lock can share a monitor with the - * other waiter atomics in the mutex data structure, so must - * take care to rate limit the waiters. - */ - udelay(1); } if (!waiter) @@ -697,7 +694,7 @@ mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx, #else static __always_inline bool mutex_optimistic_spin(struct mutex *lock, struct ww_acquire_ctx *ww_ctx, - const bool use_ww_ctx, struct mutex_waiter *waiter) + struct mutex_waiter *waiter) { return false; } @@ -917,10 +914,13 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, struct ww_mutex *ww; int ret; + if (!use_ww_ctx) + ww_ctx = NULL; + might_sleep(); ww = container_of(lock, struct ww_mutex, base); - if (use_ww_ctx && ww_ctx) { + if (ww_ctx) { if (unlikely(ww_ctx == READ_ONCE(ww->ctx))) return -EALREADY; @@ -937,10 +937,10 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip); if (__mutex_trylock(lock) || - mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, NULL)) { + mutex_optimistic_spin(lock, ww_ctx, NULL)) { /* got the lock, yay! */ lock_acquired(&lock->dep_map, ip); - if (use_ww_ctx && ww_ctx) + if (ww_ctx) ww_mutex_set_context_fastpath(ww, ww_ctx); preempt_enable(); return 0; @@ -951,7 +951,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, * After waiting to acquire the wait_lock, try again. */ if (__mutex_trylock(lock)) { - if (use_ww_ctx && ww_ctx) + if (ww_ctx) __ww_mutex_check_waiters(lock, ww_ctx); goto skip_wait; @@ -1004,7 +1004,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, goto err; } - if (use_ww_ctx && ww_ctx) { + if (ww_ctx) { ret = __ww_mutex_check_kill(lock, &waiter, ww_ctx); if (ret) goto err; @@ -1017,7 +1017,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, * ww_mutex needs to always recheck its position since its waiter * list is not FIFO ordered. */ - if ((use_ww_ctx && ww_ctx) || !first) { + if (ww_ctx || !first) { first = __mutex_waiter_is_first(lock, &waiter); if (first) __mutex_set_flag(lock, MUTEX_FLAG_HANDOFF); @@ -1030,7 +1030,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, * or we must see its unlock and acquire. */ if (__mutex_trylock(lock) || - (first && mutex_optimistic_spin(lock, ww_ctx, use_ww_ctx, &waiter))) + (first && mutex_optimistic_spin(lock, ww_ctx, &waiter))) break; spin_lock(&lock->wait_lock); @@ -1039,7 +1039,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, acquired: __set_current_state(TASK_RUNNING); - if (use_ww_ctx && ww_ctx) { + if (ww_ctx) { /* * Wound-Wait; we stole the lock (!first_waiter), check the * waiters as anyone might want to wound us. @@ -1059,7 +1059,7 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass, /* got the lock - cleanup and rejoice! */ lock_acquired(&lock->dep_map, ip); - if (use_ww_ctx && ww_ctx) + if (ww_ctx) ww_mutex_lock_acquired(ww, ww_ctx); spin_unlock(&lock->wait_lock); diff --git a/kernel/locking/osq_lock.c b/kernel/locking/osq_lock.c index 6ef600aa0f47..1f7734949ac8 100644 --- a/kernel/locking/osq_lock.c +++ b/kernel/locking/osq_lock.c @@ -134,20 +134,17 @@ bool osq_lock(struct optimistic_spin_queue *lock) * cmpxchg in an attempt to undo our queueing. */ - while (!READ_ONCE(node->locked)) { - /* - * If we need to reschedule bail... so we can block. - * Use vcpu_is_preempted() to avoid waiting for a preempted - * lock holder: - */ - if (need_resched() || vcpu_is_preempted(node_cpu(node->prev))) - goto unqueue; - - cpu_relax(); - } - return true; + /* + * Wait to acquire the lock or cancelation. Note that need_resched() + * will come with an IPI, which will wake smp_cond_load_relaxed() if it + * is implemented with a monitor-wait. vcpu_is_preempted() relies on + * polling, be careful. + */ + if (smp_cond_load_relaxed(&node->locked, VAL || need_resched() || + vcpu_is_preempted(node_cpu(node->prev)))) + return true; -unqueue: + /* unqueue */ /* * Step - A -- stabilize @prev * diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c index c7471c3fb798..16c09cda3b02 100644 --- a/kernel/locking/qrwlock.c +++ b/kernel/locking/qrwlock.c @@ -70,6 +70,8 @@ EXPORT_SYMBOL(queued_read_lock_slowpath); */ void queued_write_lock_slowpath(struct qrwlock *lock) { + int cnts; + /* Put the writer into the wait queue */ arch_spin_lock(&lock->wait_lock); @@ -83,9 +85,8 @@ void queued_write_lock_slowpath(struct qrwlock *lock) /* When no more readers or writers, set the locked flag */ do { - atomic_cond_read_acquire(&lock->cnts, VAL == _QW_WAITING); - } while (atomic_cmpxchg_relaxed(&lock->cnts, _QW_WAITING, - _QW_LOCKED) != _QW_WAITING); + cnts = atomic_cond_read_relaxed(&lock->cnts, VAL == _QW_WAITING); + } while (!atomic_try_cmpxchg_acquire(&lock->cnts, &cnts, _QW_LOCKED)); unlock: arch_spin_unlock(&lock->wait_lock); } diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 9562aaa2afdc..a5ec4f68527e 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -1719,8 +1719,7 @@ void rt_mutex_init_proxy_locked(struct rt_mutex *lock, * possible because it belongs to the pi_state which is about to be freed * and it is not longer visible to other tasks. */ -void rt_mutex_proxy_unlock(struct rt_mutex *lock, - struct task_struct *proxy_owner) +void rt_mutex_proxy_unlock(struct rt_mutex *lock) { debug_rt_mutex_proxy_unlock(lock); rt_mutex_set_owner(lock, NULL); diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h index d1d62f942be2..ca6fb489007b 100644 --- a/kernel/locking/rtmutex_common.h +++ b/kernel/locking/rtmutex_common.h @@ -133,8 +133,7 @@ enum rtmutex_chainwalk { extern struct task_struct *rt_mutex_next_owner(struct rt_mutex *lock); extern void rt_mutex_init_proxy_locked(struct rt_mutex *lock, struct task_struct *proxy_owner); -extern void rt_mutex_proxy_unlock(struct rt_mutex *lock, - struct task_struct *proxy_owner); +extern void rt_mutex_proxy_unlock(struct rt_mutex *lock); extern void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter); extern int __rt_mutex_start_proxy_lock(struct rt_mutex *lock, struct rt_mutex_waiter *waiter, diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index ddc9cbd7700b..06c4627df5a7 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -402,31 +402,35 @@ static noinline bool rwsem_spin_on_owner(struct rw_semaphore *sem) { struct task_struct *owner = READ_ONCE(sem->owner); - if (!is_rwsem_owner_spinnable(owner)) + if (!owner || !is_rwsem_owner_spinnable(owner)) return false; - rcu_read_lock(); - while (owner && (READ_ONCE(sem->owner) == owner)) { + while (true) { + bool on_cpu, same_owner; + /* - * Ensure we emit the owner->on_cpu, dereference _after_ - * checking sem->owner still matches owner, if that fails, + * Ensure sem->owner still matches owner. If that fails, * owner might point to free()d memory, if it still matches, * the rcu_read_lock() ensures the memory stays valid. */ - barrier(); + rcu_read_lock(); + same_owner = sem->owner == owner; + if (same_owner) + on_cpu = owner_on_cpu(owner); + rcu_read_unlock(); + + if (!same_owner) + break; /* * abort spinning when need_resched or owner is not running or * owner's cpu is preempted. */ - if (need_resched() || !owner_on_cpu(owner)) { - rcu_read_unlock(); + if (!on_cpu || need_resched()) return false; - } cpu_relax(); } - rcu_read_unlock(); /* * If there is a new owner or the owner is not set, we continue diff --git a/kernel/module.c b/kernel/module.c index a926363f744b..6c7065dc7546 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -65,6 +65,26 @@ #include #include #include + +#ifndef CONFIG_MODULES +SYSCALL_DEFINE2(delete_module, const char __user *, name_user, + unsigned int, flags) +{ + return 0; +} + +SYSCALL_DEFINE3(init_module, void __user *, umod, + unsigned long, len, const char __user *, uargs) +{ + return 0; +} + +SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) +{ + return 0; +} +#else + #include "module-internal.h" #define CREATE_TRACE_POINTS @@ -1806,7 +1826,6 @@ static int mod_sysfs_init(struct module *mod) if (err) mod_kobject_put(mod); - /* delay uevent until full sysfs population */ out: return err; } @@ -1843,7 +1862,6 @@ static int mod_sysfs_setup(struct module *mod, add_sect_attrs(mod, info); add_notes_attrs(mod, info); - kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); return 0; out_unreg_modinfo_attrs: @@ -2286,6 +2304,21 @@ static int verify_export_symbols(struct module *mod) return 0; } +static bool ignore_undef_symbol(Elf_Half emachine, const char *name) +{ + /* + * On x86, PIC code and Clang non-PIC code may have call foo@PLT. GNU as + * before 2.37 produces an unreferenced _GLOBAL_OFFSET_TABLE_ on x86-64. + * i386 has a similar problem but may not deserve a fix. + * + * If we ever have to ignore many symbols, consider refactoring the code to + * only warn if referenced by a relocation. + */ + if (emachine == EM_386 || emachine == EM_X86_64) + return !strcmp(name, "_GLOBAL_OFFSET_TABLE_"); + return false; +} + /* Change all symbols so that st_value encodes the pointer directly. */ static int simplify_symbols(struct module *mod, const struct load_info *info) { @@ -2331,8 +2364,10 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) break; } - /* Ok if weak. */ - if (!ksym && ELF_ST_BIND(sym[i].st_info) == STB_WEAK) + /* Ok if weak or ignored. */ + if (!ksym && + (ELF_ST_BIND(sym[i].st_info) == STB_WEAK || + ignore_undef_symbol(info->hdr->e_machine, name))) break; ret = PTR_ERR(ksym) ?: -ENOENT; @@ -3514,6 +3549,9 @@ static noinline int do_init_module(struct module *mod) blocking_notifier_call_chain(&module_notify_list, MODULE_STATE_LIVE, mod); + /* Delay uevent until module has finished its init routine */ + kobject_uevent(&mod->mkobj.kobj, KOBJ_ADD); + /* * We need to finish all async code before the module init sequence * is done. This has potential to deadlock. For example, a newly @@ -3860,6 +3898,7 @@ static int load_module(struct load_info *info, const char __user *uargs, MODULE_STATE_GOING, mod); klp_module_going(mod); bug_cleanup: + mod->state = MODULE_STATE_GOING; /* module_bug_cleanup needs module_mutex protection */ mutex_lock(&module_mutex); module_bug_cleanup(mod); @@ -4476,3 +4515,5 @@ void module_layout(struct module *mod, } EXPORT_SYMBOL(module_layout); #endif + +#endif // CONFIG_MODULES diff --git a/kernel/power/process.c b/kernel/power/process.c index 7c306edfc54f..073f27a7b039 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -147,6 +147,7 @@ int freeze_processes(void) pr_cont("\n"); BUG_ON(in_atomic()); +#ifndef CONFIG_ANDROID /* * Now that the whole userspace is frozen we need to disbale * the OOM killer to disallow any further interference with @@ -155,6 +156,7 @@ int freeze_processes(void) */ if (!error && !oom_killer_disable(msecs_to_jiffies(freeze_timeout_msecs))) error = -EBUSY; +#endif if (error) thaw_processes(); @@ -199,7 +201,9 @@ void thaw_processes(void) pm_freezing = false; pm_nosig_freezing = false; +#ifndef CONFIG_ANDROID oom_killer_enable(); +#endif pr_info("Restarting tasks ... "); diff --git a/kernel/power/qos.c b/kernel/power/qos.c index e60a7f412015..d9032b2baa30 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -51,10 +51,12 @@ #include #include +#define CPUMASK_ALL (BIT(NR_CPUS) - 1) + /* * locking rule: all changes to constraints or notifiers lists * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock - * held, taken with _irqsave. One lock to rule them all + * held. One lock to rule them all */ struct pm_qos_object { struct pm_qos_constraints *constraints; @@ -198,7 +200,6 @@ static int pm_qos_dbg_show_requests(struct seq_file *s, void *unused) struct pm_qos_constraints *c; struct pm_qos_request *req; char *type; - unsigned long flags; int tot_reqs = 0; int active_reqs = 0; @@ -213,7 +214,7 @@ static int pm_qos_dbg_show_requests(struct seq_file *s, void *unused) } /* Lock to ensure we have a snapshot */ - spin_lock_irqsave(&pm_qos_lock, flags); + spin_lock(&pm_qos_lock); if (plist_head_empty(&c->list)) { seq_puts(s, "Empty!\n"); goto out; @@ -249,7 +250,7 @@ static int pm_qos_dbg_show_requests(struct seq_file *s, void *unused) type, pm_qos_get_value(c), active_reqs, tot_reqs); out: - spin_unlock_irqrestore(&pm_qos_lock, flags); + spin_unlock(&pm_qos_lock); return 0; } @@ -266,12 +267,17 @@ static const struct file_operations pm_qos_debug_fops = { .release = single_release, }; -static inline int pm_qos_set_value_for_cpus(struct pm_qos_constraints *c, - struct cpumask *cpus) +static inline int pm_qos_set_value_for_cpus(struct pm_qos_request *new_req, + struct pm_qos_constraints *c, + unsigned long *cpus) { - struct pm_qos_request *req = NULL; + s32 qos_val[NR_CPUS] = { + [0 ... (NR_CPUS - 1)] = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE + }; + struct pm_qos_request *req; + unsigned long new_req_cpus; + bool changed = false; int cpu; - s32 qos_val[NR_CPUS] = { [0 ... (NR_CPUS - 1)] = c->default_value }; /* * pm_qos_constraints can be from different classes, @@ -281,27 +287,35 @@ static inline int pm_qos_set_value_for_cpus(struct pm_qos_constraints *c, if (c != pm_qos_array[PM_QOS_CPU_DMA_LATENCY]->constraints) return -EINVAL; + new_req_cpus = atomic_read(&new_req->cpus_affine); + for_each_cpu(cpu, to_cpumask(&new_req_cpus)) { + if (c->target_per_cpu[cpu] != new_req->node.prio) { + changed = true; + break; + } + } + + if (!changed) + return 0; + plist_for_each_entry(req, &c->list, node) { - for_each_cpu(cpu, &req->cpus_affine) { - switch (c->type) { - case PM_QOS_MIN: - if (qos_val[cpu] > req->node.prio) - qos_val[cpu] = req->node.prio; - break; - case PM_QOS_MAX: - if (req->node.prio > qos_val[cpu]) - qos_val[cpu] = req->node.prio; - break; - default: - break; - } + unsigned long affected_cpus; + + affected_cpus = atomic_read(&req->cpus_affine) & new_req_cpus; + if (!affected_cpus) + continue; + + for_each_cpu(cpu, to_cpumask(&affected_cpus)) { + if (qos_val[cpu] > req->node.prio) + qos_val[cpu] = req->node.prio; } } - for_each_possible_cpu(cpu) { - if (c->target_per_cpu[cpu] != qos_val[cpu]) - cpumask_set_cpu(cpu, cpus); - c->target_per_cpu[cpu] = qos_val[cpu]; + for_each_cpu(cpu, to_cpumask(&new_req_cpus)) { + if (c->target_per_cpu[cpu] != qos_val[cpu]) { + c->target_per_cpu[cpu] = qos_val[cpu]; + *cpus |= BIT(cpu); + } } return 0; @@ -321,12 +335,12 @@ static inline int pm_qos_set_value_for_cpus(struct pm_qos_constraints *c, int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, enum pm_qos_req_action action, int value) { - unsigned long flags; + struct pm_qos_request *req = container_of(node, typeof(*req), node); int prev_value, curr_value, new_value; - struct cpumask cpus; + unsigned long cpus = 0; int ret; - spin_lock_irqsave(&pm_qos_lock, flags); + spin_lock(&pm_qos_lock); prev_value = pm_qos_get_value(c); if (value == PM_QOS_DEFAULT_VALUE) new_value = c->default_value; @@ -355,20 +369,15 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, } curr_value = pm_qos_get_value(c); - cpumask_clear(&cpus); pm_qos_set_value(c, curr_value); - ret = pm_qos_set_value_for_cpus(c, &cpus); - - spin_unlock_irqrestore(&pm_qos_lock, flags); - - trace_pm_qos_update_target(action, prev_value, curr_value); + ret = pm_qos_set_value_for_cpus(req, c, &cpus); /* * if cpu mask bits are set, call the notifier call chain * to update the new qos restriction for the cores */ - if (!cpumask_empty(&cpus) || + if (cpus || (ret && prev_value != curr_value)) { ret = 1; if (c->notifiers) @@ -377,6 +386,11 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, } else { ret = 0; } + + spin_unlock(&pm_qos_lock); + + trace_pm_qos_update_target(action, prev_value, curr_value); + return ret; } @@ -412,10 +426,9 @@ bool pm_qos_update_flags(struct pm_qos_flags *pqf, struct pm_qos_flags_request *req, enum pm_qos_req_action action, s32 val) { - unsigned long irqflags; s32 prev_value, curr_value; - spin_lock_irqsave(&pm_qos_lock, irqflags); + spin_lock(&pm_qos_lock); prev_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags; @@ -439,7 +452,7 @@ bool pm_qos_update_flags(struct pm_qos_flags *pqf, curr_value = list_empty(&pqf->list) ? 0 : pqf->effective_flags; - spin_unlock_irqrestore(&pm_qos_lock, irqflags); + spin_unlock(&pm_qos_lock); trace_pm_qos_update_flags(action, prev_value, curr_value); return prev_value != curr_value; @@ -474,12 +487,11 @@ EXPORT_SYMBOL_GPL(pm_qos_request_active); int pm_qos_request_for_cpumask(int pm_qos_class, struct cpumask *mask) { - unsigned long irqflags; int cpu; struct pm_qos_constraints *c = NULL; int val; - spin_lock_irqsave(&pm_qos_lock, irqflags); + spin_lock(&pm_qos_lock); c = pm_qos_array[pm_qos_class]->constraints; val = c->default_value; @@ -498,7 +510,7 @@ int pm_qos_request_for_cpumask(int pm_qos_class, struct cpumask *mask) break; } } - spin_unlock_irqrestore(&pm_qos_lock, irqflags); + spin_unlock(&pm_qos_lock); return val; } @@ -515,25 +527,9 @@ static void __pm_qos_update_request(struct pm_qos_request *req, &req->node, PM_QOS_UPDATE_REQ, new_value); } -/** - * pm_qos_work_fn - the timeout handler of pm_qos_update_request_timeout - * @work: work struct for the delayed work (timeout) - * - * This cancels the timeout request by falling back to the default at timeout. - */ -static void pm_qos_work_fn(struct work_struct *work) -{ - struct pm_qos_request *req = container_of(to_delayed_work(work), - struct pm_qos_request, - work); - - __pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE); -} - #ifdef CONFIG_SMP static void pm_qos_irq_release(struct kref *ref) { - unsigned long flags; struct irq_affinity_notify *notify = container_of(ref, struct irq_affinity_notify, kref); struct pm_qos_request *req = container_of(notify, @@ -541,38 +537,21 @@ static void pm_qos_irq_release(struct kref *ref) struct pm_qos_constraints *c = pm_qos_array[req->pm_qos_class]->constraints; - spin_lock_irqsave(&pm_qos_lock, flags); - cpumask_setall(&req->cpus_affine); - spin_unlock_irqrestore(&pm_qos_lock, flags); - + atomic_set(&req->cpus_affine, CPUMASK_ALL); pm_qos_update_target(c, &req->node, PM_QOS_UPDATE_REQ, c->default_value); } static void pm_qos_irq_notify(struct irq_affinity_notify *notify, - const cpumask_t *unused_mask) + const cpumask_t *mask) { - unsigned long flags; struct pm_qos_request *req = container_of(notify, struct pm_qos_request, irq_notify); struct pm_qos_constraints *c = pm_qos_array[req->pm_qos_class]->constraints; - struct irq_desc *desc = irq_to_desc(req->irq); - struct cpumask *new_affinity = - irq_data_get_effective_affinity_mask(&desc->irq_data); - bool affinity_changed = false; - - spin_lock_irqsave(&pm_qos_lock, flags); - if (!cpumask_equal(&req->cpus_affine, new_affinity)) { - cpumask_copy(&req->cpus_affine, new_affinity); - affinity_changed = true; - } - - spin_unlock_irqrestore(&pm_qos_lock, flags); - if (affinity_changed) - pm_qos_update_target(c, &req->node, PM_QOS_UPDATE_REQ, - req->node.prio); + atomic_set(&req->cpus_affine, *cpumask_bits(mask)); + pm_qos_update_target(c, &req->node, PM_QOS_UPDATE_REQ, req->node.prio); } #endif @@ -602,9 +581,8 @@ void pm_qos_add_request(struct pm_qos_request *req, switch (req->type) { case PM_QOS_REQ_AFFINE_CORES: - if (cpumask_empty(&req->cpus_affine)) { + if (!atomic_cmpxchg_relaxed(&req->cpus_affine, 0, CPUMASK_ALL)) { req->type = PM_QOS_REQ_ALL_CORES; - cpumask_setall(&req->cpus_affine); WARN(1, "Affine cores not set for request with affinity flag\n"); } break; @@ -617,24 +595,17 @@ void pm_qos_add_request(struct pm_qos_request *req, if (!desc) return; - /* - * If the IRQ is not started, the effective affinity - * won't be set. So fallback to the default affinity. - */ - mask = irq_data_get_effective_affinity_mask( - &desc->irq_data); - if (cpumask_empty(mask)) - mask = irq_data_get_affinity_mask( - &desc->irq_data); - - cpumask_copy(&req->cpus_affine, mask); + mask = desc->irq_data.common->affinity; + + /* Get the current affinity */ + atomic_set(&req->cpus_affine, *cpumask_bits(mask)); req->irq_notify.irq = req->irq; req->irq_notify.notify = pm_qos_irq_notify; req->irq_notify.release = pm_qos_irq_release; } else { req->type = PM_QOS_REQ_ALL_CORES; - cpumask_setall(&req->cpus_affine); + atomic_set(&req->cpus_affine, CPUMASK_ALL); WARN(1, "IRQ-%d not set for request with affinity flag\n", req->irq); } @@ -644,12 +615,11 @@ void pm_qos_add_request(struct pm_qos_request *req, WARN(1, "Unknown request type %d\n", req->type); /* fall through */ case PM_QOS_REQ_ALL_CORES: - cpumask_setall(&req->cpus_affine); + atomic_set(&req->cpus_affine, CPUMASK_ALL); break; } req->pm_qos_class = pm_qos_class; - INIT_DELAYED_WORK(&req->work, pm_qos_work_fn); trace_pm_qos_add_request(pm_qos_class, value); pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints, &req->node, PM_QOS_ADD_REQ, value); @@ -664,7 +634,7 @@ void pm_qos_add_request(struct pm_qos_request *req, if (ret) { WARN(1, "IRQ affinity notify set failed\n"); req->type = PM_QOS_REQ_ALL_CORES; - cpumask_setall(&req->cpus_affine); + atomic_set(&req->cpus_affine, CPUMASK_ALL); pm_qos_update_target( pm_qos_array[pm_qos_class]->constraints, &req->node, PM_QOS_UPDATE_REQ, value); @@ -695,41 +665,10 @@ void pm_qos_update_request(struct pm_qos_request *req, return; } - cancel_delayed_work_sync(&req->work); __pm_qos_update_request(req, new_value); } EXPORT_SYMBOL_GPL(pm_qos_update_request); -/** - * pm_qos_update_request_timeout - modifies an existing qos request temporarily. - * @req : handle to list element holding a pm_qos request to use - * @new_value: defines the temporal qos request - * @timeout_us: the effective duration of this qos request in usecs. - * - * After timeout_us, this qos request is cancelled automatically. - */ -void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, - unsigned long timeout_us) -{ - if (!req) - return; - if (WARN(!pm_qos_request_active(req), - "%s called for unknown object.", __func__)) - return; - - cancel_delayed_work_sync(&req->work); - - trace_pm_qos_update_request_timeout(req->pm_qos_class, - new_value, timeout_us); - if (new_value != req->node.prio) - pm_qos_update_target( - pm_qos_array[req->pm_qos_class]->constraints, - &req->node, PM_QOS_UPDATE_REQ, new_value); - - schedule_delayed_work(&req->work, usecs_to_jiffies(timeout_us)); -} -EXPORT_SYMBOL_GPL(pm_qos_update_request_timeout); - /** * pm_qos_remove_request - modifies an existing qos request * @req: handle to request list element @@ -749,8 +688,6 @@ void pm_qos_remove_request(struct pm_qos_request *req) return; } - cancel_delayed_work_sync(&req->work); - #ifdef CONFIG_SMP if (req->type == PM_QOS_REQ_AFFINE_IRQ) { int ret = 0; @@ -871,7 +808,6 @@ static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { s32 value; - unsigned long flags; struct pm_qos_request *req = filp->private_data; if (!req) @@ -879,9 +815,9 @@ static ssize_t pm_qos_power_read(struct file *filp, char __user *buf, if (!pm_qos_request_active(req)) return -EINVAL; - spin_lock_irqsave(&pm_qos_lock, flags); + spin_lock(&pm_qos_lock); value = pm_qos_get_value(pm_qos_array[req->pm_qos_class]->constraints); - spin_unlock_irqrestore(&pm_qos_lock, flags); + spin_unlock(&pm_qos_lock); return simple_read_from_buffer(buf, count, f_pos, &value, sizeof(s32)); } @@ -918,6 +854,9 @@ static int __init pm_qos_power_init(void) BUILD_BUG_ON(ARRAY_SIZE(pm_qos_array) != PM_QOS_NUM_CLASSES); + /* Don't let userspace impose restrictions on CPU idle levels */ + return 0; + d = debugfs_create_dir("pm_qos", NULL); if (IS_ERR_OR_NULL(d)) d = NULL; diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index f2635fc751d9..185d1f5d036c 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -105,7 +105,7 @@ unsigned long image_size; void __init hibernate_image_size_init(void) { - image_size = ((totalram_pages * 2) / 5) * PAGE_SIZE; + image_size = ((totalram_pages() * 2) / 5) * PAGE_SIZE; } /* diff --git a/kernel/power/swap.c b/kernel/power/swap.c index d7f6c1a288d3..e9494c29f1ca 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -491,10 +491,10 @@ static int swap_writer_finish(struct swap_map_handle *handle, unsigned int flags, int error) { if (!error) { - flush_swap_writer(handle); pr_info("S"); error = mark_swapfiles(handle, flags); pr_cont("|\n"); + flush_swap_writer(handle); } if (error) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 9e7494f6e172..d7a45a9228b0 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -776,7 +776,7 @@ struct devkmsg_user { static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) { - char *buf, *line; + char buf[LOG_LINE_MAX + 1], *line; int level = default_message_loglevel; int facility = 1; /* LOG_USER */ struct file *file = iocb->ki_filp; @@ -797,10 +797,6 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) return ret; } - buf = kmalloc(len+1, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - buf[len] = '\0'; if (!copy_from_iter_full(buf, len, from)) { kfree(buf); @@ -833,7 +829,6 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) } printk_emit(facility, level, NULL, 0, "%s", line); - kfree(buf); return ret; } @@ -1332,14 +1327,10 @@ static size_t msg_print_text(const struct printk_log *msg, bool syslog, char *bu static int syslog_print(char __user *buf, int size) { - char *text; + char text[LOG_LINE_MAX + PREFIX_MAX]; struct printk_log *msg; int len = 0; - text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); - if (!text) - return -ENOMEM; - while (size > 0) { size_t n; size_t skip; @@ -1387,7 +1378,6 @@ static int syslog_print(char __user *buf, int size) buf += n; } - kfree(text); return len; } @@ -2205,7 +2195,7 @@ int add_preferred_console(char *name, int idx, char *options) return __add_preferred_console(name, idx, options, NULL); } -bool console_suspend_enabled = true; +bool console_suspend_enabled = false; EXPORT_SYMBOL(console_suspend_enabled); static int __init console_suspend_disable(char *str) diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c index 82003d0d2e9f..0dbc06033113 100644 --- a/kernel/printk/printk_safe.c +++ b/kernel/printk/printk_safe.c @@ -55,6 +55,8 @@ struct printk_safe_seq_buf { static DEFINE_PER_CPU(struct printk_safe_seq_buf, safe_print_seq); static DEFINE_PER_CPU(int, printk_context); +static DEFINE_RAW_SPINLOCK(safe_read_lock); + #ifdef CONFIG_PRINTK_NMI static DEFINE_PER_CPU(struct printk_safe_seq_buf, nmi_print_seq); #endif @@ -190,8 +192,6 @@ static void report_message_lost(struct printk_safe_seq_buf *s) */ static void __printk_safe_flush(struct irq_work *work) { - static raw_spinlock_t read_lock = - __RAW_SPIN_LOCK_INITIALIZER(read_lock); struct printk_safe_seq_buf *s = container_of(work, struct printk_safe_seq_buf, work); unsigned long flags; @@ -205,7 +205,7 @@ static void __printk_safe_flush(struct irq_work *work) * different CPUs. This is especially important when printing * a backtrace. */ - raw_spin_lock_irqsave(&read_lock, flags); + raw_spin_lock_irqsave(&safe_read_lock, flags); i = 0; more: @@ -242,7 +242,7 @@ static void __printk_safe_flush(struct irq_work *work) out: report_message_lost(s); - raw_spin_unlock_irqrestore(&read_lock, flags); + raw_spin_unlock_irqrestore(&safe_read_lock, flags); } /** @@ -288,6 +288,14 @@ void printk_safe_flush_on_panic(void) raw_spin_lock_init(&logbuf_lock); } + if (raw_spin_is_locked(&safe_read_lock)) { + if (num_online_cpus() > 1) + return; + + debug_locks_off(); + raw_spin_lock_init(&safe_read_lock); + } + printk_safe_flush(); } diff --git a/kernel/ptrace.c b/kernel/ptrace.c index b93eb4eaf7ac..ecdb7402072f 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -258,17 +258,11 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state) return ret; } -static bool ptrace_has_cap(const struct cred *cred, struct user_namespace *ns, - unsigned int mode) +static bool ptrace_has_cap(struct user_namespace *ns, unsigned int mode) { - int ret; - if (mode & PTRACE_MODE_NOAUDIT) - ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NOAUDIT); - else - ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NONE); - - return ret == 0; + return ns_capable_noaudit(ns, CAP_SYS_PTRACE); + return ns_capable(ns, CAP_SYS_PTRACE); } /* Returns 0 on success, -errno on denial. */ @@ -320,7 +314,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) gid_eq(caller_gid, tcred->sgid) && gid_eq(caller_gid, tcred->gid)) goto ok; - if (ptrace_has_cap(cred, tcred->user_ns, mode)) + if (ptrace_has_cap(tcred->user_ns, mode)) goto ok; rcu_read_unlock(); return -EPERM; @@ -339,7 +333,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) mm = task->mm; if (mm && ((get_dumpable(mm) != SUID_DUMP_USER) && - !ptrace_has_cap(cred, mm->user_ns, mode))) + !ptrace_has_cap(mm->user_ns, mode))) return -EPERM; return security_ptrace_access_check(task, mode); diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 329a13e71c68..72b53220a703 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -4177,7 +4177,7 @@ void __init rcu_init(void) } /* Create workqueue for expedited GPs and for Tree SRCU. */ - rcu_gp_wq = alloc_workqueue("rcu_gp", WQ_MEM_RECLAIM, 0); + rcu_gp_wq = alloc_workqueue("rcu_gp", WQ_POWER_EFFICIENT | WQ_MEM_RECLAIM, 0); WARN_ON(!rcu_gp_wq); rcu_par_gp_wq = alloc_workqueue("rcu_par_gp", WQ_MEM_RECLAIM, 0); WARN_ON(!rcu_par_gp_wq); diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 5f6de49dc78e..dd25f30e3f74 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -2487,8 +2487,8 @@ static void rcu_spawn_one_nocb_kthread(struct rcu_state *rsp, int cpu) } /* Spawn the kthread for this CPU and RCU flavor. */ - t = kthread_run(rcu_nocb_kthread, rdp_spawn, - "rcuo%c/%d", rsp->abbr, cpu); + t = kthread_run_perf_critical(cpu_lp_mask, rcu_nocb_kthread, rdp_spawn, + "rcuo%c/%d", rsp->abbr, cpu); BUG_ON(IS_ERR(t)); WRITE_ONCE(rdp_spawn->nocb_kthread, t); } diff --git a/kernel/reboot.c b/kernel/reboot.c index af4ceb7f9545..7ce085f3b970 100644 --- a/kernel/reboot.c +++ b/kernel/reboot.c @@ -616,3 +616,4 @@ static int __init get_poweroff_charger_mode(char *line) return 1; } __setup("androidboot.mode=", get_poweroff_charger_mode); + diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index 674201711f62..7c89df5ad034 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SCHED_TUNE) += tune.o obj-$(CONFIG_CGROUP_CPUACCT) += cpuacct.o obj-$(CONFIG_CPU_FREQ) += cpufreq.o obj-$(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) += cpufreq_schedutil.o + obj-$(CONFIG_CPU_FREQ_GOV_SCHEDHORIZON) += cpufreq_schedhorizon.o obj-$(CONFIG_MEMBARRIER) += membarrier.o obj-$(CONFIG_CPU_ISOLATION) += isolation.o obj-$(CONFIG_SCHED_CORE_CTL) += core_ctl.o diff --git a/kernel/sched/core.c b/kernel/sched/core.c index c9cf98e58118..a557f2031765 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -35,22 +35,6 @@ DEFINE_TRACE(kperfevents_sched_wait); DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); -#ifdef CONFIG_SCHED_DEBUG -/* - * Debugging: various feature bits - * - * If SCHED_DEBUG is disabled, each compilation unit has its own copy of - * sysctl_sched_features, defined in sched.h, to allow constants propagation - * at compile time and compiler optimization based on features default. - */ -#define SCHED_FEAT(name, enabled) \ - (1UL << __SCHED_FEAT_##name) * enabled | -const_debug unsigned int sysctl_sched_features = -#include "features.h" - 0; -#undef SCHED_FEAT -#endif - /* * Number of tasks to iterate in a single balance run. * Limited because this is done with IRQs disabled. @@ -1678,6 +1662,11 @@ static int __set_cpus_allowed_ptr(struct task_struct *p, int ret = 0; cpumask_t allowed_mask; + /* Don't allow perf-critical threads to have non-perf affinities */ + if ((p->flags & PF_PERF_CRITICAL) && new_mask != cpu_lp_mask && + new_mask != cpu_perf_mask && new_mask != cpu_prime_mask) + return -EINVAL; + rq = task_rq_lock(p, &rf); update_rq_clock(rq); @@ -1926,6 +1915,47 @@ int migrate_swap(struct task_struct *cur, struct task_struct *p, return ret; } +/* + * Calls to sched_migrate_to_cpumask_start() cannot nest. This can only be used + * in process context. + */ +void sched_migrate_to_cpumask_start(struct cpumask *old_mask, + const struct cpumask *dest) +{ + struct task_struct *p = current; + + raw_spin_lock_irq(&p->pi_lock); + *cpumask_bits(old_mask) = *cpumask_bits(&p->cpus_allowed); + raw_spin_unlock_irq(&p->pi_lock); + + /* + * This will force the current task onto the destination cpumask. It + * will sleep when a migration to another CPU is actually needed. + */ + set_cpus_allowed_ptr(p, dest); +} + +void sched_migrate_to_cpumask_end(const struct cpumask *old_mask, + const struct cpumask *dest) +{ + struct task_struct *p = current; + + /* + * Check that cpus_allowed didn't change from what it was temporarily + * set to earlier. If so, we can go ahead and lazily restore the old + * cpumask. There's no need to immediately migrate right now. + */ + raw_spin_lock_irq(&p->pi_lock); + if (*cpumask_bits(&p->cpus_allowed) == *cpumask_bits(dest)) { + struct rq *rq = this_rq(); + + raw_spin_lock(&rq->lock); + do_set_cpus_allowed(p, old_mask); + raw_spin_unlock(&rq->lock); + } + raw_spin_unlock_irq(&p->pi_lock); +} + /* * wait_task_inactive - wait for a thread to unschedule. * @@ -2387,6 +2417,7 @@ static int ttwu_remote(struct task_struct *p, int wake_flags) } #ifdef CONFIG_SMP +#if SCHED_FEAT_TTWU_QUEUE void sched_ttwu_pending(void) { struct rq *rq = this_rq(); @@ -2405,6 +2436,7 @@ void sched_ttwu_pending(void) rq_unlock_irqrestore(rq, &rf); } +#endif void scheduler_ipi(void) { @@ -2416,8 +2448,13 @@ void scheduler_ipi(void) */ preempt_fold_need_resched(); +#if SCHED_FEAT_TTWU_QUEUE if (llist_empty(&this_rq()->wake_list) && !got_nohz_idle_kick()) return; +#else + if (!got_nohz_idle_kick()) + return; +#endif /* * Not all reschedule IPI handlers call irq_enter/irq_exit, since @@ -3349,6 +3386,50 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, prepare_arch_switch(next); } +void release_task_stack(struct task_struct *tsk); +static void task_async_free(struct work_struct *work) +{ + struct task_struct *t = container_of(work, typeof(*t), async_free.work); + bool free_stack = READ_ONCE(t->async_free.free_stack); + + atomic_set(&t->async_free.running, 0); + + if (free_stack) { + release_task_stack(t); + put_task_struct(t); + } else { + __put_task_struct(t); + } +} + +static void finish_task_switch_dead(struct task_struct *prev) +{ + if (atomic_cmpxchg(&prev->async_free.running, 0, 1)) { + put_task_stack(prev); + put_task_struct(prev); + return; + } + + if (atomic_dec_and_test(&prev->stack_refcount)) { + prev->async_free.free_stack = true; + } else if (atomic_dec_and_test(&prev->usage)) { + prev->async_free.free_stack = false; + } else { + atomic_set(&prev->async_free.running, 0); + return; + } + + INIT_WORK(&prev->async_free.work, task_async_free); + queue_work(system_unbound_wq, &prev->async_free.work); +} + +static void mmdrop_async_free(struct work_struct *work) +{ + struct mm_struct *mm = container_of(work, typeof(*mm), async_put_work); + + __mmdrop(mm); +} + /** * finish_task_switch - clean up after a task-switch * @prev: the thread we just switched away from. @@ -3425,9 +3506,12 @@ static struct rq *finish_task_switch(struct task_struct *prev) * provided by mmdrop(), * - a sync_core for SYNC_CORE. */ - if (mm) { + if (mm) membarrier_mm_sync_core_before_usermode(mm); - mmdrop(mm); + + if (mm && atomic_dec_and_test(&mm->mm_count)) { + INIT_WORK(&mm->async_put_work, mmdrop_async_free); + queue_work(system_unbound_wq, &mm->async_put_work); } if (unlikely(prev_state == TASK_DEAD)) { if (prev->sched_class->task_dead) @@ -3439,10 +3523,7 @@ static struct rq *finish_task_switch(struct task_struct *prev) */ kprobe_flush_task(prev); - /* Task is done with its stack. */ - put_task_stack(prev); - - put_task_struct(prev); + finish_task_switch_dead(prev); } tick_nohz_task_switch(); @@ -4814,8 +4895,10 @@ int idle_cpu(int cpu) return 0; #ifdef CONFIG_SMP +#if SCHED_FEAT_TTWU_QUEUE if (!llist_empty(&rq->wake_list)) return 0; +#endif #endif return 1; @@ -4874,7 +4957,8 @@ static void __setscheduler_params(struct task_struct *p, if (policy == SETPARAM_POLICY) policy = p->policy; - p->policy = policy; + /* Replace SCHED_FIFO with SCHED_RR to reduce latency */ + p->policy = policy == SCHED_FIFO ? SCHED_RR : policy; if (dl_policy(policy)) __setparam_dl(p, attr); @@ -5875,12 +5959,8 @@ static void do_sched_yield(void) schedstat_inc(rq->yld_count); current->sched_class->yield_task(rq); - /* - * Since we are going to call schedule() anyway, there's - * no need to preempt or enable interrupts: - */ preempt_disable(); - rq_unlock(rq, &rf); + rq_unlock_irq(rq, &rf); sched_preempt_enable_no_resched(); schedule(); @@ -8658,7 +8738,6 @@ void sched_exit(struct task_struct *p) enqueue_task(rq, p, 0); clear_ed_task(p, rq); task_rq_unlock(rq, p, &rf); - free_task_load_ptrs(p); } #endif /* CONFIG_SCHED_WALT */ diff --git a/kernel/sched/cpufreq_schedhorizon.c b/kernel/sched/cpufreq_schedhorizon.c new file mode 100644 index 000000000000..d01388aa167c --- /dev/null +++ b/kernel/sched/cpufreq_schedhorizon.c @@ -0,0 +1,1525 @@ +/* + * CPUFreq governor based on scheduler-provided CPU utilization data. + * + * Copyright (C) 2016, Intel Corporation + * Author: Rafael J. Wysocki + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include "sched.h" + +#include +#include +#include + +static unsigned int default_efficient_freq_lp[] = {0}; +static u64 default_up_delay_lp[] = {0}; + +static unsigned int default_efficient_freq_hp[] = {1766400}; +static u64 default_up_delay_hp[] = {2000 * NSEC_PER_MSEC}; + +static unsigned int default_efficient_freq_pr[] = {2073600}; +static u64 default_up_delay_pr[] = {2000 * NSEC_PER_MSEC}; + +#define DEFAULT_RTG_BOOST_FREQ_LP 1000000 +#define DEFAULT_RTG_BOOST_FREQ_HP 0 +#define DEFAULT_RTG_BOOST_FREQ_PR 0 + +#define DEFAULT_HISPEED_LOAD_LP 90 +#define DEFAULT_HISPEED_LOAD_HP 90 +#define DEFAULT_HISPEED_LOAD_PR 90 + +#define DEFAULT_HISPEED_FREQ_LP 0 +#define DEFAULT_HISPEED_FREQ_HP 0 +#define DEFAULT_HISPEED_FREQ_PR 0 + +#define DEFAULT_PL_LP 1 +#define DEFAULT_PL_HP 1 +#define DEFAULT_PL_PR 1 + +struct sugov_tunables { + struct gov_attr_set attr_set; + unsigned int up_rate_limit_us; + unsigned int down_rate_limit_us; + unsigned int hispeed_load; + unsigned int hispeed_freq; + unsigned int rtg_boost_freq; + bool pl; + unsigned int *efficient_freq; + int nefficient_freq; + u64 *up_delay; + int nup_delay; + int current_step; +}; + +struct sugov_policy { + struct cpufreq_policy *policy; + + u64 last_ws; + u64 curr_cycles; + u64 last_cyc_update_time; + unsigned long avg_cap; + struct sugov_tunables *tunables; + struct list_head tunables_hook; + unsigned long hispeed_util; + unsigned long rtg_boost_util; + unsigned long max; + + raw_spinlock_t update_lock; /* For shared policies */ + u64 last_freq_update_time; + s64 min_rate_limit_ns; + s64 up_rate_delay_ns; + s64 down_rate_delay_ns; + unsigned int next_freq; + unsigned int cached_raw_freq; + unsigned int prev_cached_raw_freq; + u64 first_hp_request_time; + + /* The next fields are only needed if fast switch cannot be used: */ + struct irq_work irq_work; + struct kthread_work work; + struct mutex work_lock; + struct kthread_worker worker; + struct task_struct *thread; + bool work_in_progress; + + bool limits_changed; + bool need_freq_update; +}; + +struct sugov_cpu { + struct update_util_data update_util; + struct sugov_policy *sg_policy; + unsigned int cpu; + + u64 last_update; + + struct sched_walt_cpu_load walt_load; + + unsigned long util; + unsigned int flags; + + unsigned long bw_dl; + unsigned long min; + unsigned long max; + + /* The field below is for single-CPU policies only: */ +#ifdef CONFIG_NO_HZ_COMMON + unsigned long saved_idle_calls; +#endif +}; + +static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu); +static unsigned int stale_ns; +static DEFINE_PER_CPU(struct sugov_tunables *, cached_tunables); + +/************************ Governor internals ***********************/ + +static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time) +{ + s64 delta_ns; + + /* + * Since cpufreq_update_util() is called with rq->lock held for + * the @target_cpu, our per-CPU data is fully serialized. + * + * However, drivers cannot in general deal with cross-CPU + * requests, so while get_next_freq() will work, our + * sugov_update_commit() call may not for the fast switching platforms. + * + * Hence stop here for remote requests if they aren't supported + * by the hardware, as calculating the frequency is pointless if + * we cannot in fact act on it. + * + * This is needed on the slow switching platforms too to prevent CPUs + * going offline from leaving stale IRQ work items behind. + */ + if (!cpufreq_this_cpu_can_update(sg_policy->policy)) + return false; + + if (unlikely(sg_policy->limits_changed)) { + sg_policy->limits_changed = false; + sg_policy->need_freq_update = true; + return true; + } + + /* No need to recalculate next freq for min_rate_limit_us + * at least. However we might still decide to further rate + * limit once frequency change direction is decided, according + * to the separate rate limits. + */ + + delta_ns = time - sg_policy->last_freq_update_time; + return delta_ns >= sg_policy->min_rate_limit_ns; +} + +static inline bool use_pelt(void) +{ +#ifdef CONFIG_SCHED_WALT + return false; +#else + return true; +#endif +} + +static inline bool conservative_pl(void) +{ +#ifdef CONFIG_SCHED_WALT + return sysctl_sched_conservative_pl; +#else + return false; +#endif +} + +static int match_nearest_efficient_step(int freq,int maxstep,int *freq_table) +{ + int i; + + for (i=0; i= freq) + break; + } + + return i; +} + +static void do_freq_limit(struct sugov_policy *sg_policy, unsigned int *freq, u64 time) +{ + if (*freq > sg_policy->tunables->efficient_freq[sg_policy->tunables->current_step] && !sg_policy->first_hp_request_time) { + /* First request */ + *freq = sg_policy->tunables->efficient_freq[sg_policy->tunables->current_step]; + sg_policy->first_hp_request_time = time; + } else if (*freq < sg_policy->tunables->efficient_freq[sg_policy->tunables->current_step]) { + /* It's already under current efficient frequency */ + /* Goto a lower one */ + sg_policy->tunables->current_step = match_nearest_efficient_step(*freq, sg_policy->tunables->nefficient_freq, sg_policy->tunables->efficient_freq); + sg_policy->first_hp_request_time = 0; + } else if ((sg_policy->first_hp_request_time + && time < sg_policy->first_hp_request_time + sg_policy->tunables->up_delay[sg_policy->tunables->current_step])){ + /* Restrict it */ + *freq = sg_policy->tunables->efficient_freq[sg_policy->tunables->current_step]; + } else if (sg_policy->tunables->current_step + 1 <= sg_policy->tunables->nefficient_freq - 1 + && sg_policy->tunables->current_step + 1 <= sg_policy->tunables->nup_delay - 1) { + /* Unlock a higher efficient frequency */ + sg_policy->tunables->current_step++; + sg_policy->first_hp_request_time = time; + if (*freq > sg_policy->tunables->efficient_freq[sg_policy->tunables->current_step]) + *freq = sg_policy->tunables->efficient_freq[sg_policy->tunables->current_step]; + } +} + +static bool sugov_up_down_rate_limit(struct sugov_policy *sg_policy, u64 time, + unsigned int next_freq) +{ + s64 delta_ns; + + delta_ns = time - sg_policy->last_freq_update_time; + + if (next_freq > sg_policy->next_freq && + delta_ns < sg_policy->up_rate_delay_ns) + return true; + + if (next_freq < sg_policy->next_freq && + delta_ns < sg_policy->down_rate_delay_ns) + return true; + + return false; +} + +static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time, + unsigned int next_freq) +{ + if (sg_policy->next_freq == next_freq) + return false; + + if (sugov_up_down_rate_limit(sg_policy, time, next_freq)) { + /* Restore cached freq as next_freq is not changed */ + sg_policy->cached_raw_freq = sg_policy->prev_cached_raw_freq; + return false; + } + + sg_policy->next_freq = next_freq; + sg_policy->last_freq_update_time = time; + + return true; +} + +static unsigned long freq_to_util(struct sugov_policy *sg_policy, + unsigned int freq) +{ + return mult_frac(sg_policy->max, freq, + sg_policy->policy->cpuinfo.max_freq); +} + +#define KHZ 1000 +static void sugov_track_cycles(struct sugov_policy *sg_policy, + unsigned int prev_freq, + u64 upto) +{ + u64 delta_ns, cycles; + u64 next_ws = sg_policy->last_ws + sched_ravg_window; + + if (use_pelt()) + return; + + upto = min(upto, next_ws); + /* Track cycles in current window */ + delta_ns = upto - sg_policy->last_cyc_update_time; + delta_ns *= prev_freq; + do_div(delta_ns, (NSEC_PER_SEC / KHZ)); + cycles = delta_ns; + sg_policy->curr_cycles += cycles; + sg_policy->last_cyc_update_time = upto; +} + +static void sugov_calc_avg_cap(struct sugov_policy *sg_policy, u64 curr_ws, + unsigned int prev_freq) +{ + u64 last_ws = sg_policy->last_ws; + unsigned int avg_freq; + + if (use_pelt()) + return; + + BUG_ON(curr_ws < last_ws); + if (curr_ws <= last_ws) + return; + + /* If we skipped some windows */ + if (curr_ws > (last_ws + sched_ravg_window)) { + avg_freq = prev_freq; + /* Reset tracking history */ + sg_policy->last_cyc_update_time = curr_ws; + } else { + sugov_track_cycles(sg_policy, prev_freq, curr_ws); + avg_freq = sg_policy->curr_cycles; + avg_freq /= sched_ravg_window / (NSEC_PER_SEC / KHZ); + } + sg_policy->avg_cap = freq_to_util(sg_policy, avg_freq); + sg_policy->curr_cycles = 0; + sg_policy->last_ws = curr_ws; +} + +static void sugov_fast_switch(struct sugov_policy *sg_policy, u64 time, + unsigned int next_freq) +{ + struct cpufreq_policy *policy = sg_policy->policy; + unsigned int cpu; + + if (!sugov_update_next_freq(sg_policy, time, next_freq)) + return; + + sugov_track_cycles(sg_policy, sg_policy->policy->cur, time); + next_freq = cpufreq_driver_fast_switch(policy, next_freq); + if (!next_freq) + return; + + policy->cur = next_freq; + + if (trace_cpu_frequency_enabled()) { + for_each_cpu(cpu, policy->cpus) + trace_cpu_frequency(next_freq, cpu); + } +} + +static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time, + unsigned int next_freq) +{ + if (!sugov_update_next_freq(sg_policy, time, next_freq)) + return; + + if (use_pelt()) + sg_policy->work_in_progress = true; + irq_work_queue(&sg_policy->irq_work); +} + +#define TARGET_LOAD 80 +/** + * get_next_freq - Compute a new frequency for a given cpufreq policy. + * @sg_policy: schedhorizon policy object to compute the new frequency for. + * @util: Current CPU utilization. + * @max: CPU capacity. + * + * If the utilization is frequency-invariant, choose the new frequency to be + * proportional to it, that is + * + * next_freq = C * max_freq * util / max + * + * Otherwise, approximate the would-be frequency-invariant utilization by + * util_raw * (curr_freq / max_freq) which leads to + * + * next_freq = C * curr_freq * util_raw / max + * + * Take C = 1.25 for the frequency tipping point at (util / max) = 0.8. + * + * The lowest driver-supported frequency which is equal or greater than the raw + * next_freq (as calculated above) is returned, subject to policy min/max and + * cpufreq driver limitations. + */ +static unsigned int get_next_freq(struct sugov_policy *sg_policy, + unsigned long util, unsigned long max, u64 time) +{ + struct cpufreq_policy *policy = sg_policy->policy; + unsigned int freq = arch_scale_freq_invariant() ? + policy->cpuinfo.max_freq : policy->cur; + + freq = map_util_freq(util, freq, max); + do_freq_limit(sg_policy, &freq, time); + trace_sugov_next_freq(policy->cpu, util, max, freq); + + if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update) + return sg_policy->next_freq; + + sg_policy->need_freq_update = false; + sg_policy->prev_cached_raw_freq = sg_policy->cached_raw_freq; + sg_policy->cached_raw_freq = freq; + return cpufreq_driver_resolve_freq(policy, freq); +} + +extern long +schedtune_cpu_margin_with(unsigned long util, int cpu, struct task_struct *p); + +/* + * This function computes an effective utilization for the given CPU, to be + * used for frequency selection given the linear relation: f = u * f_max. + * + * The scheduler tracks the following metrics: + * + * cpu_util_{cfs,rt,dl,irq}() + * cpu_bw_dl() + * + * Where the cfs,rt and dl util numbers are tracked with the same metric and + * synchronized windows and are thus directly comparable. + * + * The @util parameter passed to this function is assumed to be the aggregation + * of RT and CFS util numbers. The cases of DL and IRQ are managed here. + * + * The cfs,rt,dl utilization are the running times measured with rq->clock_task + * which excludes things like IRQ and steal-time. These latter are then accrued + * in the irq utilization. + * + * The DL bandwidth number otoh is not a measured metric but a value computed + * based on the task model parameters and gives the minimal utilization + * required to meet deadlines. + */ +unsigned long schedhorizon_cpu_util(int cpu, unsigned long util_cfs, + unsigned long max, enum schedutil_type type, + struct task_struct *p) +{ + unsigned long dl_util, util, irq; + struct rq *rq = cpu_rq(cpu); + + if (sched_feat(SUGOV_RT_MAX_FREQ) && !IS_BUILTIN(CONFIG_UCLAMP_TASK) && + type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) { + return max; + } + + /* + * Early check to see if IRQ/steal time saturates the CPU, can be + * because of inaccuracies in how we track these -- see + * update_irq_load_avg(). + */ + irq = cpu_util_irq(rq); + if (unlikely(irq >= max)) + return max; + + /* + * Because the time spend on RT/DL tasks is visible as 'lost' time to + * CFS tasks and we use the same metric to track the effective + * utilization (PELT windows are synchronized) we can directly add them + * to obtain the CPU's actual utilization. + * + * CFS and RT utilization can be boosted or capped, depending on + * utilization clamp constraints requested by currently RUNNABLE + * tasks. + * When there are no CFS RUNNABLE tasks, clamps are released and + * frequency will be gracefully reduced with the utilization decay. + */ + util = util_cfs + cpu_util_rt(rq); + if (type == FREQUENCY_UTIL) +#ifdef CONFIG_SCHED_TUNE + util += schedtune_cpu_margin_with(util, cpu, p); +#else + util = uclamp_rq_util_with(rq, util, p); +#endif + + dl_util = cpu_util_dl(rq); + + /* + * For frequency selection we do not make cpu_util_dl() a permanent part + * of this sum because we want to use cpu_bw_dl() later on, but we need + * to check if the CFS+RT+DL sum is saturated (ie. no idle time) such + * that we select f_max when there is no idle time. + * + * NOTE: numerical errors or stop class might cause us to not quite hit + * saturation when we should -- something for later. + */ + if (util + dl_util >= max) + return max; + + /* + * OTOH, for energy computation we need the estimated running time, so + * include util_dl and ignore dl_bw. + */ + if (type == ENERGY_UTIL) + util += dl_util; + + /* + * There is still idle time; further improve the number by using the + * irq metric. Because IRQ/steal time is hidden from the task clock we + * need to scale the task numbers: + * + * 1 - irq + * U' = irq + ------- * U + * max + */ + util = scale_irq_capacity(util, irq, max); + util += irq; + + /* + * Bandwidth required by DEADLINE must always be granted while, for + * FAIR and RT, we use blocked utilization of IDLE CPUs as a mechanism + * to gracefully reduce the frequency when no tasks show up for longer + * periods of time. + * + * Ideally we would like to set bw_dl as min/guaranteed freq and util + + * bw_dl as requested freq. However, cpufreq is not yet ready for such + * an interface. So, we only do the latter for now. + */ + if (type == FREQUENCY_UTIL) + util += cpu_bw_dl(rq); + + return min(max, util); +} + +#ifdef CONFIG_SCHED_WALT +static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) +{ + struct rq *rq = cpu_rq(sg_cpu->cpu); + unsigned long max = arch_scale_cpu_capacity(NULL, sg_cpu->cpu); + + sg_cpu->max = max; + sg_cpu->bw_dl = cpu_bw_dl(rq); + + return stune_util(sg_cpu->cpu, 0, &sg_cpu->walt_load); +} +#else +static unsigned long sugov_get_util(struct sugov_cpu *sg_cpu) +{ + struct rq *rq = cpu_rq(sg_cpu->cpu); + + unsigned long util_cfs = cpu_util_cfs(rq); + unsigned long max = arch_scale_cpu_capacity(NULL, sg_cpu->cpu); + + sg_cpu->max = max; + sg_cpu->bw_dl = cpu_bw_dl(rq); + + return schedhorizon_cpu_util(sg_cpu->cpu, util_cfs, max, + FREQUENCY_UTIL, NULL); +} +#endif + +#ifdef CONFIG_NO_HZ_COMMON +static bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) +{ + unsigned long idle_calls = tick_nohz_get_idle_calls_cpu(sg_cpu->cpu); + bool ret = idle_calls == sg_cpu->saved_idle_calls; + + sg_cpu->saved_idle_calls = idle_calls; + return ret; +} +#else +static inline bool sugov_cpu_is_busy(struct sugov_cpu *sg_cpu) { return false; } +#endif /* CONFIG_NO_HZ_COMMON */ + +#define NL_RATIO 75 +static void sugov_walt_adjust(struct sugov_cpu *sg_cpu, unsigned long *util, + unsigned long *max) +{ + struct sugov_policy *sg_policy = sg_cpu->sg_policy; + bool is_migration = sg_cpu->flags & SCHED_CPUFREQ_INTERCLUSTER_MIG; + bool is_rtg_boost = sg_cpu->walt_load.rtgb_active; + unsigned long nl = sg_cpu->walt_load.nl; + unsigned long cpu_util = sg_cpu->util; + bool is_hiload; + unsigned long pl = sg_cpu->walt_load.pl; + + if (use_pelt()) + return; + + if (is_rtg_boost) + *util = max(*util, sg_policy->rtg_boost_util); + + is_hiload = (cpu_util >= mult_frac(sg_policy->avg_cap, + sg_policy->tunables->hispeed_load, + 100)); + + if (is_hiload && !is_migration) + *util = max(*util, sg_policy->hispeed_util); + + if (is_hiload && nl >= mult_frac(cpu_util, NL_RATIO, 100)) + *util = *max; + + if (sg_policy->tunables->pl) { + if (conservative_pl()) + pl = mult_frac(pl, TARGET_LOAD, 100); + *util = max(*util, pl); + } +} + +/* + * Make sugov_should_update_freq() ignore the rate limit when DL + * has increased the utilization. + */ +static inline void ignore_dl_rate_limit(struct sugov_cpu *sg_cpu, struct sugov_policy *sg_policy) +{ + if (cpu_bw_dl(cpu_rq(sg_cpu->cpu)) > sg_cpu->bw_dl) + sg_policy->limits_changed = true; +} + +static inline unsigned long target_util(struct sugov_policy *sg_policy, + unsigned int freq) +{ + unsigned long util; + + util = freq_to_util(sg_policy, freq); + util = mult_frac(util, TARGET_LOAD, 100); + return util; +} + +static void sugov_update_single(struct update_util_data *hook, u64 time, + unsigned int flags) +{ + struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); + struct sugov_policy *sg_policy = sg_cpu->sg_policy; + unsigned long util, max, hs_util, boost_util; + unsigned int next_f; + bool busy; + + if (!sg_policy->tunables->pl && flags & SCHED_CPUFREQ_PL) + return; + + sg_cpu->last_update = time; + + ignore_dl_rate_limit(sg_cpu, sg_policy); + + if (!sugov_should_update_freq(sg_policy, time)) + return; + + /* Limits may have changed, don't skip frequency update */ + busy = use_pelt() && !sg_policy->need_freq_update && + sugov_cpu_is_busy(sg_cpu); + + sg_cpu->util = util = sugov_get_util(sg_cpu); + max = sg_cpu->max; + sg_cpu->flags = flags; + + if (sg_policy->max != max) { + sg_policy->max = max; + hs_util = target_util(sg_policy, + sg_policy->tunables->hispeed_freq); + sg_policy->hispeed_util = hs_util; + + boost_util = target_util(sg_policy, + sg_policy->tunables->rtg_boost_freq); + sg_policy->rtg_boost_util = boost_util; + } + + sugov_calc_avg_cap(sg_policy, sg_cpu->walt_load.ws, + sg_policy->policy->cur); + + trace_sugov_util_update(sg_cpu->cpu, sg_cpu->util, + sg_policy->avg_cap, max, sg_cpu->walt_load.nl, + sg_cpu->walt_load.pl, + sg_cpu->walt_load.rtgb_active, flags); + + sugov_walt_adjust(sg_cpu, &util, &max); + next_f = get_next_freq(sg_policy, util, max, time); + /* + * Do not reduce the frequency if the CPU has not been idle + * recently, as the reduction is likely to be premature then. + */ + if (busy && next_f < sg_policy->next_freq) { + next_f = sg_policy->next_freq; + + /* Restore cached freq as next_freq has changed */ + sg_policy->cached_raw_freq = sg_policy->prev_cached_raw_freq; + } + + /* + * This code runs under rq->lock for the target CPU, so it won't run + * concurrently on two different CPUs for the same target and it is not + * necessary to acquire the lock in the fast switch case. + */ + if (sg_policy->policy->fast_switch_enabled) { + sugov_fast_switch(sg_policy, time, next_f); + } else { + raw_spin_lock(&sg_policy->update_lock); + sugov_deferred_update(sg_policy, time, next_f); + raw_spin_unlock(&sg_policy->update_lock); + } +} + +static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time) +{ + struct sugov_policy *sg_policy = sg_cpu->sg_policy; + struct cpufreq_policy *policy = sg_policy->policy; + unsigned long util = 0, max = 1; + unsigned int j; + + for_each_cpu(j, policy->cpus) { + struct sugov_cpu *j_sg_cpu = &per_cpu(sugov_cpu, j); + unsigned long j_util, j_max; + + /* + * If the util value for all CPUs in a policy is 0, just using > + * will result in a max value of 1. WALT stats can later update + * the aggregated util value, causing get_next_freq() to compute + * freq = max_freq * 1.25 * (util / max) for nonzero util, + * leading to spurious jumps to fmax. + */ + j_util = j_sg_cpu->util; + j_max = j_sg_cpu->max; + + if (j_util * max >= j_max * util) { + util = j_util; + max = j_max; + } + + sugov_walt_adjust(j_sg_cpu, &util, &max); + } + + return get_next_freq(sg_policy, util, max, time); +} + +static void +sugov_update_shared(struct update_util_data *hook, u64 time, unsigned int flags) +{ + struct sugov_cpu *sg_cpu = container_of(hook, struct sugov_cpu, update_util); + struct sugov_policy *sg_policy = sg_cpu->sg_policy; + unsigned long hs_util, boost_util; + unsigned int next_f; + + if (!sg_policy->tunables->pl && flags & SCHED_CPUFREQ_PL) + return; + + sg_cpu->util = sugov_get_util(sg_cpu); + sg_cpu->flags = flags; + raw_spin_lock(&sg_policy->update_lock); + + if (sg_policy->max != sg_cpu->max) { + sg_policy->max = sg_cpu->max; + hs_util = target_util(sg_policy, + sg_policy->tunables->hispeed_freq); + sg_policy->hispeed_util = hs_util; + + boost_util = target_util(sg_policy, + sg_policy->tunables->rtg_boost_freq); + sg_policy->rtg_boost_util = boost_util; + } + + sg_cpu->last_update = time; + + sugov_calc_avg_cap(sg_policy, sg_cpu->walt_load.ws, + sg_policy->policy->cur); + ignore_dl_rate_limit(sg_cpu, sg_policy); + + trace_sugov_util_update(sg_cpu->cpu, sg_cpu->util, sg_policy->avg_cap, + sg_cpu->max, sg_cpu->walt_load.nl, + sg_cpu->walt_load.pl, + sg_cpu->walt_load.rtgb_active, flags); + + if (sugov_should_update_freq(sg_policy, time) && + !(flags & SCHED_CPUFREQ_CONTINUE)) { + next_f = sugov_next_freq_shared(sg_cpu, time); + + if (sg_policy->policy->fast_switch_enabled) + sugov_fast_switch(sg_policy, time, next_f); + else + sugov_deferred_update(sg_policy, time, next_f); + } + + raw_spin_unlock(&sg_policy->update_lock); +} + +static void sugov_work(struct kthread_work *work) +{ + struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work); + unsigned int freq; + unsigned long flags; + + /* + * Hold sg_policy->update_lock shortly to handle the case where: + * incase sg_policy->next_freq is read here, and then updated by + * sugov_deferred_update() just before work_in_progress is set to false + * here, we may miss queueing the new update. + * + * Note: If a work was queued after the update_lock is released, + * sugov_work() will just be called again by kthread_work code; and the + * request will be proceed before the sugov thread sleeps. + */ + raw_spin_lock_irqsave(&sg_policy->update_lock, flags); + freq = sg_policy->next_freq; + if (use_pelt()) + sg_policy->work_in_progress = false; + sugov_track_cycles(sg_policy, sg_policy->policy->cur, + ktime_get_ns()); + raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags); + + mutex_lock(&sg_policy->work_lock); + __cpufreq_driver_target(sg_policy->policy, freq, CPUFREQ_RELATION_L); + mutex_unlock(&sg_policy->work_lock); +} + +static void sugov_irq_work(struct irq_work *irq_work) +{ + struct sugov_policy *sg_policy; + + sg_policy = container_of(irq_work, struct sugov_policy, irq_work); + + kthread_queue_work(&sg_policy->worker, &sg_policy->work); +} + +static unsigned int *resolve_data_freq (const char *buf, int *num_ret,size_t count) +{ + const char *cp; + unsigned int *output; + int num = 1, i; + + cp = buf; + while ((cp = strpbrk(cp + 1, " "))) + num++; + + output = kmalloc(num * sizeof(unsigned int), GFP_KERNEL); + + cp = buf; + i = 0; + while (i < num && cp-bufmin_rate_limit_ns = min(sg_policy->up_rate_delay_ns, + sg_policy->down_rate_delay_ns); + mutex_unlock(&min_rate_lock); +} + +static ssize_t up_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return scnprintf(buf, PAGE_SIZE, "%u\n", tunables->up_rate_limit_us); +} + +static ssize_t down_rate_limit_us_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return scnprintf(buf, PAGE_SIZE, "%u\n", tunables->down_rate_limit_us); +} + +static ssize_t up_rate_limit_us_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + struct sugov_policy *sg_policy; + unsigned int rate_limit_us; + + if (kstrtouint(buf, 10, &rate_limit_us)) + return -EINVAL; + + tunables->up_rate_limit_us = rate_limit_us; + + list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { + sg_policy->up_rate_delay_ns = rate_limit_us * NSEC_PER_USEC; + update_min_rate_limit_ns(sg_policy); + } + + return count; +} + +static ssize_t down_rate_limit_us_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + struct sugov_policy *sg_policy; + unsigned int rate_limit_us; + + if (kstrtouint(buf, 10, &rate_limit_us)) + return -EINVAL; + + tunables->down_rate_limit_us = rate_limit_us; + + list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { + sg_policy->down_rate_delay_ns = rate_limit_us * NSEC_PER_USEC; + update_min_rate_limit_ns(sg_policy); + } + + return count; +} + +static struct governor_attr up_rate_limit_us = __ATTR_RW(up_rate_limit_us); +static struct governor_attr down_rate_limit_us = __ATTR_RW(down_rate_limit_us); + +static ssize_t hispeed_load_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return scnprintf(buf, PAGE_SIZE, "%u\n", tunables->hispeed_load); +} + +static ssize_t hispeed_load_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + if (kstrtouint(buf, 10, &tunables->hispeed_load)) + return -EINVAL; + + tunables->hispeed_load = min(100U, tunables->hispeed_load); + + return count; +} + +static ssize_t hispeed_freq_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return scnprintf(buf, PAGE_SIZE, "%u\n", tunables->hispeed_freq); +} + +static ssize_t hispeed_freq_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + unsigned int val; + struct sugov_policy *sg_policy; + unsigned long hs_util; + unsigned long flags; + + if (kstrtouint(buf, 10, &val)) + return -EINVAL; + + tunables->hispeed_freq = val; + list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { + raw_spin_lock_irqsave(&sg_policy->update_lock, flags); + hs_util = target_util(sg_policy, + sg_policy->tunables->hispeed_freq); + sg_policy->hispeed_util = hs_util; + raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags); + } + + return count; +} + +static ssize_t rtg_boost_freq_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return scnprintf(buf, PAGE_SIZE, "%u\n", tunables->rtg_boost_freq); +} + +static ssize_t rtg_boost_freq_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + unsigned int val; + struct sugov_policy *sg_policy; + unsigned long boost_util; + unsigned long flags; + + if (kstrtouint(buf, 10, &val)) + return -EINVAL; + + tunables->rtg_boost_freq = val; + list_for_each_entry(sg_policy, &attr_set->policy_list, tunables_hook) { + raw_spin_lock_irqsave(&sg_policy->update_lock, flags); + boost_util = target_util(sg_policy, + sg_policy->tunables->rtg_boost_freq); + sg_policy->rtg_boost_util = boost_util; + raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags); + } + + return count; +} + +static ssize_t pl_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + return scnprintf(buf, PAGE_SIZE, "%u\n", tunables->pl); +} + +static ssize_t pl_store(struct gov_attr_set *attr_set, const char *buf, + size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + + if (kstrtobool(buf, &tunables->pl)) + return -EINVAL; + + return count; +} + +static ssize_t efficient_freq_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + int i; + ssize_t ret = 0; + + for (i = 0; i < tunables->nefficient_freq; i++) + ret += sprintf(buf + ret, "%llu%s", tunables->efficient_freq[i], " "); + + sprintf(buf + ret - 1, "\n"); + + return ret; +} + +static ssize_t up_delay_show(struct gov_attr_set *attr_set, char *buf) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + int i; + ssize_t ret = 0; + + for (i = 0; i < tunables->nup_delay; i++) + ret += sprintf(buf + ret, "%u%s", tunables->up_delay[i] / NSEC_PER_MSEC, " "); + + sprintf(buf + ret - 1, "\n"); + + return ret; +} + +static ssize_t efficient_freq_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + int new_num; + unsigned int *new_efficient_freq = NULL, *old; + + new_efficient_freq = resolve_data_freq(buf, &new_num, count); + + if (new_efficient_freq) { + old = tunables->efficient_freq; + tunables->efficient_freq = new_efficient_freq; + tunables->nefficient_freq = new_num; + tunables->current_step = 0; + if (old != default_efficient_freq_lp + && old != default_efficient_freq_hp + && old != default_efficient_freq_pr) + kfree(old); + } + + return count; +} + +static ssize_t up_delay_store(struct gov_attr_set *attr_set, + const char *buf, size_t count) +{ + struct sugov_tunables *tunables = to_sugov_tunables(attr_set); + int new_num; + u64 *new_up_delay = NULL, *old; + + new_up_delay = resolve_data_delay(buf, &new_num, count); + + if (new_up_delay) { + old = tunables->up_delay; + tunables->up_delay = new_up_delay; + tunables->nup_delay = new_num; + tunables->current_step = 0; + if (old != default_up_delay_lp + && old != default_up_delay_hp + && old != default_up_delay_pr) + kfree(old); + } + + return count; +} + +static struct governor_attr hispeed_load = __ATTR_RW(hispeed_load); +static struct governor_attr hispeed_freq = __ATTR_RW(hispeed_freq); +static struct governor_attr rtg_boost_freq = __ATTR_RW(rtg_boost_freq); +static struct governor_attr pl = __ATTR_RW(pl); +static struct governor_attr efficient_freq = __ATTR_RW(efficient_freq); +static struct governor_attr up_delay = __ATTR_RW(up_delay); + +static struct attribute *sugov_attributes[] = { + &up_rate_limit_us.attr, + &down_rate_limit_us.attr, + &hispeed_load.attr, + &hispeed_freq.attr, + &rtg_boost_freq.attr, + &pl.attr, + &efficient_freq.attr, + &up_delay.attr, + NULL +}; + +static struct kobj_type sugov_tunables_ktype = { + .default_attrs = sugov_attributes, + .sysfs_ops = &governor_sysfs_ops, +}; + +/********************** cpufreq governor interface *********************/ + +static struct cpufreq_governor schedhorizon_gov; + +static struct sugov_policy *sugov_policy_alloc(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy; + + sg_policy = kzalloc(sizeof(*sg_policy), GFP_KERNEL); + if (!sg_policy) + return NULL; + + sg_policy->policy = policy; + raw_spin_lock_init(&sg_policy->update_lock); + return sg_policy; +} + +static void sugov_policy_free(struct sugov_policy *sg_policy) +{ + kfree(sg_policy); +} + +static int sugov_kthread_create(struct sugov_policy *sg_policy) +{ + struct task_struct *thread; + struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO / 2 }; + struct cpufreq_policy *policy = sg_policy->policy; + int ret; + + /* kthread only required for slow path */ + if (policy->fast_switch_enabled) + return 0; + + kthread_init_work(&sg_policy->work, sugov_work); + kthread_init_worker(&sg_policy->worker); + thread = kthread_create(kthread_worker_fn, &sg_policy->worker, + "sugov:%d", + cpumask_first(policy->related_cpus)); + if (IS_ERR(thread)) { + pr_err("failed to create sugov thread: %ld\n", PTR_ERR(thread)); + return PTR_ERR(thread); + } + + ret = sched_setscheduler_nocheck(thread, SCHED_FIFO, ¶m); + if (ret) { + kthread_stop(thread); + pr_warn("%s: failed to set SCHED_FIFO\n", __func__); + return ret; + } + + sg_policy->thread = thread; + kthread_bind_mask(thread, policy->related_cpus); + init_irq_work(&sg_policy->irq_work, sugov_irq_work); + mutex_init(&sg_policy->work_lock); + + wake_up_process(thread); + + return 0; +} + +static void sugov_kthread_stop(struct sugov_policy *sg_policy) +{ + /* kthread only required for slow path */ + if (sg_policy->policy->fast_switch_enabled) + return; + + kthread_flush_worker(&sg_policy->worker); + kthread_stop(sg_policy->thread); + mutex_destroy(&sg_policy->work_lock); +} + +static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_policy) +{ + struct sugov_tunables *tunables; + + tunables = kzalloc(sizeof(*tunables), GFP_KERNEL); + if (tunables) { + gov_attr_set_init(&tunables->attr_set, &sg_policy->tunables_hook); + if (!have_governor_per_policy()) + global_tunables = tunables; + } + return tunables; +} + +static void sugov_tunables_save(struct cpufreq_policy *policy, + struct sugov_tunables *tunables) +{ + int cpu; + struct sugov_tunables *cached = per_cpu(cached_tunables, policy->cpu); + + if (!have_governor_per_policy()) + return; + + if (!cached) { + cached = kzalloc(sizeof(*tunables), GFP_KERNEL); + if (!cached) + return; + + for_each_cpu(cpu, policy->related_cpus) + per_cpu(cached_tunables, cpu) = cached; + } + + cached->pl = tunables->pl; + cached->hispeed_load = tunables->hispeed_load; + cached->rtg_boost_freq = tunables->rtg_boost_freq; + cached->hispeed_freq = tunables->hispeed_freq; + cached->up_rate_limit_us = tunables->up_rate_limit_us; + cached->down_rate_limit_us = tunables->down_rate_limit_us; + cached->efficient_freq = tunables->efficient_freq; + cached->up_delay = tunables->up_delay; + cached->nefficient_freq = tunables->nefficient_freq; + cached->nup_delay = tunables->nup_delay; +} + +static void sugov_tunables_free(struct sugov_tunables *tunables) +{ + if (!have_governor_per_policy()) + global_tunables = NULL; + + kfree(tunables); +} + +static void sugov_tunables_restore(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + struct sugov_tunables *tunables = sg_policy->tunables; + struct sugov_tunables *cached = per_cpu(cached_tunables, policy->cpu); + + if (!cached) + return; + + tunables->pl = cached->pl; + tunables->hispeed_load = cached->hispeed_load; + tunables->rtg_boost_freq = cached->rtg_boost_freq; + tunables->hispeed_freq = cached->hispeed_freq; + tunables->up_rate_limit_us = cached->up_rate_limit_us; + tunables->down_rate_limit_us = cached->down_rate_limit_us; + tunables->efficient_freq = cached->efficient_freq; + tunables->up_delay = cached->up_delay; + tunables->nefficient_freq = cached->nefficient_freq; + tunables->nup_delay = cached->nup_delay; +} + +static int sugov_init(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy; + struct sugov_tunables *tunables; + unsigned long util; + int ret = 0; + + /* State should be equivalent to EXIT */ + if (policy->governor_data) + return -EBUSY; + + cpufreq_enable_fast_switch(policy); + + sg_policy = sugov_policy_alloc(policy); + if (!sg_policy) { + ret = -ENOMEM; + goto disable_fast_switch; + } + + ret = sugov_kthread_create(sg_policy); + if (ret) + goto free_sg_policy; + + mutex_lock(&global_tunables_lock); + + if (global_tunables) { + if (WARN_ON(have_governor_per_policy())) { + ret = -EINVAL; + goto stop_kthread; + } + policy->governor_data = sg_policy; + sg_policy->tunables = global_tunables; + + gov_attr_set_get(&global_tunables->attr_set, &sg_policy->tunables_hook); + goto out; + } + + tunables = sugov_tunables_alloc(sg_policy); + if (!tunables) { + ret = -ENOMEM; + goto stop_kthread; + } + + tunables->up_rate_limit_us = cpufreq_policy_transition_delay_us(policy); + tunables->down_rate_limit_us = cpufreq_policy_transition_delay_us(policy); + + if (cpumask_test_cpu(sg_policy->policy->cpu, cpu_lp_mask)) { + tunables->efficient_freq = default_efficient_freq_lp; + tunables->nefficient_freq = ARRAY_SIZE(default_efficient_freq_lp); + tunables->up_delay = default_up_delay_lp; + tunables->nup_delay = ARRAY_SIZE(default_up_delay_lp); + tunables->rtg_boost_freq = DEFAULT_RTG_BOOST_FREQ_LP; + tunables->hispeed_load = DEFAULT_HISPEED_LOAD_LP; + tunables->hispeed_freq = DEFAULT_HISPEED_FREQ_LP; + tunables->pl = DEFAULT_PL_LP; + } else if (cpumask_test_cpu(sg_policy->policy->cpu, cpu_perf_mask)) { + tunables->efficient_freq = default_efficient_freq_hp; + tunables->nefficient_freq = ARRAY_SIZE(default_efficient_freq_hp); + tunables->up_delay = default_up_delay_hp; + tunables->nup_delay = ARRAY_SIZE(default_up_delay_hp); + tunables->rtg_boost_freq = DEFAULT_RTG_BOOST_FREQ_HP; + tunables->hispeed_load = DEFAULT_HISPEED_LOAD_HP; + tunables->hispeed_freq = DEFAULT_HISPEED_FREQ_HP; + tunables->pl = DEFAULT_PL_HP; + } else { + tunables->efficient_freq = default_efficient_freq_pr; + tunables->nefficient_freq = ARRAY_SIZE(default_efficient_freq_pr); + tunables->up_delay = default_up_delay_pr; + tunables->nup_delay = ARRAY_SIZE(default_up_delay_pr); + tunables->rtg_boost_freq = DEFAULT_RTG_BOOST_FREQ_PR; + tunables->hispeed_load = DEFAULT_HISPEED_LOAD_PR; + tunables->hispeed_freq = DEFAULT_HISPEED_FREQ_PR; + tunables->pl = DEFAULT_PL_PR; + } + + policy->governor_data = sg_policy; + sg_policy->tunables = tunables; + + util = target_util(sg_policy, sg_policy->tunables->rtg_boost_freq); + sg_policy->rtg_boost_util = util; + + stale_ns = sched_ravg_window + (sched_ravg_window >> 3); + + sugov_tunables_restore(policy); + + ret = kobject_init_and_add(&tunables->attr_set.kobj, &sugov_tunables_ktype, + get_governor_parent_kobj(policy), "%s", + schedhorizon_gov.name); + if (ret) + goto fail; + +out: + mutex_unlock(&global_tunables_lock); + return 0; + +fail: + kobject_put(&tunables->attr_set.kobj); + policy->governor_data = NULL; + sugov_tunables_free(tunables); + +stop_kthread: + sugov_kthread_stop(sg_policy); + mutex_unlock(&global_tunables_lock); + +free_sg_policy: + sugov_policy_free(sg_policy); + +disable_fast_switch: + cpufreq_disable_fast_switch(policy); + + pr_err("initialization failed (error %d)\n", ret); + return ret; +} + +static void sugov_exit(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + struct sugov_tunables *tunables = sg_policy->tunables; + unsigned int count; + + mutex_lock(&global_tunables_lock); + + count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook); + policy->governor_data = NULL; + if (!count) { + sugov_tunables_save(policy, tunables); + sugov_tunables_free(tunables); + } + + mutex_unlock(&global_tunables_lock); + + sugov_kthread_stop(sg_policy); + sugov_policy_free(sg_policy); + cpufreq_disable_fast_switch(policy); +} + +static int sugov_start(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + unsigned int cpu; + + sg_policy->up_rate_delay_ns = + sg_policy->tunables->up_rate_limit_us * NSEC_PER_USEC; + sg_policy->down_rate_delay_ns = + sg_policy->tunables->down_rate_limit_us * NSEC_PER_USEC; + update_min_rate_limit_ns(sg_policy); + sg_policy->last_freq_update_time = 0; + sg_policy->next_freq = 0; + sg_policy->work_in_progress = false; + sg_policy->limits_changed = false; + sg_policy->need_freq_update = false; + sg_policy->cached_raw_freq = 0; + sg_policy->prev_cached_raw_freq = 0; + + for_each_cpu(cpu, policy->cpus) { + struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); + + memset(sg_cpu, 0, sizeof(*sg_cpu)); + sg_cpu->cpu = cpu; + sg_cpu->sg_policy = sg_policy; + sg_cpu->min = + (SCHED_CAPACITY_SCALE * policy->cpuinfo.min_freq) / + policy->cpuinfo.max_freq; + } + + for_each_cpu(cpu, policy->cpus) { + struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu); + + cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util, + policy_is_shared(policy) ? + sugov_update_shared : + sugov_update_single); + } + return 0; +} + +static void sugov_stop(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + unsigned int cpu; + + for_each_cpu(cpu, policy->cpus) + cpufreq_remove_update_util_hook(cpu); + + synchronize_sched(); + + if (!policy->fast_switch_enabled) { + irq_work_sync(&sg_policy->irq_work); + kthread_cancel_work_sync(&sg_policy->work); + } +} + +static void sugov_limits(struct cpufreq_policy *policy) +{ + struct sugov_policy *sg_policy = policy->governor_data; + unsigned long flags, now; + unsigned int freq; + + if (!policy->fast_switch_enabled) { + mutex_lock(&sg_policy->work_lock); + raw_spin_lock_irqsave(&sg_policy->update_lock, flags); + sugov_track_cycles(sg_policy, sg_policy->policy->cur, + ktime_get_ns()); + raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags); + cpufreq_policy_apply_limits(policy); + mutex_unlock(&sg_policy->work_lock); + } else { + raw_spin_lock_irqsave(&sg_policy->update_lock, flags); + freq = policy->cur; + now = ktime_get_ns(); + + /* + * cpufreq_driver_resolve_freq() has a clamp, so we do not need + * to do any sort of additional validation here. + */ + freq = cpufreq_driver_resolve_freq(policy, freq); + sg_policy->cached_raw_freq = freq; + sugov_fast_switch(sg_policy, now, freq); + raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags); + } + + sg_policy->limits_changed = true; +} + +static struct cpufreq_governor schedhorizon_gov = { + .name = "schedhorizon", + .owner = THIS_MODULE, + .dynamic_switching = true, + .init = sugov_init, + .exit = sugov_exit, + .start = sugov_start, + .stop = sugov_stop, + .limits = sugov_limits, +}; + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDHORIZON +struct cpufreq_governor *cpufreq_default_governor(void) +{ + return &schedhorizon_gov; +} +#endif + +static int __init sugov_register(void) +{ + return cpufreq_register_governor(&schedhorizon_gov); +} +fs_initcall(sugov_register); + diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 452ea9fa5bdd..e059f2db3c45 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -2475,7 +2475,7 @@ int sched_dl_global_validate(void) u64 period = global_rt_period(); u64 new_bw = to_ratio(period, runtime); struct dl_bw *dl_b; - int cpu, ret = 0; + int cpu, cpus, ret = 0; unsigned long flags; /* @@ -2490,9 +2490,10 @@ int sched_dl_global_validate(void) for_each_possible_cpu(cpu) { rcu_read_lock_sched(); dl_b = dl_bw_of(cpu); + cpus = dl_bw_cpus(cpu); raw_spin_lock_irqsave(&dl_b->lock, flags); - if (new_bw < dl_b->total_bw) + if (new_bw * cpus < dl_b->total_bw) ret = -EBUSY; raw_spin_unlock_irqrestore(&dl_b->lock, flags); diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index c3092ff76ac2..f21cd1cd3dd4 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -50,134 +50,10 @@ static unsigned long nsec_low(unsigned long long nsec) #define SPLIT_NS(x) nsec_high(x), nsec_low(x) -#define SCHED_FEAT(name, enabled) \ - #name , - -static const char * const sched_feat_names[] = { -#include "features.h" -}; - -#undef SCHED_FEAT - -static int sched_feat_show(struct seq_file *m, void *v) -{ - int i; - - for (i = 0; i < __SCHED_FEAT_NR; i++) { - if (!(sysctl_sched_features & (1UL << i))) - seq_puts(m, "NO_"); - seq_printf(m, "%s ", sched_feat_names[i]); - } - seq_puts(m, "\n"); - - return 0; -} - -#ifdef CONFIG_JUMP_LABEL - -#define jump_label_key__true STATIC_KEY_INIT_TRUE -#define jump_label_key__false STATIC_KEY_INIT_FALSE - -#define SCHED_FEAT(name, enabled) \ - jump_label_key__##enabled , - -struct static_key sched_feat_keys[__SCHED_FEAT_NR] = { -#include "features.h" -}; - -#undef SCHED_FEAT - -static void sched_feat_disable(int i) -{ - static_key_disable_cpuslocked(&sched_feat_keys[i]); -} - -static void sched_feat_enable(int i) -{ - static_key_enable_cpuslocked(&sched_feat_keys[i]); -} -#else -static void sched_feat_disable(int i) { }; -static void sched_feat_enable(int i) { }; -#endif /* CONFIG_JUMP_LABEL */ - -static int sched_feat_set(char *cmp) -{ - int i; - int neg = 0; - - if (strncmp(cmp, "NO_", 3) == 0) { - neg = 1; - cmp += 3; - } - - i = match_string(sched_feat_names, __SCHED_FEAT_NR, cmp); - if (i < 0) - return i; - - if (neg) { - sysctl_sched_features &= ~(1UL << i); - sched_feat_disable(i); - } else { - sysctl_sched_features |= (1UL << i); - sched_feat_enable(i); - } - - return 0; -} - -static ssize_t -sched_feat_write(struct file *filp, const char __user *ubuf, - size_t cnt, loff_t *ppos) -{ - char buf[64]; - char *cmp; - int ret; - struct inode *inode; - - if (cnt > 63) - cnt = 63; - - if (copy_from_user(&buf, ubuf, cnt)) - return -EFAULT; - - buf[cnt] = 0; - cmp = strstrip(buf); - - /* Ensure the static_key remains in a consistent state */ - inode = file_inode(filp); - cpus_read_lock(); - inode_lock(inode); - ret = sched_feat_set(cmp); - inode_unlock(inode); - cpus_read_unlock(); - if (ret < 0) - return ret; - - *ppos += cnt; - - return cnt; -} - -static int sched_feat_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, sched_feat_show, NULL); -} - -static const struct file_operations sched_feat_fops = { - .open = sched_feat_open, - .write = sched_feat_write, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - __read_mostly bool sched_debug_enabled; static __init int sched_init_debug(void) { - debugfs_create_file("sched_features", 0644, NULL, NULL, - &sched_feat_fops); debugfs_create_bool("sched_debug", 0644, NULL, &sched_debug_enabled); @@ -760,7 +636,6 @@ static void sched_debug_header(struct seq_file *m) PN(sysctl_sched_min_granularity); PN(sysctl_sched_wakeup_granularity); P(sysctl_sched_child_runs_first); - P(sysctl_sched_features); #ifdef CONFIG_SCHED_WALT P(sched_init_task_load_windows); P(sched_ravg_window); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 98c7b00cc399..52bf0c46bcfa 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2530,7 +2530,8 @@ void task_numa_fault(int last_cpupid, int mem_node, int pages, int flags) struct numa_group *ng; int priv; - if (!static_branch_likely(&sched_numa_balancing)) + if (!IS_ENABLED(CONFIG_NUMA_BALANCING) || + !static_branch_likely(&sched_numa_balancing)) return; /* for example, ksmd faulting in a user's mm */ @@ -7980,7 +7981,7 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f rcu_read_lock(); for_each_domain(cpu, tmp) { if (!(tmp->flags & SD_LOAD_BALANCE)) - break; + continue; /* * If both 'cpu' and 'prev_cpu' are part of this domain, @@ -12099,7 +12100,8 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued) entity_tick(cfs_rq, se, queued); } - if (static_branch_unlikely(&sched_numa_balancing)) + if (IS_ENABLED(CONFIG_NUMA_BALANCING) && + static_branch_unlikely(&sched_numa_balancing)) task_tick_numa(rq, curr); update_misfit_status(curr, rq); diff --git a/kernel/sched/features.h b/kernel/sched/features.h index 842c262757ac..f911c5eb888c 100644 --- a/kernel/sched/features.h +++ b/kernel/sched/features.h @@ -4,66 +4,66 @@ * them to run sooner, but does not allow tons of sleepers to * rip the spread apart. */ -SCHED_FEAT(GENTLE_FAIR_SLEEPERS, true) +#define SCHED_FEAT_GENTLE_FAIR_SLEEPERS 0 /* * Place new tasks ahead so that they do not starve already running * tasks */ -SCHED_FEAT(START_DEBIT, true) +#define SCHED_FEAT_START_DEBIT 1 /* * Prefer to schedule the task we woke last (assuming it failed * wakeup-preemption), since its likely going to consume data we * touched, increases cache locality. */ -SCHED_FEAT(NEXT_BUDDY, false) + #define SCHED_FEAT_NEXT_BUDDY 0 /* * Prefer to schedule the task that ran last (when we did * wake-preempt) as that likely will touch the same data, increases * cache locality. */ -SCHED_FEAT(LAST_BUDDY, true) + #define SCHED_FEAT_LAST_BUDDY 1 /* * Consider buddies to be cache hot, decreases the likelyness of a * cache buddy being migrated away, increases cache locality. */ -SCHED_FEAT(CACHE_HOT_BUDDY, true) + #define SCHED_FEAT_CACHE_HOT_BUDDY 1 /* * Allow wakeup-time preemption of the current task: */ -SCHED_FEAT(WAKEUP_PREEMPTION, true) + #define SCHED_FEAT_WAKEUP_PREEMPTION 1 -SCHED_FEAT(HRTICK, false) -SCHED_FEAT(DOUBLE_TICK, false) -SCHED_FEAT(LB_BIAS, true) +#define SCHED_FEAT_HRTICK 0 +#define SCHED_FEAT_DOUBLE_TICK 0 +#define SCHED_FEAT_LB_BIAS 0 /* * Decrement CPU capacity based on time not spent running tasks */ -SCHED_FEAT(NONTASK_CAPACITY, true) + #define SCHED_FEAT_NONTASK_CAPACITY 1 /* * Queue remote wakeups on the target CPU and process them * using the scheduler IPI. Reduces rq->lock contention/bounces. */ -SCHED_FEAT(TTWU_QUEUE, false) + #define SCHED_FEAT_TTWU_QUEUE 1 /* * When doing wakeups, attempt to limit superfluous scans of the LLC domain. */ -SCHED_FEAT(SIS_AVG_CPU, false) -SCHED_FEAT(SIS_PROP, true) +#define SCHED_FEAT_SIS_AVG_CPU 0 +#define SCHED_FEAT_SIS_PROP 1 /* * Issue a WARN when we do multiple update_rq_clock() calls * in a single rq->lock section. Default disabled because the * annotations are not complete. */ -SCHED_FEAT(WARN_DOUBLE_CLOCK, false) + #define SCHED_FEAT_WARN_DOUBLE_CLOCK 0 #ifdef HAVE_RT_PUSH_IPI /* @@ -75,27 +75,29 @@ SCHED_FEAT(WARN_DOUBLE_CLOCK, false) * IPI to that CPU and let that CPU push the RT task to where * it should go may be a better scenario. */ -SCHED_FEAT(RT_PUSH_IPI, true) +#define SCHED_FEAT_RT_PUSH_IPI 1 +#else +#define SCHED_FEAT_RT_PUSH_IPI 0 #endif -SCHED_FEAT(RT_RUNTIME_SHARE, true) -SCHED_FEAT(LB_MIN, false) -SCHED_FEAT(ATTACH_AGE_LOAD, true) +#define SCHED_FEAT_RT_RUNTIME_SHARE 0 +#define SCHED_FEAT_LB_MIN 0 +#define SCHED_FEAT_ATTACH_AGE_LOAD 1 -SCHED_FEAT(WA_IDLE, true) -SCHED_FEAT(WA_WEIGHT, true) -SCHED_FEAT(WA_BIAS, true) +#define SCHED_FEAT_WA_IDLE 1 +#define SCHED_FEAT_WA_WEIGHT 1 +#define SCHED_FEAT_WA_BIAS 1 /* * UtilEstimation. Use estimated CPU utilization. */ -SCHED_FEAT(UTIL_EST, true) -SCHED_FEAT(UTIL_EST_FASTUP, true) +#define SCHED_FEAT_UTIL_EST 1 +#define SCHED_FEAT_UTIL_EST_FASTUP 1 /* * Fast pre-selection of CPU candidates for EAS. */ -SCHED_FEAT(FIND_BEST_TARGET, true) +#define SCHED_FEAT_FIND_BEST_TARGET 1 /* * Energy aware scheduling algorithm choices: @@ -104,12 +106,12 @@ SCHED_FEAT(FIND_BEST_TARGET, true) * the EAS path for wakeup task placement. Otherwise, put * those tasks through the mainline slow path. */ -SCHED_FEAT(EAS_PREFER_IDLE, true) +#define SCHED_FEAT_EAS_PREFER_IDLE 0 /* * Request max frequency from schedutil whenever a RT task is running. */ -SCHED_FEAT(SUGOV_RT_MAX_FREQ, false) +#define SCHED_FEAT_SUGOV_RT_MAX_FREQ 0 /* * Apply schedtune boost hold to tasks of all sched classes. @@ -120,4 +122,4 @@ SCHED_FEAT(SUGOV_RT_MAX_FREQ, false) * If disabled, this behaviour will only apply to tasks of the * RT class. */ -SCHED_FEAT(SCHEDTUNE_BOOST_HOLD_ALL, false) + #define SCHED_FEAT_SCHEDTUNE_BOOST_HOLD_ALL 0 diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 2d69df8a9b6b..49612166e00e 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -2722,10 +2722,11 @@ const struct sched_class rt_sched_class = { */ static DEFINE_MUTEX(rt_constraints_mutex); -/* Must be called with tasklist_lock held */ static inline int tg_has_rt_tasks(struct task_group *tg) { - struct task_struct *g, *p; + struct task_struct *task; + struct css_task_iter it; + int ret = 0; /* * Autogroups do not have RT tasks; see autogroup_create(). @@ -2733,12 +2734,12 @@ static inline int tg_has_rt_tasks(struct task_group *tg) if (task_group_is_autogroup(tg)) return 0; - for_each_process_thread(g, p) { - if (rt_task(p) && task_group(p) == tg) - return 1; - } + css_task_iter_start(&tg->css, 0, &it); + while (!ret && (task = css_task_iter_next(&it))) + ret |= rt_task(task); + css_task_iter_end(&it); - return 0; + return ret; } struct rt_schedulable_data { @@ -2769,9 +2770,10 @@ static int tg_rt_schedulable(struct task_group *tg, void *data) return -EINVAL; /* - * Ensure we don't starve existing RT tasks. + * Ensure we don't starve existing RT tasks if runtime turns zero. */ - if (rt_bandwidth_enabled() && !runtime && tg_has_rt_tasks(tg)) + if (rt_bandwidth_enabled() && !runtime && + tg->rt_bandwidth.rt_runtime && tg_has_rt_tasks(tg)) return -EBUSY; total = to_ratio(period, runtime); @@ -2837,7 +2839,6 @@ static int tg_set_rt_bandwidth(struct task_group *tg, return -EINVAL; mutex_lock(&rt_constraints_mutex); - read_lock(&tasklist_lock); err = __rt_schedulable(tg, rt_period, rt_runtime); if (err) goto unlock; @@ -2855,7 +2856,6 @@ static int tg_set_rt_bandwidth(struct task_group *tg, } raw_spin_unlock_irq(&tg->rt_bandwidth.rt_runtime_lock); unlock: - read_unlock(&tasklist_lock); mutex_unlock(&rt_constraints_mutex); return err; @@ -2914,9 +2914,7 @@ static int sched_rt_global_constraints(void) int ret = 0; mutex_lock(&rt_constraints_mutex); - read_lock(&tasklist_lock); ret = __rt_schedulable(NULL, 0, 0); - read_unlock(&tasklist_lock); mutex_unlock(&rt_constraints_mutex); return ret; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index a7e770a6e10e..3b011df5acda 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -75,6 +75,7 @@ #include "cpupri.h" #include "cpudeadline.h" +#include "features.h" #ifdef CONFIG_SCHED_DEBUG # define SCHED_WARN_ON(x) WARN_ONCE(x, #x) @@ -277,7 +278,7 @@ static inline int task_has_dl_policy(struct task_struct *p) static inline bool dl_entity_is_special(struct sched_dl_entity *dl_se) { -#ifdef CONFIG_CPU_FREQ_GOV_SCHEDUTIL + #if defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) || defined(CONFIG_CPU_FREQ_GOV_SCHEDHORIZON) return unlikely(dl_se->flags & SCHED_FLAG_SUGOV); #else return false; @@ -313,30 +314,6 @@ struct rt_bandwidth { void __dl_clear_params(struct task_struct *p); -/* - * To keep the bandwidth of -deadline tasks and groups under control - * we need some place where: - * - store the maximum -deadline bandwidth of the system (the group); - * - cache the fraction of that bandwidth that is currently allocated. - * - * This is all done in the data structure below. It is similar to the - * one used for RT-throttling (rt_bandwidth), with the main difference - * that, since here we are only interested in admission control, we - * do not decrease any runtime while the group "executes", neither we - * need a timer to replenish it. - * - * With respect to SMP, the bandwidth is given on a per-CPU basis, - * meaning that: - * - dl_bw (< 100%) is the bandwidth of the system (group) on each CPU; - * - dl_total_bw array contains, in the i-eth element, the currently - * allocated bandwidth on the i-eth CPU. - * Moreover, groups consume bandwidth on each CPU, while tasks only - * consume bandwidth on the CPU they're running on. - * Finally, dl_total_bw_cpu is used to cache the index of dl_total_bw - * that will be shown the next time the proc or cgroup controls will - * be red. It on its turn can be changed by writing on its own - * control. - */ struct dl_bandwidth { raw_spinlock_t dl_runtime_lock; u64 dl_runtime; @@ -348,6 +325,24 @@ static inline int dl_bandwidth_enabled(void) return sysctl_sched_rt_runtime >= 0; } +/* + * To keep the bandwidth of -deadline tasks under control + * we need some place where: + * - store the maximum -deadline bandwidth of each cpu; + * - cache the fraction of bandwidth that is currently allocated in + * each root domain; + * + * This is all done in the data structure below. It is similar to the + * one used for RT-throttling (rt_bandwidth), with the main difference + * that, since here we are only interested in admission control, we + * do not decrease any runtime while the group "executes", neither we + * need a timer to replenish it. + * + * With respect to SMP, bandwidth is given on a per root domain basis, + * meaning that: + * - bw (< 100%) is the deadline bandwidth of each CPU; + * - total_bw is the currently allocated bandwidth in each root domain; + */ struct dl_bw { raw_spinlock_t lock; u64 bw; @@ -1446,7 +1441,11 @@ queue_balance_callback(struct rq *rq, rq->balance_callback = head; } +#if SCHED_FEAT_TTWU_QUEUE extern void sched_ttwu_pending(void); +#else +static inline void sched_ttwu_pending(void) { } +#endif #define rcu_dereference_check_sched_domain(p) \ rcu_dereference_check((p), \ @@ -1672,60 +1671,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) # define const_debug const #endif -#define SCHED_FEAT(name, enabled) \ - __SCHED_FEAT_##name , - -enum { -#include "features.h" - __SCHED_FEAT_NR, -}; - -#undef SCHED_FEAT - -#ifdef CONFIG_SCHED_DEBUG - -/* - * To support run-time toggling of sched features, all the translation units - * (but core.c) reference the sysctl_sched_features defined in core.c. - */ -extern const_debug unsigned int sysctl_sched_features; - -#ifdef CONFIG_JUMP_LABEL -#define SCHED_FEAT(name, enabled) \ -static __always_inline bool static_branch_##name(struct static_key *key) \ -{ \ - return static_key_##enabled(key); \ -} - -#include "features.h" -#undef SCHED_FEAT - -extern struct static_key sched_feat_keys[__SCHED_FEAT_NR]; -#define sched_feat(x) (static_branch_##x(&sched_feat_keys[__SCHED_FEAT_##x])) - -#else /* !CONFIG_JUMP_LABEL */ - -#define sched_feat(x) (sysctl_sched_features & (1UL << __SCHED_FEAT_##x)) - -#endif /* CONFIG_JUMP_LABEL */ - -#else /* !SCHED_DEBUG */ - -/* - * Each translation unit has its own copy of sysctl_sched_features to allow - * constants propagation at compile time and compiler optimization based on - * features default. - */ -#define SCHED_FEAT(name, enabled) \ - (1UL << __SCHED_FEAT_##name) * enabled | -static const_debug __maybe_unused unsigned int sysctl_sched_features = -#include "features.h" - 0; -#undef SCHED_FEAT - -#define sched_feat(x) !!(sysctl_sched_features & (1UL << __SCHED_FEAT_##x)) - -#endif /* SCHED_DEBUG */ +#define sched_feat(x) SCHED_FEAT_##x extern struct static_key_false sched_numa_balancing; extern struct static_key_false sched_schedstats; @@ -2679,7 +2625,7 @@ static inline unsigned long cpu_util_cfs(struct rq *rq) } #endif -#ifdef CONFIG_CPU_FREQ_GOV_SCHEDUTIL + #if defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) || defined(CONFIG_CPU_FREQ_GOV_SCHEDHORIZON) unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs, unsigned long max, enum schedutil_type type, diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 0de9dcfde495..59f23bfea116 100644 --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c @@ -36,6 +36,17 @@ void add_wait_queue_exclusive(struct wait_queue_head *wq_head, struct wait_queue } EXPORT_SYMBOL(add_wait_queue_exclusive); +void add_wait_queue_exclusive_lifo(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry) +{ + unsigned long flags; + + wq_entry->flags |= WQ_FLAG_EXCLUSIVE; + spin_lock_irqsave(&wq_head->lock, flags); + __add_wait_queue(wq_head, wq_entry); + spin_unlock_irqrestore(&wq_head->lock, flags); +} +EXPORT_SYMBOL(add_wait_queue_exclusive_lifo); + void remove_wait_queue(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry) { unsigned long flags; @@ -249,6 +260,19 @@ prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_ent } EXPORT_SYMBOL(prepare_to_wait_exclusive); +void prepare_to_wait_exclusive_lifo(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state) +{ + unsigned long flags; + + wq_entry->flags |= WQ_FLAG_EXCLUSIVE; + spin_lock_irqsave(&wq_head->lock, flags); + if (list_empty(&wq_entry->entry)) + __add_wait_queue(wq_head, wq_entry); + set_current_state(state); + spin_unlock_irqrestore(&wq_head->lock, flags); +} +EXPORT_SYMBOL(prepare_to_wait_exclusive_lifo); + void init_wait_entry(struct wait_queue_entry *wq_entry, int flags) { wq_entry->flags = flags; diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index dca7f17cc51b..c77fc314c63b 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -2150,11 +2150,6 @@ void init_new_task_load(struct task_struct *p) memset(&p->ravg, 0, sizeof(struct ravg)); p->cpu_cycles = 0; - p->ravg.curr_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), - GFP_KERNEL | __GFP_NOFAIL); - p->ravg.prev_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), - GFP_KERNEL | __GFP_NOFAIL); - if (init_load_pct) { init_load_windows = div64_u64((u64)init_load_pct * (u64)sched_ravg_window, 100); @@ -2172,46 +2167,28 @@ void init_new_task_load(struct task_struct *p) p->unfilter = sysctl_sched_task_unfilter_period; } -/* - * kfree() may wakeup kswapd. So this function should NOT be called - * with any CPU's rq->lock acquired. - */ -void free_task_load_ptrs(struct task_struct *p) -{ - kfree(p->ravg.curr_window_cpu); - kfree(p->ravg.prev_window_cpu); - - /* - * update_task_ravg() can be called for exiting tasks. While the - * function itself ensures correct behavior, the corresponding - * trace event requires that these pointers be NULL. - */ - p->ravg.curr_window_cpu = NULL; - p->ravg.prev_window_cpu = NULL; -} - void reset_task_stats(struct task_struct *p) { - u32 sum = 0; - u32 *curr_window_ptr = NULL; - u32 *prev_window_ptr = NULL; + u32 sum; + u32 curr_window_saved[CONFIG_NR_CPUS]; + u32 prev_window_saved[CONFIG_NR_CPUS]; if (exiting_task(p)) { sum = EXITING_TASK_MARKER; - } else { - curr_window_ptr = p->ravg.curr_window_cpu; - prev_window_ptr = p->ravg.prev_window_cpu; - memset(curr_window_ptr, 0, sizeof(u32) * nr_cpu_ids); - memset(prev_window_ptr, 0, sizeof(u32) * nr_cpu_ids); - } - memset(&p->ravg, 0, sizeof(struct ravg)); + memset(&p->ravg, 0, sizeof(struct ravg)); - p->ravg.curr_window_cpu = curr_window_ptr; - p->ravg.prev_window_cpu = prev_window_ptr; + /* Retain EXITING_TASK marker */ + p->ravg.sum_history[0] = sum; + } else { + memcpy(curr_window_saved, p->ravg.curr_window_cpu, sizeof(curr_window_saved)); + memcpy(prev_window_saved, p->ravg.prev_window_cpu, sizeof(prev_window_saved)); + + memset(&p->ravg, 0, sizeof(struct ravg)); - /* Retain EXITING_TASK marker */ - p->ravg.sum_history[0] = sum; + memcpy(p->ravg.curr_window_cpu, curr_window_saved, sizeof(curr_window_saved)); + memcpy(p->ravg.prev_window_cpu, prev_window_saved, sizeof(prev_window_saved)); + } } void mark_task_starting(struct task_struct *p) diff --git a/kernel/scs.c b/kernel/scs.c index ad74d13f2c0f..c8e53358e20a 100644 --- a/kernel/scs.c +++ b/kernel/scs.c @@ -185,36 +185,31 @@ int scs_prepare(struct task_struct *tsk, int node) } #ifdef CONFIG_DEBUG_STACK_USAGE -static inline unsigned long scs_used(struct task_struct *tsk) +static void scs_check_usage(struct task_struct *tsk) { + static unsigned long highest; + unsigned long *p = __scs_base(tsk); unsigned long *end = scs_magic(p); - unsigned long s = (unsigned long)p; - - while (p < end && READ_ONCE_NOCHECK(*p)) - p++; + unsigned long prev, curr = highest, used = 0; - return (unsigned long)p - s; -} - -static void scs_check_usage(struct task_struct *tsk) -{ - static DEFINE_SPINLOCK(lock); - static unsigned long highest; - unsigned long used = scs_used(tsk); + for (; p < end; ++p) { + if (!READ_ONCE_NOCHECK(*p)) + break; + used += sizeof(*p); + } - if (used <= highest) - return; + while (used > curr) { + prev = cmpxchg_relaxed(&highest, curr, used); - spin_lock(&lock); + if (prev == curr) { + pr_info("%s (%d): highest shadow stack usage: %lu bytes\n", + tsk->comm, task_pid_nr(tsk), used); + break; + } - if (used > highest) { - pr_info("%s (%d): highest shadow stack usage: %lu bytes\n", - tsk->comm, task_pid_nr(tsk), used); - highest = used; + curr = prev; } - - spin_unlock(&lock); } #else static inline void scs_check_usage(struct task_struct *tsk) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 56e69203b658..a9dd2325bdda 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -383,8 +383,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog) * behavior of privileged children. */ if (!task_no_new_privs(current) && - security_capable(current_cred(), current_user_ns(), - CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0) + !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN)) return ERR_PTR(-EACCES); /* Allocate a new seccomp_filter */ @@ -772,6 +771,8 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, const bool recheck_after_trace) { BUG(); + + return -1; } #endif diff --git a/kernel/signal.c b/kernel/signal.c index 89d3272a83b6..80dbade6659f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1932,8 +1932,12 @@ bool do_notify_parent(struct task_struct *tsk, int sig) if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) sig = 0; } + /* + * Send with __send_signal as si_pid and si_uid are in the + * parent's namespaces. + */ if (valid_signal(sig) && sig) - __group_send_sig_info(sig, &info, tsk->parent); + __send_signal(sig, &info, tsk->parent, PIDTYPE_TGID, false); __wake_up_parent(tsk, tsk->parent); spin_unlock_irqrestore(&psig->siglock, flags); diff --git a/kernel/smpboot.c b/kernel/smpboot.c index c230c2dd48e1..84c16654d859 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -187,6 +187,7 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) kfree(td); return PTR_ERR(tsk); } + kthread_set_per_cpu(tsk, cpu); /* * Park the thread so that it could start right on the CPU * when it is available. diff --git a/kernel/sys.c b/kernel/sys.c index db88cc3ac9e3..b8caebaab029 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2494,10 +2494,18 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, error = SET_ENDIAN(me, arg2); break; case PR_GET_SECCOMP: +#ifdef CONFIG_SECCOMP error = prctl_get_seccomp(); +#else + error = 0; +#endif break; case PR_SET_SECCOMP: +#ifdef CONFIG_SECCOMP error = prctl_set_seccomp(arg2, (char __user *)arg3); +#else + error = 0; +#endif break; case PR_GET_TSC: error = GET_TSC_CTL(arg2); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 65b62793e696..549e9b136900 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -69,6 +69,8 @@ #include #include +#include "../lib/kstrtox.h" + #include #include @@ -134,6 +136,7 @@ static unsigned long one_ul = 1; static unsigned long long_max = LONG_MAX; static int one_hundred = 100; static int one_thousand = 1000; +static int max_swappiness = 200; #ifdef CONFIG_PRINTK static int ten_thousand = 10000; #endif @@ -800,7 +803,7 @@ static struct ctl_table kern_table[] = { .extra1 = &zero, .extra2 = &two_hundred_fifty_five, }, -#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) + #if defined(CONFIG_ENERGY_MODEL) && ((defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL) || defined(CONFIG_CPU_FREQ_GOV_SCHEDHORIZON))) { .procname = "sched_energy_aware", .data = &sysctl_sched_energy_aware, @@ -1734,7 +1737,7 @@ static struct ctl_table vm_table[] = { .mode = 0644, .proc_handler = proc_dointvec_minmax, .extra1 = &zero, - .extra2 = &one_hundred, + .extra2 = &max_swappiness, }, { .procname = "want_old_faultaround_pte", @@ -2496,6 +2499,41 @@ static void proc_skip_char(char **buf, size_t *size, const char v) } } +/** + * strtoul_lenient - parse an ASCII formatted integer from a buffer and only + * fail on overflow + * + * @cp: kernel buffer containing the string to parse + * @endp: pointer to store the trailing characters + * @base: the base to use + * @res: where the parsed integer will be stored + * + * In case of success 0 is returned and @res will contain the parsed integer, + * @endp will hold any trailing characters. + * This function will fail the parse on overflow. If there wasn't an overflow + * the function will defer the decision what characters count as invalid to the + * caller. + */ +static int strtoul_lenient(const char *cp, char **endp, unsigned int base, + unsigned long *res) +{ + unsigned long long result; + unsigned int rv; + + cp = _parse_integer_fixup_radix(cp, &base); + rv = _parse_integer(cp, base, &result); + if ((rv & KSTRTOX_OVERFLOW) || (result != (unsigned long)result)) + return -ERANGE; + + cp += rv; + + if (endp) + *endp = (char *)cp; + + *res = (unsigned long)result; + return 0; +} + #define TMPBUFLEN 22 /** * proc_get_long - reads an ASCII formatted integer from a user buffer @@ -2539,7 +2577,8 @@ static int proc_get_long(char **buf, size_t *size, if (!isdigit(*p)) return -EINVAL; - *val = simple_strtoul(p, &p, 0); + if (strtoul_lenient(p, &p, 0, val)) + return -EINVAL; len = p - tmp; diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 5deea8ecd0cd..196a854cf078 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -287,10 +287,8 @@ static int alarmtimer_suspend(struct device *dev) if (min == 0) return 0; - if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) { - __pm_wakeup_event(ws, 2 * MSEC_PER_SEC); - return -EBUSY; - } + if (ktime_to_ns(min) < NSEC_PER_SEC / 2) + __pm_wakeup_event(ws, MSEC_PER_SEC / 2); trace_alarmtimer_suspend(expires, type); @@ -823,9 +821,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags, if (flags == TIMER_ABSTIME) return -ERESTARTNOHAND; - restart->fn = alarm_timer_nsleep_restart; restart->nanosleep.clockid = type; restart->nanosleep.expires = exp; + set_restart_fn(restart, alarm_timer_nsleep_restart); return ret; } diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 3b8e78b0995f..7d6aa80fe6cd 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -544,8 +544,11 @@ static ktime_t __hrtimer_next_event_base(struct hrtimer_cpu_base *cpu_base, } /* - * Recomputes cpu_base::*next_timer and returns the earliest expires_next but - * does not set cpu_base::*expires_next, that is done by hrtimer_reprogram. + * Recomputes cpu_base::*next_timer and returns the earliest expires_next + * but does not set cpu_base::*expires_next, that is done by + * hrtimer[_force]_reprogram and hrtimer_interrupt only. When updating + * cpu_base::*expires_next right away, reprogramming logic would no longer + * work. * * When a softirq is pending, we can ignore the HRTIMER_ACTIVE_SOFT bases, * those timers will get run whenever the softirq gets handled, at the end of @@ -586,6 +589,37 @@ __hrtimer_get_next_event(struct hrtimer_cpu_base *cpu_base, unsigned int active_ return expires_next; } +static ktime_t hrtimer_update_next_event(struct hrtimer_cpu_base *cpu_base) +{ + ktime_t expires_next, soft = KTIME_MAX; + + /* + * If the soft interrupt has already been activated, ignore the + * soft bases. They will be handled in the already raised soft + * interrupt. + */ + if (!cpu_base->softirq_activated) { + soft = __hrtimer_get_next_event(cpu_base, HRTIMER_ACTIVE_SOFT); + /* + * Update the soft expiry time. clock_settime() might have + * affected it. + */ + cpu_base->softirq_expires_next = soft; + } + + expires_next = __hrtimer_get_next_event(cpu_base, HRTIMER_ACTIVE_HARD); + /* + * If a softirq timer is expiring first, update cpu_base->next_timer + * and program the hardware with the soft expiry time. + */ + if (expires_next > soft) { + cpu_base->next_timer = cpu_base->softirq_next_timer; + expires_next = soft; + } + + return expires_next; +} + static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) { ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; @@ -626,23 +660,7 @@ hrtimer_force_reprogram(struct hrtimer_cpu_base *cpu_base, int skip_equal) { ktime_t expires_next; - /* - * Find the current next expiration time. - */ - expires_next = __hrtimer_get_next_event(cpu_base, HRTIMER_ACTIVE_ALL); - - if (cpu_base->next_timer && cpu_base->next_timer->is_soft) { - /* - * When the softirq is activated, hrtimer has to be - * programmed with the first hard hrtimer because soft - * timer interrupt could occur too late. - */ - if (cpu_base->softirq_activated) - expires_next = __hrtimer_get_next_event(cpu_base, - HRTIMER_ACTIVE_HARD); - else - cpu_base->softirq_expires_next = expires_next; - } + expires_next = hrtimer_update_next_event(cpu_base); if (skip_equal && expires_next == cpu_base->expires_next) return; @@ -1538,8 +1556,8 @@ void hrtimer_interrupt(struct clock_event_device *dev) __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD); - /* Reevaluate the clock bases for the next expiry */ - expires_next = __hrtimer_get_next_event(cpu_base, HRTIMER_ACTIVE_ALL); + /* Reevaluate the clock bases for the [soft] next expiry */ + expires_next = hrtimer_update_next_event(cpu_base); /* * Store the new expiry value so the migration code can verify * against it. @@ -1771,9 +1789,9 @@ long hrtimer_nanosleep(const struct timespec64 *rqtp, } restart = ¤t->restart_block; - restart->fn = hrtimer_nanosleep_restart; restart->nanosleep.clockid = t.timer.base->clockid; restart->nanosleep.expires = hrtimer_get_expires_tv64(&t.timer); + set_restart_fn(restart, hrtimer_nanosleep_restart); out: destroy_hrtimer_on_stack(&t.timer); return ret; diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 9a65713c8309..2e2b335ef101 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c @@ -154,10 +154,6 @@ static void set_cpu_itimer(struct task_struct *tsk, unsigned int clock_id, u64 oval, nval, ointerval, ninterval; struct cpu_itimer *it = &tsk->signal->it[clock_id]; - /* - * Use the to_ktime conversion because that clamps the maximum - * value to KTIME_MAX and avoid multiplication overflows. - */ nval = ktime_to_ns(timeval_to_ktime(value->it_value)); ninterval = ktime_to_ns(timeval_to_ktime(value->it_interval)); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index e1110a7bd3e6..c6c144e1ba43 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -513,7 +513,7 @@ static void sched_sync_hw_clock(struct timespec64 now, * the algorithm is very likely to require a short-sleep retry * after the above long sleep to synchronize ts_nsec. */ - next.tv_sec = 0; + next.tv_sec = 10; } /* Compute the needed delay that will get to tv_nsec == target_nsec */ diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c index d62d7ae5201c..bfaa44a80c03 100644 --- a/kernel/time/posix-cpu-timers.c +++ b/kernel/time/posix-cpu-timers.c @@ -1371,8 +1371,8 @@ static int posix_cpu_nsleep(const clockid_t which_clock, int flags, if (flags & TIMER_ABSTIME) return -ERESTARTNOHAND; - restart_block->fn = posix_cpu_nsleep_restart; restart_block->nanosleep.clockid = which_clock; + set_restart_fn(restart_block, posix_cpu_nsleep_restart); } return error; } diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index a02e0f6b287c..0a3cc37e4b83 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -520,6 +521,7 @@ void tick_unfreeze(void) trace_suspend_resume(TPS("timekeeping_freeze"), smp_processor_id(), false); } else { + touch_softlockup_watchdog(); tick_resume_local(); } diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index cb91395ac461..bc0b74ff1138 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -30,6 +30,7 @@ #include #include #include +#include #include diff --git a/kernel/time/timer.c b/kernel/time/timer.c index dd4f75d98b6a..88e99296f6c7 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -1699,13 +1699,6 @@ void update_process_times(int user_tick) scheduler_tick(); if (IS_ENABLED(CONFIG_POSIX_TIMERS)) run_posix_cpu_timers(p); - - /* The current CPU might make use of net randoms without receiving IRQs - * to renew them often enough. Let's update the net_rand_state from a - * non-constant value that's not affine to the number of calls to make - * sure it's updated when there's some activity (we don't care in idle). - */ - this_cpu_add(net_rand_state.s1, rol32(jiffies, 24) + user_tick); } /** diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 75b31bc13823..0ca50f377f9a 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -146,6 +146,20 @@ config GENERIC_TRACER bool select TRACING +if TRACING + +config DISABLE_TRACE_PRINTK + bool "Force disable trace_printk() usage" + default y + help + When trace_printk() is used in any of the kernel source, it enables + debugging functions which are not desired for production kernel. + Enabling this option will replace trace_printk() with pr_debug(). + + If in doubt, say Y. + +endif + # # Minimum requirements an architecture has to meet for us to # be able to offer generic tracing facilities: @@ -504,7 +518,7 @@ config KPROBE_EVENTS config KPROBE_EVENTS_ON_NOTRACE bool "Do NOT protect notrace function from kprobe events" depends on KPROBE_EVENTS - depends on KPROBES_ON_FTRACE + depends on DYNAMIC_FTRACE default n help This is only for the developers who want to debug ftrace itself diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 83c4e76f513a..7ecbc464dae6 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -561,6 +561,8 @@ tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) return &bpf_probe_read_proto; case BPF_FUNC_ktime_get_ns: return &bpf_ktime_get_ns_proto; + case BPF_FUNC_ktime_get_boot_ns: + return &bpf_ktime_get_boot_ns_proto; case BPF_FUNC_tail_call: return &bpf_tail_call_proto; case BPF_FUNC_get_current_pid_tgid: diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3b8422a88b7e..214c62a3c50f 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -1651,6 +1651,8 @@ static bool test_rec_ops_needs_regs(struct dyn_ftrace *rec) static struct ftrace_ops * ftrace_find_tramp_ops_any(struct dyn_ftrace *rec); static struct ftrace_ops * +ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude); +static struct ftrace_ops * ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops); static bool __ftrace_hash_rec_update(struct ftrace_ops *ops, @@ -1788,7 +1790,7 @@ static bool __ftrace_hash_rec_update(struct ftrace_ops *ops, * to it. */ if (ftrace_rec_count(rec) == 1 && - ftrace_find_tramp_ops_any(rec)) + ftrace_find_tramp_ops_any_other(rec, ops)) rec->flags |= FTRACE_FL_TRAMP; else rec->flags &= ~FTRACE_FL_TRAMP; @@ -2216,6 +2218,24 @@ ftrace_find_tramp_ops_any(struct dyn_ftrace *rec) return NULL; } +static struct ftrace_ops * +ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude) +{ + struct ftrace_ops *op; + unsigned long ip = rec->ip; + + do_for_each_ftrace_op(op, ftrace_ops_list) { + + if (op == op_exclude || !op->trampoline) + continue; + + if (hash_contains_ip(ip, op->func_hash)) + return op; + } while_for_each_ftrace_op(op); + + return NULL; +} + static struct ftrace_ops * ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *op) @@ -6860,7 +6880,6 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) } if (t->ret_stack == NULL) { - atomic_set(&t->tracing_graph_pause, 0); atomic_set(&t->trace_overrun, 0); t->curr_ret_stack = -1; t->curr_ret_depth = -1; @@ -7073,7 +7092,6 @@ static DEFINE_PER_CPU(struct ftrace_ret_stack *, idle_ret_stack); static void graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack) { - atomic_set(&t->tracing_graph_pause, 0); atomic_set(&t->trace_overrun, 0); t->ftrace_timestamp = 0; /* make curr_ret_stack visible before we add the ret_stack */ diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 868d6280d27a..cd5b9db0b040 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2293,7 +2293,7 @@ trace_event_buffer_lock_reserve(struct ring_buffer **current_rb, (entry = this_cpu_read(trace_buffered_event))) { /* Try to use the per cpu buffer first */ val = this_cpu_inc_return(trace_buffered_event_cnt); - if (val == 1) { + if ((len < (PAGE_SIZE - sizeof(*entry))) && val == 1) { trace_event_setup(entry, type, flags, pc); entry->array[0] = len; return entry; @@ -2418,7 +2418,7 @@ void trace_buffer_unlock_commit_regs(struct trace_array *tr, * two. They are not that meaningful. */ ftrace_trace_stack(tr, buffer, flags, regs ? 0 : STACK_SKIP, pc, regs); - ftrace_trace_userstack(buffer, flags, pc); + ftrace_trace_userstack(tr, buffer, flags, pc); } /* @@ -2647,7 +2647,8 @@ static void __ftrace_trace_stack(struct ring_buffer *buffer, size *= sizeof(unsigned long); event = __trace_buffer_lock_reserve(buffer, TRACE_STACK, - sizeof(*entry) + size, flags, pc); + (sizeof(*entry) - sizeof(entry->caller)) + size, + flags, pc); if (!event) goto out; entry = ring_buffer_event_data(event); @@ -2738,14 +2739,15 @@ void trace_dump_stack(int skip) static DEFINE_PER_CPU(int, user_stack_count); void -ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, int pc) +ftrace_trace_userstack(struct trace_array *tr, + struct ring_buffer *buffer, unsigned long flags, int pc) { struct trace_event_call *call = &event_user_stack; struct ring_buffer_event *event; struct userstack_entry *entry; struct stack_trace trace; - if (!(global_trace.trace_flags & TRACE_ITER_USERSTACKTRACE)) + if (!(tr->trace_flags & TRACE_ITER_USERSTACKTRACE)) return; /* diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index e791fc26d752..21849b4c3af4 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -745,13 +745,15 @@ void update_max_tr_single(struct trace_array *tr, #endif /* CONFIG_TRACER_MAX_TRACE */ #ifdef CONFIG_STACKTRACE -void ftrace_trace_userstack(struct ring_buffer *buffer, unsigned long flags, +void ftrace_trace_userstack(struct trace_array *tr, + struct ring_buffer *buffer, unsigned long flags, int pc); void __trace_stack(struct trace_array *tr, unsigned long flags, int skip, int pc); #else -static inline void ftrace_trace_userstack(struct ring_buffer *buffer, +static inline void ftrace_trace_userstack(struct trace_array *tr, + struct ring_buffer *buffer, unsigned long flags, int pc) { } diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 78204c217635..50f0fd0add8b 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1113,7 +1113,8 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, mutex_lock(&event_mutex); list_for_each_entry(file, &tr->events, list) { call = file->event_call; - if (!trace_event_name(call) || !call->class || !call->class->reg) + if ((call->flags & TRACE_EVENT_FL_IGNORE_ENABLE) || + !trace_event_name(call) || !call->class || !call->class->reg) continue; if (system && strcmp(call->class->system, system->name) != 0) diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index 568918fae8d4..ade6c3070c62 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -355,7 +355,7 @@ static int start_kthread(struct trace_array *tr) struct task_struct *kthread; int next_cpu; - if (WARN_ON(hwlat_kthread)) + if (hwlat_kthread) return 0; /* Just pick the first CPU on first iteration */ diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index c45b017bacd4..61eff45653f5 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -112,9 +112,9 @@ bool trace_kprobe_on_func_entry(struct trace_event_call *call) { struct trace_kprobe *tk = (struct trace_kprobe *)call->data; - return kprobe_on_func_entry(tk->rp.kp.addr, + return (kprobe_on_func_entry(tk->rp.kp.addr, tk->rp.kp.addr ? NULL : tk->rp.kp.symbol_name, - tk->rp.kp.addr ? 0 : tk->rp.kp.offset); + tk->rp.kp.addr ? 0 : tk->rp.kp.offset) == 0); } bool trace_kprobe_error_injectable(struct trace_event_call *call) @@ -517,7 +517,7 @@ disable_trace_kprobe(struct trace_kprobe *tk, struct trace_event_file *file) return ret; } -#if defined(CONFIG_KPROBES_ON_FTRACE) && \ +#if defined(CONFIG_DYNAMIC_FTRACE) && \ !defined(CONFIG_KPROBE_EVENTS_ON_NOTRACE) static bool __within_notrace_func(unsigned long addr) { diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index a3be42304485..d5ce69231912 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -66,6 +66,12 @@ struct tp_probes { struct tracepoint_func probes[0]; }; +/* Called in removal of a func but failed to allocate a new tp_funcs */ +static void tp_stub_func(void) +{ + return; +} + static inline void *allocate_probes(int count) { struct tp_probes *p = kmalloc(count * sizeof(struct tracepoint_func) @@ -144,6 +150,7 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, { struct tracepoint_func *old, *new; int nr_probes = 0; + int stub_funcs = 0; int pos = -1; if (WARN_ON(!tp_func->func)) @@ -160,14 +167,34 @@ func_add(struct tracepoint_func **funcs, struct tracepoint_func *tp_func, if (old[nr_probes].func == tp_func->func && old[nr_probes].data == tp_func->data) return ERR_PTR(-EEXIST); + if (old[nr_probes].func == tp_stub_func) + stub_funcs++; } } - /* + 2 : one for new probe, one for NULL func */ - new = allocate_probes(nr_probes + 2); + /* + 2 : one for new probe, one for NULL func - stub functions */ + new = allocate_probes(nr_probes + 2 - stub_funcs); if (new == NULL) return ERR_PTR(-ENOMEM); if (old) { - if (pos < 0) { + if (stub_funcs) { + /* Need to copy one at a time to remove stubs */ + int probes = 0; + + pos = -1; + for (nr_probes = 0; old[nr_probes].func; nr_probes++) { + if (old[nr_probes].func == tp_stub_func) + continue; + if (pos < 0 && old[nr_probes].prio < prio) + pos = probes++; + new[probes++] = old[nr_probes]; + } + nr_probes = probes; + if (pos < 0) + pos = probes; + else + nr_probes--; /* Account for insertion */ + + } else if (pos < 0) { pos = nr_probes; memcpy(new, old, nr_probes * sizeof(struct tracepoint_func)); } else { @@ -201,8 +228,9 @@ static void *func_remove(struct tracepoint_func **funcs, /* (N -> M), (N > 1, M >= 0) probes */ if (tp_func->func) { for (nr_probes = 0; old[nr_probes].func; nr_probes++) { - if (old[nr_probes].func == tp_func->func && - old[nr_probes].data == tp_func->data) + if ((old[nr_probes].func == tp_func->func && + old[nr_probes].data == tp_func->data) || + old[nr_probes].func == tp_stub_func) nr_del++; } } @@ -221,14 +249,32 @@ static void *func_remove(struct tracepoint_func **funcs, /* N -> M, (N > 1, M > 0) */ /* + 1 for NULL */ new = allocate_probes(nr_probes - nr_del + 1); - if (new == NULL) - return ERR_PTR(-ENOMEM); - for (i = 0; old[i].func; i++) - if (old[i].func != tp_func->func - || old[i].data != tp_func->data) - new[j++] = old[i]; - new[nr_probes - nr_del].func = NULL; - *funcs = new; + if (new) { + for (i = 0; old[i].func; i++) + if ((old[i].func != tp_func->func + || old[i].data != tp_func->data) + && old[i].func != tp_stub_func) + new[j++] = old[i]; + new[nr_probes - nr_del].func = NULL; + *funcs = new; + } else { + /* + * Failed to allocate, replace the old function + * with calls to tp_stub_func. + */ + for (i = 0; old[i].func; i++) + if (old[i].func == tp_func->func && + old[i].data == tp_func->data) { + old[i].func = tp_stub_func; + /* Set the prio to the next event. */ + if (old[i + 1].func) + old[i].prio = + old[i + 1].prio; + else + old[i].prio = -1; + } + *funcs = old; + } } debug_print_probes(*funcs); return old; @@ -284,10 +330,12 @@ static int tracepoint_remove_func(struct tracepoint *tp, tp_funcs = rcu_dereference_protected(tp->funcs, lockdep_is_held(&tracepoints_mutex)); old = func_remove(&tp_funcs, func); - if (IS_ERR(old)) { - WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM); + if (WARN_ON_ONCE(IS_ERR(old))) return PTR_ERR(old); - } + + if (tp_funcs == old) + /* Failed allocating new tp_funcs, replaced func with stub */ + return 0; if (!tp_funcs) { /* Removed last function */ diff --git a/kernel/workqueue.c b/kernel/workqueue.c index f3ca7e0394b9..05ea8b4a1288 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -288,7 +288,7 @@ module_param_named(disable_numa, wq_disable_numa, bool, 0444); /* see the comment above the definition of WQ_POWER_EFFICIENT */ static bool wq_power_efficient = IS_ENABLED(CONFIG_WQ_POWER_EFFICIENT_DEFAULT); -module_param_named(power_efficient, wq_power_efficient, bool, 0444); +module_param_named(power_efficient, wq_power_efficient, bool, 0644); static bool wq_online; /* can kworkers be created yet? */ @@ -1415,7 +1415,6 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, */ lockdep_assert_irqs_disabled(); - debug_work_activate(work); /* if draining, only works from the same workqueue are allowed */ if (unlikely(wq->flags & __WQ_DRAINING) && @@ -1498,6 +1497,7 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, worklist = &pwq->delayed_works; } + debug_work_activate(work); insert_work(pwq, work, worklist, work_flags); spin_unlock(&pwq->pool->lock); @@ -1768,12 +1768,6 @@ static void worker_attach_to_pool(struct worker *worker, { mutex_lock(&wq_pool_attach_mutex); - /* - * set_cpus_allowed_ptr() will fail if the cpumask doesn't have any - * online CPUs. It'll be re-applied when any of the CPUs come up. - */ - set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask); - /* * The wq_pool_attach_mutex ensures %POOL_DISASSOCIATED remains * stable across this function. See the comments above the flag @@ -1782,6 +1776,9 @@ static void worker_attach_to_pool(struct worker *worker, if (pool->flags & POOL_DISASSOCIATED) worker->flags |= WORKER_UNBOUND; + if (worker->rescue_wq) + set_cpus_allowed_ptr(worker->task, pool->attrs->cpumask); + list_add_tail(&worker->node, &pool->workers); worker->pool = pool; @@ -3597,17 +3594,24 @@ static void pwq_adjust_max_active(struct pool_workqueue *pwq) * is updated and visible. */ if (!freezable || !workqueue_freezing) { + bool kick = false; + pwq->max_active = wq->saved_max_active; while (!list_empty(&pwq->delayed_works) && - pwq->nr_active < pwq->max_active) + pwq->nr_active < pwq->max_active) { pwq_activate_first_delayed(pwq); + kick = true; + } /* * Need to kick a worker after thawed or an unbound wq's - * max_active is bumped. It's a slow path. Do it always. + * max_active is bumped. In realtime scenarios, always kicking a + * worker will cause interference on the isolated cpu cores, so + * let's kick iff work items were activated. */ - wake_up_worker(pwq->pool); + if (kick) + wake_up_worker(pwq->pool); } else { pwq->max_active = 0; } @@ -5757,13 +5761,13 @@ static void __init wq_numa_init(void) int __init workqueue_init_early(void) { int std_nice[NR_STD_WORKER_POOLS] = { 0, HIGHPRI_NICE_LEVEL }; - int hk_flags = HK_FLAG_DOMAIN | HK_FLAG_WQ; + int hk_flags __maybe_unused = HK_FLAG_DOMAIN | HK_FLAG_WQ; int i, cpu; WARN_ON(__alignof__(struct pool_workqueue) < __alignof__(long long)); BUG_ON(!alloc_cpumask_var(&wq_unbound_cpumask, GFP_KERNEL)); - cpumask_copy(wq_unbound_cpumask, housekeeping_cpumask(hk_flags)); + cpumask_copy(wq_unbound_cpumask, cpu_lp_mask); pwq_cache = KMEM_CACHE(pool_workqueue, SLAB_PANIC); diff --git a/lib/Makefile b/lib/Makefile index 424494d6160d..3297bdc93c2d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,8 +35,9 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ flex_proportions.o ratelimit.o show_mem.o \ is_single_threaded.o plist.o decompress.o kobject_uevent.o \ earlycpio.o seq_buf.o siphash.o dec_and_lock.o \ - nmi_backtrace.o nodemask.o win_minmax.o + nodemask.o win_minmax.o +lib-$(!CONFIG_ARM64) += nmi_backtrace.o lib-$(CONFIG_PRINTK) += dump_stack.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o diff --git a/lib/crc32.c b/lib/crc32.c index 1a5d08470044..17acc6aa540b 100644 --- a/lib/crc32.c +++ b/lib/crc32.c @@ -183,21 +183,21 @@ static inline u32 __pure crc32_le_generic(u32 crc, unsigned char const *p, } #if CRC_LE_BITS == 1 -u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) +u32 __pure __weak crc32_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, NULL, CRC32_POLY_LE); } -u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len) +u32 __pure __weak __crc32c_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, NULL, CRC32C_POLY_LE); } #else -u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len) +u32 __pure __weak crc32_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, (const u32 (*)[256])crc32table_le, CRC32_POLY_LE); } -u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len) +u32 __pure __weak __crc32c_le(u32 crc, unsigned char const *p, size_t len) { return crc32_le_generic(crc, p, len, (const u32 (*)[256])crc32ctable_le, CRC32C_POLY_LE); @@ -206,6 +206,9 @@ u32 __pure __crc32c_le(u32 crc, unsigned char const *p, size_t len) EXPORT_SYMBOL(crc32_le); EXPORT_SYMBOL(__crc32c_le); +u32 crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le); +u32 __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le); + /* * This multiplies the polynomials x and y modulo the given modulus. * This follows the "little-endian" CRC convention that the lsbit diff --git a/lib/genalloc.c b/lib/genalloc.c index 7e85d1e37a6e..0b8ee173cf3a 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -83,14 +83,14 @@ static int clear_bits_ll(unsigned long *addr, unsigned long mask_to_clear) * users set the same bit, one user will return remain bits, otherwise * return 0. */ -static int bitmap_set_ll(unsigned long *map, int start, int nr) +static int bitmap_set_ll(unsigned long *map, unsigned long start, unsigned long nr) { unsigned long *p = map + BIT_WORD(start); - const int size = start + nr; + const unsigned long size = start + nr; int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start); - while (nr - bits_to_set >= 0) { + while (nr >= bits_to_set) { if (set_bits_ll(p, mask_to_set)) return nr; nr -= bits_to_set; @@ -118,14 +118,15 @@ static int bitmap_set_ll(unsigned long *map, int start, int nr) * users clear the same bit, one user will return remain bits, * otherwise return 0. */ -static int bitmap_clear_ll(unsigned long *map, int start, int nr) +static unsigned long +bitmap_clear_ll(unsigned long *map, unsigned long start, unsigned long nr) { unsigned long *p = map + BIT_WORD(start); - const int size = start + nr; + const unsigned long size = start + nr; int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG); unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start); - while (nr - bits_to_clear >= 0) { + while (nr >= bits_to_clear) { if (clear_bits_ll(p, mask_to_clear)) return nr; nr -= bits_to_clear; @@ -184,8 +185,8 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy size_t size, int nid) { struct gen_pool_chunk *chunk; - int nbits = size >> pool->min_alloc_order; - int nbytes = sizeof(struct gen_pool_chunk) + + unsigned long nbits = size >> pool->min_alloc_order; + unsigned long nbytes = sizeof(struct gen_pool_chunk) + BITS_TO_LONGS(nbits) * sizeof(long); chunk = vzalloc_node(nbytes, nid); @@ -242,7 +243,7 @@ void gen_pool_destroy(struct gen_pool *pool) struct list_head *_chunk, *_next_chunk; struct gen_pool_chunk *chunk; int order = pool->min_alloc_order; - int bit, end_bit; + unsigned long bit, end_bit; list_for_each_safe(_chunk, _next_chunk, &pool->chunks) { chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk); @@ -293,7 +294,7 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, struct gen_pool_chunk *chunk; unsigned long addr = 0; int order = pool->min_alloc_order; - int nbits, start_bit, end_bit, remain; + unsigned long nbits, start_bit, end_bit, remain; #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG BUG_ON(in_nmi()); @@ -376,7 +377,7 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) { struct gen_pool_chunk *chunk; int order = pool->min_alloc_order; - int start_bit, nbits, remain; + unsigned long start_bit, nbits, remain; #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG BUG_ON(in_nmi()); @@ -638,7 +639,7 @@ unsigned long gen_pool_best_fit(unsigned long *map, unsigned long size, index = bitmap_find_next_zero_area(map, size, start, nr, 0); while (index < size) { - int next_bit = find_next_bit(map, size, index + nr); + unsigned long next_bit = find_next_bit(map, size, index + nr); if ((next_bit - index) < len) { len = next_bit - index; start_bit = index; diff --git a/lib/logic_pio.c b/lib/logic_pio.c index 905027574e5d..774bb02fff10 100644 --- a/lib/logic_pio.c +++ b/lib/logic_pio.c @@ -27,6 +27,8 @@ static DEFINE_MUTEX(io_range_mutex); * @new_range: pointer to the IO range to be registered. * * Returns 0 on success, the error code in case of failure. + * If the range already exists, -EEXIST will be returned, which should be + * considered a success. * * Register a new IO range node in the IO range list. */ @@ -49,6 +51,7 @@ int logic_pio_register_range(struct logic_pio_hwaddr *new_range) list_for_each_entry(range, &io_range_list, list) { if (range->fwnode == new_range->fwnode) { /* range already there */ + ret = -EEXIST; goto end_register; } if (range->flags == LOGIC_PIO_CPU_MMIO && diff --git a/lib/lz4/lz4_compress.c b/lib/lz4/lz4_compress.c index cc7b6d4cc7c7..90bb67994688 100644 --- a/lib/lz4/lz4_compress.c +++ b/lib/lz4/lz4_compress.c @@ -446,7 +446,7 @@ static FORCE_INLINE int LZ4_compress_generic( *op++ = (BYTE)(lastRun << ML_BITS); } - memcpy(op, anchor, lastRun); + LZ4_memcpy(op, anchor, lastRun); op += lastRun; } @@ -708,7 +708,7 @@ static int LZ4_compress_destSize_generic( } else { *op++ = (BYTE)(lastRunSize< decode everything */ - if ((partialDecoding) && (oexit > oend - MFLIMIT)) - oexit = oend - MFLIMIT; + assert(lowPrefix <= op); + assert(src != NULL); /* Empty output buffer */ if ((endOnInput) && (unlikely(outputSize == 0))) - return ((inputSize == 1) && (*ip == 0)) ? 0 : -1; + return ((srcSize == 1) && (*ip == 0)) ? 0 : -1; if ((!endOnInput) && (unlikely(outputSize == 0))) return (*ip == 0 ? 1 : -1); + if ((endOnInput) && unlikely(srcSize == 0)) + return -1; + /* Main Loop : decode sequences */ while (1) { size_t length; @@ -111,12 +125,74 @@ static FORCE_INLINE int LZ4_decompress_generic( /* get literal length */ unsigned int const token = *ip++; - length = token>>ML_BITS; + /* ip < iend before the increment */ + assert(!endOnInput || ip <= iend); + + /* + * A two-stage shortcut for the most common case: + * 1) If the literal length is 0..14, and there is enough + * space, enter the shortcut and copy 16 bytes on behalf + * of the literals (in the fast mode, only 8 bytes can be + * safely copied this way). + * 2) Further if the match length is 4..18, copy 18 bytes + * in a similar manner; but we ensure that there's enough + * space in the output for those 18 bytes earlier, upon + * entering the shortcut (in other words, there is a + * combined check for both stages). + */ + if ((endOnInput ? length != RUN_MASK : length <= 8) + /* + * strictly "less than" on input, to re-enter + * the loop with at least one byte + */ + && likely((endOnInput ? ip < shortiend : 1) & + (op <= shortoend))) { + /* Copy the literals */ + LZ4_memcpy(op, ip, endOnInput ? 16 : 8); + op += length; ip += length; + + /* + * The second stage: + * prepare for match copying, decode full info. + * If it doesn't work out, the info won't be wasted. + */ + length = token & ML_MASK; /* match length */ + offset = LZ4_readLE16(ip); + ip += 2; + match = op - offset; + assert(match <= op); /* check overflow */ + + /* Do not deal with overlapping matches. */ + if ((length != ML_MASK) && + (offset >= 8) && + (dict == withPrefix64k || match >= lowPrefix)) { + /* Copy the match. */ + LZ4_memcpy(op + 0, match + 0, 8); + LZ4_memcpy(op + 8, match + 8, 8); + LZ4_memcpy(op + 16, match + 16, 2); + op += length + MINMATCH; + /* Both stages worked, load the next token. */ + continue; + } + + /* + * The second stage didn't work out, but the info + * is ready. Propel it right to the point of match + * copying. + */ + goto _copy_match; + } + + /* decode literal length */ if (length == RUN_MASK) { unsigned int s; + if (unlikely(endOnInput ? ip >= iend - RUN_MASK : 0)) { + /* overflow detection */ + goto _output_error; + } do { s = *ip++; length += s; @@ -125,14 +201,14 @@ static FORCE_INLINE int LZ4_decompress_generic( : 1) & (s == 255)); if ((safeDecode) - && unlikely( - (size_t)(op + length) < (size_t)(op))) { + && unlikely((uptrval)(op) + + length < (uptrval)(op))) { /* overflow detection */ goto _output_error; } if ((safeDecode) - && unlikely( - (size_t)(ip + length) < (size_t)(ip))) { + && unlikely((uptrval)(ip) + + length < (uptrval)(ip))) { /* overflow detection */ goto _output_error; } @@ -140,16 +216,19 @@ static FORCE_INLINE int LZ4_decompress_generic( /* copy literals */ cpy = op + length; - if (((endOnInput) && ((cpy > (partialDecoding ? oexit : oend - MFLIMIT)) + LZ4_STATIC_ASSERT(MFLIMIT >= WILDCOPYLENGTH); + + if (((endOnInput) && ((cpy > oend - MFLIMIT) || (ip + length > iend - (2 + 1 + LASTLITERALS)))) || ((!endOnInput) && (cpy > oend - WILDCOPYLENGTH))) { if (partialDecoding) { if (cpy > oend) { /* - * Error : - * write attempt beyond end of output buffer + * Partial decoding : + * stop in the middle of literal segment */ - goto _output_error; + cpy = oend; + length = oend - op; } if ((endOnInput) && (ip + length > iend)) { @@ -181,32 +260,50 @@ static FORCE_INLINE int LZ4_decompress_generic( } } - memcpy(op, ip, length); + /* + * supports overlapping memory regions; only matters + * for in-place decompression scenarios + */ + LZ4_memmove(op, ip, length); ip += length; op += length; + /* Necessarily EOF, due to parsing restrictions */ - break; + if (!partialDecoding || (cpy == oend)) + break; + } else { + /* may overwrite up to WILDCOPYLENGTH beyond cpy */ + LZ4_wildCopy(op, ip, cpy); + ip += length; + op = cpy; } - LZ4_wildCopy(op, ip, cpy); - ip += length; - op = cpy; - /* get offset */ offset = LZ4_readLE16(ip); ip += 2; match = op - offset; - if ((checkOffset) && (unlikely(match < lowLimit))) { + /* get matchlength */ + length = token & ML_MASK; + +_copy_match: + if ((checkOffset) && (unlikely(match + dictSize < lowPrefix))) { /* Error : offset outside buffers */ goto _output_error; } /* costs ~1%; silence an msan warning when offset == 0 */ - LZ4_write32(op, (U32)offset); + /* + * note : when partialDecoding, there is no guarantee that + * at least 4 bytes remain available in output buffer + */ + if (!partialDecoding) { + assert(oend > op); + assert(oend - op >= 4); + + LZ4_write32(op, (U32)offset); + } - /* get matchlength */ - length = token & ML_MASK; if (length == ML_MASK) { unsigned int s; @@ -221,7 +318,7 @@ static FORCE_INLINE int LZ4_decompress_generic( if ((safeDecode) && unlikely( - (size_t)(op + length) < (size_t)op)) { + (uptrval)(op) + length < (uptrval)op)) { /* overflow detection */ goto _output_error; } @@ -229,32 +326,33 @@ static FORCE_INLINE int LZ4_decompress_generic( length += MINMATCH; - /* check external dictionary */ + /* match starting within external dictionary */ if ((dict == usingExtDict) && (match < lowPrefix)) { if (unlikely(op + length > oend - LASTLITERALS)) { /* doesn't respect parsing restriction */ - goto _output_error; + if (!partialDecoding) + goto _output_error; + length = min(length, (size_t)(oend - op)); } if (length <= (size_t)(lowPrefix - match)) { /* - * match can be copied as a single segment - * from external dictionary + * match fits entirely within external + * dictionary : just copy */ memmove(op, dictEnd - (lowPrefix - match), length); op += length; } else { /* - * match encompass external + * match stretches into both external * dictionary and current block */ size_t const copySize = (size_t)(lowPrefix - match); size_t const restSize = length - copySize; - memcpy(op, dictEnd - copySize, copySize); + LZ4_memcpy(op, dictEnd - copySize, copySize); op += copySize; - if (restSize > (size_t)(op - lowPrefix)) { /* overlap copy */ BYTE * const endOfMatch = op + restSize; @@ -263,27 +361,48 @@ static FORCE_INLINE int LZ4_decompress_generic( while (op < endOfMatch) *op++ = *copyFrom++; } else { - memcpy(op, lowPrefix, restSize); + LZ4_memcpy(op, lowPrefix, restSize); op += restSize; } } - continue; } /* copy match within block */ cpy = op + length; - if (unlikely(offset < 8)) { - const int dec64 = dec64table[offset]; + /* + * partialDecoding : + * may not respect endBlock parsing restrictions + */ + assert(op <= oend); + if (partialDecoding && + (cpy > oend - MATCH_SAFEGUARD_DISTANCE)) { + size_t const mlen = min(length, (size_t)(oend - op)); + const BYTE * const matchEnd = match + mlen; + BYTE * const copyEnd = op + mlen; + + if (matchEnd > op) { + /* overlap copy */ + while (op < copyEnd) + *op++ = *match++; + } else { + LZ4_memcpy(op, match, mlen); + } + op = copyEnd; + if (op == oend) + break; + continue; + } + if (unlikely(offset < 8)) { op[0] = match[0]; op[1] = match[1]; op[2] = match[2]; op[3] = match[3]; - match += dec32table[offset]; - memcpy(op + 4, match, 4); - match -= dec64; + match += inc32table[offset]; + LZ4_memcpy(op + 4, match, 4); + match -= dec64table[offset]; } else { LZ4_copy8(op, match); match += 8; @@ -291,7 +410,7 @@ static FORCE_INLINE int LZ4_decompress_generic( op += 8; - if (unlikely(cpy > oend - 12)) { + if (unlikely(cpy > oend - MATCH_SAFEGUARD_DISTANCE)) { BYTE * const oCopyLimit = oend - (WILDCOPYLENGTH - 1); if (cpy > oend - LASTLITERALS) { @@ -307,60 +426,139 @@ static FORCE_INLINE int LZ4_decompress_generic( match += oCopyLimit - op; op = oCopyLimit; } - while (op < cpy) *op++ = *match++; } else { LZ4_copy8(op, match); - if (length > 16) LZ4_wildCopy(op + 8, match + 8, cpy); } - - op = cpy; /* correction */ + op = cpy; /* wildcopy correction */ } /* end of decoding */ if (endOnInput) { /* Nb of output bytes decoded */ - return (int) (((char *)op) - dest); + return (int) (((char *)op) - dst); } else { /* Nb of input bytes read */ - return (int) (((const char *)ip) - source); + return (int) (((const char *)ip) - src); } /* Overflow error detected */ _output_error: - return -1; + return (int) (-(((const char *)ip) - src)) - 1; } int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize) { - return LZ4_decompress_generic(source, dest, compressedSize, - maxDecompressedSize, endOnInputSize, full, 0, - noDict, (BYTE *)dest, NULL, 0); + return LZ4_decompress_generic(source, dest, + compressedSize, maxDecompressedSize, + endOnInputSize, decode_full_block, + noDict, (BYTE *)dest, NULL, 0); } -int LZ4_decompress_safe_partial(const char *source, char *dest, - int compressedSize, int targetOutputSize, int maxDecompressedSize) +int LZ4_decompress_safe_partial(const char *src, char *dst, + int compressedSize, int targetOutputSize, int dstCapacity) { - return LZ4_decompress_generic(source, dest, compressedSize, - maxDecompressedSize, endOnInputSize, partial, - targetOutputSize, noDict, (BYTE *)dest, NULL, 0); + dstCapacity = min(targetOutputSize, dstCapacity); + return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity, + endOnInputSize, partial_decode, + noDict, (BYTE *)dst, NULL, 0); } int LZ4_decompress_fast(const char *source, char *dest, int originalSize) { return LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, full, 0, withPrefix64k, - (BYTE *)(dest - 64 * KB), NULL, 64 * KB); + endOnOutputSize, decode_full_block, + withPrefix64k, + (BYTE *)dest - 64 * KB, NULL, 0); +} + +/* ===== Instantiate a few more decoding cases, used more than once. ===== */ + +int LZ4_decompress_safe_withPrefix64k(const char *source, char *dest, + int compressedSize, int maxOutputSize) +{ + return LZ4_decompress_generic(source, dest, + compressedSize, maxOutputSize, + endOnInputSize, decode_full_block, + withPrefix64k, + (BYTE *)dest - 64 * KB, NULL, 0); +} + +static int LZ4_decompress_safe_withSmallPrefix(const char *source, char *dest, + int compressedSize, + int maxOutputSize, + size_t prefixSize) +{ + return LZ4_decompress_generic(source, dest, + compressedSize, maxOutputSize, + endOnInputSize, decode_full_block, + noDict, + (BYTE *)dest - prefixSize, NULL, 0); +} + +int LZ4_decompress_safe_forceExtDict(const char *source, char *dest, + int compressedSize, int maxOutputSize, + const void *dictStart, size_t dictSize) +{ + return LZ4_decompress_generic(source, dest, + compressedSize, maxOutputSize, + endOnInputSize, decode_full_block, + usingExtDict, (BYTE *)dest, + (const BYTE *)dictStart, dictSize); } +static int LZ4_decompress_fast_extDict(const char *source, char *dest, + int originalSize, + const void *dictStart, size_t dictSize) +{ + return LZ4_decompress_generic(source, dest, + 0, originalSize, + endOnOutputSize, decode_full_block, + usingExtDict, (BYTE *)dest, + (const BYTE *)dictStart, dictSize); +} + +/* + * The "double dictionary" mode, for use with e.g. ring buffers: the first part + * of the dictionary is passed as prefix, and the second via dictStart + dictSize. + * These routines are used only once, in LZ4_decompress_*_continue(). + */ +static FORCE_INLINE +int LZ4_decompress_safe_doubleDict(const char *source, char *dest, + int compressedSize, int maxOutputSize, + size_t prefixSize, + const void *dictStart, size_t dictSize) +{ + return LZ4_decompress_generic(source, dest, + compressedSize, maxOutputSize, + endOnInputSize, decode_full_block, + usingExtDict, (BYTE *)dest - prefixSize, + (const BYTE *)dictStart, dictSize); +} + +static FORCE_INLINE +int LZ4_decompress_fast_doubleDict(const char *source, char *dest, + int originalSize, size_t prefixSize, + const void *dictStart, size_t dictSize) +{ + return LZ4_decompress_generic(source, dest, + 0, originalSize, + endOnOutputSize, decode_full_block, + usingExtDict, (BYTE *)dest - prefixSize, + (const BYTE *)dictStart, dictSize); +} + +/* ===== streaming decompression functions ===== */ + int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, const char *dictionary, int dictSize) { - LZ4_streamDecode_t_internal *lz4sd = (LZ4_streamDecode_t_internal *) LZ4_streamDecode; + LZ4_streamDecode_t_internal *lz4sd = + &LZ4_streamDecode->internal_donotuse; lz4sd->prefixSize = (size_t) dictSize; lz4sd->prefixEnd = (const BYTE *) dictionary + dictSize; @@ -382,35 +580,51 @@ int LZ4_setStreamDecode(LZ4_streamDecode_t *LZ4_streamDecode, int LZ4_decompress_safe_continue(LZ4_streamDecode_t *LZ4_streamDecode, const char *source, char *dest, int compressedSize, int maxOutputSize) { - LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse; + LZ4_streamDecode_t_internal *lz4sd = + &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixEnd == (BYTE *)dest) { - result = LZ4_decompress_generic(source, dest, - compressedSize, - maxOutputSize, - endOnInputSize, full, 0, - usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, - lz4sd->externalDict, - lz4sd->extDictSize); - + if (lz4sd->prefixSize == 0) { + /* The first call, no dictionary yet. */ + assert(lz4sd->extDictSize == 0); + result = LZ4_decompress_safe(source, dest, + compressedSize, maxOutputSize); + if (result <= 0) + return result; + lz4sd->prefixSize = result; + lz4sd->prefixEnd = (BYTE *)dest + result; + } else if (lz4sd->prefixEnd == (BYTE *)dest) { + /* They're rolling the current segment. */ + if (lz4sd->prefixSize >= 64 * KB - 1) + result = LZ4_decompress_safe_withPrefix64k(source, dest, + compressedSize, maxOutputSize); + else if (lz4sd->extDictSize == 0) + result = LZ4_decompress_safe_withSmallPrefix(source, + dest, compressedSize, maxOutputSize, + lz4sd->prefixSize); + else + result = LZ4_decompress_safe_doubleDict(source, dest, + compressedSize, maxOutputSize, + lz4sd->prefixSize, + lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; - lz4sd->prefixSize += result; - lz4sd->prefixEnd += result; + lz4sd->prefixEnd += result; } else { + /* + * The buffer wraps around, or they're + * switching to another buffer. + */ lz4sd->extDictSize = lz4sd->prefixSize; lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_generic(source, dest, + result = LZ4_decompress_safe_forceExtDict(source, dest, compressedSize, maxOutputSize, - endOnInputSize, full, 0, - usingExtDict, (BYTE *)dest, lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize = result; - lz4sd->prefixEnd = (BYTE *)dest + result; + lz4sd->prefixEnd = (BYTE *)dest + result; } return result; @@ -422,75 +636,66 @@ int LZ4_decompress_fast_continue(LZ4_streamDecode_t *LZ4_streamDecode, LZ4_streamDecode_t_internal *lz4sd = &LZ4_streamDecode->internal_donotuse; int result; - if (lz4sd->prefixEnd == (BYTE *)dest) { - result = LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, full, 0, - usingExtDict, - lz4sd->prefixEnd - lz4sd->prefixSize, - lz4sd->externalDict, lz4sd->extDictSize); - + if (lz4sd->prefixSize == 0) { + assert(lz4sd->extDictSize == 0); + result = LZ4_decompress_fast(source, dest, originalSize); + if (result <= 0) + return result; + lz4sd->prefixSize = originalSize; + lz4sd->prefixEnd = (BYTE *)dest + originalSize; + } else if (lz4sd->prefixEnd == (BYTE *)dest) { + if (lz4sd->prefixSize >= 64 * KB - 1 || + lz4sd->extDictSize == 0) + result = LZ4_decompress_fast(source, dest, + originalSize); + else + result = LZ4_decompress_fast_doubleDict(source, dest, + originalSize, lz4sd->prefixSize, + lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; - lz4sd->prefixSize += originalSize; - lz4sd->prefixEnd += originalSize; + lz4sd->prefixEnd += originalSize; } else { lz4sd->extDictSize = lz4sd->prefixSize; lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; - result = LZ4_decompress_generic(source, dest, 0, originalSize, - endOnOutputSize, full, 0, - usingExtDict, (BYTE *)dest, - lz4sd->externalDict, lz4sd->extDictSize); + result = LZ4_decompress_fast_extDict(source, dest, + originalSize, lz4sd->externalDict, lz4sd->extDictSize); if (result <= 0) return result; lz4sd->prefixSize = originalSize; - lz4sd->prefixEnd = (BYTE *)dest + originalSize; + lz4sd->prefixEnd = (BYTE *)dest + originalSize; } - return result; } -/* - * Advanced decoding functions : - * *_usingDict() : - * These decoding functions work the same as "_continue" ones, - * the dictionary must be explicitly provided within parameters - */ -static FORCE_INLINE int LZ4_decompress_usingDict_generic(const char *source, - char *dest, int compressedSize, int maxOutputSize, int safe, - const char *dictStart, int dictSize) +int LZ4_decompress_safe_usingDict(const char *source, char *dest, + int compressedSize, int maxOutputSize, + const char *dictStart, int dictSize) { if (dictSize == 0) - return LZ4_decompress_generic(source, dest, - compressedSize, maxOutputSize, safe, full, 0, - noDict, (BYTE *)dest, NULL, 0); - if (dictStart + dictSize == dest) { - if (dictSize >= (int)(64 * KB - 1)) - return LZ4_decompress_generic(source, dest, - compressedSize, maxOutputSize, safe, full, 0, - withPrefix64k, (BYTE *)dest - 64 * KB, NULL, 0); - return LZ4_decompress_generic(source, dest, compressedSize, - maxOutputSize, safe, full, 0, noDict, - (BYTE *)dest - dictSize, NULL, 0); + return LZ4_decompress_safe(source, dest, + compressedSize, maxOutputSize); + if (dictStart+dictSize == dest) { + if (dictSize >= 64 * KB - 1) + return LZ4_decompress_safe_withPrefix64k(source, dest, + compressedSize, maxOutputSize); + return LZ4_decompress_safe_withSmallPrefix(source, dest, + compressedSize, maxOutputSize, dictSize); } - return LZ4_decompress_generic(source, dest, compressedSize, - maxOutputSize, safe, full, 0, usingExtDict, - (BYTE *)dest, (const BYTE *)dictStart, dictSize); -} - -int LZ4_decompress_safe_usingDict(const char *source, char *dest, - int compressedSize, int maxOutputSize, - const char *dictStart, int dictSize) -{ - return LZ4_decompress_usingDict_generic(source, dest, - compressedSize, maxOutputSize, 1, dictStart, dictSize); + return LZ4_decompress_safe_forceExtDict(source, dest, + compressedSize, maxOutputSize, dictStart, dictSize); } int LZ4_decompress_fast_usingDict(const char *source, char *dest, - int originalSize, const char *dictStart, int dictSize) + int originalSize, + const char *dictStart, int dictSize) { - return LZ4_decompress_usingDict_generic(source, dest, 0, - originalSize, 0, dictStart, dictSize); + if (dictSize == 0 || dictStart + dictSize == dest) + return LZ4_decompress_fast(source, dest, originalSize); + + return LZ4_decompress_fast_extDict(source, dest, originalSize, + dictStart, dictSize); } #ifndef STATIC diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h index 00a0b58a0871..673bd206aa98 100644 --- a/lib/lz4/lz4defs.h +++ b/lib/lz4/lz4defs.h @@ -75,6 +75,11 @@ typedef uintptr_t uptrval; #define WILDCOPYLENGTH 8 #define LASTLITERALS 5 #define MFLIMIT (WILDCOPYLENGTH + MINMATCH) +/* + * ensure it's possible to write 2 x wildcopyLength + * without overflowing output buffer + */ +#define MATCH_SAFEGUARD_DISTANCE ((2 * WILDCOPYLENGTH) - MINMATCH) /* Increase this value ==> compression run slower on incompressible data */ #define LZ4_SKIPTRIGGER 6 @@ -132,6 +137,17 @@ static FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value) return put_unaligned_le16(value, memPtr); } +/* + * LZ4 relies on memcpy with a constant size being inlined. In freestanding + * environments, the compiler can't assume the implementation of memcpy() is + * standard compliant, so apply its specialized memcpy() inlining logic. When + * possible, use __builtin_memcpy() to tell the compiler to analyze memcpy() + * as-if it were standard compliant, so it can inline it in freestanding + * environments. This is needed when decompressing the Linux Kernel, for example. + */ +#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size) +#define LZ4_memmove(dst, src, size) __builtin_memmove(dst, src, size) + static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) { #if LZ4_ARCH64 @@ -222,6 +238,8 @@ typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; -typedef enum { full = 0, partial = 1 } earlyEnd_directive; +typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; + +#define LZ4_STATIC_ASSERT(c) BUILD_BUG_ON(!(c)) #endif diff --git a/lib/lz4/lz4hc_compress.c b/lib/lz4/lz4hc_compress.c index 176f03b83e56..ccbf0e89d713 100644 --- a/lib/lz4/lz4hc_compress.c +++ b/lib/lz4/lz4hc_compress.c @@ -570,7 +570,7 @@ static int LZ4HC_compress_generic( *op++ = (BYTE) lastRun; } else *op++ = (BYTE)(lastRun< #include -#ifdef CONFIG_RANDOM32_SELFTEST -static void __init prandom_state_selftest(void); -#else -static inline void prandom_state_selftest(void) -{ -} -#endif - -DEFINE_PER_CPU(struct rnd_state, net_rand_state) __latent_entropy; - /** * prandom_u32_state - seeded pseudo-random number generator. * @state: pointer to state structure holding seeded state. @@ -69,25 +59,6 @@ u32 prandom_u32_state(struct rnd_state *state) } EXPORT_SYMBOL(prandom_u32_state); -/** - * prandom_u32 - pseudo random number generator - * - * A 32 bit pseudo-random number is generated using a fast - * algorithm suitable for simulation. This algorithm is NOT - * considered safe for cryptographic use. - */ -u32 prandom_u32(void) -{ - struct rnd_state *state = &get_cpu_var(net_rand_state); - u32 res; - - res = prandom_u32_state(state); - put_cpu_var(net_rand_state); - - return res; -} -EXPORT_SYMBOL(prandom_u32); - /** * prandom_bytes_state - get the requested number of pseudo-random bytes * @@ -119,20 +90,6 @@ void prandom_bytes_state(struct rnd_state *state, void *buf, size_t bytes) } EXPORT_SYMBOL(prandom_bytes_state); -/** - * prandom_bytes - get the requested number of pseudo-random bytes - * @buf: where to copy the pseudo-random bytes to - * @bytes: the requested number of bytes - */ -void prandom_bytes(void *buf, size_t bytes) -{ - struct rnd_state *state = &get_cpu_var(net_rand_state); - - prandom_bytes_state(state, buf, bytes); - put_cpu_var(net_rand_state); -} -EXPORT_SYMBOL(prandom_bytes); - static void prandom_warmup(struct rnd_state *state) { /* Calling RNG ten times to satisfy recurrence condition */ @@ -148,96 +105,6 @@ static void prandom_warmup(struct rnd_state *state) prandom_u32_state(state); } -static u32 __extract_hwseed(void) -{ - unsigned int val = 0; - - (void)(arch_get_random_seed_int(&val) || - arch_get_random_int(&val)); - - return val; -} - -static void prandom_seed_early(struct rnd_state *state, u32 seed, - bool mix_with_hwseed) -{ -#define LCG(x) ((x) * 69069U) /* super-duper LCG */ -#define HWSEED() (mix_with_hwseed ? __extract_hwseed() : 0) - state->s1 = __seed(HWSEED() ^ LCG(seed), 2U); - state->s2 = __seed(HWSEED() ^ LCG(state->s1), 8U); - state->s3 = __seed(HWSEED() ^ LCG(state->s2), 16U); - state->s4 = __seed(HWSEED() ^ LCG(state->s3), 128U); -} - -/** - * prandom_seed - add entropy to pseudo random number generator - * @seed: seed value - * - * Add some additional seeding to the prandom pool. - */ -void prandom_seed(u32 entropy) -{ - int i; - /* - * No locking on the CPUs, but then somewhat random results are, well, - * expected. - */ - for_each_possible_cpu(i) { - struct rnd_state *state = &per_cpu(net_rand_state, i); - - state->s1 = __seed(state->s1 ^ entropy, 2U); - prandom_warmup(state); - } -} -EXPORT_SYMBOL(prandom_seed); - -/* - * Generate some initially weak seeding values to allow - * to start the prandom_u32() engine. - */ -static int __init prandom_init(void) -{ - int i; - - prandom_state_selftest(); - - for_each_possible_cpu(i) { - struct rnd_state *state = &per_cpu(net_rand_state, i); - u32 weak_seed = (i + jiffies) ^ random_get_entropy(); - - prandom_seed_early(state, weak_seed, true); - prandom_warmup(state); - } - - return 0; -} -core_initcall(prandom_init); - -static void __prandom_timer(struct timer_list *unused); - -static DEFINE_TIMER(seed_timer, __prandom_timer); - -static void __prandom_timer(struct timer_list *unused) -{ - u32 entropy; - unsigned long expires; - - get_random_bytes(&entropy, sizeof(entropy)); - prandom_seed(entropy); - - /* reseed every ~60 seconds, in [40 .. 80) interval with slack */ - expires = 40 + prandom_u32_max(40); - seed_timer.expires = jiffies + msecs_to_jiffies(expires * MSEC_PER_SEC); - - add_timer(&seed_timer); -} - -static void __init __prandom_start_seed_timer(void) -{ - seed_timer.expires = jiffies + msecs_to_jiffies(40 * MSEC_PER_SEC); - add_timer(&seed_timer); -} - void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state) { int i; @@ -257,51 +124,6 @@ void prandom_seed_full_state(struct rnd_state __percpu *pcpu_state) } EXPORT_SYMBOL(prandom_seed_full_state); -/* - * Generate better values after random number generator - * is fully initialized. - */ -static void __prandom_reseed(bool late) -{ - unsigned long flags; - static bool latch = false; - static DEFINE_SPINLOCK(lock); - - /* Asking for random bytes might result in bytes getting - * moved into the nonblocking pool and thus marking it - * as initialized. In this case we would double back into - * this function and attempt to do a late reseed. - * Ignore the pointless attempt to reseed again if we're - * already waiting for bytes when the nonblocking pool - * got initialized. - */ - - /* only allow initial seeding (late == false) once */ - if (!spin_trylock_irqsave(&lock, flags)) - return; - - if (latch && !late) - goto out; - - latch = true; - prandom_seed_full_state(&net_rand_state); -out: - spin_unlock_irqrestore(&lock, flags); -} - -void prandom_reseed_late(void) -{ - __prandom_reseed(true); -} - -static int __init prandom_reseed(void) -{ - __prandom_reseed(false); - __prandom_start_seed_timer(); - return 0; -} -late_initcall(prandom_reseed); - #ifdef CONFIG_RANDOM32_SELFTEST static struct prandom_test1 { u32 seed; @@ -421,7 +243,28 @@ static struct prandom_test2 { { 407983964U, 921U, 728767059U }, }; -static void __init prandom_state_selftest(void) +static u32 __extract_hwseed(void) +{ + unsigned int val = 0; + + (void)(arch_get_random_seed_int(&val) || + arch_get_random_int(&val)); + + return val; +} + +static void prandom_seed_early(struct rnd_state *state, u32 seed, + bool mix_with_hwseed) +{ +#define LCG(x) ((x) * 69069U) /* super-duper LCG */ +#define HWSEED() (mix_with_hwseed ? __extract_hwseed() : 0) + state->s1 = __seed(HWSEED() ^ LCG(seed), 2U); + state->s2 = __seed(HWSEED() ^ LCG(state->s1), 8U); + state->s3 = __seed(HWSEED() ^ LCG(state->s2), 16U); + state->s4 = __seed(HWSEED() ^ LCG(state->s3), 128U); +} + +static int __init prandom_state_selftest(void) { int i, j, errors = 0, runs = 0; bool error = false; @@ -461,5 +304,266 @@ static void __init prandom_state_selftest(void) pr_warn("prandom: %d/%d self tests failed\n", errors, runs); else pr_info("prandom: %d self tests passed\n", runs); + return 0; } +core_initcall(prandom_state_selftest); #endif + +/* + * The prandom_u32() implementation is now completely separate from the + * prandom_state() functions, which are retained (for now) for compatibility. + * + * Because of (ab)use in the networking code for choosing random TCP/UDP port + * numbers, which open DoS possibilities if guessable, we want something + * stronger than a standard PRNG. But the performance requirements of + * the network code do not allow robust crypto for this application. + * + * So this is a homebrew Junior Spaceman implementation, based on the + * lowest-latency trustworthy crypto primitive available, SipHash. + * (The authors of SipHash have not been consulted about this abuse of + * their work.) + * + * Standard SipHash-2-4 uses 2n+4 rounds to hash n words of input to + * one word of output. This abbreviated version uses 2 rounds per word + * of output. + */ + +struct siprand_state { + unsigned long v0; + unsigned long v1; + unsigned long v2; + unsigned long v3; +}; + +static DEFINE_PER_CPU(struct siprand_state, net_rand_state) __latent_entropy; + +/* + * This is the core CPRNG function. As "pseudorandom", this is not used + * for truly valuable things, just intended to be a PITA to guess. + * For maximum speed, we do just two SipHash rounds per word. This is + * the same rate as 4 rounds per 64 bits that SipHash normally uses, + * so hopefully it's reasonably secure. + * + * There are two changes from the official SipHash finalization: + * - We omit some constants XORed with v2 in the SipHash spec as irrelevant; + * they are there only to make the output rounds distinct from the input + * rounds, and this application has no input rounds. + * - Rather than returning v0^v1^v2^v3, return v1+v3. + * If you look at the SipHash round, the last operation on v3 is + * "v3 ^= v0", so "v0 ^ v3" just undoes that, a waste of time. + * Likewise "v1 ^= v2". (The rotate of v2 makes a difference, but + * it still cancels out half of the bits in v2 for no benefit.) + * Second, since the last combining operation was xor, continue the + * pattern of alternating xor/add for a tiny bit of extra non-linearity. + */ +static inline u32 siprand_u32(struct siprand_state *s) +{ + unsigned long v0 = s->v0, v1 = s->v1, v2 = s->v2, v3 = s->v3; + + PRND_SIPROUND(v0, v1, v2, v3); + PRND_SIPROUND(v0, v1, v2, v3); + s->v0 = v0; s->v1 = v1; s->v2 = v2; s->v3 = v3; + return v1 + v3; +} + + +/** + * prandom_u32 - pseudo random number generator + * + * A 32 bit pseudo-random number is generated using a fast + * algorithm suitable for simulation. This algorithm is NOT + * considered safe for cryptographic use. + */ +u32 prandom_u32(void) +{ + struct siprand_state *state = get_cpu_ptr(&net_rand_state); + u32 res = siprand_u32(state); + + put_cpu_ptr(&net_rand_state); + return res; +} +EXPORT_SYMBOL(prandom_u32); + +/** + * prandom_bytes - get the requested number of pseudo-random bytes + * @buf: where to copy the pseudo-random bytes to + * @bytes: the requested number of bytes + */ +void prandom_bytes(void *buf, size_t bytes) +{ + struct siprand_state *state = get_cpu_ptr(&net_rand_state); + u8 *ptr = buf; + + while (bytes >= sizeof(u32)) { + put_unaligned(siprand_u32(state), (u32 *)ptr); + ptr += sizeof(u32); + bytes -= sizeof(u32); + } + + if (bytes > 0) { + u32 rem = siprand_u32(state); + + do { + *ptr++ = (u8)rem; + rem >>= BITS_PER_BYTE; + } while (--bytes > 0); + } + put_cpu_ptr(&net_rand_state); +} +EXPORT_SYMBOL(prandom_bytes); + +/** + * prandom_seed - add entropy to pseudo random number generator + * @entropy: entropy value + * + * Add some additional seed material to the prandom pool. + * The "entropy" is actually our IP address (the only caller is + * the network code), not for unpredictability, but to ensure that + * different machines are initialized differently. + */ +void prandom_seed(u32 entropy) +{ + int i; + + add_device_randomness(&entropy, sizeof(entropy)); + + for_each_possible_cpu(i) { + struct siprand_state *state = per_cpu_ptr(&net_rand_state, i); + unsigned long v0 = state->v0, v1 = state->v1; + unsigned long v2 = state->v2, v3 = state->v3; + + do { + v3 ^= entropy; + PRND_SIPROUND(v0, v1, v2, v3); + PRND_SIPROUND(v0, v1, v2, v3); + v0 ^= entropy; + } while (unlikely(!v0 || !v1 || !v2 || !v3)); + + WRITE_ONCE(state->v0, v0); + WRITE_ONCE(state->v1, v1); + WRITE_ONCE(state->v2, v2); + WRITE_ONCE(state->v3, v3); + } +} +EXPORT_SYMBOL(prandom_seed); + +/* + * Generate some initially weak seeding values to allow + * the prandom_u32() engine to be started. + */ +static int __init prandom_init_early(void) +{ + int i; + unsigned long v0, v1, v2, v3; + + if (!arch_get_random_long(&v0)) + v0 = jiffies; + if (!arch_get_random_long(&v1)) + v1 = random_get_entropy(); + v2 = v0 ^ PRND_K0; + v3 = v1 ^ PRND_K1; + + for_each_possible_cpu(i) { + struct siprand_state *state; + + v3 ^= i; + PRND_SIPROUND(v0, v1, v2, v3); + PRND_SIPROUND(v0, v1, v2, v3); + v0 ^= i; + + state = per_cpu_ptr(&net_rand_state, i); + state->v0 = v0; state->v1 = v1; + state->v2 = v2; state->v3 = v3; + } + + return 0; +} +core_initcall(prandom_init_early); + + +/* Stronger reseeding when available, and periodically thereafter. */ +static void prandom_reseed(struct timer_list *unused); + +static DEFINE_TIMER(seed_timer, prandom_reseed); + +static void prandom_reseed(struct timer_list *unused) +{ + unsigned long expires; + int i; + + /* + * Reinitialize each CPU's PRNG with 128 bits of key. + * No locking on the CPUs, but then somewhat random results are, + * well, expected. + */ + for_each_possible_cpu(i) { + struct siprand_state *state; + unsigned long v0 = get_random_long(), v2 = v0 ^ PRND_K0; + unsigned long v1 = get_random_long(), v3 = v1 ^ PRND_K1; +#if BITS_PER_LONG == 32 + int j; + + /* + * On 32-bit machines, hash in two extra words to + * approximate 128-bit key length. Not that the hash + * has that much security, but this prevents a trivial + * 64-bit brute force. + */ + for (j = 0; j < 2; j++) { + unsigned long m = get_random_long(); + + v3 ^= m; + PRND_SIPROUND(v0, v1, v2, v3); + PRND_SIPROUND(v0, v1, v2, v3); + v0 ^= m; + } +#endif + /* + * Probably impossible in practice, but there is a + * theoretical risk that a race between this reseeding + * and the target CPU writing its state back could + * create the all-zero SipHash fixed point. + * + * To ensure that never happens, ensure the state + * we write contains no zero words. + */ + state = per_cpu_ptr(&net_rand_state, i); + WRITE_ONCE(state->v0, v0 ? v0 : -1ul); + WRITE_ONCE(state->v1, v1 ? v1 : -1ul); + WRITE_ONCE(state->v2, v2 ? v2 : -1ul); + WRITE_ONCE(state->v3, v3 ? v3 : -1ul); + } + + /* reseed every ~60 seconds, in [40 .. 80) interval with slack */ + expires = round_jiffies(jiffies + 40 * HZ + prandom_u32_max(40 * HZ)); + mod_timer(&seed_timer, expires); +} + +/* + * The random ready callback can be called from almost any interrupt. + * To avoid worrying about whether it's safe to delay that interrupt + * long enough to seed all CPUs, just schedule an immediate timer event. + */ +static void prandom_timer_start(struct random_ready_callback *unused) +{ + mod_timer(&seed_timer, jiffies); +} + +/* + * Start periodic full reseeding as soon as strong + * random numbers are available. + */ +static int __init prandom_init_late(void) +{ + static struct random_ready_callback random_ready = { + .func = prandom_timer_start + }; + int ret = add_random_ready_callback(&random_ready); + + if (ret == -EALREADY) { + prandom_timer_start(&random_ready); + ret = 0; + } + return ret; +} +late_initcall(prandom_init_late); diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 3b859201f84c..cabcf0848b30 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -150,31 +150,12 @@ EXPORT_SYMBOL(sg_init_one); */ static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask) { - if (nents == SG_MAX_SINGLE_ALLOC) { - /* - * Kmemleak doesn't track page allocations as they are not - * commonly used (in a raw form) for kernel data structures. - * As we chain together a list of pages and then a normal - * kmalloc (tracked by kmemleak), in order to for that last - * allocation not to become decoupled (and thus a - * false-positive) we need to inform kmemleak of all the - * intermediate allocations. - */ - void *ptr = (void *) __get_free_page(gfp_mask); - kmemleak_alloc(ptr, PAGE_SIZE, 1, gfp_mask); - return ptr; - } else - return kmalloc_array(nents, sizeof(struct scatterlist), - gfp_mask); + return kmalloc_array(nents, sizeof(struct scatterlist), gfp_mask); } static void sg_kfree(struct scatterlist *sg, unsigned int nents) { - if (nents == SG_MAX_SINGLE_ALLOC) { - kmemleak_free(sg); - free_page((unsigned long) sg); - } else - kfree(sg); + kfree(sg); } /** diff --git a/mm/Kconfig b/mm/Kconfig index b6dbab55f77a..98ff2fcc1103 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -885,3 +885,7 @@ config FORCE_ALLOC_FROM_DMA_ZONE always using ZONE_DMA32 memory. If unsure, say "n". + +config VMSTAT_INTERVAL + int "Default interval in seconds to update vmstat" + default 1 diff --git a/mm/bootmem.c b/mm/bootmem.c index c20dbd623a08..1be94a6ca8f1 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -203,7 +203,7 @@ void free_bootmem_late(unsigned long physaddr, unsigned long size) for (; cursor < end; cursor++) { __free_pages_bootmem(pfn_to_page(cursor), cursor, 0); - totalram_pages++; + totalram_pages_inc(); } } @@ -314,7 +314,7 @@ unsigned long __init free_all_bootmem(void) list_for_each_entry(bdata, &bdata_list, list) total_pages += free_all_bootmem_core(bdata); - totalram_pages += total_pages; + totalram_pages() += total_pages; return total_pages; } diff --git a/mm/gup.c b/mm/gup.c index 91c2caa6c887..216253ab1295 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -61,13 +61,22 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address, } /* - * FOLL_FORCE can write to even unwritable pte's, but only - * after we've gone through a COW cycle and they are dirty. + * FOLL_FORCE or a forced COW break can write even to unwritable pte's, + * but only after we've gone through a COW cycle and they are dirty. */ static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) { - return pte_write(pte) || - ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); + return pte_write(pte) || ((flags & FOLL_COW) && pte_dirty(pte)); +} + +/* + * A (separate) COW fault might break the page the other way and + * get_user_pages() would return the page from what is now the wrong + * VM. So we need to force a COW break at GUP time even for reads. + */ +static inline bool should_force_cow_break(struct vm_area_struct *vma, unsigned int flags) +{ + return is_cow_mapping(vma->vm_flags) && (flags & FOLL_GET); } static struct page *follow_page_pte(struct vm_area_struct *vma, @@ -712,12 +721,18 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, if (!vma || check_vma_flags(vma, gup_flags)) return i ? : -EFAULT; if (is_vm_hugetlb_page(vma)) { + if (should_force_cow_break(vma, foll_flags)) + foll_flags |= FOLL_WRITE; i = follow_hugetlb_page(mm, vma, pages, vmas, &start, &nr_pages, i, - gup_flags, nonblocking); + foll_flags, nonblocking); continue; } } + + if (should_force_cow_break(vma, foll_flags)) + foll_flags |= FOLL_WRITE; + retry: /* * If we have a pending SIGKILL, don't keep faulting pages and @@ -1808,6 +1823,10 @@ bool gup_fast_permitted(unsigned long start, int nr_pages, int write) * the regular GUP. * Note a difference with get_user_pages_fast: this always returns the * number of pages pinned, 0 if no pages were pinned. + * + * Careful, careful! COW breaking can go either way, so a non-write + * access can get ambiguous page results. If you call this function without + * 'write' set, you'd better be sure that you're ok with that ambiguity. */ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, struct page **pages) @@ -1835,6 +1854,12 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write, * * We do not adopt an rcu_read_lock(.) here as we also want to * block IPIs that come from THPs splitting. + * + * NOTE! We allow read-only gup_fast() here, but you'd better be + * careful about possible COW pages. You'll get _a_ COW page, but + * not necessarily the one you intended to get depending on what + * COW event happens after this. COW may break the page copy in a + * random direction. */ if (gup_fast_permitted(start, nr_pages, write)) { @@ -1880,9 +1905,16 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, (void __user *)start, len))) return -EFAULT; + /* + * The FAST_GUP case requires FOLL_WRITE even for pure reads, + * because get_user_pages() may need to cause an early COW in + * order to avoid confusing the normal COW routines. So only + * targets that are already writable are safe to do by just + * looking at the page tables. + */ if (gup_fast_permitted(start, nr_pages, write)) { local_irq_disable(); - gup_pgd_range(addr, end, write, pages, &nr); + gup_pgd_range(addr, end, 1, pages, &nr); local_irq_enable(); ret = nr; } diff --git a/mm/highmem.c b/mm/highmem.c index 59db3223a5d6..107b10f9878e 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -105,9 +105,8 @@ static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color) } #endif -unsigned long totalhigh_pages __read_mostly; -EXPORT_SYMBOL(totalhigh_pages); - +atomic_long_t _totalhigh_pages __read_mostly; +EXPORT_SYMBOL(_totalhigh_pages); EXPORT_PER_CPU_SYMBOL(__kmap_atomic_idx); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index b48a74f3df62..753d11248935 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -423,7 +423,7 @@ static int __init hugepage_init(void) * where the extra memory used could hurt more than TLB overhead * is likely to save. The admin can still enable it through /sys. */ - if (totalram_pages < (512 << (20 - PAGE_SHIFT))) { + if (totalram_pages() < (512 << (20 - PAGE_SHIFT))) { transparent_hugepage_flags = 0; return 0; } @@ -694,7 +694,6 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf) transparent_hugepage_use_zero_page()) { pgtable_t pgtable; struct page *zero_page; - bool set; vm_fault_t ret; pgtable = pte_alloc_one(vma->vm_mm, haddr); if (unlikely(!pgtable)) @@ -707,25 +706,25 @@ vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf) } vmf->ptl = pmd_lock(vma->vm_mm, vmf->pmd); ret = 0; - set = false; if (pmd_none(*vmf->pmd)) { ret = check_stable_address_space(vma->vm_mm); if (ret) { spin_unlock(vmf->ptl); + pte_free(vma->vm_mm, pgtable); } else if (userfaultfd_missing(vma)) { spin_unlock(vmf->ptl); + pte_free(vma->vm_mm, pgtable); ret = handle_userfault(vmf, VM_UFFD_MISSING); VM_BUG_ON(ret & VM_FAULT_FALLBACK); } else { set_huge_zero_page(pgtable, vma->vm_mm, vma, haddr, vmf->pmd, zero_page); spin_unlock(vmf->ptl); - set = true; } - } else + } else { spin_unlock(vmf->ptl); - if (!set) pte_free(vma->vm_mm, pgtable); + } return ret; } gfp = alloc_hugepage_direct_gfpmask(vma); @@ -1433,13 +1432,12 @@ vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd) } /* - * FOLL_FORCE can write to even unwritable pmd's, but only - * after we've gone through a COW cycle and they are dirty. + * FOLL_FORCE or a forced COW break can write even to unwritable pmd's, + * but only after we've gone through a COW cycle and they are dirty. */ static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags) { - return pmd_write(pmd) || - ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd)); + return pmd_write(pmd) || ((flags & FOLL_COW) && pmd_dirty(pmd)); } struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, @@ -2277,7 +2275,7 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, spinlock_t *ptl; struct mm_struct *mm = vma->vm_mm; unsigned long haddr = address & HPAGE_PMD_MASK; - bool was_locked = false; + bool do_unlock_page = false; pmd_t _pmd; mmu_notifier_invalidate_range_start(mm, haddr, haddr + HPAGE_PMD_SIZE); @@ -2290,7 +2288,6 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, VM_BUG_ON(freeze && !page); if (page) { VM_WARN_ON_ONCE(!PageLocked(page)); - was_locked = true; if (page != pmd_page(*pmd)) goto out; } @@ -2299,19 +2296,29 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, if (pmd_trans_huge(*pmd)) { if (!page) { page = pmd_page(*pmd); - if (unlikely(!trylock_page(page))) { - get_page(page); - _pmd = *pmd; - spin_unlock(ptl); - lock_page(page); - spin_lock(ptl); - if (unlikely(!pmd_same(*pmd, _pmd))) { - unlock_page(page); + /* + * An anonymous page must be locked, to ensure that a + * concurrent reuse_swap_page() sees stable mapcount; + * but reuse_swap_page() is not used on shmem or file, + * and page lock must not be taken when zap_pmd_range() + * calls __split_huge_pmd() while i_mmap_lock is held. + */ + if (PageAnon(page)) { + if (unlikely(!trylock_page(page))) { + get_page(page); + _pmd = *pmd; + spin_unlock(ptl); + lock_page(page); + spin_lock(ptl); + if (unlikely(!pmd_same(*pmd, _pmd))) { + unlock_page(page); + put_page(page); + page = NULL; + goto repeat; + } put_page(page); - page = NULL; - goto repeat; } - put_page(page); + do_unlock_page = true; } } if (PageMlocked(page)) @@ -2321,7 +2328,7 @@ void __split_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, __split_huge_pmd_locked(vma, pmd, haddr, freeze); out: spin_unlock(ptl); - if (!was_locked && page) + if (do_unlock_page) unlock_page(page); /* * No need to double call mmu_notifier->invalidate_range() callback. diff --git a/mm/hugetlb.c b/mm/hugetlb.c index df155e1419f8..3d1bfa75d78c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -68,6 +68,21 @@ DEFINE_SPINLOCK(hugetlb_lock); static int num_fault_mutexes; struct mutex *hugetlb_fault_mutex_table ____cacheline_aligned_in_smp; +static inline bool PageHugeFreed(struct page *head) +{ + return page_private(head + 4) == -1UL; +} + +static inline void SetPageHugeFreed(struct page *head) +{ + set_page_private(head + 4, -1UL); +} + +static inline void ClearPageHugeFreed(struct page *head) +{ + set_page_private(head + 4, 0); +} + /* Forward declaration */ static int hugetlb_acct_memory(struct hstate *h, long delta); @@ -858,6 +873,7 @@ static void enqueue_huge_page(struct hstate *h, struct page *page) list_move(&page->lru, &h->hugepage_freelists[nid]); h->free_huge_pages++; h->free_huge_pages_node[nid]++; + SetPageHugeFreed(page); } static struct page *dequeue_huge_page_node_exact(struct hstate *h, int nid) @@ -875,6 +891,7 @@ static struct page *dequeue_huge_page_node_exact(struct hstate *h, int nid) return NULL; list_move(&page->lru, &h->hugepage_activelist); set_page_refcounted(page); + ClearPageHugeFreed(page); h->free_huge_pages--; h->free_huge_pages_node[nid]--; return page; @@ -1154,14 +1171,16 @@ static inline void destroy_compound_gigantic_page(struct page *page, static void update_and_free_page(struct hstate *h, struct page *page) { int i; + struct page *subpage = page; if (hstate_is_gigantic(h) && !gigantic_page_supported()) return; h->nr_huge_pages--; h->nr_huge_pages_node[page_to_nid(page)]--; - for (i = 0; i < pages_per_huge_page(h); i++) { - page[i].flags &= ~(1 << PG_locked | 1 << PG_error | + for (i = 0; i < pages_per_huge_page(h); + i++, subpage = mem_map_next(subpage, page, i)) { + subpage->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced | 1 << PG_dirty | 1 << PG_active | 1 << PG_private | 1 << PG_writeback); @@ -1196,12 +1215,11 @@ struct hstate *size_to_hstate(unsigned long size) */ bool page_huge_active(struct page *page) { - VM_BUG_ON_PAGE(!PageHuge(page), page); - return PageHead(page) && PagePrivate(&page[1]); + return PageHeadHuge(page) && PagePrivate(&page[1]); } /* never called for tail page */ -static void set_page_huge_active(struct page *page) +void set_page_huge_active(struct page *page) { VM_BUG_ON_PAGE(!PageHeadHuge(page), page); SetPagePrivate(&page[1]); @@ -1305,6 +1323,7 @@ static void prep_new_huge_page(struct hstate *h, struct page *page, int nid) set_hugetlb_cgroup(page, NULL); h->nr_huge_pages++; h->nr_huge_pages_node[nid]++; + ClearPageHugeFreed(page); spin_unlock(&hugetlb_lock); } @@ -1500,6 +1519,7 @@ int dissolve_free_huge_page(struct page *page) { int rc = -EBUSY; +retry: /* Not to disrupt normal path by vainly holding hugetlb_lock */ if (!PageHuge(page)) return 0; @@ -1516,6 +1536,26 @@ int dissolve_free_huge_page(struct page *page) int nid = page_to_nid(head); if (h->free_huge_pages - h->resv_huge_pages == 0) goto out; + + /* + * We should make sure that the page is already on the free list + * when it is dissolved. + */ + if (unlikely(!PageHugeFreed(head))) { + spin_unlock(&hugetlb_lock); + cond_resched(); + + /* + * Theoretically, we should return -EBUSY when we + * encounter this race. In fact, we have a chance + * to successfully dissolve the page if we do a + * retry. Because the race window is quite small. + * If we seize this opportunity, it is an optimization + * for increasing the success rate of dissolving page. + */ + goto retry; + } + /* * Move PageHWPoison flag from head page to the raw error page, * which makes any subpages rather than the error page reusable. @@ -2172,7 +2212,7 @@ static void __init gather_bootmem_prealloc(void) /* * If we had gigantic hugepages allocated at boot time, we need - * to restore the 'stolen' pages to totalram_pages in order to + * to restore the 'stolen' pages to totalram_pages() in order to * fix confusing memory reports from free(1) and another * side-effects, like CommitLimit going negative. */ @@ -2610,8 +2650,10 @@ static int hugetlb_sysfs_add_hstate(struct hstate *h, struct kobject *parent, return -ENOMEM; retval = sysfs_create_group(hstate_kobjs[hi], hstate_attr_group); - if (retval) + if (retval) { kobject_put(hstate_kobjs[hi]); + hstate_kobjs[hi] = NULL; + } return retval; } @@ -3854,7 +3896,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm, * So we need to block hugepage fault by PG_hwpoison bit check. */ if (unlikely(PageHWPoison(page))) { - ret = VM_FAULT_HWPOISON | + ret = VM_FAULT_HWPOISON_LARGE | VM_FAULT_SET_HINDEX(hstate_index(h)); goto backout_unlocked; } @@ -4666,21 +4708,23 @@ static bool vma_shareable(struct vm_area_struct *vma, unsigned long addr) void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma, unsigned long *start, unsigned long *end) { - unsigned long a_start, a_end; + unsigned long v_start = ALIGN(vma->vm_start, PUD_SIZE), + v_end = ALIGN_DOWN(vma->vm_end, PUD_SIZE); - if (!(vma->vm_flags & VM_MAYSHARE)) + /* + * vma need span at least one aligned PUD size and the start,end range + * must at least partialy within it. + */ + if (!(vma->vm_flags & VM_MAYSHARE) || !(v_end > v_start) || + (*end <= v_start) || (*start >= v_end)) return; /* Extend the range to be PUD aligned for a worst case scenario */ - a_start = ALIGN_DOWN(*start, PUD_SIZE); - a_end = ALIGN(*end, PUD_SIZE); + if (*start > v_start) + *start = ALIGN_DOWN(*start, PUD_SIZE); - /* - * Intersect the range with the vma range, since pmd sharing won't be - * across vma after all - */ - *start = max(vma->vm_start, a_start); - *end = min(vma->vm_end, a_end); + if (*end < v_end) + *end = ALIGN(*end, PUD_SIZE); } /* @@ -4942,9 +4986,9 @@ bool isolate_huge_page(struct page *page, struct list_head *list) { bool ret = true; - VM_BUG_ON_PAGE(!PageHead(page), page); spin_lock(&hugetlb_lock); - if (!page_huge_active(page) || !get_page_unless_zero(page)) { + if (!PageHeadHuge(page) || !page_huge_active(page) || + !get_page_unless_zero(page)) { ret = false; goto unlock; } diff --git a/mm/kasan/init.c b/mm/kasan/init.c index 1f2d7d832c68..807b5416b375 100644 --- a/mm/kasan/init.c +++ b/mm/kasan/init.c @@ -383,9 +383,10 @@ static void kasan_remove_pmd_table(pmd_t *pmd, unsigned long addr, if (kasan_pte_table(*pmd)) { if (IS_ALIGNED(addr, PMD_SIZE) && - IS_ALIGNED(next, PMD_SIZE)) + IS_ALIGNED(next, PMD_SIZE)) { pmd_clear(pmd); - continue; + continue; + } } pte = pte_offset_kernel(pmd, addr); kasan_remove_pte_table(pte, addr, next); @@ -408,9 +409,10 @@ static void kasan_remove_pud_table(pud_t *pud, unsigned long addr, if (kasan_pmd_table(*pud)) { if (IS_ALIGNED(addr, PUD_SIZE) && - IS_ALIGNED(next, PUD_SIZE)) + IS_ALIGNED(next, PUD_SIZE)) { pud_clear(pud); - continue; + continue; + } } pmd = pmd_offset(pud, addr); pmd_base = pmd_offset(pud, 0); @@ -434,9 +436,10 @@ static void kasan_remove_p4d_table(p4d_t *p4d, unsigned long addr, if (kasan_pud_table(*p4d)) { if (IS_ALIGNED(addr, P4D_SIZE) && - IS_ALIGNED(next, P4D_SIZE)) + IS_ALIGNED(next, P4D_SIZE)) { p4d_clear(p4d); - continue; + continue; + } } pud = pud_offset(p4d, addr); kasan_remove_pud_table(pud, addr, next); @@ -468,9 +471,10 @@ void kasan_remove_zero_shadow(void *start, unsigned long size) if (kasan_p4d_table(*pgd)) { if (IS_ALIGNED(addr, PGDIR_SIZE) && - IS_ALIGNED(next, PGDIR_SIZE)) + IS_ALIGNED(next, PGDIR_SIZE)) { pgd_clear(pgd); - continue; + continue; + } } p4d = p4d_offset(pgd, addr); @@ -494,7 +498,6 @@ int kasan_add_zero_shadow(void *start, unsigned long size) ret = kasan_populate_early_shadow(shadow_start, shadow_end); if (ret) - kasan_remove_zero_shadow(shadow_start, - size >> KASAN_SHADOW_SCALE_SHIFT); + kasan_remove_zero_shadow(start, size); return ret; } diff --git a/mm/kasan/quarantine.c b/mm/kasan/quarantine.c index 57334ef2d7ef..978bc4a3eb51 100644 --- a/mm/kasan/quarantine.c +++ b/mm/kasan/quarantine.c @@ -237,7 +237,7 @@ void quarantine_reduce(void) * Update quarantine size in case of hotplug. Allocate a fraction of * the installed memory to quarantine minus per-cpu queue limits. */ - total_size = (READ_ONCE(totalram_pages) << PAGE_SHIFT) / + total_size = (totalram_pages() << PAGE_SHIFT) / QUARANTINE_FRACTION; percpu_quarantines = QUARANTINE_PERCPU_SIZE * num_online_cpus(); new_quarantine_size = (total_size < percpu_quarantines) ? diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 740cba23f4a3..73680678efde 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -563,11 +563,10 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size, struct kmemleak_object *object, *parent; struct rb_node **link, *rb_parent; - object = kmem_cache_alloc(object_cache, gfp_kmemleak_mask(gfp)); - if (!object) { - pr_warn("Cannot allocate a kmemleak_object structure\n"); - kmemleak_disable(); - return NULL; + while (1) { + object = kmem_cache_alloc(object_cache, gfp_kmemleak_mask(gfp)); + if (object) + break; } INIT_LIST_HEAD(&object->object_list); diff --git a/mm/list_lru.c b/mm/list_lru.c index 758653dd1443..f7d2ffc209fb 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -542,7 +542,6 @@ static void memcg_drain_list_lru_node(struct list_lru *lru, int nid, struct list_lru_node *nlru = &lru->node[nid]; int dst_idx = dst_memcg->kmemcg_id; struct list_lru_one *src, *dst; - bool set; /* * Since list_lru_{add,del} may be called under an IRQ-safe lock, @@ -554,11 +553,12 @@ static void memcg_drain_list_lru_node(struct list_lru *lru, int nid, dst = list_lru_from_memcg_idx(nlru, dst_idx); list_splice_init(&src->list, &dst->list); - set = (!dst->nr_items && src->nr_items); - dst->nr_items += src->nr_items; - if (set) + + if (src->nr_items) { + dst->nr_items += src->nr_items; memcg_set_shrinker_bit(dst_memcg, nid, lru_shrinker_id(lru)); - src->nr_items = 0; + src->nr_items = 0; + } spin_unlock_irq(&nlru->lock); } diff --git a/mm/memblock.c b/mm/memblock.c index 91795949cb89..315b5785be14 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -234,14 +234,6 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end, * * Find @size free area aligned to @align in the specified range and node. * - * When allocation direction is bottom-up, the @start should be greater - * than the end of the kernel image. Otherwise, it will be trimmed. The - * reason is that we want the bottom-up allocation just near the kernel - * image so it is highly likely that the allocated memory and the kernel - * will reside in the same node. - * - * If bottom-up allocation failed, will try to allocate memory top-down. - * * Return: * Found address on success, 0 on failure. */ @@ -250,8 +242,6 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, phys_addr_t end, int nid, enum memblock_flags flags) { - phys_addr_t kernel_end, ret; - /* pump up @end */ if (end == MEMBLOCK_ALLOC_ACCESSIBLE || end == MEMBLOCK_ALLOC_KASAN) @@ -260,40 +250,13 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, /* avoid allocating the first page */ start = max_t(phys_addr_t, start, PAGE_SIZE); end = max(start, end); - kernel_end = __pa_symbol(_end); - - /* - * try bottom-up allocation only when bottom-up mode - * is set and @end is above the kernel image. - */ - if (memblock_bottom_up() && end > kernel_end) { - phys_addr_t bottom_up_start; - - /* make sure we will allocate above the kernel */ - bottom_up_start = max(start, kernel_end); - /* ok, try bottom-up allocation first */ - ret = __memblock_find_range_bottom_up(bottom_up_start, end, - size, align, nid, flags); - if (ret) - return ret; - - /* - * we always limit bottom-up allocation above the kernel, - * but top-down allocation doesn't have the limit, so - * retrying top-down allocation may succeed when bottom-up - * allocation failed. - * - * bottom-up allocation is expected to be fail very rarely, - * so we use WARN_ONCE() here to see the stack trace if - * fail happens. - */ - WARN_ONCE(IS_ENABLED(CONFIG_MEMORY_HOTREMOVE), - "memblock: bottom-up allocation failed, memory hotremove may be affected\n"); - } - - return __memblock_find_range_top_down(start, end, size, align, nid, - flags); + if (memblock_bottom_up()) + return __memblock_find_range_bottom_up(start, end, size, align, + nid, flags); + else + return __memblock_find_range_top_down(start, end, size, align, + nid, flags); } /** @@ -1575,7 +1538,7 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size) for (; cursor < end; cursor++) { __free_pages_bootmem(pfn_to_page(cursor), cursor, 0); - totalram_pages++; + totalram_pages_inc(); } } diff --git a/mm/memory.c b/mm/memory.c index dba4d66222de..2d760c8f5564 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -153,7 +153,7 @@ static int __init init_zero_pfn(void) zero_pfn = page_to_pfn(ZERO_PAGE(0)); return 0; } -core_initcall(init_zero_pfn); +early_initcall(init_zero_pfn); /* * Only trace rss_stat when there is a 512kb cross over. @@ -2036,11 +2036,11 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr, unsigned long end, unsigned long pfn, pgprot_t prot) { - pte_t *pte; + pte_t *pte, *mapped_pte; spinlock_t *ptl; int err = 0; - pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); + mapped_pte = pte = pte_alloc_map_lock(mm, pmd, addr, &ptl); if (!pte) return -ENOMEM; arch_enter_lazy_mmu_mode(); @@ -2054,7 +2054,7 @@ static int remap_pte_range(struct mm_struct *mm, pmd_t *pmd, pfn++; } while (pte++, addr += PAGE_SIZE, addr != end); arch_leave_lazy_mmu_mode(); - pte_unmap_unlock(pte - 1, ptl); + pte_unmap_unlock(mapped_pte, ptl); return err; } @@ -5420,17 +5420,19 @@ long copy_huge_page_from_user(struct page *dst_page, void *page_kaddr; unsigned long i, rc = 0; unsigned long ret_val = pages_per_huge_page * PAGE_SIZE; + struct page *subpage = dst_page; - for (i = 0; i < pages_per_huge_page; i++) { + for (i = 0; i < pages_per_huge_page; + i++, subpage = mem_map_next(subpage, dst_page, i)) { if (allow_pagefault) - page_kaddr = kmap(dst_page + i); + page_kaddr = kmap(subpage); else - page_kaddr = kmap_atomic(dst_page + i); + page_kaddr = kmap_atomic(subpage); rc = copy_from_user(page_kaddr, (const void __user *)(src + i * PAGE_SIZE), PAGE_SIZE); if (allow_pagefault) - kunmap(dst_page + i); + kunmap(subpage); else kunmap_atomic(page_kaddr); diff --git a/mm/mm_init.c b/mm/mm_init.c index 6838a530789b..33917105a3a2 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -146,7 +146,7 @@ static void __meminit mm_compute_batch(void) s32 batch = max_t(s32, nr*2, 32); /* batch size set to 0.4% of (total memory/#cpus), or max int32 */ - memsized_batch = min_t(u64, (totalram_pages/nr)/256, 0x7fffffff); + memsized_batch = min_t(u64, (totalram_pages()/nr)/256, 0x7fffffff); vm_committed_as_batch = max_t(s32, memsized_batch, batch); } diff --git a/mm/mremap.c b/mm/mremap.c index f1247602c12a..531d6b3960f9 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -191,6 +191,52 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, drop_rmap_locks(vma); } +#ifdef CONFIG_HAVE_MOVE_PMD +static bool move_normal_pmd(struct vm_area_struct *vma, unsigned long old_addr, + unsigned long new_addr, unsigned long old_end, + pmd_t *old_pmd, pmd_t *new_pmd) +{ + spinlock_t *old_ptl, *new_ptl; + struct mm_struct *mm = vma->vm_mm; + pmd_t pmd; + + if ((old_addr & ~PMD_MASK) || (new_addr & ~PMD_MASK) + || old_end - old_addr < PMD_SIZE) + return false; + + /* + * The destination pmd shouldn't be established, free_pgtables() + * should have release it. + */ + if (WARN_ON(!pmd_none(*new_pmd))) + return false; + + /* + * We don't have to worry about the ordering of src and dst + * ptlocks because exclusive mmap_sem prevents deadlock. + */ + old_ptl = pmd_lock(vma->vm_mm, old_pmd); + new_ptl = pmd_lockptr(mm, new_pmd); + if (new_ptl != old_ptl) + spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING); + + /* Clear the pmd */ + pmd = *old_pmd; + pmd_clear(old_pmd); + + VM_BUG_ON(!pmd_none(*new_pmd)); + + /* Set the new pmd */ + set_pmd_at(mm, new_addr, new_pmd, pmd); + flush_tlb_range(vma, old_addr, old_addr + PMD_SIZE); + if (new_ptl != old_ptl) + spin_unlock(new_ptl); + spin_unlock(old_ptl); + + return true; +} +#endif + unsigned long move_page_tables(struct vm_area_struct *vma, unsigned long old_addr, struct vm_area_struct *new_vma, unsigned long new_addr, unsigned long len, @@ -237,7 +283,25 @@ unsigned long move_page_tables(struct vm_area_struct *vma, split_huge_pmd(vma, old_pmd, old_addr); if (pmd_trans_unstable(old_pmd)) continue; + } else if (extent == PMD_SIZE) { +#ifdef CONFIG_HAVE_MOVE_PMD + /* + * If the extent is PMD-sized, try to speed the move by + * moving at the PMD level if possible. + */ + bool moved; + + if (need_rmap_locks) + take_rmap_locks(vma); + moved = move_normal_pmd(vma, old_addr, new_addr, + old_end, old_pmd, new_pmd); + if (need_rmap_locks) + drop_rmap_locks(vma); + if (moved) + continue; +#endif } + if (pte_alloc(new_vma->vm_mm, new_pmd, new_addr)) break; next = (new_addr + PMD_SIZE) & PMD_MASK; diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 2bd550e31802..afb51eb646cf 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -92,7 +92,7 @@ void free_bootmem_late(unsigned long addr, unsigned long size) for (; cursor < end; cursor++) { __free_pages_bootmem(pfn_to_page(cursor), cursor, 0); - totalram_pages++; + totalram_pages_inc(); } } @@ -185,7 +185,7 @@ unsigned long __init free_all_bootmem(void) reset_all_zones_managed_pages(); pages = free_low_memory_core_early(); - totalram_pages += pages; + totalram_pages_add(pages); return pages; } diff --git a/mm/oom_kill.c b/mm/oom_kill.c index a76ca7a269f3..0af869c75c94 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -451,7 +451,7 @@ static enum oom_constraint constrained_alloc(struct oom_control *oc) } /* Default to all available memory */ - oc->totalpages = totalram_pages + total_swap_pages; + oc->totalpages = totalram_pages() + total_swap_pages; if (!IS_ENABLED(CONFIG_NUMA)) return CONSTRAINT_NONE; @@ -912,7 +912,7 @@ void exit_oom_victim(void) void oom_killer_enable(void) { oom_killer_disabled = false; - pr_info("OOM killer enabled.\n"); + pr_debug("OOM killer enabled.\n"); } /** @@ -949,7 +949,7 @@ bool oom_killer_disable(signed long timeout) oom_killer_enable(); return false; } - pr_info("OOM killer disabled.\n"); + pr_debug("OOM killer disabled.\n"); return true; } @@ -1272,7 +1272,7 @@ bool out_of_memory(struct oom_control *oc) unsigned long freed = 0; enum oom_constraint constraint = CONSTRAINT_NONE; - if (oom_killer_disabled) + if (oom_killer_disabled || IS_ENABLED(CONFIG_ANDROID_SIMPLE_LMK)) return false; if (try_online_one_block(numa_node_id())) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 28a209e2fe8c..5d4ae7352fa8 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -133,7 +134,8 @@ EXPORT_SYMBOL(node_states); /* Protect totalram_pages and zone->managed_pages */ static DEFINE_SPINLOCK(managed_page_count_lock); -unsigned long totalram_pages __read_mostly; +atomic_long_t _totalram_pages __read_mostly; +EXPORT_SYMBOL(_totalram_pages); unsigned long totalreserve_pages __read_mostly; unsigned long totalcma_pages __read_mostly; @@ -4720,8 +4722,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, /* Avoid allocations with no watermarks from looping endlessly */ if (tsk_is_oom_victim(current) && (alloc_flags == ALLOC_OOM || - (gfp_mask & __GFP_NOMEMALLOC))) + (gfp_mask & __GFP_NOMEMALLOC))) { + gfp_mask |= __GFP_NOWARN; goto nopage; + } /* Retry as long as the OOM killer is making progress */ if (did_some_progress) { @@ -5254,11 +5258,11 @@ EXPORT_SYMBOL_GPL(si_mem_available); void si_meminfo(struct sysinfo *val) { - val->totalram = totalram_pages; + val->totalram = totalram_pages(); val->sharedram = global_node_page_state(NR_SHMEM); val->freeram = global_zone_page_state(NR_FREE_PAGES); val->bufferram = nr_blockdev_pages(); - val->totalhigh = totalhigh_pages; + val->totalhigh = totalhigh_pages(); val->freehigh = nr_free_highpages(); val->mem_unit = PAGE_SIZE; } @@ -7516,10 +7520,10 @@ void adjust_managed_page_count(struct page *page, long count) { spin_lock(&managed_page_count_lock); page_zone(page)->managed_pages += count; - totalram_pages += count; + totalram_pages_add(count); #ifdef CONFIG_HIGHMEM if (PageHighMem(page)) - totalhigh_pages += count; + totalram_pages_add(count); #endif spin_unlock(&managed_page_count_lock); } @@ -7618,10 +7622,10 @@ void __init mem_init_print_info(const char *str) physpages << (PAGE_SHIFT - 10), codesize >> 10, datasize >> 10, rosize >> 10, (init_data_size + init_code_size) >> 10, bss_size >> 10, - (physpages - totalram_pages - totalcma_pages) << (PAGE_SHIFT - 10), + (physpages - totalram_pages() - totalcma_pages) << (PAGE_SHIFT - 10), totalcma_pages << (PAGE_SHIFT - 10), #ifdef CONFIG_HIGHMEM - totalhigh_pages << (PAGE_SHIFT - 10), + totalhigh_pages() << (PAGE_SHIFT - 10), #endif str ? ", " : "", str ? str : ""); } diff --git a/mm/page_io.c b/mm/page_io.c index abf04404c49b..27043e6c7087 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -39,7 +39,6 @@ static struct bio *get_swap_bio(gfp_t gfp_flags, bio->bi_iter.bi_sector = map_swap_page(page, &bdev); bio_set_dev(bio, bdev); - bio->bi_iter.bi_sector <<= PAGE_SHIFT - 9; bio->bi_end_io = end_io; for (i = 0; i < nr; i++) @@ -264,11 +263,6 @@ int swap_writepage(struct page *page, struct writeback_control *wbc) return ret; } -static sector_t swap_page_sector(struct page *page) -{ - return (sector_t)__page_file_index(page) << (PAGE_SHIFT - 9); -} - static inline void count_swpout_vm_event(struct page *page) { #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -327,7 +321,8 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, return ret; } - ret = bdev_write_page(sis->bdev, swap_page_sector(page), page, wbc); + ret = bdev_write_page(sis->bdev, map_swap_page(page, &sis->bdev), + page, wbc); if (!ret) { count_swpout_vm_event(page); return 0; @@ -387,7 +382,7 @@ int swap_readpage(struct page *page, bool synchronous) goto out; } - ret = bdev_read_page(sis->bdev, swap_page_sector(page), page); + ret = bdev_read_page(sis->bdev, map_swap_page(page, &sis->bdev), page); if (!ret) { if (trylock_page(page)) { swap_slot_free_notify(page); diff --git a/mm/shmem.c b/mm/shmem.c index 3a657d3288ad..5024c50e8505 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -109,12 +109,14 @@ struct shmem_falloc { #ifdef CONFIG_TMPFS static unsigned long shmem_default_max_blocks(void) { - return totalram_pages / 2; + return totalram_pages() / 2; } static unsigned long shmem_default_max_inodes(void) { - return min(totalram_pages - totalhigh_pages, totalram_pages / 2); + unsigned long nr_pages = totalram_pages(); + + return min(nr_pages - totalhigh_pages(), nr_pages / 2); } #endif @@ -3377,7 +3379,7 @@ static int shmem_parse_options(char *options, struct shmem_sb_info *sbinfo, size = memparse(value,&rest); if (*rest == '%') { size <<= PAGE_SHIFT; - size *= totalram_pages; + size *= totalram_pages(); do_div(size, 100); rest++; } diff --git a/mm/slab.c b/mm/slab.c index fa53bb09495d..7283e312e229 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1238,7 +1238,7 @@ void __init kmem_cache_init(void) * page orders on machines with more than 32MB of memory if * not overridden on the command line. */ - if (!slab_max_order_set && totalram_pages > (32 << 20) >> PAGE_SHIFT) + if (!slab_max_order_set && totalram_pages() > (32 << 20) >> PAGE_SHIFT) slab_max_order = SLAB_MAX_ORDER_HI; /* Bootstrap is tricky, because several objects are allocated diff --git a/mm/slub.c b/mm/slub.c index dc50ed7f3a88..7af3842a597e 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2954,20 +2954,21 @@ static void __slab_free(struct kmem_cache *s, struct page *page, if (likely(!n)) { - /* - * If we just froze the page then put it onto the - * per cpu partial list. - */ - if (new.frozen && !was_frozen) { + if (likely(was_frozen)) { + /* + * The list lock was not taken therefore no list + * activity can be necessary. + */ + stat(s, FREE_FROZEN); + } else if (new.frozen) { + /* + * If we just froze the page then put it onto the + * per cpu partial list. + */ put_cpu_partial(s, page, 1); stat(s, CPU_PARTIAL_FREE); } - /* - * The list lock was not taken therefore no list - * activity can be necessary. - */ - if (was_frozen) - stat(s, FREE_FROZEN); + return; } @@ -5860,10 +5861,8 @@ static int sysfs_slab_add(struct kmem_cache *s) s->kobj.kset = kset; err = kobject_init_and_add(&s->kobj, &slab_ktype, NULL, "%s", name); - if (err) { - kobject_put(&s->kobj); + if (err) goto out; - } err = sysfs_create_group(&s->kobj, &slab_attr_group); if (err) diff --git a/mm/swap.c b/mm/swap.c index c48106674912..beeab1df30ff 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -1032,13 +1032,13 @@ EXPORT_SYMBOL(pagevec_lookup_range_nr_tag); */ void __init swap_setup(void) { - unsigned long megs = totalram_pages >> (20 - PAGE_SHIFT); + unsigned long megs = totalram_pages() >> (20 - PAGE_SHIFT); /* Use a smaller cluster for small-memory machines */ if (megs < 16) page_cluster = 2; else - page_cluster = 3; + page_cluster = 0; /* * Right now other parts of the system means that we * _really_ don't want to cluster much more diff --git a/mm/swap_state.c b/mm/swap_state.c index 565e3464a364..6bf49f12d15a 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -588,6 +588,10 @@ struct page *swap_cluster_readahead(swp_entry_t entry, gfp_t gfp_mask, if (!mask) goto skip; + /* If exiting, don't do swap readahead. */ + if (current->flags & PF_EXITING) + goto skip; + do_poll = false; /* Read a page_cluster sized and aligned cluster around offset. */ start_offset = offset & ~mask; diff --git a/mm/swapfile.c b/mm/swapfile.c index c1eb8bdc8300..fd2ce14e790f 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -2326,7 +2326,7 @@ sector_t map_swap_page(struct page *page, struct block_device **bdev) { swp_entry_t entry; entry.val = page_private(page); - return map_swap_entry(entry, bdev); + return map_swap_entry(entry, bdev) << (PAGE_SHIFT - 9); } /* @@ -2847,6 +2847,7 @@ late_initcall(max_swapfiles_check); static struct swap_info_struct *alloc_swap_info(void) { struct swap_info_struct *p; + struct swap_info_struct *defer = NULL; unsigned int type; int i; int size = sizeof(*p) + nr_node_ids * sizeof(struct plist_node); @@ -2876,7 +2877,7 @@ static struct swap_info_struct *alloc_swap_info(void) smp_wmb(); WRITE_ONCE(nr_swapfiles, nr_swapfiles + 1); } else { - kvfree(p); + defer = p; p = swap_info[type]; /* * Do not memset this entry: a racing procfs swap_next() @@ -2889,6 +2890,7 @@ static struct swap_info_struct *alloc_swap_info(void) plist_node_init(&p->avail_lists[i], 0); p->flags = SWP_USED; spin_unlock(&swap_lock); + kvfree(defer); spin_lock_init(&p->lock); spin_lock_init(&p->cont_lock); diff --git a/mm/util.c b/mm/util.c index 65b4ea61c2d8..99465792337a 100644 --- a/mm/util.c +++ b/mm/util.c @@ -618,7 +618,7 @@ unsigned long vm_commit_limit(void) if (sysctl_overcommit_kbytes) allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10); else - allowed = ((totalram_pages - hugetlb_total_pages()) + allowed = ((totalram_pages() - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100); allowed += total_swap_pages; diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 8f63ba92fdb9..84c0a7b12075 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -364,6 +364,13 @@ static LIST_HEAD(free_vmap_area_list); */ static struct rb_root free_vmap_area_root = RB_ROOT; +/* + * Preload a CPU with one object for "no edge" split case. The + * aim is to get rid of allocations from the atomic context, thus + * to use more permissive allocation masks. + */ +static DEFINE_PER_CPU(struct vmap_area *, ne_fit_preload_node); + static __always_inline unsigned long va_size(struct vmap_area *va) { @@ -874,7 +881,7 @@ find_vmap_lowest_match(unsigned long size, } /* - * OK. We roll back and find the fist right sub-tree, + * OK. We roll back and find the first right sub-tree, * that will satisfy the search criteria. It can happen * only once due to "vstart" restriction. */ @@ -1010,9 +1017,24 @@ adjust_va_to_fit_type(struct vmap_area *va, * L V NVA V R * |---|-------|---| */ - lva = kmem_cache_alloc(vmap_area_cachep, GFP_NOWAIT); - if (unlikely(!lva)) - return -1; + lva = __this_cpu_xchg(ne_fit_preload_node, NULL); + if (unlikely(!lva)) { + /* + * For percpu allocator we do not do any pre-allocation + * and leave it as it is. The reason is it most likely + * never ends up with NE_FIT_TYPE splitting. In case of + * percpu allocations offsets and sizes are aligned to + * fixed align request, i.e. RE_FIT_TYPE and FL_FIT_TYPE + * are its main fitting cases. + * + * There are a few exceptions though, as an example it is + * a first allocation (early boot up) when we have "one" + * big free space that has to be split. + */ + lva = kmem_cache_alloc(vmap_area_cachep, GFP_NOWAIT); + if (!lva) + return -1; + } /* * Build the remainder. @@ -1045,7 +1067,7 @@ adjust_va_to_fit_type(struct vmap_area *va, */ static __always_inline unsigned long __alloc_vmap_area(unsigned long size, unsigned long align, - unsigned long vstart, unsigned long vend, int node) + unsigned long vstart, unsigned long vend) { unsigned long nva_start_addr; struct vmap_area *va; @@ -1091,7 +1113,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size, unsigned long vstart, unsigned long vend, int node, gfp_t gfp_mask) { - struct vmap_area *va; + struct vmap_area *va, *pva; unsigned long addr; int purged = 0; @@ -1116,13 +1138,38 @@ static struct vmap_area *alloc_vmap_area(unsigned long size, kmemleak_scan_area(&va->rb_node, SIZE_MAX, gfp_mask & GFP_RECLAIM_MASK); retry: + /* + * Preload this CPU with one extra vmap_area object to ensure + * that we have it available when fit type of free area is + * NE_FIT_TYPE. + * + * The preload is done in non-atomic context, thus it allows us + * to use more permissive allocation masks to be more stable under + * low memory condition and high memory pressure. + * + * Even if it fails we do not really care about that. Just proceed + * as it is. "overflow" path will refill the cache we allocate from. + */ + preempt_disable(); + if (!__this_cpu_read(ne_fit_preload_node)) { + preempt_enable(); + pva = kmem_cache_alloc_node(vmap_area_cachep, GFP_KERNEL, node); + preempt_disable(); + + if (__this_cpu_cmpxchg(ne_fit_preload_node, NULL, pva)) { + if (pva) + kmem_cache_free(vmap_area_cachep, pva); + } + } + spin_lock(&vmap_area_lock); + preempt_enable(); /* * If an allocation fails, the "vend" address is * returned. Therefore trigger the overflow path. */ - addr = __alloc_vmap_area(size, align, vstart, vend, node); + addr = __alloc_vmap_area(size, align, vstart, vend); if (unlikely(addr == vend)) goto overflow; @@ -2278,6 +2325,14 @@ void vfree_atomic(const void *addr) __vfree_deferred(addr); } +static void __vfree(const void *addr) +{ + if (unlikely(in_interrupt())) + __vfree_deferred(addr); + else + __vunmap(addr, 1); +} + /** * vfree - release memory allocated by vmalloc() * @addr: memory base address @@ -2290,6 +2345,8 @@ void vfree_atomic(const void *addr) * have CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG, but making the calling * conventions for vfree() arch-depenedent would be a really bad idea) * + * May sleep if called *not* from interrupt context. + * * NOTE: assumes that the object at @addr has a size >= sizeof(llist_node) */ void vfree(const void *addr) @@ -2298,12 +2355,12 @@ void vfree(const void *addr) kmemleak_free(addr); + might_sleep_if(!in_interrupt()); + if (!addr) return; - if (unlikely(in_interrupt())) - __vfree_deferred(addr); - else - __vunmap(addr, 1); + + __vfree(addr); } EXPORT_SYMBOL(vfree); @@ -2343,7 +2400,7 @@ void *vmap(struct page **pages, unsigned int count, might_sleep(); - if (count > totalram_pages) + if (count > totalram_pages()) return NULL; size = (unsigned long)count << PAGE_SHIFT; @@ -2422,7 +2479,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, warn_alloc(gfp_mask, NULL, "vmalloc: allocation failure, allocated %ld of %ld bytes", (area->nr_pages*PAGE_SIZE), area->size); - vfree(area->addr); + __vfree(area->addr); return NULL; } @@ -2452,7 +2509,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, unsigned long real_size = size; size = PAGE_ALIGN(size); - if (!size || (size >> PAGE_SHIFT) > totalram_pages) + if (!size || (size >> PAGE_SHIFT) > totalram_pages()) goto fail; area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED | @@ -2487,6 +2544,15 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align, return NULL; } +/* + * This is only for performance analysis of vmalloc and stress purpose. + * It is required by vmalloc test module, therefore do not use it other + * than that. + */ +#ifdef CONFIG_TEST_VMALLOC_MODULE +EXPORT_SYMBOL_GPL(__vmalloc_node_range); +#endif + /** * __vmalloc_node - allocate virtually contiguous memory * @size: allocation size @@ -2583,18 +2649,10 @@ EXPORT_SYMBOL(vzalloc); */ void *vmalloc_user(unsigned long size) { - struct vm_struct *area; - void *ret; - - ret = __vmalloc_node(size, SHMLBA, - GFP_KERNEL | __GFP_ZERO, - PAGE_KERNEL, NUMA_NO_NODE, - __builtin_return_address(0)); - if (ret) { - area = find_vm_area(ret); - area->flags |= VM_USERMAP; - } - return ret; + return __vmalloc_node_range(size, SHMLBA, VMALLOC_START, VMALLOC_END, + GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL, + VM_USERMAP, NUMA_NO_NODE, + __builtin_return_address(0)); } EXPORT_SYMBOL(vmalloc_user); @@ -2688,16 +2746,10 @@ EXPORT_SYMBOL(vmalloc_32); */ void *vmalloc_32_user(unsigned long size) { - struct vm_struct *area; - void *ret; - - ret = __vmalloc_node(size, 1, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL, - NUMA_NO_NODE, __builtin_return_address(0)); - if (ret) { - area = find_vm_area(ret); - area->flags |= VM_USERMAP; - } - return ret; + return __vmalloc_node_range(size, SHMLBA, VMALLOC_START, VMALLOC_END, + GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL, + VM_USERMAP, NUMA_NO_NODE, + __builtin_return_address(0)); } EXPORT_SYMBOL(vmalloc_32_user); diff --git a/mm/vmpressure.c b/mm/vmpressure.c index cf75fcab8a70..7cb746f9fe8d 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -24,24 +24,9 @@ #include #include #include +#include #include -/* - * The window size (vmpressure_win) is the number of scanned pages before - * we try to analyze scanned/reclaimed ratio. So the window is used as a - * rate-limit tunable for the "low" level notification, and also for - * averaging the ratio for medium/critical levels. Using small window - * sizes can cause lot of false positives, but too big window size will - * delay the notifications. - * - * As the vmscan reclaimer logic works with chunks which are multiple of - * SWAP_CLUSTER_MAX, it makes sense to use it for the window size as well. - * - * TODO: Make the window size depend on machine size, as we do for vmstat - * thresholds. Currently we set it to 512 pages (2MB for 4KB pages). - */ -static unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; - /* * These thresholds are used when we account memory pressure through * scanned/reclaimed ratio. The current values were chosen empirically. In @@ -51,6 +36,11 @@ static unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; static const unsigned int vmpressure_level_med = 60; static const unsigned int vmpressure_level_critical = 95; +static unsigned long vmpressure_scale_max = 100; + +/* vmpressure values >= this will be scaled based on allocstalls */ +static unsigned long allocstall_threshold = 70; + static struct vmpressure global_vmpressure; static BLOCKING_NOTIFIER_HEAD(vmpressure_notifier); @@ -178,6 +168,19 @@ static unsigned long vmpressure_calc_pressure(unsigned long scanned, return pressure; } +static unsigned long vmpressure_account_stall(unsigned long pressure, + unsigned long stall, unsigned long scanned) +{ + unsigned long scale; + + if (pressure < allocstall_threshold) + return pressure; + + scale = ((vmpressure_scale_max - pressure) * stall) / scanned; + + return pressure + scale; +} + struct vmpressure_event { struct eventfd_ctx *efd; enum vmpressure_levels level; @@ -248,25 +251,34 @@ static void vmpressure_work_fn(struct work_struct *work) } while ((vmpr = vmpressure_parent(vmpr))); } -#ifdef CONFIG_MEMCG -static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed) +static unsigned long calculate_vmpressure_win(void) { - struct vmpressure *vmpr = memcg_to_vmpressure(memcg); + long x; + x = global_node_page_state(NR_FILE_PAGES) - + global_node_page_state(NR_SHMEM) - + total_swapcache_pages() + + global_zone_page_state(NR_FREE_PAGES); + if (x < 1) + return 1; /* - * Here we only want to account pressure that userland is able to - * help us with. For example, suppose that DMA zone is under - * pressure; if we notify userland about that kind of pressure, - * then it will be mostly a waste as it will trigger unnecessary - * freeing of memory by userland (since userland is more likely to - * have HIGHMEM/MOVABLE pages instead of the DMA fallback). That - * is why we include only movable, highmem and FS/IO pages. - * Indirect reclaim (kswapd) sets sc->gfp_mask to GFP_KERNEL, so - * we account it too. + * For low (free + cached), vmpressure window should be + * small, and high for higher values of (free + cached). + * But it should not be linear as well. This ensures + * timely vmpressure notifications when system is under + * memory pressure, and optimal number of events when + * cached is high. The sqaure root function is empirically + * found to serve the purpose. */ - if (!(gfp & (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_IO | __GFP_FS))) - return; + return int_sqrt(x); +} + +#ifdef CONFIG_MEMCG +static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool critical, + bool tree, unsigned long scanned, + unsigned long reclaimed) +{ + struct vmpressure *vmpr = memcg_to_vmpressure(memcg); /* * If we got here with no pages scanned, then that is an indicator @@ -276,7 +288,9 @@ static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, * (scanning depth) goes too high (deep), we will be notified * through vmpressure_prio(). But so far, keep calm. */ - if (!scanned) + if (critical) + scanned = calculate_vmpressure_win(); + else if (!scanned) return; if (tree) { @@ -285,7 +299,7 @@ static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, vmpr->tree_reclaimed += reclaimed; spin_unlock(&vmpr->sr_lock); - if (scanned < vmpressure_win) + if (!critical && scanned < calculate_vmpressure_win()) return; schedule_work(&vmpr->work); } else { @@ -299,7 +313,7 @@ static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, spin_lock(&vmpr->sr_lock); scanned = vmpr->scanned += scanned; reclaimed = vmpr->reclaimed += reclaimed; - if (scanned < vmpressure_win) { + if (!critical && scanned < calculate_vmpressure_win()) { spin_unlock(&vmpr->sr_lock); return; } @@ -323,69 +337,64 @@ static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, } } #else -static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed) -{ -} +static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool critical, + bool tree, unsigned long scanned, + unsigned long reclaimed) { } #endif -static void calculate_vmpressure_win(void) -{ - long x; - - x = global_node_page_state(NR_FILE_PAGES) - - global_node_page_state(NR_SHMEM) - - total_swapcache_pages() + - global_zone_page_state(NR_FREE_PAGES); - if (x < 1) - x = 1; - /* - * For low (free + cached), vmpressure window should be - * small, and high for higher values of (free + cached). - * But it should not be linear as well. This ensures - * timely vmpressure notifications when system is under - * memory pressure, and optimal number of events when - * cached is high. The sqaure root function is empirically - * found to serve the purpose. - */ - x = int_sqrt(x); - vmpressure_win = x; -} - -static void vmpressure_global(gfp_t gfp, unsigned long scanned, - unsigned long reclaimed) +static void vmpressure_global(gfp_t gfp, unsigned long scanned, bool critical, + unsigned long reclaimed) { struct vmpressure *vmpr = &global_vmpressure; unsigned long pressure; + unsigned long stall; - if (!(gfp & (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_IO | __GFP_FS))) - return; + if (critical) + scanned = calculate_vmpressure_win(); - if (!scanned) - return; + if (scanned) { + spin_lock(&vmpr->sr_lock); + vmpr->scanned += scanned; + vmpr->reclaimed += reclaimed; - spin_lock(&vmpr->sr_lock); - if (!vmpr->scanned) - calculate_vmpressure_win(); + if (!current_is_kswapd()) + vmpr->stall += scanned; - vmpr->scanned += scanned; - vmpr->reclaimed += reclaimed; - scanned = vmpr->scanned; - reclaimed = vmpr->reclaimed; - spin_unlock(&vmpr->sr_lock); + stall = vmpr->stall; + scanned = vmpr->scanned; + reclaimed = vmpr->reclaimed; + spin_unlock(&vmpr->sr_lock); - if (scanned < vmpressure_win) - return; + if (!critical && scanned < calculate_vmpressure_win()) + return; + } spin_lock(&vmpr->sr_lock); vmpr->scanned = 0; vmpr->reclaimed = 0; + vmpr->stall = 0; spin_unlock(&vmpr->sr_lock); - pressure = vmpressure_calc_pressure(scanned, reclaimed); + if (scanned) { + pressure = vmpressure_calc_pressure(scanned, reclaimed); + pressure = vmpressure_account_stall(pressure, stall, scanned); + } else { + pressure = 100; + } vmpressure_notify(pressure); } +static void __vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool critical, + bool tree, unsigned long scanned, + unsigned long reclaimed) +{ + if (!memcg && tree) + vmpressure_global(gfp, scanned, critical, reclaimed); + + if (IS_ENABLED(CONFIG_MEMCG)) + vmpressure_memcg(gfp, memcg, critical, tree, scanned, reclaimed); +} + /** * vmpressure() - Account memory pressure through scanned/reclaimed ratio * @gfp: reclaimer's gfp mask @@ -408,13 +417,12 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned, * This function does not return any value. */ void vmpressure(gfp_t gfp, struct mem_cgroup *memcg, bool tree, - unsigned long scanned, unsigned long reclaimed) + unsigned long scanned, unsigned long reclaimed, int order) { - if (!memcg && tree) - vmpressure_global(gfp, scanned, reclaimed); + if (order > PAGE_ALLOC_COSTLY_ORDER) + return; - if (IS_ENABLED(CONFIG_MEMCG)) - vmpressure_memcg(gfp, memcg, tree, scanned, reclaimed); + __vmpressure(gfp, memcg, false, tree, scanned, reclaimed); } /** @@ -444,7 +452,7 @@ void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio) * to the vmpressure() basically means that we signal 'critical' * level. */ - vmpressure(gfp, memcg, true, vmpressure_win, 0); + __vmpressure(gfp, memcg, true, true, 0, 0); } #define MAX_VMPRESSURE_ARGS_LEN (strlen("critical") + strlen("hierarchy") + 2) diff --git a/mm/vmscan.c b/mm/vmscan.c index bfe52b7ed24e..46220a459bb4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -174,9 +174,9 @@ int kswapd_threads_current = DEF_KSWAPD_THREADS_PER_NODE; #endif /* - * From 0 .. 100. Higher means more swappy. + * From 0 .. 200. Higher means more swappy. */ -int vm_swappiness = 60; +int vm_swappiness = 160; /* * The total number of pages which are beyond the high watermark within all * zones. @@ -2825,7 +2825,7 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) /* Record the group's reclaim efficiency */ vmpressure(sc->gfp_mask, memcg, false, sc->nr_scanned - scanned, - sc->nr_reclaimed - reclaimed); + sc->nr_reclaimed - reclaimed, sc->order); /* * Direct reclaim and kswapd have to scan all memory @@ -2854,7 +2854,7 @@ static bool shrink_node(pg_data_t *pgdat, struct scan_control *sc) */ vmpressure(sc->gfp_mask, sc->target_mem_cgroup, true, sc->nr_scanned - nr_scanned, - sc->nr_reclaimed - nr_reclaimed); + sc->nr_reclaimed - nr_reclaimed, sc->order); if (reclaim_state) { sc->nr_reclaimed += reclaim_state->reclaimed_slab; diff --git a/mm/vmstat.c b/mm/vmstat.c index 3d81d4fbe5bd..4b653842e52c 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1744,7 +1744,7 @@ static const struct seq_operations vmstat_op = { #ifdef CONFIG_SMP static DEFINE_PER_CPU(struct delayed_work, vmstat_work); -int sysctl_stat_interval __read_mostly = HZ; +int sysctl_stat_interval __read_mostly = CONFIG_VMSTAT_INTERVAL * HZ; #ifdef CONFIG_PROC_FS static void refresh_vm_stats(struct work_struct *work) diff --git a/mm/workingset.c b/mm/workingset.c index 99b7f7c09b13..df279c8e34c9 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -524,7 +524,7 @@ static unsigned long scan_shadow_nodes(struct shrinker *shrinker, static struct shrinker workingset_shadow_shrinker = { .count_objects = count_shadow_nodes, .scan_objects = scan_shadow_nodes, - .seeks = DEFAULT_SEEKS, + .seeks = 0, /* ->count reports only fully expendable nodes */ .flags = SHRINKER_NUMA_AWARE | SHRINKER_MEMCG_AWARE, }; @@ -544,12 +544,12 @@ static int __init workingset_init(void) /* * Calculate the eviction bucket size to cover the longest * actionable refault distance, which is currently half of - * memory (totalram_pages/2). However, memory hotplug may add + * memory (totalram_pages()/2). However, memory hotplug may add * some more pages at runtime, so keep working with up to - * double the initial memory by using totalram_pages as-is. + * double the initial memory by using totalram_pages() as-is. */ timestamp_bits = BITS_PER_LONG - EVICTION_SHIFT; - max_order = fls_long(totalram_pages - 1); + max_order = fls_long(totalram_pages() - 1); if (max_order > timestamp_bits) bucket_order = max_order - timestamp_bits; pr_info("workingset: timestamp_bits=%d max_order=%d bucket_order=%u\n", diff --git a/mm/zswap.c b/mm/zswap.c index cd91fd9d96b8..a4e4d36ec085 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -219,8 +219,8 @@ static const struct zpool_ops zswap_zpool_ops = { static bool zswap_is_full(void) { - return totalram_pages * zswap_max_pool_percent / 100 < - DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE); + return totalram_pages() * zswap_max_pool_percent / 100 < + DIV_ROUND_UP(zswap_pool_total_size, PAGE_SIZE); } static void zswap_update_total_size(void) diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 5e9950453955..512ada90657b 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -277,7 +277,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) return 0; out_free_newdev: - if (new_dev->reg_state == NETREG_UNINITIALIZED) + if (new_dev->reg_state == NETREG_UNINITIALIZED || + new_dev->reg_state == NETREG_UNREGISTERED) free_netdev(new_dev); return err; } diff --git a/net/Kconfig b/net/Kconfig index 6870f6c838e5..67307eec5ea2 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -291,7 +291,7 @@ config BQL config BPF_JIT bool "enable BPF Just In Time compiler" depends on HAVE_CBPF_JIT || HAVE_EBPF_JIT - depends on MODULES + depends on MODULES || ARM64 ---help--- Berkeley Packet Filter filtering capabilities are normally handled by an interpreter. This option allows kernel to generate a native diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 2880ac470379..20ec8e7f9423 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1573,8 +1573,8 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) struct sk_buff *skb; struct net_device *dev; struct ddpehdr *ddp; - int size; - struct atalk_route *rt; + int size, hard_header_len; + struct atalk_route *rt, *rt_lo = NULL; int err; if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) @@ -1637,7 +1637,22 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", sk, size, dev->name); - size += dev->hard_header_len; + hard_header_len = dev->hard_header_len; + /* Leave room for loopback hardware header if necessary */ + if (usat->sat_addr.s_node == ATADDR_BCAST && + (dev->flags & IFF_LOOPBACK || !(rt->flags & RTF_GATEWAY))) { + struct atalk_addr at_lo; + + at_lo.s_node = 0; + at_lo.s_net = 0; + + rt_lo = atrtr_find(&at_lo); + + if (rt_lo && rt_lo->dev->hard_header_len > hard_header_len) + hard_header_len = rt_lo->dev->hard_header_len; + } + + size += hard_header_len; release_sock(sk); skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); lock_sock(sk); @@ -1645,7 +1660,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) goto out; skb_reserve(skb, ddp_dl->header_length); - skb_reserve(skb, dev->hard_header_len); + skb_reserve(skb, hard_header_len); skb->dev = dev; SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); @@ -1696,18 +1711,12 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) /* loop back */ skb_orphan(skb); if (ddp->deh_dnode == ATADDR_BCAST) { - struct atalk_addr at_lo; - - at_lo.s_node = 0; - at_lo.s_net = 0; - - rt = atrtr_find(&at_lo); - if (!rt) { + if (!rt_lo) { kfree_skb(skb); err = -ENETUNREACH; goto out; } - dev = rt->dev; + dev = rt_lo->dev; skb->dev = dev; } ddp_dl->request(ddp_dl, skb, dev->dev_addr); diff --git a/net/batman-adv/log.c b/net/batman-adv/log.c index 853773e45f79..837f67c9fad3 100644 --- a/net/batman-adv/log.c +++ b/net/batman-adv/log.c @@ -205,6 +205,7 @@ static const struct file_operations batadv_log_fops = { .read = batadv_log_read, .poll = batadv_log_poll, .llseek = no_llseek, + .owner = THIS_MODULE, }; /** diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 9fa5389ea244..cc350ab4de0a 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -904,6 +904,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { tt_vlan->vid = htons(vlan->vid); tt_vlan->crc = htonl(vlan->tt.crc); + tt_vlan->reserved = 0; tt_vlan++; } @@ -987,6 +988,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, tt_vlan->vid = htons(vlan->vid); tt_vlan->crc = htonl(vlan->tt.crc); + tt_vlan->reserved = 0; tt_vlan++; } diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index be9640e9ca00..e09ea78356c3 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -388,9 +388,9 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, hdev = hci_dev_get(req->id); if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) { struct a2mp_amp_assoc_rsp rsp; - rsp.id = req->id; memset(&rsp, 0, sizeof(rsp)); + rsp.id = req->id; if (tmp) { rsp.status = A2MP_STATUS_COLLISION_OCCURED; @@ -519,6 +519,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, assoc = kmemdup(req->amp_assoc, assoc_len, GFP_KERNEL); if (!assoc) { amp_ctrl_put(ctrl); + hci_dev_put(hdev); return -ENOMEM; } diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index 78bec8df8525..72ef967c5663 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c @@ -305,6 +305,9 @@ void amp_read_loc_assoc_final_data(struct hci_dev *hdev, struct hci_request req; int err; + if (!mgr) + return; + cp.phy_handle = hcon->handle; cp.len_so_far = cpu_to_le16(0); cp.max_len = cpu_to_le16(hdev->amp_assoc_size); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index e03faca84919..04d6f50798c9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1316,8 +1316,10 @@ int hci_inquiry(void __user *arg) * cleared). If it is interrupted by a signal, return -EINTR. */ if (wait_on_bit(&hdev->flags, HCI_INQUIRY, - TASK_INTERRUPTIBLE)) - return -EINTR; + TASK_INTERRUPTIBLE)) { + err = -EINTR; + goto done; + } } /* for unlimited number of responses we will use buffer with diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d98d8e78b736..b58afd2d5ebf 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4672,6 +4672,11 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev, return; } + if (!hcon->amp_mgr) { + hci_dev_unlock(hdev); + return; + } + if (ev->status) { hci_conn_del(hcon); hci_dev_unlock(hdev); @@ -5596,21 +5601,19 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) { u8 num_reports = skb->data[0]; - void *ptr = &skb->data[1]; + struct hci_ev_le_direct_adv_info *ev = (void *)&skb->data[1]; - hci_dev_lock(hdev); + if (!num_reports || skb->len < num_reports * sizeof(*ev) + 1) + return; - while (num_reports--) { - struct hci_ev_le_direct_adv_info *ev = ptr; + hci_dev_lock(hdev); + for (; num_reports; num_reports--, ev++) process_adv_report(hdev, ev->evt_type, &ev->bdaddr, ev->bdaddr_type, &ev->direct_addr, ev->direct_addr_type, ev->rssi, NULL, 0, false); - ptr += sizeof(*ev); - } - hci_dev_unlock(hdev); } diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 9ce661e2590d..a350c05b7ff5 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -215,6 +215,7 @@ static void br_get_stats64(struct net_device *dev, sum.rx_packets += tmp.rx_packets; } + netdev_stats_to_stats64(stats, &dev->stats); stats->tx_bytes = sum.tx_bytes; stats->tx_packets = sum.tx_packets; stats->rx_bytes = sum.rx_bytes; diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index ccab290c14d4..c5380c6baf2e 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -719,6 +719,11 @@ static int br_nf_dev_queue_xmit(struct net *net, struct sock *sk, struct sk_buff mtu_reserved = nf_bridge_mtu_reduction(skb); mtu = skb->dev->mtu; + if (nf_bridge->pkt_otherhost) { + skb->pkt_type = PACKET_OTHERHOST; + nf_bridge->pkt_otherhost = false; + } + if (nf_bridge->frag_max_size && nf_bridge->frag_max_size < mtu) mtu = nf_bridge->frag_max_size; @@ -812,8 +817,6 @@ static unsigned int br_nf_post_routing(void *priv, else return NF_ACCEPT; - /* We assume any code from br_dev_queue_push_xmit onwards doesn't care - * about the value of skb->pkt_type. */ if (skb->pkt_type == PACKET_OTHERHOST) { skb->pkt_type = PACKET_HOST; nf_bridge->pkt_otherhost = true; diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 7c87a2fe5248..e9e2a3b1f477 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c @@ -59,9 +59,8 @@ static BRPORT_ATTR(_name, 0644, \ static int store_flag(struct net_bridge_port *p, unsigned long v, unsigned long mask) { - unsigned long flags; - - flags = p->flags; + unsigned long flags = p->flags; + int err; if (v) flags |= mask; @@ -69,6 +68,10 @@ static int store_flag(struct net_bridge_port *p, unsigned long v, flags &= ~mask; if (flags != p->flags) { + err = br_switchdev_set_port_flag(p, flags, mask); + if (err) + return err; + p->flags = flags; br_port_flags_change(p, mask); } diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 5f3950f00f73..a82d0021d461 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -242,8 +242,10 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags) } masterv = br_vlan_get_master(br, v->vid); - if (!masterv) + if (!masterv) { + err = -ENOMEM; goto out_filt; + } v->brvlan = masterv; v->stats = masterv->stats; } else { diff --git a/net/can/af_can.c b/net/can/af_can.c index 04132b0b5d36..b3edb8092124 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -722,16 +722,25 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, { struct canfd_frame *cfd = (struct canfd_frame *)skb->data; - if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU || - cfd->len > CAN_MAX_DLEN)) { - pr_warn_once("PF_CAN: dropped non conform CAN skbuf: dev type %d, len %d, datalen %d\n", + if (unlikely(dev->type != ARPHRD_CAN || skb->len != CAN_MTU)) { + pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n", + dev->type, skb->len); + goto free_skb; + } + + /* This check is made separately since cfd->len would be uninitialized if skb->len = 0. */ + if (unlikely(cfd->len > CAN_MAX_DLEN)) { + pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d, datalen %d\n", dev->type, skb->len, cfd->len); - kfree_skb(skb); - return NET_RX_DROP; + goto free_skb; } can_receive(skb, dev); return NET_RX_SUCCESS; + +free_skb: + kfree_skb(skb); + return NET_RX_DROP; } static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, @@ -739,16 +748,25 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, { struct canfd_frame *cfd = (struct canfd_frame *)skb->data; - if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU || - cfd->len > CANFD_MAX_DLEN)) { - pr_warn_once("PF_CAN: dropped non conform CAN FD skbuf: dev type %d, len %d, datalen %d\n", + if (unlikely(dev->type != ARPHRD_CAN || skb->len != CANFD_MTU)) { + pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n", + dev->type, skb->len); + goto free_skb; + } + + /* This check is made separately since cfd->len would be uninitialized if skb->len = 0. */ + if (unlikely(cfd->len > CANFD_MAX_DLEN)) { + pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d, datalen %d\n", dev->type, skb->len, cfd->len); - kfree_skb(skb); - return NET_RX_DROP; + goto free_skb; } can_receive(skb, dev); return NET_RX_SUCCESS; + +free_skb: + kfree_skb(skb); + return NET_RX_DROP; } /* diff --git a/net/can/proc.c b/net/can/proc.c index 70fea17bb04c..a3071f43acd7 100644 --- a/net/can/proc.c +++ b/net/can/proc.c @@ -467,6 +467,9 @@ void can_init_proc(struct net *net) */ void can_remove_proc(struct net *net) { + if (!net->can.proc_dir) + return; + if (net->can.pde_version) remove_proc_entry(CAN_PROC_VERSION, net->can.proc_dir); @@ -494,6 +497,5 @@ void can_remove_proc(struct net *net) if (net->can.pde_rcvlist_sff) remove_proc_entry(CAN_PROC_RCVLIST_SFF, net->can.proc_dir); - if (net->can.proc_dir) - remove_proc_entry("can", net->proc_net); + remove_proc_entry("can", net->proc_net); } diff --git a/net/core/dev.c b/net/core/dev.c index c7ee9db77b1e..82f36ae35426 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8376,6 +8376,11 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, } } + if ((features & NETIF_F_HW_TLS_RX) && !(features & NETIF_F_RXCSUM)) { + netdev_dbg(dev, "Dropping TLS RX HW offload feature since no RXCSUM feature.\n"); + features &= ~NETIF_F_HW_TLS_RX; + } + return features; } @@ -9728,7 +9733,7 @@ static void __net_exit default_device_exit(struct net *net) continue; /* Leave virtual devices for the generic cleanup */ - if (dev->rtnl_link_ops) + if (dev->rtnl_link_ops && !dev->rtnl_link_ops->netns_refund) continue; /* Push remaining network devices to init_net */ diff --git a/net/core/devlink.c b/net/core/devlink.c index a77e3777c8dd..6ad095264896 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -1113,7 +1113,7 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, pool_index, &cur, &max); if (err && err != -EOPNOTSUPP) - return err; + goto sb_occ_get_failure; if (!err) { if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) goto nla_put_failure; @@ -1126,8 +1126,10 @@ static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, return 0; nla_put_failure: + err = -EMSGSIZE; +sb_occ_get_failure: genlmsg_cancel(msg, hdr); - return -EMSGSIZE; + return err; } static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, diff --git a/net/core/filter.c b/net/core/filter.c index 9f4a617ac255..1e29aa99b623 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4540,6 +4540,7 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, { struct net *net = dev_net(skb->dev); int rc = -EAFNOSUPPORT; + bool check_mtu = false; if (plen < sizeof(*params)) return -EINVAL; @@ -4547,22 +4548,28 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, if (flags & ~(BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT)) return -EINVAL; + if (params->tot_len) + check_mtu = true; + switch (params->family) { #if IS_ENABLED(CONFIG_INET) case AF_INET: - rc = bpf_ipv4_fib_lookup(net, params, flags, false); + rc = bpf_ipv4_fib_lookup(net, params, flags, check_mtu); break; #endif #if IS_ENABLED(CONFIG_IPV6) case AF_INET6: - rc = bpf_ipv6_fib_lookup(net, params, flags, false); + rc = bpf_ipv6_fib_lookup(net, params, flags, check_mtu); break; #endif } - if (!rc) { + if (rc == BPF_FIB_LKUP_RET_SUCCESS && !check_mtu) { struct net_device *dev; + /* When tot_len isn't provided by user, check skb + * against MTU of FIB lookup resulting net_device + */ dev = dev_get_by_index_rcu(net, params->ifindex); if (!is_skb_forwardable(dev, skb)) rc = BPF_FIB_LKUP_RET_FRAG_NEEDED; @@ -4883,6 +4890,8 @@ bpf_base_func_proto(enum bpf_func_id func_id) return &bpf_tail_call_proto; case BPF_FUNC_ktime_get_ns: return &bpf_ktime_get_ns_proto; + case BPF_FUNC_ktime_get_boot_ns: + return &bpf_ktime_get_boot_ns_proto; case BPF_FUNC_trace_printk: if (capable(CAP_SYS_ADMIN)) return bpf_get_trace_printk_proto(); diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index e4e442d70c2d..752744db11ff 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -84,11 +84,11 @@ static void est_timer(struct timer_list *t) u64 rate, brate; est_fetch_counters(est, &b); - brate = (b.bytes - est->last_bytes) << (10 - est->ewma_log - est->intvl_log); - brate -= (est->avbps >> est->ewma_log); + brate = (b.bytes - est->last_bytes) << (10 - est->intvl_log); + brate = (brate >> est->ewma_log) - (est->avbps >> est->ewma_log); - rate = (u64)(b.packets - est->last_packets) << (10 - est->ewma_log - est->intvl_log); - rate -= (est->avpps >> est->ewma_log); + rate = (u64)(b.packets - est->last_packets) << (10 - est->intvl_log); + rate = (rate >> est->ewma_log) - (est->avpps >> est->ewma_log); write_seqcount_begin(&est->seq); est->avbps += brate; @@ -147,6 +147,9 @@ int gen_new_estimator(struct gnet_stats_basic_packed *bstats, if (parm->interval < -2 || parm->interval > 3) return -EINVAL; + if (parm->ewma_log == 0 || parm->ewma_log >= 31) + return -EINVAL; + est = kzalloc(sizeof(*est), GFP_KERNEL); if (!est) return -ENOBUFS; diff --git a/net/core/lwt_bpf.c b/net/core/lwt_bpf.c index a648568c5e8f..4a5f4fbffd83 100644 --- a/net/core/lwt_bpf.c +++ b/net/core/lwt_bpf.c @@ -44,12 +44,11 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt, { int ret; - /* Preempt disable is needed to protect per-cpu redirect_info between - * BPF prog and skb_do_redirect(). The call_rcu in bpf_prog_put() and - * access to maps strictly require a rcu_read_lock() for protection, - * mixing with BH RCU lock doesn't work. + /* Preempt disable and BH disable are needed to protect per-cpu + * redirect_info between BPF prog and skb_do_redirect(). */ preempt_disable(); + local_bh_disable(); bpf_compute_data_pointers(skb); ret = bpf_prog_run_save_cb(lwt->prog, skb); @@ -82,6 +81,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt, break; } + local_bh_enable(); preempt_enable(); return ret; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 89725f7aec6c..d5bcb179f385 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1271,7 +1271,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, * we can reinject the packet there. */ n2 = NULL; - if (dst) { + if (dst && dst->obsolete != DST_OBSOLETE_DEAD) { n2 = dst_neigh_lookup_skb(dst, skb); if (n2) n1 = n2; diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 001d7f07e780..fe0d255d66c8 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1244,8 +1244,8 @@ static const struct attribute_group dql_group = { static ssize_t xps_cpus_show(struct netdev_queue *queue, char *buf) { + int cpu, len, ret, num_tc = 1, tc = 0; struct net_device *dev = queue->dev; - int cpu, len, num_tc = 1, tc = 0; struct xps_dev_maps *dev_maps; cpumask_var_t mask; unsigned long index; @@ -1255,22 +1255,31 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue, index = get_netdev_queue_index(queue); + if (!rtnl_trylock()) + return restart_syscall(); + if (dev->num_tc) { /* Do not allow XPS on subordinate device directly */ num_tc = dev->num_tc; - if (num_tc < 0) - return -EINVAL; + if (num_tc < 0) { + ret = -EINVAL; + goto err_rtnl_unlock; + } /* If queue belongs to subordinate dev use its map */ dev = netdev_get_tx_queue(dev, index)->sb_dev ? : dev; tc = netdev_txq_to_tc(dev, index); - if (tc < 0) - return -EINVAL; + if (tc < 0) { + ret = -EINVAL; + goto err_rtnl_unlock; + } } - if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) - return -ENOMEM; + if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { + ret = -ENOMEM; + goto err_rtnl_unlock; + } rcu_read_lock(); dev_maps = rcu_dereference(dev->xps_cpus_map); @@ -1293,9 +1302,15 @@ static ssize_t xps_cpus_show(struct netdev_queue *queue, } rcu_read_unlock(); + rtnl_unlock(); + len = snprintf(buf, PAGE_SIZE, "%*pb\n", cpumask_pr_args(mask)); free_cpumask_var(mask); return len < PAGE_SIZE ? len : -EINVAL; + +err_rtnl_unlock: + rtnl_unlock(); + return ret; } static ssize_t xps_cpus_store(struct netdev_queue *queue, @@ -1323,7 +1338,13 @@ static ssize_t xps_cpus_store(struct netdev_queue *queue, return err; } + if (!rtnl_trylock()) { + free_cpumask_var(mask); + return restart_syscall(); + } + err = netif_set_xps_queue(dev, mask, index); + rtnl_unlock(); free_cpumask_var(mask); @@ -1335,23 +1356,30 @@ static struct netdev_queue_attribute xps_cpus_attribute __ro_after_init static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf) { + int j, len, ret, num_tc = 1, tc = 0; struct net_device *dev = queue->dev; struct xps_dev_maps *dev_maps; unsigned long *mask, index; - int j, len, num_tc = 1, tc = 0; index = get_netdev_queue_index(queue); + if (!rtnl_trylock()) + return restart_syscall(); + if (dev->num_tc) { num_tc = dev->num_tc; tc = netdev_txq_to_tc(dev, index); - if (tc < 0) - return -EINVAL; + if (tc < 0) { + ret = -EINVAL; + goto err_rtnl_unlock; + } } mask = kcalloc(BITS_TO_LONGS(dev->num_rx_queues), sizeof(long), GFP_KERNEL); - if (!mask) - return -ENOMEM; + if (!mask) { + ret = -ENOMEM; + goto err_rtnl_unlock; + } rcu_read_lock(); dev_maps = rcu_dereference(dev->xps_rxqs_map); @@ -1377,10 +1405,16 @@ static ssize_t xps_rxqs_show(struct netdev_queue *queue, char *buf) out_no_maps: rcu_read_unlock(); + rtnl_unlock(); + len = bitmap_print_to_pagebuf(false, buf, mask, dev->num_rx_queues); kfree(mask); return len < PAGE_SIZE ? len : -EINVAL; + +err_rtnl_unlock: + rtnl_unlock(); + return ret; } static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf, @@ -1407,10 +1441,17 @@ static ssize_t xps_rxqs_store(struct netdev_queue *queue, const char *buf, return err; } + if (!rtnl_trylock()) { + bitmap_free(mask); + return restart_syscall(); + } + cpus_read_lock(); err = __netif_set_xps_queue(dev, mask, index, true); cpus_read_unlock(); + rtnl_unlock(); + kfree(mask); return err ? : len; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 023ce0fbb496..41e32a958d08 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -638,15 +639,15 @@ EXPORT_SYMBOL_GPL(__netpoll_setup); int netpoll_setup(struct netpoll *np) { - struct net_device *ndev = NULL; + struct net_device *ndev = NULL, *dev = NULL; + struct net *net = current->nsproxy->net_ns; struct in_device *in_dev; int err; rtnl_lock(); - if (np->dev_name[0]) { - struct net *net = current->nsproxy->net_ns; + if (np->dev_name[0]) ndev = __dev_get_by_name(net, np->dev_name); - } + if (!ndev) { np_err(np, "%s doesn't exist, aborting\n", np->dev_name); err = -ENODEV; @@ -654,6 +655,19 @@ int netpoll_setup(struct netpoll *np) } dev_hold(ndev); + /* bring up DSA management network devices up first */ + for_each_netdev(net, dev) { + if (!netdev_uses_dsa(dev)) + continue; + + err = dev_change_flags(dev, dev->flags | IFF_UP); + if (err < 0) { + np_err(np, "%s failed to open %s\n", + np->dev_name, dev->name); + goto put; + } + } + if (netdev_master_upper_dev_get(ndev)) { np_err(np, "%s is a slave device, aborting\n", np->dev_name); err = -EBUSY; diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 092fa3d75b32..3714cd9e3111 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3471,7 +3471,7 @@ static int pktgen_thread_worker(void *arg) struct pktgen_dev *pkt_dev = NULL; int cpu = t->cpu; - BUG_ON(smp_processor_id() != cpu); + WARN_ON(smp_processor_id() != cpu); init_waitqueue_head(&t->queue); complete(&t->start_done); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index d5324eb855f9..a110c4ad8664 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -401,7 +401,11 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int len, len += NET_SKB_PAD; - if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) || + /* If requested length is either too small or too big, + * we use kmalloc() for skb->head allocation. + */ + if (len <= SKB_WITH_OVERHEAD(1024) || + len > SKB_WITH_OVERHEAD(PAGE_SIZE) || (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) { skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE); if (!skb) @@ -462,13 +466,17 @@ EXPORT_SYMBOL(__netdev_alloc_skb); struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, gfp_t gfp_mask) { - struct napi_alloc_cache *nc = this_cpu_ptr(&napi_alloc_cache); + struct napi_alloc_cache *nc; struct sk_buff *skb; void *data; len += NET_SKB_PAD + NET_IP_ALIGN; - if ((len > SKB_WITH_OVERHEAD(PAGE_SIZE)) || + /* If requested length is either too small or too big, + * we use kmalloc() for skb->head allocation. + */ + if (len <= SKB_WITH_OVERHEAD(1024) || + len > SKB_WITH_OVERHEAD(PAGE_SIZE) || (gfp_mask & (__GFP_DIRECT_RECLAIM | GFP_DMA))) { skb = __alloc_skb(len, gfp_mask, SKB_ALLOC_RX, NUMA_NO_NODE); if (!skb) @@ -476,6 +484,7 @@ struct sk_buff *__napi_alloc_skb(struct napi_struct *napi, unsigned int len, goto skb_success; } + nc = this_cpu_ptr(&napi_alloc_cache); len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); len = SKB_DATA_ALIGN(len); @@ -1856,6 +1865,12 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len) skb->csum = csum_block_sub(skb->csum, skb_checksum(skb, len, delta, 0), len); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len; + int offset = skb_checksum_start_offset(skb) + skb->csum_offset; + + if (offset + sizeof(__sum16) > hdlen) + return -EINVAL; } return __pskb_trim(skb, len); } @@ -3080,7 +3095,19 @@ EXPORT_SYMBOL(skb_split); */ static int skb_prepare_for_shift(struct sk_buff *skb) { - return skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + int ret = 0; + + if (skb_cloned(skb)) { + /* Save and restore truesize: pskb_expand_head() may reallocate + * memory where ksize(kmalloc(S)) != ksize(kmalloc(S)), but we + * cannot change truesize at this point. + */ + unsigned int save_truesize = skb->truesize; + + ret = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); + skb->truesize = save_truesize; + } + return ret; } /** @@ -4268,7 +4295,7 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk) if (skb && (skb_next = skb_peek(q))) { icmp_next = is_icmp_err_skb(skb_next); if (icmp_next) - sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_origin; + sk->sk_err = SKB_EXT_ERR(skb_next)->ee.ee_errno; } spin_unlock_irqrestore(&q->lock, flags); diff --git a/net/core/sock.c b/net/core/sock.c index cff7ce6708c0..0a61d735c0f9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1436,15 +1436,17 @@ static inline void sock_lock_init(struct sock *sk) static void sock_copy(struct sock *nsk, const struct sock *osk) { #ifdef CONFIG_SECURITY_NETWORK - void *sptr = nsk->sk_security; + struct sk_security_struct sksec; + memcpy(&sksec, nsk->sk_security, sizeof(sksec)); #endif + memcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin)); memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end, osk->sk_prot->obj_size - offsetof(struct sock, sk_dontcopy_end)); #ifdef CONFIG_SECURITY_NETWORK - nsk->sk_security = sptr; + memcpy(nsk->sk_security, &sksec, sizeof(sksec)); security_sk_clone(osk, nsk); #endif } diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c index 9c85ef2b7e1d..375a3bbe6485 100644 --- a/net/core/sock_reuseport.c +++ b/net/core/sock_reuseport.c @@ -299,7 +299,7 @@ struct sock *reuseport_select_sock(struct sock *sk, i = j = reciprocal_scale(hash, socks); while (reuse->socks[i]->sk_state == TCP_ESTABLISHED) { i++; - if (i >= reuse->num_socks) + if (i >= socks) i = 0; if (i == j) goto out; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index 5ee6b94131b2..33684f1818a8 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -1756,6 +1756,8 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, fn = &reply_funcs[dcb->cmd]; if (!fn->cb) return -EOPNOTSUPP; + if (fn->type == RTM_SETDCB && !netlink_capable(skb, CAP_NET_ADMIN)) + return -EPERM; if (!tb[DCB_ATTR_IFNAME]) return -EINVAL; diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index b438bed6749d..2cd3508a3786 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -319,6 +319,11 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) return 0; /* discard, don't send a reset here */ + if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) { + __IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS); + return 0; + } + if (dccp_bad_service_code(sk, service)) { dcb->dccpd_reset_code = DCCP_RESET_CODE_BAD_SERVICE_CODE; goto drop; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 43733accf58e..208bbeb528b2 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1154,10 +1154,10 @@ static int __init dccp_init(void) * * The methodology is similar to that of the buffer cache. */ - if (totalram_pages >= (128 * 1024)) - goal = totalram_pages >> (21 - PAGE_SHIFT); + if (totalram_pages() >= (128 * 1024)) + goal = totalram_pages() >> (21 - PAGE_SHIFT); else - goal = totalram_pages >> (23 - PAGE_SHIFT); + goal = totalram_pages() >> (23 - PAGE_SHIFT); if (thash_entries) goal = (thash_entries * diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 658191fba94e..2a2e9500c825 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -1868,7 +1868,7 @@ void __init dn_route_init(void) dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ; add_timer(&dn_route_timer); - goal = totalram_pages >> (26 - PAGE_SHIFT); + goal = totalram_pages() >> (26 - PAGE_SHIFT); for(order = 0; (1UL << order) < goal; order++) /* NOTHING */; diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 4183e4ba27a5..81f620a3c32b 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -8,6 +8,7 @@ config NET_DSA tristate "Distributed Switch Architecture" depends on HAVE_NET_DSA && MAY_USE_DEVLINK depends on BRIDGE || BRIDGE=n + select GRO_CELLS select NET_SWITCHDEV select PHYLINK ---help--- diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 601534a5bfe8..598200e9d522 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c @@ -191,7 +191,7 @@ static int dsa_switch_rcv(struct sk_buff *skb, struct net_device *dev, if (dsa_skb_defer_rx_timestamp(p, skb)) return 0; - netif_receive_skb(skb); + gro_cells_receive(&p->gcells, skb); return 0; } diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h index 3964c6f7a7c0..79d17507609a 100644 --- a/net/dsa/dsa_priv.h +++ b/net/dsa/dsa_priv.h @@ -15,6 +15,7 @@ #include #include #include +#include enum { DSA_NOTIFIER_AGEING_TIME, @@ -72,6 +73,8 @@ struct dsa_slave_priv { struct pcpu_sw_netstats *stats64; + struct gro_cells gcells; + /* DSA port data, such as switch, port index, etc. */ struct dsa_port *dp; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index d03c67e761df..11f1560de639 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1337,6 +1337,11 @@ int dsa_slave_create(struct dsa_port *port) free_netdev(slave_dev); return -ENOMEM; } + + ret = gro_cells_init(&p->gcells, slave_dev); + if (ret) + goto out_free; + p->dp = port; INIT_LIST_HEAD(&p->mall_tc_list); p->xmit = cpu_dp->tag_ops->xmit; @@ -1347,7 +1352,7 @@ int dsa_slave_create(struct dsa_port *port) ret = dsa_slave_phy_setup(slave_dev); if (ret) { netdev_err(master, "error %d setting up slave phy\n", ret); - goto out_free; + goto out_gcells; } dsa_slave_notify(slave_dev, DSA_PORT_REGISTER); @@ -1366,6 +1371,8 @@ int dsa_slave_create(struct dsa_port *port) phylink_disconnect_phy(p->dp->pl); rtnl_unlock(); phylink_destroy(p->dp->pl); +out_gcells: + gro_cells_destroy(&p->gcells); out_free: free_percpu(p->stats64); free_netdev(slave_dev); @@ -1386,6 +1393,7 @@ void dsa_slave_destroy(struct net_device *slave_dev) dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER); unregister_netdev(slave_dev); phylink_destroy(dp->pl); + gro_cells_destroy(&p->gcells); free_percpu(p->stats64); free_netdev(slave_dev); } diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c index 6574425ad94c..1f57dce969f7 100644 --- a/net/dsa/tag_mtk.c +++ b/net/dsa/tag_mtk.c @@ -20,6 +20,7 @@ #define MTK_HDR_LEN 4 #define MTK_HDR_XMIT_UNTAGGED 0 #define MTK_HDR_XMIT_TAGGED_TPID_8100 1 +#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2 #define MTK_HDR_RECV_SOURCE_PORT_MASK GENMASK(2, 0) #define MTK_HDR_XMIT_DP_BIT_MASK GENMASK(5, 0) #define MTK_HDR_XMIT_SA_DIS BIT(6) @@ -28,8 +29,8 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, struct net_device *dev) { struct dsa_port *dp = dsa_slave_to_port(dev); + u8 xmit_tpid; u8 *mtk_tag; - bool is_vlan_skb = true; unsigned char *dest = eth_hdr(skb)->h_dest; bool is_multicast_skb = is_multicast_ether_addr(dest) && !is_broadcast_ether_addr(dest); @@ -40,13 +41,20 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, * the both special and VLAN tag at the same time and then look up VLAN * table with VID. */ - if (!skb_vlan_tagged(skb)) { + switch (skb->protocol) { + case htons(ETH_P_8021Q): + xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_8100; + break; + case htons(ETH_P_8021AD): + xmit_tpid = MTK_HDR_XMIT_TAGGED_TPID_88A8; + break; + default: if (skb_cow_head(skb, MTK_HDR_LEN) < 0) return NULL; + xmit_tpid = MTK_HDR_XMIT_UNTAGGED; skb_push(skb, MTK_HDR_LEN); memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN); - is_vlan_skb = false; } mtk_tag = skb->data + 2 * ETH_ALEN; @@ -54,8 +62,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, /* Mark tag attribute on special tag insertion to notify hardware * whether that's a combined special tag with 802.1Q header. */ - mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 : - MTK_HDR_XMIT_UNTAGGED; + mtk_tag[0] = xmit_tpid; mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK; /* Disable SA learning for multicast frames */ @@ -63,7 +70,7 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb, mtk_tag[1] |= MTK_HDR_XMIT_SA_DIS; /* Tag control information is kept for 802.1Q */ - if (!is_vlan_skb) { + if (xmit_tpid == MTK_HDR_XMIT_UNTAGGED) { mtk_tag[2] = 0; mtk_tag[3] = 0; } diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index d3cbb3258718..c0930b9fe848 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -559,9 +559,7 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]); if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) { - if (!info->attrs[IEEE802154_ATTR_PAN_ID] && - !(info->attrs[IEEE802154_ATTR_SHORT_ADDR] || - info->attrs[IEEE802154_ATTR_HW_ADDR])) + if (!info->attrs[IEEE802154_ATTR_PAN_ID]) return -EINVAL; desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]); @@ -570,6 +568,9 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, desc->device_addr.mode = IEEE802154_ADDR_SHORT; desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]); } else { + if (!info->attrs[IEEE802154_ATTR_HW_ADDR]) + return -EINVAL; + desc->device_addr.mode = IEEE802154_ADDR_LONG; desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); } diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 99f6c254ea77..b1c55db73764 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -836,8 +836,13 @@ nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, goto nla_put_failure; #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + goto out; + if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0) goto nla_put_failure; + +out: #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ genlmsg_end(msg, hdr); @@ -1402,6 +1407,9 @@ static int nl802154_set_llsec_params(struct sk_buff *skb, u32 changed = 0; int ret; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (info->attrs[NL802154_ATTR_SEC_ENABLED]) { u8 enabled; @@ -1508,6 +1516,11 @@ nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; @@ -1562,7 +1575,8 @@ static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) struct ieee802154_llsec_key_id id = { }; u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; - if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_KEY] || + nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) return -EINVAL; @@ -1612,7 +1626,8 @@ static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; struct ieee802154_llsec_key_id id; - if (nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_KEY] || + nla_parse_nested(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) return -EINVAL; @@ -1678,6 +1693,11 @@ nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; @@ -1765,6 +1785,9 @@ static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info) struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_device dev_desc; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE], &dev_desc) < 0) return -EINVAL; @@ -1780,7 +1803,8 @@ static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; __le64 extended_addr; - if (nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_DEVICE] || + nla_parse_nested(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy, info->extack)) return -EINVAL; @@ -1850,6 +1874,11 @@ nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; @@ -1907,6 +1936,9 @@ static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info struct ieee802154_llsec_device_key key; __le64 extended_addr; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], @@ -1940,7 +1972,8 @@ static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info struct ieee802154_llsec_device_key key; __le64 extended_addr; - if (nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, + if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || + nla_parse_nested(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack)) return -EINVAL; @@ -2015,6 +2048,11 @@ nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; @@ -2100,6 +2138,9 @@ static int nl802154_add_llsec_seclevel(struct sk_buff *skb, struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_seclevel sl; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], &sl) < 0) return -EINVAL; @@ -2115,6 +2156,9 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb, struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_seclevel sl; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_LEVEL] || llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], &sl) < 0) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 5535b722f66d..6a1b52b34e20 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -533,16 +533,10 @@ int cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info) ret_val = -ENOENT; goto doi_remove_return; } - if (!refcount_dec_and_test(&doi_def->refcount)) { - spin_unlock(&cipso_v4_doi_list_lock); - ret_val = -EBUSY; - goto doi_remove_return; - } list_del_rcu(&doi_def->list); spin_unlock(&cipso_v4_doi_list_lock); - cipso_v4_cache_invalidate(); - call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu); + cipso_v4_doi_putdef(doi_def); ret_val = 0; doi_remove_return: @@ -599,9 +593,6 @@ void cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def) if (!refcount_dec_and_test(&doi_def->refcount)) return; - spin_lock(&cipso_v4_doi_list_lock); - list_del_rcu(&doi_def->list); - spin_unlock(&cipso_v4_doi_list_lock); cipso_v4_cache_invalidate(); call_rcu(&doi_def->rcu, cipso_v4_doi_free_rcu); diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 114f9def1ec5..0792a9e2a555 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -270,7 +270,6 @@ static int esp_output_udp_encap(struct xfrm_state *x, struct sk_buff *skb, struc int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) { u8 *tail; - u8 *vaddr; int nfrags; int esph_offset; struct page *page; @@ -312,14 +311,10 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * page = pfrag->page; get_page(page); - vaddr = kmap_atomic(page); - - tail = vaddr + pfrag->offset; + tail = page_address(page) + pfrag->offset; esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto); - kunmap_atomic(vaddr); - nfrags = skb_shinfo(skb)->nr_frags; __skb_fill_page_desc(skb, nfrags, page, pfrag->offset, diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 7f4ec36e5f70..b96aa88087be 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -302,7 +302,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb) .flowi4_iif = LOOPBACK_IFINDEX, .flowi4_oif = l3mdev_master_ifindex_rcu(dev), .daddr = ip_hdr(skb)->saddr, - .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), + .flowi4_tos = ip_hdr(skb)->tos & IPTOS_RT_MASK, .flowi4_scope = scope, .flowi4_mark = vmark ? skb->mark : 0, }; diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c index ad9ea82daeb3..9376b30cf626 100644 --- a/net/ipv4/gre_demux.c +++ b/net/ipv4/gre_demux.c @@ -133,7 +133,7 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, * to 0 and sets the configured key in the * inner erspan header field */ - if (greh->protocol == htons(ETH_P_ERSPAN) || + if ((greh->protocol == htons(ETH_P_ERSPAN) && hdr_len != 4) || greh->protocol == htons(ETH_P_ERSPAN2)) { struct erspan_base_hdr *ershdr; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 56e86467078d..546f124a8319 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -425,7 +425,7 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) * having to remove and re-insert us on the wait queue. */ for (;;) { - prepare_to_wait_exclusive(sk_sleep(sk), &wait, + prepare_to_wait_exclusive_lifo(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); release_sock(sk); if (reqsk_queue_empty(&icsk->icsk_accept_queue)) @@ -705,12 +705,15 @@ static bool reqsk_queue_unlink(struct request_sock_queue *queue, return found; } -void inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req) +bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req) { - if (reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req)) { + bool unlinked = reqsk_queue_unlink(&inet_csk(sk)->icsk_accept_queue, req); + + if (unlinked) { reqsk_queue_removed(&inet_csk(sk)->icsk_accept_queue, req); reqsk_put(req); } + return unlinked; } EXPORT_SYMBOL(inet_csk_reqsk_queue_drop); diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index f0957ebf82cf..d07917059d70 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -392,8 +392,10 @@ static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb, r->idiag_inode = 0; if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, - inet_rsk(reqsk)->ir_mark)) + inet_rsk(reqsk)->ir_mark)) { + nlmsg_cancel(skb, nlh); return -EMSGSIZE; + } nlmsg_end(skb, nlh); return 0; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index c4e67bc7f031..7860d6eac7b0 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -315,7 +315,7 @@ static int ip_finish_output(struct net *net, struct sock *sk, struct sk_buff *sk if (skb_is_gso(skb)) return ip_finish_output_gso(net, sk, skb, mtu); - if (skb->len > mtu || (IPCB(skb)->flags & IPSKB_FRAG_PMTU)) + if (skb->len > mtu || IPCB(skb)->frag_max_size) return ip_fragment(net, sk, skb, mtu, ip_finish_output2); return ip_finish_output2(net, sk, skb); diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 375d0e516d85..bdd073ea300a 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -330,7 +330,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) } dev->needed_headroom = t_hlen + hlen; - mtu -= (dev->hard_header_len + t_hlen); + mtu -= t_hlen; if (mtu < IPV4_MIN_MTU) mtu = IPV4_MIN_MTU; @@ -360,7 +360,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net, nt = netdev_priv(dev); t_hlen = nt->hlen + sizeof(struct iphdr); dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen; + dev->max_mtu = IP_MAX_MTU - t_hlen; ip_tunnel_add(itn, nt); return nt; @@ -502,12 +502,11 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, const struct iphdr *inner_iph) { struct ip_tunnel *tunnel = netdev_priv(dev); - int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; + int pkt_size = skb->len - tunnel->hlen; int mtu; if (df) - mtu = dst_mtu(&rt->dst) - dev->hard_header_len - - sizeof(struct iphdr) - tunnel->hlen; + mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel->hlen); else mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; @@ -736,7 +735,11 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) { + df = tnl_params->frag_off; + if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df) + df |= (inner_iph->frag_off & htons(IP_DF)); + + if (tnl_update_pmtu(dev, skb, rt, df, inner_iph)) { ip_rt_put(rt); goto tx_error; } @@ -764,10 +767,6 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, ttl = ip4_dst_hoplimit(&rt->dst); } - df = tnl_params->frag_off; - if (skb->protocol == htons(ETH_P_IP) && !tunnel->ignore_df) - df |= (inner_iph->frag_off&htons(IP_DF)); - max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr) + rt->dst.header_len + ip_encap_hlen(&tunnel->encap); if (max_headroom > dev->needed_headroom) @@ -935,7 +934,7 @@ int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict) { struct ip_tunnel *tunnel = netdev_priv(dev); int t_hlen = tunnel->hlen + sizeof(struct iphdr); - int max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen; + int max_mtu = IP_MAX_MTU - t_hlen; if (new_mtu < ETH_MIN_MTU) return -EINVAL; @@ -1112,10 +1111,9 @@ int ip_tunnel_newlink(struct net_device *dev, struct nlattr *tb[], mtu = ip_tunnel_bind_dev(dev); if (tb[IFLA_MTU]) { - unsigned int max = IP_MAX_MTU - dev->hard_header_len - nt->hlen; + unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr)); - mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, - (unsigned int)(max - sizeof(struct iphdr))); + mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max); } err = dev_set_mtu(dev, mtu); diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index fbef59a68202..7a838c19f216 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -17,17 +17,19 @@ #include /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */ -int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_type) +int ip_route_me_harder(struct net *net, struct sock *sk, struct sk_buff *skb, unsigned int addr_type) { const struct iphdr *iph = ip_hdr(skb); struct rtable *rt; struct flowi4 fl4 = {}; __be32 saddr = iph->saddr; - const struct sock *sk = skb_to_full_sk(skb); - __u8 flags = sk ? inet_sk_flowi_flags(sk) : 0; + __u8 flags; struct net_device *dev = skb_dst(skb)->dev; unsigned int hh_len; + sk = sk_to_full_sk(sk); + flags = sk ? inet_sk_flowi_flags(sk) : 0; + if (addr_type == RTN_UNSPEC) addr_type = inet_addr_type_dev_table(net, dev, saddr); if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST) @@ -96,8 +98,8 @@ int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry) skb->mark == rt_info->mark && iph->daddr == rt_info->daddr && iph->saddr == rt_info->saddr)) - return ip_route_me_harder(entry->state.net, skb, - RTN_UNSPEC); + return ip_route_me_harder(entry->state.net, entry->state.sk, + skb, RTN_UNSPEC); } return 0; } diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 2b52e40f94bf..5275c71bae87 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1176,6 +1176,8 @@ static int translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_ARP_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 4e9970856829..07a0d4be85c9 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1413,6 +1413,8 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c index 690b17ef6a44..d64b1ef43c10 100644 --- a/net/ipv4/netfilter/ipt_SYNPROXY.c +++ b/net/ipv4/netfilter/ipt_SYNPROXY.c @@ -54,7 +54,7 @@ synproxy_send_tcp(struct net *net, skb_dst_set_noref(nskb, skb_dst(skb)); nskb->protocol = htons(ETH_P_IP); - if (ip_route_me_harder(net, nskb, RTN_UNSPEC)) + if (ip_route_me_harder(net, nskb->sk, nskb, RTN_UNSPEC)) goto free_nskb; if (nfct) { diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index 74b19a5c572e..088320ce77a1 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c @@ -94,7 +94,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) flow.daddr = iph->saddr; flow.saddr = rpfilter_get_saddr(iph->daddr); flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; - flow.flowi4_tos = RT_TOS(iph->tos); + flow.flowi4_tos = iph->tos & IPTOS_RT_MASK; flow.flowi4_scope = RT_SCOPE_UNIVERSE; flow.flowi4_oif = l3mdev_master_ifindex_rcu(xt_in(par)); diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index dea138ca8925..0829f46ddfdd 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c @@ -65,7 +65,7 @@ ipt_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) iph->daddr != daddr || skb->mark != mark || iph->tos != tos) { - err = ip_route_me_harder(state->net, skb, RTN_UNSPEC); + err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index 0fb3776869b5..593d89c05066 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c @@ -329,7 +329,7 @@ nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, if (ct->tuplehash[dir].tuple.dst.u3.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { - err = ip_route_me_harder(state->net, skb, RTN_UNSPEC); + err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv4/netfilter/nf_reject_ipv4.c b/net/ipv4/netfilter/nf_reject_ipv4.c index 5cd06ba3535d..4996db1f64a1 100644 --- a/net/ipv4/netfilter/nf_reject_ipv4.c +++ b/net/ipv4/netfilter/nf_reject_ipv4.c @@ -129,7 +129,7 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook) ip4_dst_hoplimit(skb_dst(nskb))); nf_reject_ip_tcphdr_put(nskb, oldskb, oth); - if (ip_route_me_harder(net, nskb, RTN_UNSPEC)) + if (ip_route_me_harder(net, nskb->sk, nskb, RTN_UNSPEC)) goto free_nskb; niph = ip_hdr(nskb); diff --git a/net/ipv4/netfilter/nft_chain_route_ipv4.c b/net/ipv4/netfilter/nft_chain_route_ipv4.c index 7d82934c46f4..61003768e52b 100644 --- a/net/ipv4/netfilter/nft_chain_route_ipv4.c +++ b/net/ipv4/netfilter/nft_chain_route_ipv4.c @@ -50,7 +50,7 @@ static unsigned int nf_route_table_hook(void *priv, iph->daddr != daddr || skb->mark != mark || iph->tos != tos) { - err = ip_route_me_harder(state->net, skb, RTN_UNSPEC); + err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 48081e6d50b4..2fe50f6f876d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2876,7 +2876,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, memset(&fl4, 0, sizeof(fl4)); fl4.daddr = dst; fl4.saddr = src; - fl4.flowi4_tos = rtm->rtm_tos; + fl4.flowi4_tos = rtm->rtm_tos & IPTOS_RT_MASK; fl4.flowi4_oif = tb[RTA_OIF] ? nla_get_u32(tb[RTA_OIF]) : 0; fl4.flowi4_mark = mark; fl4.flowi4_uid = uid; @@ -2900,8 +2900,9 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, fl4.flowi4_iif = iif; /* for rt_fill_info */ skb->dev = dev; skb->mark = mark; - err = ip_route_input_rcu(skb, dst, src, rtm->rtm_tos, - dev, &res); + err = ip_route_input_rcu(skb, dst, src, + rtm->rtm_tos & IPTOS_RT_MASK, dev, + &res); rt = skb_rtable(skb); if (err == 0 && rt->dst.error) diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index f66b2e6d97a7..1a06850ef3cc 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -296,7 +296,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) __u32 cookie = ntohl(th->ack_seq) - 1; struct sock *ret = sk; struct request_sock *req; - int mss; + int full_space, mss; struct rtable *rt; __u8 rcv_wscale; struct flowi4 fl4; @@ -391,8 +391,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb) /* Try to redo what tcp_v4_send_synack did. */ req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW); + /* limit the window selection if the user enforce a smaller rx buffer */ + full_space = tcp_full_space(sk); + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && + (req->rsk_window_clamp > full_space || req->rsk_window_clamp == 0)) + req->rsk_window_clamp = full_space; - tcp_select_initial_window(sk, tcp_full_space(sk), req->mss, + tcp_select_initial_window(sk, full_space, req->mss, &req->rsk_rcv_wnd, &req->rsk_window_clamp, ireq->wscale_ok, &rcv_wscale, dst_metric(&rt->dst, RTAX_INITRWND)); diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index d1bb0f703a92..f2196e8c1931 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -572,7 +572,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait) (state != TCP_SYN_RECV || tp->fastopen_rsk)) { int target = sock_rcvlowat(sk, 0, INT_MAX); - if (tp->urg_seq == tp->copied_seq && + if (tp->urg_seq == READ_ONCE(tp->copied_seq) && !sock_flag(sk, SOCK_URGINLINE) && tp->urg_data) target++; @@ -633,7 +633,7 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) unlock_sock_fast(sk, slow); break; case SIOCATMARK: - answ = tp->urg_data && tp->urg_seq == tp->copied_seq; + answ = tp->urg_data && tp->urg_seq == READ_ONCE(tp->copied_seq); break; case SIOCOUTQ: if (sk->sk_state == TCP_LISTEN) @@ -1704,9 +1704,9 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, sk_eat_skb(sk, skb); if (!desc->count) break; - tp->copied_seq = seq; + WRITE_ONCE(tp->copied_seq, seq); } - tp->copied_seq = seq; + WRITE_ONCE(tp->copied_seq, seq); tcp_rcv_space_adjust(sk); @@ -1843,7 +1843,7 @@ static int tcp_zerocopy_receive(struct sock *sk, out: up_read(¤t->mm->mmap_sem); if (length) { - tp->copied_seq = seq; + WRITE_ONCE(tp->copied_seq, seq); tcp_rcv_space_adjust(sk); /* Clean up data we have read: This will do ACK frames. */ @@ -2120,7 +2120,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, if (urg_offset < used) { if (!urg_offset) { if (!sock_flag(sk, SOCK_URGINLINE)) { - ++*seq; + WRITE_ONCE(*seq, *seq + 1); urg_hole++; offset++; used--; @@ -2142,7 +2142,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, } } - *seq += used; + WRITE_ONCE(*seq, *seq + used); copied += used; len -= used; @@ -2171,7 +2171,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, found_fin_ok: /* Process the FIN. */ - ++*seq; + WRITE_ONCE(*seq, *seq + 1); if (!(flags & MSG_PEEK)) sk_eat_skb(sk, skb); break; @@ -2588,7 +2588,7 @@ int tcp_disconnect(struct sock *sk, int flags) tcp_clear_xmit_timers(sk); __skb_queue_purge(&sk->sk_receive_queue); - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); tp->urg_data = 0; tcp_write_queue_purge(sk); tcp_fastopen_active_disable_ofo_check(sk); @@ -3936,8 +3936,8 @@ void __init tcp_init(void) tcp_init_mem(); /* Set per-socket limits to no more than 1/128 the pressure threshold */ limit = nr_free_buffer_pages() << (PAGE_SHIFT - 7); - max_wshare = min(4UL*1024*1024, limit); - max_rshare = min(6UL*1024*1024, limit); + max_wshare = min(16UL*1024*1024, limit); + max_rshare = min(16UL*1024*1024, limit); init_net.ipv4.sysctl_tcp_wmem[0] = SK_MEM_QUANTUM; init_net.ipv4.sysctl_tcp_wmem[1] = 16*1024; diff --git a/net/ipv4/tcp_bbr.c b/net/ipv4/tcp_bbr.c index 93f176336297..b70c9365e131 100644 --- a/net/ipv4/tcp_bbr.c +++ b/net/ipv4/tcp_bbr.c @@ -917,7 +917,7 @@ static void bbr_update_min_rtt(struct sock *sk, const struct rate_sample *rs) filter_expired = after(tcp_jiffies32, bbr->min_rtt_stamp + bbr_min_rtt_win_sec * HZ); if (rs->rtt_us >= 0 && - (rs->rtt_us <= bbr->min_rtt_us || + (rs->rtt_us < bbr->min_rtt_us || (filter_expired && !rs->is_ack_delayed))) { bbr->min_rtt_us = rs->rtt_us; bbr->min_rtt_stamp = tcp_jiffies32; diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 32c3162baf3e..00a7482b6fbd 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -196,6 +196,11 @@ static void tcp_reinit_congestion_control(struct sock *sk, icsk->icsk_ca_setsockopt = 1; memset(icsk->icsk_ca_priv, 0, sizeof(icsk->icsk_ca_priv)); + if (ca->flags & TCP_CONG_NEEDS_ECN) + INET_ECN_xmit(sk); + else + INET_ECN_dontxmit(sk); + if (!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) tcp_init_congestion_control(sk); } diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c index c9e97f304f98..a96b252c742c 100644 --- a/net/ipv4/tcp_diag.c +++ b/net/ipv4/tcp_diag.c @@ -30,7 +30,8 @@ static void tcp_diag_get_info(struct sock *sk, struct inet_diag_msg *r, } else if (sk->sk_type == SOCK_STREAM) { const struct tcp_sock *tp = tcp_sk(sk); - r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - tp->copied_seq, 0); + r->idiag_rqueue = max_t(int, READ_ONCE(tp->rcv_nxt) - + READ_ONCE(tp->copied_seq), 0); r->idiag_wqueue = tp->write_seq - tp->snd_una; } if (info) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9fc0a90f0251..4a0c17926496 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -439,7 +439,6 @@ void tcp_init_buffer_space(struct sock *sk) if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) tcp_sndbuf_expand(sk); - tp->rcvq_space.space = min_t(u32, tp->rcv_wnd, TCP_INIT_CWND * tp->advmss); tcp_mstamp_refresh(tp); tp->rcvq_space.time = tp->tcp_mstamp; tp->rcvq_space.seq = tp->copied_seq; @@ -463,6 +462,8 @@ void tcp_init_buffer_space(struct sock *sk) tp->rcv_ssthresh = min(tp->rcv_ssthresh, tp->window_clamp); tp->snd_cwnd_stamp = tcp_jiffies32; + tp->rcvq_space.space = min3(tp->rcv_ssthresh, tp->rcv_wnd, + (u32)TCP_INIT_CWND * tp->advmss); } /* 4. Recalculate window clamp after socket hit its memory bounds. */ @@ -2750,7 +2751,8 @@ static void tcp_identify_packet_loss(struct sock *sk, int *ack_flag) } else if (tcp_is_rack(sk)) { u32 prior_retrans = tp->retrans_out; - tcp_rack_mark_lost(sk); + if (tcp_rack_mark_lost(sk)) + *ack_flag &= ~FLAG_SET_XMIT_TIMER; if (prior_retrans > tp->retrans_out) *ack_flag |= FLAG_LOST_RETRANS; } @@ -3693,9 +3695,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (tp->tlp_high_seq) tcp_process_tlp_ack(sk, ack, flag); - /* If needed, reset TLP/RTO timer; RACK may later override this. */ - if (flag & FLAG_SET_XMIT_TIMER) - tcp_set_xmit_timer(sk); if (tcp_ack_is_dubious(sk, flag)) { is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); @@ -3703,6 +3702,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) &rexmit); } + /* If needed, reset TLP/RTO timer when RACK doesn't set. */ + if (flag & FLAG_SET_XMIT_TIMER) + tcp_set_xmit_timer(sk); + if ((flag & FLAG_FORWARD_PROGRESS) || !(flag & FLAG_NOT_DUP)) sk_dst_confirm(sk); @@ -5888,7 +5891,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, /* Remember, tcp_poll() does not lock socket! * Change state from SYN-SENT only after copied_seq * is initialized. */ - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); smc_check_reset_syn(tp); @@ -5963,7 +5966,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, } WRITE_ONCE(tp->rcv_nxt, TCP_SKB_CB(skb)->seq + 1); - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1; /* RFC1323: The window in SYN & SYN/ACK segments is @@ -6125,7 +6128,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) tcp_rearm_rto(sk); } else { tcp_init_transfer(sk, BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB); - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); } smp_mb(); tcp_set_state(sk, TCP_ESTABLISHED); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9877fbc56d0c..c21b967e5cb3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2344,7 +2344,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i) * we might find a transient negative value. */ rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) - - tp->copied_seq, 0); + READ_ONCE(tp->copied_seq), 0); seq_printf(f, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X %02X:%08lX " "%08X %5u %8d %lu %d %pK %lu %lu %u %u %d", @@ -2538,7 +2538,7 @@ static int __net_init tcp_sk_init(struct net *net) *per_cpu_ptr(net->ipv4.tcp_sk, cpu) = sk; } - net->ipv4.sysctl_tcp_ecn = 2; + net->ipv4.sysctl_tcp_ecn = 1; net->ipv4.sysctl_tcp_ecn_fallback = 1; net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS; diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 03b51cdcc731..b467a7cabf40 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -1000,7 +1000,7 @@ static int __net_init tcp_net_metrics_init(struct net *net) slots = tcpmhash_entries; if (!slots) { - if (totalram_pages >= 128 * 1024) + if (totalram_pages() >= 128 * 1024) slots = 16 * 1024; else slots = 8 * 1024; diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 7ba8a90772b0..2d61e77ef2ea 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -470,7 +470,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, seq = treq->rcv_isn + 1; newtp->rcv_wup = seq; - newtp->copied_seq = seq; + WRITE_ONCE(newtp->copied_seq, seq); WRITE_ONCE(newtp->rcv_nxt, seq); newtp->segs_in = 1; @@ -815,8 +815,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, tcp_reset(sk); } if (!fastopen) { - inet_csk_reqsk_queue_drop(sk, req); - __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); + bool unlinked = inet_csk_reqsk_queue_drop(sk, req); + + if (unlinked) + __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); + *req_stolen = !unlinked; } return NULL; } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e2a2e132a207..418094fd8405 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1622,7 +1622,8 @@ static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited) * window, and remember whether we were cwnd-limited then. */ if (!before(tp->snd_una, tp->max_packets_seq) || - tp->packets_out > tp->max_packets_out) { + tp->packets_out > tp->max_packets_out || + is_cwnd_limited) { tp->max_packets_out = tp->packets_out; tp->max_packets_seq = tp->snd_nxt; tp->is_cwnd_limited = is_cwnd_limited; @@ -2410,6 +2411,10 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, else tcp_chrono_stop(sk, TCP_CHRONO_RWND_LIMITED); + is_cwnd_limited |= (tcp_packets_in_flight(tp) >= tp->snd_cwnd); + if (likely(sent_pkts || is_cwnd_limited)) + tcp_cwnd_validate(sk, is_cwnd_limited); + if (likely(sent_pkts)) { if (tcp_in_cwnd_reduction(sk)) tp->prr_out += sent_pkts; @@ -2417,8 +2422,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, /* Send one loss probe per tail loss episode. */ if (push_one != 2) tcp_schedule_loss_probe(sk, false); - is_cwnd_limited |= (tcp_packets_in_flight(tp) >= tp->snd_cwnd); - tcp_cwnd_validate(sk, is_cwnd_limited); return false; } return !tp->packets_out && !tcp_write_queue_empty(sk); @@ -3381,7 +3384,7 @@ static void tcp_connect_init(struct sock *sk) else tp->rcv_tstamp = tcp_jiffies32; tp->rcv_wup = tp->rcv_nxt; - tp->copied_seq = tp->rcv_nxt; + WRITE_ONCE(tp->copied_seq, tp->rcv_nxt); inet_csk(sk)->icsk_rto = tcp_timeout_init(sk); inet_csk(sk)->icsk_retransmits = 0; diff --git a/net/ipv4/tcp_recovery.c b/net/ipv4/tcp_recovery.c index c81aadff769b..0d96decba13d 100644 --- a/net/ipv4/tcp_recovery.c +++ b/net/ipv4/tcp_recovery.c @@ -109,13 +109,13 @@ static void tcp_rack_detect_loss(struct sock *sk, u32 *reo_timeout) } } -void tcp_rack_mark_lost(struct sock *sk) +bool tcp_rack_mark_lost(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); u32 timeout; if (!tp->rack.advanced) - return; + return false; /* Reset the advanced flag to avoid unnecessary queue scanning */ tp->rack.advanced = 0; @@ -125,6 +125,7 @@ void tcp_rack_mark_lost(struct sock *sk) inet_csk_reset_xmit_timer(sk, ICSK_TIME_REO_TIMEOUT, timeout, inet_csk(sk)->icsk_rto); } + return !!timeout; } /* Record the most recently (re)sent time among the (s)acked packets diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c59a2deeee57..af085a16b203 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2449,7 +2449,8 @@ int udp_v4_early_demux(struct sk_buff *skb) */ if (!inet_sk(sk)->inet_daddr && in_dev) return ip_mc_validate_source(skb, iph->daddr, - iph->saddr, iph->tos, + iph->saddr, + iph->tos & IPTOS_RT_MASK, skb->dev, in_dev, &itag); } return 0; diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 7e848ddb1b31..23ded542ae63 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -418,7 +418,7 @@ struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb, } if (NAPI_GRO_CB(skb)->encap_mark || - (skb->ip_summed != CHECKSUM_PARTIAL && + (uh->check && skb->ip_summed != CHECKSUM_PARTIAL && NAPI_GRO_CB(skb)->csum_cnt == 0 && !NAPI_GRO_CB(skb)->csum_valid) || !udp_sk(sk)->gro_receive) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f6975a633074..cd46eaeb4e61 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2426,8 +2426,9 @@ static void addrconf_add_mroute(struct net_device *dev) .fc_ifindex = dev->ifindex, .fc_dst_len = 8, .fc_flags = RTF_UP, - .fc_type = RTN_UNICAST, + .fc_type = RTN_MULTICAST, .fc_nlinfo.nl_net = dev_net(dev), + .fc_protocol = RTPROT_KERNEL, }; ipv6_addr_set(&cfg.fc_dst, htonl(0xFF000000), 0, 0, 0); diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 1d6ced37ad71..c7dc8b2de6c2 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c @@ -306,7 +306,9 @@ static int ip6addrlbl_del(struct net *net, /* add default label */ static int __net_init ip6addrlbl_net_init(struct net *net) { - int err = 0; + struct ip6addrlbl_entry *p = NULL; + struct hlist_node *n; + int err; int i; ADDRLABEL(KERN_DEBUG "%s\n", __func__); @@ -315,14 +317,20 @@ static int __net_init ip6addrlbl_net_init(struct net *net) INIT_HLIST_HEAD(&net->ipv6.ip6addrlbl_table.head); for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { - int ret = ip6addrlbl_add(net, - ip6addrlbl_init_table[i].prefix, - ip6addrlbl_init_table[i].prefixlen, - 0, - ip6addrlbl_init_table[i].label, 0); - /* XXX: should we free all rules when we catch an error? */ - if (ret && (!err || err != -ENOMEM)) - err = ret; + err = ip6addrlbl_add(net, + ip6addrlbl_init_table[i].prefix, + ip6addrlbl_init_table[i].prefixlen, + 0, + ip6addrlbl_init_table[i].label, 0); + if (err) + goto err_ip6addrlbl_add; + } + return 0; + +err_ip6addrlbl_add: + hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) { + hlist_del_rcu(&p->list); + kfree_rcu(p, rcu); } return err; } diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 78c974391567..2b68bd7c83c4 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -600,7 +600,8 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); memset(ah->auth_data, 0, ahp->icv_trunc_len); - if (ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN)) + err = ipv6_clear_mutable_options(ip6h, hdr_len, XFRM_POLICY_IN); + if (err) goto out_free; ip6h->priority = 0; diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index 70611784c071..afc76062e1a1 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c @@ -97,6 +97,9 @@ struct calipso_map_cache_entry { static struct calipso_map_cache_bkt *calipso_cache; +static void calipso_cache_invalidate(void); +static void calipso_doi_putdef(struct calipso_doi *doi_def); + /* Label Mapping Cache Functions */ @@ -458,15 +461,10 @@ static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info) ret_val = -ENOENT; goto doi_remove_return; } - if (!refcount_dec_and_test(&doi_def->refcount)) { - spin_unlock(&calipso_doi_list_lock); - ret_val = -EBUSY; - goto doi_remove_return; - } list_del_rcu(&doi_def->list); spin_unlock(&calipso_doi_list_lock); - call_rcu(&doi_def->rcu, calipso_doi_free_rcu); + calipso_doi_putdef(doi_def); ret_val = 0; doi_remove_return: @@ -522,10 +520,8 @@ static void calipso_doi_putdef(struct calipso_doi *doi_def) if (!refcount_dec_and_test(&doi_def->refcount)) return; - spin_lock(&calipso_doi_list_lock); - list_del_rcu(&doi_def->list); - spin_unlock(&calipso_doi_list_lock); + calipso_cache_invalidate(); call_rcu(&doi_def->rcu, calipso_doi_free_rcu); } diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index a7d996148eed..25317d5ccf2c 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -237,7 +237,6 @@ static void esp_output_fill_trailer(u8 *tail, int tfclen, int plen, __u8 proto) int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *esp) { u8 *tail; - u8 *vaddr; int nfrags; struct page *page; struct sk_buff *trailer; @@ -270,14 +269,10 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info page = pfrag->page; get_page(page); - vaddr = kmap_atomic(page); - - tail = vaddr + pfrag->offset; + tail = page_address(page) + pfrag->offset; esp_output_fill_trailer(tail, esp->tfclen, esp->plen, esp->proto); - kunmap_atomic(vaddr); - nfrags = skb_shinfo(skb)->nr_frags; __skb_fill_page_desc(skb, nfrags, page, pfrag->offset, diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 6d14cbe443f8..da0637b7e456 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -418,8 +418,8 @@ static int icmp6_iif(const struct sk_buff *skb) /* * Send an ICMP message in response to a packet in error */ -static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, - const struct in6_addr *force_saddr) +void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, + const struct in6_addr *force_saddr) { struct inet6_dev *idev = NULL; struct ipv6hdr *hdr = ipv6_hdr(skb); @@ -592,6 +592,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info, out_bh_enable: local_bh_enable(); } +EXPORT_SYMBOL(icmp6_send); /* Slightly more convenient version of icmp6_send. */ diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 8b5459b34bc4..e0e464b72c1f 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -906,6 +906,8 @@ static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn, { struct fib6_table *table = rt->fib6_table; + /* Flush all cached dst in exception table */ + rt6_flush_exceptions(rt); if (rt->rt6i_pcpu) fib6_drop_pcpu_from(rt, table); @@ -1756,9 +1758,6 @@ static void fib6_del_route(struct fib6_table *table, struct fib6_node *fn, net->ipv6.rt6_stats->fib_rt_entries--; net->ipv6.rt6_stats->fib_discarded_routes++; - /* Flush all cached dst in exception table */ - rt6_flush_exceptions(rt); - /* Reset round-robin state, if necessary */ if (rcu_access_pointer(fn->rr_ptr) == rt) fn->rr_ptr = NULL; diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 7cc9cd83ecb5..86c8ea7d7006 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1140,8 +1140,13 @@ static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu, return; if (rt->dst.dev) { - dev->needed_headroom = rt->dst.dev->hard_header_len + - t_hlen; + unsigned short dst_len = rt->dst.dev->hard_header_len + + t_hlen; + + if (t->dev->header_ops) + dev->hard_header_len = dst_len; + else + dev->needed_headroom = dst_len; if (set_mtu) { dev->mtu = rt->dst.dev->mtu - t_hlen; @@ -1166,7 +1171,12 @@ static int ip6gre_calc_hlen(struct ip6_tnl *tunnel) tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen; t_hlen = tunnel->hlen + sizeof(struct ipv6hdr); - tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen; + + if (tunnel->dev->header_ops) + tunnel->dev->hard_header_len = LL_MAX_HEADER + t_hlen; + else + tunnel->dev->needed_headroom = LL_MAX_HEADER + t_hlen; + return t_hlen; } diff --git a/net/ipv6/ip6_icmp.c b/net/ipv6/ip6_icmp.c index e0086758b6ee..70c8c2f36c98 100644 --- a/net/ipv6/ip6_icmp.c +++ b/net/ipv6/ip6_icmp.c @@ -9,6 +9,8 @@ #if IS_ENABLED(CONFIG_IPV6) +#if !IS_BUILTIN(CONFIG_IPV6) + static ip6_icmp_send_t __rcu *ip6_icmp_send; int inet6_register_icmp_sender(ip6_icmp_send_t *fn) @@ -37,14 +39,12 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) rcu_read_lock(); send = rcu_dereference(ip6_icmp_send); - - if (!send) - goto out; - send(skb, type, code, info, NULL); -out: + if (send) + send(skb, type, code, info, NULL); rcu_read_unlock(); } EXPORT_SYMBOL(icmpv6_send); +#endif #if IS_ENABLED(CONFIG_NF_NAT) #include diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a925d8212dea..5496f8363118 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -222,16 +222,6 @@ static struct sk_buff *ip6_rcv_core(struct sk_buff *skb, struct net_device *dev, if (ipv6_addr_is_multicast(&hdr->saddr)) goto err; - /* While RFC4291 is not explicit about v4mapped addresses - * in IPv6 headers, it seems clear linux dual-stack - * model can not deal properly with these. - * Security models could be fooled by ::ffff:127.0.0.1 for example. - * - * https://tools.ietf.org/html/draft-itojun-v6ops-v4mapped-harmful-02 - */ - if (ipv6_addr_v4mapped(&hdr->saddr)) - goto err; - skb->transport_header = skb->network_header + sizeof(*hdr); IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 22665e3638ac..e1bb7db88483 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -128,8 +128,42 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * return -EINVAL; } +static int +ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk, + struct sk_buff *skb, unsigned int mtu) +{ + struct sk_buff *segs, *nskb; + netdev_features_t features; + int ret = 0; + + /* Please see corresponding comment in ip_finish_output_gso + * describing the cases where GSO segment length exceeds the + * egress MTU. + */ + features = netif_skb_features(skb); + segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); + if (IS_ERR_OR_NULL(segs)) { + kfree_skb(skb); + return -ENOMEM; + } + + consume_skb(skb); + + skb_list_walk_safe(segs, segs, nskb) { + int err; + + skb_mark_not_on_list(segs); + err = ip6_fragment(net, sk, segs, ip6_finish_output2); + if (err && ret == 0) + ret = err; + } + + return ret; +} + static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb) { + unsigned int mtu; int ret; ret = BPF_CGROUP_RUN_PROG_INET_EGRESS(sk, skb); @@ -146,7 +180,11 @@ static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *s } #endif - if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || + mtu = ip6_skb_dst_mtu(skb); + if (skb_is_gso(skb) && !skb_gso_validate_network_len(skb, mtu)) + return ip6_finish_output_gso_slowpath_drop(net, sk, skb, mtu); + + if ((skb->len > mtu && !skb_is_gso(skb)) || dst_allfrag(skb_dst(skb)) || (IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size)) return ip6_fragment(net, sk, skb, ip6_finish_output2); diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index b825ac025d5b..28c4a693ab98 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -2222,6 +2222,16 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head t = rtnl_dereference(t->next); } } + + t = rtnl_dereference(ip6n->tnls_wc[0]); + while (t) { + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, list); + t = rtnl_dereference(t->next); + } } static int __net_init ip6_tnl_init_net(struct net *net) diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 6d0b1f3e927b..5679fa3f696a 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c @@ -17,10 +17,10 @@ #include #include -int ip6_route_me_harder(struct net *net, struct sk_buff *skb) +int ip6_route_me_harder(struct net *net, struct sock *sk_partial, struct sk_buff *skb) { const struct ipv6hdr *iph = ipv6_hdr(skb); - struct sock *sk = sk_to_full_sk(skb->sk); + struct sock *sk = sk_to_full_sk(sk_partial); unsigned int hh_len; struct dst_entry *dst; int strict = (ipv6_addr_type(&iph->daddr) & @@ -81,7 +81,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || skb->mark != rt_info->mark) - return ip6_route_me_harder(entry->state.net, skb); + return ip6_route_me_harder(entry->state.net, entry->state.sk, skb); } return 0; } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index cf3106c5a793..25b04be9a1d6 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1429,6 +1429,8 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index b0524b18c4fb..acba3757ff60 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c @@ -60,7 +60,7 @@ ip6t_mangle_out(struct sk_buff *skb, const struct nf_hook_state *state) skb->mark != mark || ipv6_hdr(skb)->hop_limit != hop_limit || flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { - err = ip6_route_me_harder(state->net, skb); + err = ip6_route_me_harder(state->net, state->sk, skb); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index ca6d38698b1a..2b6a3b27f670 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c @@ -352,7 +352,7 @@ nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &ct->tuplehash[!dir].tuple.src.u3)) { - err = ip6_route_me_harder(state->net, skb); + err = ip6_route_me_harder(state->net, state->sk, skb); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv6/netfilter/nft_chain_route_ipv6.c b/net/ipv6/netfilter/nft_chain_route_ipv6.c index da3f1f8cb325..afe79cb46e63 100644 --- a/net/ipv6/netfilter/nft_chain_route_ipv6.c +++ b/net/ipv6/netfilter/nft_chain_route_ipv6.c @@ -52,7 +52,7 @@ static unsigned int nf_route_table_hook(void *priv, skb->mark != mark || ipv6_hdr(skb)->hop_limit != hop_limit || flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { - err = ip6_route_me_harder(state->net, skb); + err = ip6_route_me_harder(state->net, state->sk, skb); if (err < 0) ret = NF_DROP_ERR(err); } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 8d19729f8516..98c8f98a7660 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -303,7 +303,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) */ v4addr = LOOPBACK4_IPV6; if (!(addr_type & IPV6_ADDR_MULTICAST) && - !sock_net(sk)->ipv6.sysctl.ip_nonlocal_bind) { + !ipv6_can_nonlocal_bind(sock_net(sk), inet)) { err = -EADDRNOTAVAIL; if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, dev, 0)) { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ed0128997e00..b6b317d7d52f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -4490,9 +4490,11 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, * nexthops have been replaced by first new, the rest should * be added to it. */ - cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | - NLM_F_REPLACE); - cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; + if (cfg->fc_nlinfo.nlh) { + cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | + NLM_F_REPLACE); + cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; + } nhn++; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index bfed7508ba19..ad737b68b8e9 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1087,7 +1087,6 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) if (tdev && !netif_is_l3_master(tdev)) { int t_hlen = tunnel->hlen + sizeof(struct iphdr); - dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr); dev->mtu = tdev->mtu - t_hlen; if (dev->mtu < IPV6_MIN_MTU) dev->mtu = IPV6_MIN_MTU; @@ -1377,7 +1376,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) dev->priv_destructor = ipip6_dev_free; dev->type = ARPHRD_SIT; - dev->hard_header_len = LL_MAX_HEADER + t_hlen; dev->mtu = ETH_DATA_LEN - t_hlen; dev->min_mtu = IPV6_MIN_MTU; dev->max_mtu = IP6_MAX_MTU - t_hlen; @@ -1598,8 +1596,11 @@ static int ipip6_newlink(struct net *src_net, struct net_device *dev, } #ifdef CONFIG_IPV6_SIT_6RD - if (ipip6_netlink_6rd_parms(data, &ip6rd)) + if (ipip6_netlink_6rd_parms(data, &ip6rd)) { err = ipip6_tunnel_update_6rd(nt, &ip6rd); + if (err < 0) + unregister_netdevice_queue(dev, NULL); + } #endif return err; @@ -1817,9 +1818,9 @@ static void __net_exit sit_destroy_tunnels(struct net *net, if (dev->rtnl_link_ops == &sit_link_ops) unregister_netdevice_queue(dev, head); - for (prio = 1; prio < 4; prio++) { + for (prio = 0; prio < 4; prio++) { int h; - for (h = 0; h < IP6_SIT_HASH_SIZE; h++) { + for (h = 0; h < (prio ? IP6_SIT_HASH_SIZE : 1); h++) { struct ip_tunnel *t; t = rtnl_dereference(sitn->tunnels[prio][h]); diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index a377be8a9fb4..ec61b67a92be 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -141,7 +141,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) __u32 cookie = ntohl(th->ack_seq) - 1; struct sock *ret = sk; struct request_sock *req; - int mss; + int full_space, mss; struct dst_entry *dst; __u8 rcv_wscale; u32 tsoff = 0; @@ -246,7 +246,13 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) } req->rsk_window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); - tcp_select_initial_window(sk, tcp_full_space(sk), req->mss, + /* limit the window selection if the user enforce a smaller rx buffer */ + full_space = tcp_full_space(sk); + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK && + (req->rsk_window_clamp > full_space || req->rsk_window_clamp == 0)) + req->rsk_window_clamp = full_space; + + tcp_select_initial_window(sk, full_space, req->mss, &req->rsk_rcv_wnd, &req->rsk_window_clamp, ireq->wscale_ok, &rcv_wscale, dst_metric(dst, RTAX_INITRWND)); diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d56f2373753a..3506d6220f9e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1038,6 +1038,11 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) if (!ipv6_unicast_destination(skb)) goto drop; + if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) { + __IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS); + return 0; + } + return tcp_conn_request(&tcp6_request_sock_ops, &tcp_request_sock_ipv6_ops, sk, skb); @@ -1840,7 +1845,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) * we might find a transient negative value. */ rx_queue = max_t(int, READ_ONCE(tp->rcv_nxt) - - tp->copied_seq, 0); + READ_ONCE(tp->copied_seq), 0); if (inet->transparent) state_seq |= 0x80; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 23a1002ed86d..d59f2341bfec 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1571,7 +1571,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how) break; } - if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) { + if ((how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) && + sk->sk_state == IUCV_CONNECTED) { if (iucv->transport == AF_IUCV_TRANS_IUCV) { txmsg.class = 0; txmsg.tag = 0; @@ -1781,7 +1782,7 @@ static int iucv_callback_connreq(struct iucv_path *path, } /* Create the new socket */ - nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC, 0); + nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0); if (!nsk) { err = pr_iucv->path_sever(path, user_data); iucv_path_free(path); @@ -1991,7 +1992,7 @@ static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb) goto out; } - nsk = iucv_sock_alloc(NULL, sk->sk_type, GFP_ATOMIC, 0); + nsk = iucv_sock_alloc(NULL, sk->sk_protocol, GFP_ATOMIC, 0); bh_lock_sock(sk); if ((sk->sk_state != IUCV_LISTEN) || sk_acceptq_is_full(sk) || diff --git a/net/key/af_key.c b/net/key/af_key.c index e340e97224c3..c7d5a6015389 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -2908,7 +2908,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t) break; if (!aalg->pfkey_supported) continue; - if (aalg_tmpl_set(t, aalg) && aalg->available) + if (aalg_tmpl_set(t, aalg)) sz += sizeof(struct sadb_comb); } return sz + sizeof(struct sadb_prop); @@ -2926,7 +2926,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) if (!ealg->pfkey_supported) continue; - if (!(ealg_tmpl_set(t, ealg) && ealg->available)) + if (!(ealg_tmpl_set(t, ealg))) continue; for (k = 1; ; k++) { @@ -2937,7 +2937,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t) if (!aalg->pfkey_supported) continue; - if (aalg_tmpl_set(t, aalg) && aalg->available) + if (aalg_tmpl_set(t, aalg)) sz += sizeof(struct sadb_comb); } } diff --git a/net/lapb/lapb_out.c b/net/lapb/lapb_out.c index eda726e22f64..621c66f00117 100644 --- a/net/lapb/lapb_out.c +++ b/net/lapb/lapb_out.c @@ -87,7 +87,8 @@ void lapb_kick(struct lapb_cb *lapb) skb = skb_dequeue(&lapb->write_queue); do { - if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { + skbn = skb_copy(skb, GFP_ATOMIC); + if (!skbn) { skb_queue_head(&lapb->write_queue, skb); break; } diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 9926455dd546..6804cdd43bef 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1548,8 +1548,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, } if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && - sta->sdata->u.vlan.sta) + sta->sdata->u.vlan.sta) { + ieee80211_clear_fast_rx(sta); RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL); + } if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) ieee80211_vif_dec_num_mcast(sta->sdata); @@ -2777,14 +2779,14 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, continue; for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) { - if (~sdata->rc_rateidx_mcs_mask[i][j]) { + if (sdata->rc_rateidx_mcs_mask[i][j] != 0xff) { sdata->rc_has_mcs_mask[i] = true; break; } } for (j = 0; j < NL80211_VHT_NSS_MAX; j++) { - if (~sdata->rc_rateidx_vht_mcs_mask[i][j]) { + if (sdata->rc_rateidx_vht_mcs_mask[i][j] != 0xffff) { sdata->rc_has_vht_mcs_mask[i] = true; break; } diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c index f783d1377d9a..9f0f437a09b9 100644 --- a/net/mac80211/driver-ops.c +++ b/net/mac80211/driver-ops.c @@ -128,8 +128,11 @@ int drv_sta_state(struct ieee80211_local *local, } else if (old_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_ASSOC) { ret = drv_sta_add(local, sdata, &sta->sta); - if (ret == 0) + if (ret == 0) { sta->uploaded = true; + if (rcu_access_pointer(sta->sta.rates)) + drv_sta_rate_tbl_update(local, sdata, &sta->sta); + } } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTH) { drv_sta_remove(local, sdata, &sta->sta); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a879d8071712..fc715bba5914 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1051,6 +1051,7 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_FLUSH, IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN, IEEE80211_QUEUE_STOP_REASON_RESERVE_TID, + IEEE80211_QUEUE_STOP_REASON_IFTYPE_CHANGE, IEEE80211_QUEUE_STOP_REASONS, }; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 152d4365f961..511ca6f74239 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1542,6 +1542,10 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, if (ret) return ret; + ieee80211_stop_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_IFTYPE_CHANGE); + synchronize_net(); + ieee80211_do_stop(sdata, false); ieee80211_teardown_sdata(sdata); @@ -1562,6 +1566,8 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, err = ieee80211_do_open(&sdata->wdev, false); WARN(err, "type change: do_open returned %d", err); + ieee80211_wake_vif_queues(local, sdata, + IEEE80211_QUEUE_STOP_REASON_IFTYPE_CHANGE); return ret; } diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 68db2a356443..f44d00f35fe7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -931,8 +931,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) continue; if (!dflt_chandef.chan) { + /* + * Assign the first enabled channel to dflt_chandef + * from the list of channels + */ + for (i = 0; i < sband->n_channels; i++) + if (!(sband->channels[i].flags & + IEEE80211_CHAN_DISABLED)) + break; + /* if none found then use the first anyway */ + if (i == sband->n_channels) + i = 0; cfg80211_chandef_create(&dflt_chandef, - &sband->channels[0], + &sband->channels[i], NL80211_CHAN_NO_HT); /* init channel we're on */ if (!local->use_chanctx && !local->_oper_chandef.chan) { diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 6219b6b0c7e1..18158855d98c 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -355,7 +355,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, */ tx_time = (device_constant + 10 * test_frame_len / rate); estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); - result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT); + result = ((u64)tx_time * estimated_retx) >> (2 * ARITH_SHIFT); return (u32)result; } diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 4fc720c77e37..6dc5f93b1e4d 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -63,6 +63,7 @@ static struct mesh_table *mesh_table_alloc(void) atomic_set(&newtbl->entries, 0); spin_lock_init(&newtbl->gates_lock); spin_lock_init(&newtbl->walk_lock); + rhashtable_init(&newtbl->rhead, &mesh_rht_params); return newtbl; } @@ -786,9 +787,6 @@ int mesh_pathtbl_init(struct ieee80211_sub_if_data *sdata) goto free_path; } - rhashtable_init(&tbl_path->rhead, &mesh_rht_params); - rhashtable_init(&tbl_mpp->rhead, &mesh_rht_params); - sdata->u.mesh.mesh_paths = tbl_path; sdata->u.mesh.mpp_paths = tbl_mpp; diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 76f303fda3ed..954b932fd7b8 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -941,7 +941,8 @@ int rate_control_set_rates(struct ieee80211_hw *hw, if (old) kfree_rcu(old, rcu_head); - drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta); + if (sta->uploaded) + drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta); ieee80211_sta_set_expected_throughput(pubsta, sta_get_expected_throughput(sta)); diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 07fb219327d6..1f3c420c01c7 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -276,7 +276,7 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, success = !!(info->flags & IEEE80211_TX_STAT_ACK); for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (ar[i].idx < 0) + if (ar[i].idx < 0 || !ar[i].count) break; ndx = rix_to_ndx(mi, ar[i].idx); @@ -289,12 +289,6 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, mi->r[ndx].stats.success += success; } - if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) - mi->sample_packets++; - - if (mi->sample_deferred > 0) - mi->sample_deferred--; - if (time_after(jiffies, mi->last_stats_update + (mp->update_interval * HZ) / 1000)) minstrel_update_stats(mp, mi); @@ -373,7 +367,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, return; delta = (mi->total_packets * sampling_ratio / 100) - - (mi->sample_packets + mi->sample_deferred / 2); + mi->sample_packets; /* delta < 0: no sampling required */ prev_sample = mi->prev_sample; @@ -382,7 +376,6 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, return; if (mi->total_packets >= 10000) { - mi->sample_deferred = 0; mi->sample_packets = 0; mi->total_packets = 0; } else if (delta > mi->n_rates * 2) { @@ -407,19 +400,8 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, * rate sampling method should be used. * Respect such rates that are not sampled for 20 interations. */ - if (mrr_capable && - msr->perfect_tx_time > mr->perfect_tx_time && - msr->stats.sample_skipped < 20) { - /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark - * packets that have the sampling rate deferred to the - * second MRR stage. Increase the sample counter only - * if the deferred sample rate was actually used. - * Use the sample_deferred counter to make sure that - * the sampling is not done in large bursts */ - info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; - rate++; - mi->sample_deferred++; - } else { + if (msr->perfect_tx_time < mr->perfect_tx_time || + msr->stats.sample_skipped >= 20) { if (!msr->sample_limit) return; @@ -439,6 +421,7 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, rate->idx = mi->r[ndx].rix; rate->count = minstrel_get_retry_count(&mi->r[ndx], info); + info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; } diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index be6c3f35f48b..d60413adb215 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h @@ -98,7 +98,6 @@ struct minstrel_sta_info { u8 max_prob_rate; unsigned int total_packets; unsigned int sample_packets; - int sample_deferred; unsigned int sample_row; unsigned int sample_column; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5e56719f999c..9e92e5e2336b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -4003,6 +4003,8 @@ void ieee80211_check_fast_rx(struct sta_info *sta) rcu_read_lock(); key = rcu_dereference(sta->ptk[sta->ptk_idx]); + if (!key) + key = rcu_dereference(sdata->default_unicast_key); if (key) { switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_TKIP: diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 9968b8a976f1..c0fae954082b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -244,6 +244,24 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, */ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) { + /* + * If we had used sta_info_pre_move_state() then we might not + * have gone through the state transitions down again, so do + * it here now (and warn if it's inserted). + * + * This will clear state such as fast TX/RX that may have been + * allocated during state transitions. + */ + while (sta->sta_state > IEEE80211_STA_NONE) { + int ret; + + WARN_ON_ONCE(test_sta_flag(sta, WLAN_STA_INSERTED)); + + ret = sta_info_move_state(sta, sta->sta_state - 1); + if (WARN_ONCE(ret, "sta_info_move_state() returned %d\n", ret)) + break; + } + if (sta->rate_ctrl) rate_control_free_sta(sta); @@ -616,7 +634,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) out_drop_sta: local->num_sta--; synchronize_net(); - __cleanup_single_sta(sta); + cleanup_single_sta(sta); out_err: mutex_unlock(&local->sta_mtx); kfree(sinfo); @@ -635,19 +653,13 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) err = sta_info_insert_check(sta); if (err) { + sta_info_free(local, sta); mutex_unlock(&local->sta_mtx); rcu_read_lock(); - goto out_free; + return err; } - err = sta_info_insert_finish(sta); - if (err) - goto out_free; - - return 0; - out_free: - sta_info_free(local, sta); - return err; + return sta_info_insert_finish(sta); } int sta_info_insert(struct sta_info *sta) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 7d7eb75ce901..e89d341a03e5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1909,19 +1909,24 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, /* device xmit handlers */ +enum ieee80211_encrypt { + ENCRYPT_NO, + ENCRYPT_MGMT, + ENCRYPT_DATA, +}; + static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, - int head_need, bool may_encrypt) + int head_need, + enum ieee80211_encrypt encrypt) { struct ieee80211_local *local = sdata->local; - struct ieee80211_hdr *hdr; bool enc_tailroom; int tail_need = 0; - hdr = (struct ieee80211_hdr *) skb->data; - enc_tailroom = may_encrypt && - (sdata->crypto_tx_tailroom_needed_cnt || - ieee80211_is_mgmt(hdr->frame_control)); + enc_tailroom = encrypt == ENCRYPT_MGMT || + (encrypt == ENCRYPT_DATA && + sdata->crypto_tx_tailroom_needed_cnt); if (enc_tailroom) { tail_need = IEEE80211_ENCRYPT_TAILROOM; @@ -1953,23 +1958,29 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; int headroom; - bool may_encrypt; + enum ieee80211_encrypt encrypt; - may_encrypt = !(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT); + if (info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT) + encrypt = ENCRYPT_NO; + else if (ieee80211_is_mgmt(hdr->frame_control)) + encrypt = ENCRYPT_MGMT; + else + encrypt = ENCRYPT_DATA; headroom = local->tx_headroom; - if (may_encrypt) + if (encrypt != ENCRYPT_NO) headroom += sdata->encrypt_headroom; headroom -= skb_headroom(skb); headroom = max_t(int, 0, headroom); - if (ieee80211_skb_resize(sdata, skb, headroom, may_encrypt)) { + if (ieee80211_skb_resize(sdata, skb, headroom, encrypt)) { ieee80211_free_txskb(&local->hw, skb); return; } + /* reload after potential resize */ hdr = (struct ieee80211_hdr *) skb->data; info->control.vif = &sdata->vif; @@ -2752,7 +2763,7 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, head_need += sdata->encrypt_headroom; head_need += local->tx_headroom; head_need = max_t(int, 0, head_need); - if (ieee80211_skb_resize(sdata, skb, head_need, true)) { + if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) { ieee80211_free_txskb(&local->hw, skb); skb = NULL; return ERR_PTR(-ENOMEM); @@ -3415,7 +3426,7 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, if (unlikely(ieee80211_skb_resize(sdata, skb, max_t(int, extra_head + hw_headroom - skb_headroom(skb), 0), - false))) { + ENCRYPT_NO))) { kfree_skb(skb); return true; } diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 4d154efb80c8..d691c2f2e92e 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -421,12 +421,18 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) * IEEE80211-2016 specification makes higher bandwidth operation * possible on the TDLS link if the peers have wider bandwidth * capability. + * + * However, in this case, and only if the TDLS peer is authorized, + * limit to the tdls_chandef so that the configuration here isn't + * wider than what's actually requested on the channel context. */ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) && - test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW)) - return bw; - - bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width)); + test_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW) && + test_sta_flag(sta, WLAN_STA_AUTHORIZED) && + sta->tdls_chandef.chan) + bw = min(bw, ieee80211_chan_width_to_rx_bw(sta->tdls_chandef.width)); + else + bw = min(bw, ieee80211_chan_width_to_rx_bw(bss_width)); return bw; } diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index 7e29f88dbf6a..ff1e56bca29c 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c @@ -160,7 +160,7 @@ llsec_key_alloc(const struct ieee802154_llsec_key *template) crypto_free_sync_skcipher(key->tfm0); err_tfm: for (i = 0; i < ARRAY_SIZE(key->tfm); i++) - if (key->tfm[i]) + if (!IS_ERR_OR_NULL(key->tfm[i])) crypto_free_aead(key->tfm[i]); kzfree(key); diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c index b4da6d8e8632..2129856b5933 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c @@ -18,6 +18,7 @@ #include #include #include +#include static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, netdev_features_t features) @@ -31,6 +32,8 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, skb_reset_network_header(skb); mpls_hlen = skb_inner_network_header(skb) - skb_network_header(skb); + if (unlikely(!mpls_hlen || mpls_hlen % MPLS_HLEN)) + goto out; if (unlikely(!pskb_may_pull(skb, mpls_hlen))) goto out; diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c index 091284760d21..9fd20fa90000 100644 --- a/net/ncsi/ncsi-manage.c +++ b/net/ncsi/ncsi-manage.c @@ -84,13 +84,20 @@ static void ncsi_channel_monitor(struct timer_list *t) monitor_state = nc->monitor.state; spin_unlock_irqrestore(&nc->lock, flags); - if (!enabled || chained) { - ncsi_stop_channel_monitor(nc); - return; - } + if (!enabled) + return; /* expected race disabling timer */ + if (WARN_ON_ONCE(chained)) + goto bad_state; + if (state != NCSI_CHANNEL_INACTIVE && state != NCSI_CHANNEL_ACTIVE) { - ncsi_stop_channel_monitor(nc); +bad_state: + netdev_warn(ndp->ndev.dev, + "Bad NCSI monitor state channel %d 0x%x %s queue\n", + nc->id, state, chained ? "on" : "off"); + spin_lock_irqsave(&nc->lock, flags); + nc->monitor.enabled = false; + spin_unlock_irqrestore(&nc->lock, flags); return; } @@ -117,10 +124,9 @@ static void ncsi_channel_monitor(struct timer_list *t) ndp->flags |= NCSI_DEV_RESHUFFLE; } - ncsi_stop_channel_monitor(nc); - ncm = &nc->modes[NCSI_MODE_LINK]; spin_lock_irqsave(&nc->lock, flags); + nc->monitor.enabled = false; nc->state = NCSI_CHANNEL_INVISIBLE; ncm->data[2] &= ~0x1; spin_unlock_irqrestore(&nc->lock, flags); @@ -1484,9 +1490,6 @@ struct ncsi_dev *ncsi_register_dev(struct net_device *dev, ndp->ptype.dev = dev; dev_add_pack(&ndp->ptype); - /* Set up generic netlink interface */ - ncsi_init_netlink(dev); - return nd; } EXPORT_SYMBOL_GPL(ncsi_register_dev); @@ -1566,8 +1569,6 @@ void ncsi_unregister_dev(struct ncsi_dev *nd) #endif spin_unlock_irqrestore(&ncsi_dev_lock, flags); - ncsi_unregister_netlink(nd->dev); - kfree(ndp); } EXPORT_SYMBOL_GPL(ncsi_unregister_dev); diff --git a/net/ncsi/ncsi-netlink.c b/net/ncsi/ncsi-netlink.c index 45f33d6dedf7..a2f4280e2889 100644 --- a/net/ncsi/ncsi-netlink.c +++ b/net/ncsi/ncsi-netlink.c @@ -397,24 +397,8 @@ static struct genl_family ncsi_genl_family __ro_after_init = { .n_ops = ARRAY_SIZE(ncsi_ops), }; -int ncsi_init_netlink(struct net_device *dev) +static int __init ncsi_init_netlink(void) { - int rc; - - rc = genl_register_family(&ncsi_genl_family); - if (rc) - netdev_err(dev, "ncsi: failed to register netlink family\n"); - - return rc; -} - -int ncsi_unregister_netlink(struct net_device *dev) -{ - int rc; - - rc = genl_unregister_family(&ncsi_genl_family); - if (rc) - netdev_err(dev, "ncsi: failed to unregister netlink family\n"); - - return rc; + return genl_register_family(&ncsi_genl_family); } +subsys_initcall(ncsi_init_netlink); diff --git a/net/ncsi/ncsi-netlink.h b/net/ncsi/ncsi-netlink.h index 91a5c256f8c4..6c55a6775157 100644 --- a/net/ncsi/ncsi-netlink.h +++ b/net/ncsi/ncsi-netlink.h @@ -14,7 +14,4 @@ #include "internal.h" -int ncsi_init_netlink(struct net_device *dev); -int ncsi_unregister_netlink(struct net_device *dev); - #endif /* __NCSI_NETLINK_H__ */ diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c index 930c1d3796f0..a43c9a44f870 100644 --- a/net/ncsi/ncsi-rsp.c +++ b/net/ncsi/ncsi-rsp.c @@ -949,7 +949,7 @@ int ncsi_rcv_rsp(struct sk_buff *skb, struct net_device *dev, int payload, i, ret; /* Find the NCSI device */ - nd = ncsi_find_dev(dev); + nd = ncsi_find_dev(orig_dev); ndp = nd ? TO_NCSI_DEV_PRIV(nd) : NULL; if (!ndp) return -ENODEV; diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 36ebc40a4313..0427e66bc478 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -488,13 +488,14 @@ ip_set_match_extensions(struct ip_set *set, const struct ip_set_ext *ext, if (SET_WITH_COUNTER(set)) { struct ip_set_counter *counter = ext_counter(data, set); + ip_set_update_counter(counter, ext, flags); + if (flags & IPSET_FLAG_MATCH_COUNTERS && !(ip_set_match_counter(ip_set_get_packets(counter), mext->packets, mext->packets_op) && ip_set_match_counter(ip_set_get_bytes(counter), mext->bytes, mext->bytes_op))) return false; - ip_set_update_counter(counter, ext, flags); } if (SET_WITH_SKBINFO(set)) ip_set_get_skbinfo(ext_skbinfo(data, set), diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index ddfe06d7530b..154b40f2f2a8 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h @@ -115,20 +115,6 @@ htable_size(u8 hbits) return hsize * sizeof(struct hbucket *) + sizeof(struct htable); } -/* Compute htable_bits from the user input parameter hashsize */ -static u8 -htable_bits(u32 hashsize) -{ - /* Assume that hashsize == 2^htable_bits */ - u8 bits = fls(hashsize - 1); - - if (jhash_size(bits) != hashsize) - /* Round up to the first 2^n value */ - bits = fls(hashsize); - - return bits; -} - #ifdef IP_SET_HASH_WITH_NETS #if IPSET_NET_COUNT > 1 #define __CIDR(cidr, i) (cidr[i]) @@ -1287,7 +1273,11 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, if (!h) return -ENOMEM; - hbits = htable_bits(hashsize); + /* Compute htable_bits from the user input parameter hashsize. + * Assume that hashsize == 2^htable_bits, + * otherwise round up to the first 2^n value. + */ + hbits = fls(hashsize - 1); hsize = htable_size(hbits); if (hsize == 0) { kfree(h); diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index d5e4329579e2..acaeeaf81441 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -725,12 +725,12 @@ static int ip_vs_route_me_harder(struct netns_ipvs *ipvs, int af, struct dst_entry *dst = skb_dst(skb); if (dst->dev && !(dst->dev->flags & IFF_LOOPBACK) && - ip6_route_me_harder(ipvs->net, skb) != 0) + ip6_route_me_harder(ipvs->net, skb->sk, skb) != 0) return 1; } else #endif if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL) && - ip_route_me_harder(ipvs->net, skb, RTN_LOCAL) != 0) + ip_route_me_harder(ipvs->net, skb->sk, skb, RTN_LOCAL) != 0) return 1; return 0; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index ad1da6b2fb60..eb9a8cb5914f 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -1063,7 +1063,8 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, * Let nf_ct_resolve_clash() deal with this later. */ if (nf_ct_tuple_equal(&ignored_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple, - &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)) + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple) && + nf_ct_zone_equal(ct, zone, IP_CT_DIR_ORIGINAL)) continue; NF_CT_STAT_INC_ATOMIC(net, found); @@ -2306,11 +2307,11 @@ int nf_conntrack_init_start(void) * >= 4GB machines have 65536 buckets. */ nf_conntrack_htable_size - = (((totalram_pages << PAGE_SHIFT) / 16384) + = (((totalram_pages() << PAGE_SHIFT) / 16384) / sizeof(struct hlist_head)); - if (totalram_pages > (4 * (1024 * 1024 * 1024 / PAGE_SIZE))) + if (totalram_pages() > (4 * (1024 * 1024 * 1024 / PAGE_SIZE))) nf_conntrack_htable_size = 65536; - else if (totalram_pages > (1024 * 1024 * 1024 / PAGE_SIZE)) + else if (totalram_pages() > (1024 * 1024 * 1024 / PAGE_SIZE)) nf_conntrack_htable_size = 16384; if (nf_conntrack_htable_size < 32) nf_conntrack_htable_size = 32; diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 0b89609a6e9d..15c9fbcd32f2 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -2656,6 +2656,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb, memset(&m, 0xFF, sizeof(m)); memcpy(&m.src.u3, &mask->src.u3, sizeof(m.src.u3)); m.src.u.all = mask->src.u.all; + m.src.l3num = tuple->src.l3num; m.dst.protonum = tuple->dst.protonum; nest_parms = nla_nest_start(skb, CTA_EXPECT_MASK | NLA_F_NESTED); diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 4c94f3ba2ae4..2e3ae494f369 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -262,6 +262,7 @@ static const char* l4proto_name(u16 proto) case IPPROTO_GRE: return "gre"; case IPPROTO_SCTP: return "sctp"; case IPPROTO_UDPLITE: return "udplite"; + case IPPROTO_ICMPV6: return "icmpv6"; } return "unknown"; @@ -500,6 +501,9 @@ nf_conntrack_hash_sysctl(struct ctl_table *table, int write, { int ret; + /* module_param hashsize could have changed value */ + nf_conntrack_htable_size_user = nf_conntrack_htable_size; + ret = proc_dointvec(table, write, buffer, lenp, ppos); if (ret < 0 || !write) return ret; diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index 890799c16aa4..b3957fe7eced 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c @@ -360,7 +360,7 @@ static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff, return -1; tcph = (void *)(skb_network_header(skb) + thoff); - inet_proto_csum_replace2(&tcph->check, skb, port, new_port, true); + inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false); return 0; } @@ -377,7 +377,7 @@ static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff, udph = (void *)(skb_network_header(skb) + thoff); if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { inet_proto_csum_replace2(&udph->check, skb, port, - new_port, true); + new_port, false); if (!udph->check) udph->check = CSUM_MANGLED_0; } diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 2268b10a9dcf..c31df6a76504 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c @@ -1068,6 +1068,7 @@ static int __init nf_nat_init(void) ret = register_pernet_subsys(&nat_net_ops); if (ret < 0) { nf_ct_extend_unregister(&nat_extend); + kvfree(nf_nat_bysource); return ret; } diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 5b4632826dc6..9cc8e92f4b00 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -532,7 +532,8 @@ static void nft_request_module(struct net *net, const char *fmt, ...) static void lockdep_nfnl_nft_mutex_not_held(void) { #ifdef CONFIG_PROVE_LOCKING - WARN_ON_ONCE(lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES)); + if (debug_locks) + WARN_ON_ONCE(lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES)); #endif } diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c index eb7f9a5f2aeb..4e544044fc2d 100644 --- a/net/netfilter/nft_dynset.c +++ b/net/netfilter/nft_dynset.c @@ -213,8 +213,10 @@ static int nft_dynset_init(const struct nft_ctx *ctx, nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_EXPR, priv->expr->ops->size); if (set->flags & NFT_SET_TIMEOUT) { - if (timeout || set->timeout) + if (timeout || set->timeout) { + nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_TIMEOUT); nft_set_ext_add(&priv->tmpl, NFT_SET_EXT_EXPIRATION); + } } priv->timeout = timeout; diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c index 72f13a1144dd..a7bdc532479a 100644 --- a/net/netfilter/nft_limit.c +++ b/net/netfilter/nft_limit.c @@ -79,13 +79,13 @@ static int nft_limit_init(struct nft_limit *limit, return -EOVERFLOW; if (pkts) { - tokens = div_u64(limit->nsecs, limit->rate) * limit->burst; + tokens = div64_u64(limit->nsecs, limit->rate) * limit->burst; } else { /* The token bucket size limits the number of tokens can be * accumulated. tokens_max specifies the bucket size. * tokens_max = unit * (rate + burst) / rate. */ - tokens = div_u64(limit->nsecs * (limit->rate + limit->burst), + tokens = div64_u64(limit->nsecs * (limit->rate + limit->burst), limit->rate); } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index c0c6beb99ee5..1c91815d73b5 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -335,6 +335,7 @@ static int match_revfn(u8 af, const char *name, u8 revision, int *bestp) const struct xt_match *m; int have_rev = 0; + mutex_lock(&xt[af].mutex); list_for_each_entry(m, &xt[af].match, list) { if (strcmp(m->name, name) == 0) { if (m->revision > *bestp) @@ -343,6 +344,7 @@ static int match_revfn(u8 af, const char *name, u8 revision, int *bestp) have_rev = 1; } } + mutex_unlock(&xt[af].mutex); if (af != NFPROTO_UNSPEC && !have_rev) return match_revfn(NFPROTO_UNSPEC, name, revision, bestp); @@ -355,6 +357,7 @@ static int target_revfn(u8 af, const char *name, u8 revision, int *bestp) const struct xt_target *t; int have_rev = 0; + mutex_lock(&xt[af].mutex); list_for_each_entry(t, &xt[af].target, list) { if (strcmp(t->name, name) == 0) { if (t->revision > *bestp) @@ -363,6 +366,7 @@ static int target_revfn(u8 af, const char *name, u8 revision, int *bestp) have_rev = 1; } } + mutex_unlock(&xt[af].mutex); if (af != NFPROTO_UNSPEC && !have_rev) return target_revfn(NFPROTO_UNSPEC, name, revision, bestp); @@ -376,12 +380,10 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target, { int have_rev, best = -1; - mutex_lock(&xt[af].mutex); if (target == 1) have_rev = target_revfn(af, name, revision, &best); else have_rev = match_revfn(af, name, revision, &best); - mutex_unlock(&xt[af].mutex); /* Nothing at all? Return 0 to try loading module. */ if (best == -1) { @@ -736,7 +738,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, { const struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; - int pad, off = xt_compat_match_offset(match); + int off = xt_compat_match_offset(match); u_int16_t msize = cm->u.user.match_size; char name[sizeof(m->u.user.name)]; @@ -746,9 +748,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, match->compat_from_user(m->data, cm->data); else memcpy(m->data, cm->data, msize - sizeof(*cm)); - pad = XT_ALIGN(match->matchsize) - match->matchsize; - if (pad > 0) - memset(m->data + match->matchsize, 0, pad); msize += off; m->u.user.match_size = msize; @@ -1119,7 +1118,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, { const struct xt_target *target = t->u.kernel.target; struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; - int pad, off = xt_compat_target_offset(target); + int off = xt_compat_target_offset(target); u_int16_t tsize = ct->u.user.target_size; char name[sizeof(t->u.user.name)]; @@ -1129,9 +1128,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, target->compat_from_user(t->data, ct->data); else memcpy(t->data, ct->data, tsize - sizeof(*ct)); - pad = XT_ALIGN(target->targetsize) - target->targetsize; - if (pad > 0) - memset(t->data + target->targetsize, 0, pad); tsize += off; t->u.user.target_size = tsize; diff --git a/net/netfilter/xt_HARDIDLETIMER.c b/net/netfilter/xt_HARDIDLETIMER.c index 055763b785ce..6bab1345b77f 100644 --- a/net/netfilter/xt_HARDIDLETIMER.c +++ b/net/netfilter/xt_HARDIDLETIMER.c @@ -33,19 +33,13 @@ #include #include -struct hardidletimer_tg_attr { - struct attribute attr; - ssize_t (*show)(struct kobject *kobj, - struct attribute *attr, char *buf); -}; - struct hardidletimer_tg { struct list_head entry; struct alarm alarm; struct work_struct work; struct kobject *kobj; - struct hardidletimer_tg_attr attr; + struct device_attribute attr; unsigned int refcnt; bool send_nl_msg; @@ -96,8 +90,8 @@ struct hardidletimer_tg *__hardidletimer_tg_find_by_label(const char *label) return NULL; } -static ssize_t hardidletimer_tg_show(struct kobject *kobj, - struct attribute *attr, char *buf) +static ssize_t hardidletimer_tg_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct hardidletimer_tg *timer; ktime_t expires; @@ -106,7 +100,7 @@ static ssize_t hardidletimer_tg_show(struct kobject *kobj, memset(&ktimespec, 0, sizeof(struct timespec)); mutex_lock(&list_mutex); - timer = __hardidletimer_tg_find_by_label(attr->name); + timer = __hardidletimer_tg_find_by_label(attr->attr.name); if (timer) { expires = alarm_expires_remaining(&timer->alarm); ktimespec = ktime_to_timespec(expires); diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 9e05c86ba5c4..932c0ae99bdc 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c @@ -118,6 +118,9 @@ static int xt_rateest_tg_checkentry(const struct xt_tgchk_param *par) } cfg; int ret; + if (strnlen(info->name, sizeof(est->name)) >= sizeof(est->name)) + return -ENAMETOOLONG; + net_get_random_once(&jhash_rnd, sizeof(jhash_rnd)); mutex_lock(&xn->hash_lock); diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index 0c2dc6def86d..676fad1b7682 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -279,9 +279,9 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg, if (cfg->size) { size = cfg->size; } else { - size = (totalram_pages << PAGE_SHIFT) / 16384 / + size = (totalram_pages() << PAGE_SHIFT) / 16384 / sizeof(struct hlist_head); - if (totalram_pages > 1024 * 1024 * 1024 / PAGE_SIZE) + if (totalram_pages() > 1024 * 1024 * 1024 / PAGE_SIZE) size = 8192; if (size < 16) size = 16; diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index 570144507df1..cb58bc7ae30d 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c @@ -155,7 +155,8 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e) /* * Drop entries with timestamps older then 'time'. */ -static void recent_entry_reap(struct recent_table *t, unsigned long time) +static void recent_entry_reap(struct recent_table *t, unsigned long time, + struct recent_entry *working, bool update) { struct recent_entry *e; @@ -164,6 +165,12 @@ static void recent_entry_reap(struct recent_table *t, unsigned long time) */ e = list_entry(t->lru_list.next, struct recent_entry, lru_list); + /* + * Do not reap the entry which are going to be updated. + */ + if (e == working && update) + return; + /* * The last time stamp is the most recent. */ @@ -306,7 +313,8 @@ recent_mt(const struct sk_buff *skb, struct xt_action_param *par) /* info->seconds must be non-zero */ if (info->check_set & XT_RECENT_REAP) - recent_entry_reap(t, time); + recent_entry_reap(t, time, e, + info->check_set & XT_RECENT_UPDATE && ret); } if (info->check_set & XT_RECENT_SET || diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 9aacf2da3d98..3e3494c8d42f 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c @@ -581,6 +581,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) break; } + cipso_v4_doi_putdef(doi_def); rcu_read_unlock(); genlmsg_end(ans_skb, data); @@ -589,12 +590,14 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) list_retry: /* XXX - this limit is a guesstimate */ if (nlsze_mult < 4) { + cipso_v4_doi_putdef(doi_def); rcu_read_unlock(); kfree_skb(ans_skb); nlsze_mult *= 2; goto list_start; } list_failure_lock: + cipso_v4_doi_putdef(doi_def); rcu_read_unlock(); list_failure: kfree_skb(ans_skb); diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index c92894c3e40a..0067f472367b 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1179,12 +1179,13 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, struct netlbl_unlhsh_walk_arg cb_arg; u32 skip_bkt = cb->args[0]; u32 skip_chain = cb->args[1]; - u32 iter_bkt; - u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; + u32 skip_addr4 = cb->args[2]; + u32 iter_bkt, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; struct netlbl_unlhsh_iface *iface; struct list_head *iter_list; struct netlbl_af4list *addr4; #if IS_ENABLED(CONFIG_IPV6) + u32 skip_addr6 = cb->args[3]; struct netlbl_af6list *addr6; #endif @@ -1195,7 +1196,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, rcu_read_lock(); for (iter_bkt = skip_bkt; iter_bkt < rcu_dereference(netlbl_unlhsh)->size; - iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { + iter_bkt++) { iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt]; list_for_each_entry_rcu(iface, iter_list, list) { if (!iface->valid || @@ -1203,7 +1204,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, continue; netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { - if (iter_addr4++ < cb->args[2]) + if (iter_addr4++ < skip_addr4) continue; if (netlbl_unlabel_staticlist_gen( NLBL_UNLABEL_C_STATICLIST, @@ -1216,10 +1217,12 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, goto unlabel_staticlist_return; } } + iter_addr4 = 0; + skip_addr4 = 0; #if IS_ENABLED(CONFIG_IPV6) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { - if (iter_addr6++ < cb->args[3]) + if (iter_addr6++ < skip_addr6) continue; if (netlbl_unlabel_staticlist_gen( NLBL_UNLABEL_C_STATICLIST, @@ -1232,8 +1235,12 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, goto unlabel_staticlist_return; } } + iter_addr6 = 0; + skip_addr6 = 0; #endif /* IPv6 */ } + iter_chain = 0; + skip_chain = 0; } unlabel_staticlist_return: diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 7d766350c08e..bc269e83e1e5 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -120,11 +120,13 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) llcp_sock->service_name_len, GFP_KERNEL); if (!llcp_sock->service_name) { + nfc_llcp_local_put(llcp_sock->local); ret = -ENOMEM; goto put_dev; } llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); kfree(llcp_sock->service_name); llcp_sock->service_name = NULL; ret = -EADDRINUSE; @@ -683,6 +685,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ret = -EISCONN; goto error; } + if (sk->sk_state == LLCP_CONNECTING) { + ret = -EINPROGRESS; + goto error; + } dev = nfc_get_device(addr->dev_idx); if (dev == NULL) { @@ -714,6 +720,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, llcp_sock->local = nfc_llcp_local_get(local); llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); ret = -ENOMEM; goto put_dev; } @@ -751,8 +758,11 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, sock_unlink: nfc_llcp_put_ssap(local, llcp_sock->ssap); + nfc_llcp_local_put(llcp_sock->local); nfc_llcp_sock_unlink(&local->connecting_sockets, sk); + kfree(llcp_sock->service_name); + llcp_sock->service_name = NULL; put_dev: nfc_put_device(dev); diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index 310872a9d660..4884e1987562 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c @@ -871,6 +871,7 @@ static int nfc_genl_stop_poll(struct sk_buff *skb, struct genl_info *info) if (!dev->polling) { device_unlock(&dev->dev); + nfc_put_device(dev); return -EINVAL; } diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index b927730d9ab0..57a07ab80d92 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -117,7 +117,7 @@ static int rawsock_connect(struct socket *sock, struct sockaddr *_addr, if (addr->target_idx > dev->target_next_idx - 1 || addr->target_idx < dev->target_next_idx - dev->n_targets) { rc = -EINVAL; - goto error; + goto put_dev; } rc = nfc_activate_target(dev, addr->target_idx, addr->nfc_protocol); diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index e8f5bb848ee9..3a6799bedf24 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -1612,8 +1612,10 @@ static int qrtr_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) plen = (len + 3) & ~3; skb = sock_alloc_send_skb(sk, plen + QRTR_HDR_MAX_SIZE, msg->msg_flags & MSG_DONTWAIT, &rc); - if (!skb) + if (!skb) { + rc = -ENOMEM; goto out_node; + } skb_reserve(skb, QRTR_HDR_MAX_SIZE); diff --git a/net/qrtr/tun.c b/net/qrtr/tun.c index e35869e81766..cb425e216d46 100644 --- a/net/qrtr/tun.c +++ b/net/qrtr/tun.c @@ -31,6 +31,7 @@ static int qrtr_tun_send(struct qrtr_endpoint *ep, struct sk_buff *skb) static int qrtr_tun_open(struct inode *inode, struct file *filp) { struct qrtr_tun *tun; + int ret; tun = kzalloc(sizeof(*tun), GFP_KERNEL); if (!tun) @@ -43,7 +44,16 @@ static int qrtr_tun_open(struct inode *inode, struct file *filp) filp->private_data = tun; - return qrtr_endpoint_register(&tun->ep, QRTR_EP_NID_AUTO); + ret = qrtr_endpoint_register(&tun->ep, QRTR_EP_NID_AUTO); + if (ret) + goto out; + + return 0; + +out: + filp->private_data = NULL; + kfree(tun); + return ret; } static ssize_t qrtr_tun_read_iter(struct kiocb *iocb, struct iov_iter *to) @@ -80,6 +90,12 @@ static ssize_t qrtr_tun_write_iter(struct kiocb *iocb, struct iov_iter *from) ssize_t ret; void *kbuf; + if (!len) + return -EINVAL; + + if (len > KMALLOC_MAX_SIZE) + return -ENOMEM; + kbuf = kzalloc(len, GFP_KERNEL); if (!kbuf) return -ENOMEM; diff --git a/net/rds/rdma.c b/net/rds/rdma.c index e1965d9cbcf8..9882cebfcad6 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -531,6 +531,9 @@ int rds_rdma_extra_size(struct rds_rdma_args *args, if (args->nr_local == 0) return -EINVAL; + if (args->nr_local > UIO_MAXIOV) + return -EMSGSIZE; + iov->iov = kcalloc(args->nr_local, sizeof(struct rds_iovec), GFP_KERNEL); diff --git a/net/rose/rose_loopback.c b/net/rose/rose_loopback.c index 094a6621f8e8..c318e5c9f6df 100644 --- a/net/rose/rose_loopback.c +++ b/net/rose/rose_loopback.c @@ -99,10 +99,19 @@ static void rose_loopback_timer(struct timer_list *unused) } if (frametype == ROSE_CALL_REQUEST) { - if ((dev = rose_dev_get(dest)) != NULL) { - if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) - kfree_skb(skb); - } else { + if (!rose_loopback_neigh->dev) { + kfree_skb(skb); + continue; + } + + dev = rose_dev_get(dest); + if (!dev) { + kfree_skb(skb); + continue; + } + + if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) { + dev_put(dev); kfree_skb(skb); } } else { diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 57f835d2442e..fb7e3fffcb5e 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -1010,7 +1010,7 @@ static int __init af_rxrpc_init(void) goto error_security; } - ret = register_pernet_subsys(&rxrpc_net_ops); + ret = register_pernet_device(&rxrpc_net_ops); if (ret) goto error_pernet; @@ -1055,7 +1055,7 @@ static int __init af_rxrpc_init(void) error_sock: proto_unregister(&rxrpc_proto); error_proto: - unregister_pernet_subsys(&rxrpc_net_ops); + unregister_pernet_device(&rxrpc_net_ops); error_pernet: rxrpc_exit_security(); error_security: @@ -1077,7 +1077,7 @@ static void __exit af_rxrpc_exit(void) unregister_key_type(&key_type_rxrpc); sock_unregister(PF_RXRPC); proto_unregister(&rxrpc_proto); - unregister_pernet_subsys(&rxrpc_net_ops); + unregister_pernet_device(&rxrpc_net_ops); ASSERTCMP(atomic_read(&rxrpc_n_tx_skbs), ==, 0); ASSERTCMP(atomic_read(&rxrpc_n_rx_skbs), ==, 0); diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 7778f0fb48cf..7ecfbff1f0d0 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c @@ -211,6 +211,7 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx) tail = b->peer_backlog_tail; while (CIRC_CNT(head, tail, size) > 0) { struct rxrpc_peer *peer = b->peer_backlog[tail]; + rxrpc_put_local(peer->local); kfree(peer); tail = (tail + 1) & (size - 1); } diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 58bd558a277a..40711f410828 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -446,7 +446,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb, if (state >= RXRPC_CALL_COMPLETE) return; - if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) { + if (state == RXRPC_CALL_SERVER_RECV_REQUEST) { unsigned long timo = READ_ONCE(call->next_req_timo); unsigned long now, expect_req_by; diff --git a/net/rxrpc/key.c b/net/rxrpc/key.c index 2fe2add62a8e..9be6b35fd9b2 100644 --- a/net/rxrpc/key.c +++ b/net/rxrpc/key.c @@ -1112,7 +1112,7 @@ static long rxrpc_read(const struct key *key, default: /* we have a ticket we can't encode */ pr_err("Unsupported key token type (%u)\n", token->security_index); - continue; + return -ENOPKG; } _debug("token[%u]: toksize=%u", ntoks, toksize); @@ -1227,7 +1227,9 @@ static long rxrpc_read(const struct key *key, break; default: - break; + pr_err("Unsupported key token type (%u)\n", + token->security_index); + return -ENOPKG; } ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==, diff --git a/net/sched/act_api.c b/net/sched/act_api.c index f2c4bfc79663..26710b297dcb 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -900,6 +900,9 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, return ERR_PTR(-EINVAL); } + if (!bind && ovr && err == ACT_P_CREATED) + refcount_set(&a->tcfa_refcnt, 2); + return a; err_mod: diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 0d7a0aac8dbb..e41bc5ecaa09 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -339,9 +339,13 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, if (tb[TCA_TCINDEX_MASK]) cp->mask = nla_get_u16(tb[TCA_TCINDEX_MASK]); - if (tb[TCA_TCINDEX_SHIFT]) + if (tb[TCA_TCINDEX_SHIFT]) { cp->shift = nla_get_u32(tb[TCA_TCINDEX_SHIFT]); - + if (cp->shift > 16) { + err = -EINVAL; + goto errout; + } + } if (!cp->hash) { /* Hash not specified, use perfect hash if the upper limit * of the hashing index is below the threshold. diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index 8af781054a52..6a2fc91f9dfa 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -398,7 +398,8 @@ struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r, { struct qdisc_rate_table *rtab; - if (tab == NULL || r->rate == 0 || r->cell_log == 0 || + if (tab == NULL || r->rate == 0 || + r->cell_log == 0 || r->cell_log >= 32 || nla_len(tab) != TC_RTAB_SIZE) { NL_SET_ERR_MSG(extack, "Invalid rate table parameters for searching"); return NULL; @@ -2081,7 +2082,7 @@ static int tc_dump_tclass_qdisc(struct Qdisc *q, struct sk_buff *skb, static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, struct tcmsg *tcm, struct netlink_callback *cb, - int *t_p, int s_t) + int *t_p, int s_t, bool recur) { struct Qdisc *q; int b; @@ -2092,7 +2093,7 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb, if (tc_dump_tclass_qdisc(root, skb, tcm, cb, t_p, s_t) < 0) return -1; - if (!qdisc_dev(root)) + if (!qdisc_dev(root) || !recur) return 0; if (tcm->tcm_parent) { @@ -2127,13 +2128,13 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb) s_t = cb->args[0]; t = 0; - if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t) < 0) + if (tc_dump_tclass_root(dev->qdisc, skb, tcm, cb, &t, s_t, true) < 0) goto done; dev_queue = dev_ingress_queue(dev); if (dev_queue && tc_dump_tclass_root(dev_queue->qdisc_sleeping, skb, tcm, cb, - &t, s_t) < 0) + &t, s_t, false) < 0) goto done; done: diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index 63bfceeb8e3c..8b72aed77ed4 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -355,6 +355,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt, struct sk_buff **old = NULL; unsigned int mask; u32 max_P; + u8 *stab; if (opt == NULL) return -EINVAL; @@ -370,8 +371,8 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt, max_P = tb[TCA_CHOKE_MAX_P] ? nla_get_u32(tb[TCA_CHOKE_MAX_P]) : 0; ctl = nla_data(tb[TCA_CHOKE_PARMS]); - - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) + stab = nla_data(tb[TCA_CHOKE_STAB]); + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log, stab)) return -EINVAL; if (ctl->limit > CHOKE_MAX_QUEUE) @@ -421,7 +422,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt, red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, - nla_data(tb[TCA_CHOKE_STAB]), + stab, max_P); red_set_vars(&q->vars); diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 4a042abf844c..db7a91a29b59 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -357,7 +357,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp, struct gred_sched *table = qdisc_priv(sch); struct gred_sched_data *q = table->tab[dp]; - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Scell_log, stab)) return -EINVAL; if (!q) { diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 56c181c3feeb..e42f890fa147 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -199,6 +199,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt, struct Qdisc *child = NULL; int err; u32 max_P; + u8 *stab; if (opt == NULL) return -EINVAL; @@ -214,7 +215,9 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt, max_P = tb[TCA_RED_MAX_P] ? nla_get_u32(tb[TCA_RED_MAX_P]) : 0; ctl = nla_data(tb[TCA_RED_PARMS]); - if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog)) + stab = nla_data(tb[TCA_RED_STAB]); + if (!red_check_params(ctl->qth_min, ctl->qth_max, ctl->Wlog, + ctl->Scell_log, stab)) return -EINVAL; if (ctl->limit > 0) { @@ -240,7 +243,7 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt, red_set_parms(&q->parms, ctl->qth_min, ctl->qth_max, ctl->Wlog, ctl->Plog, ctl->Scell_log, - nla_data(tb[TCA_RED_STAB]), + stab, max_P); red_set_vars(&q->vars); diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index b89cf0971d3d..1bfdf90fa0cc 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -651,7 +651,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt) } if (ctl_v1 && !red_check_params(ctl_v1->qth_min, ctl_v1->qth_max, - ctl_v1->Wlog)) + ctl_v1->Wlog, ctl_v1->Scell_log, NULL)) return -EINVAL; if (ctl_v1 && ctl_v1->qth_min) { p = kmalloc(sizeof(*p), GFP_KERNEL); diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 7ed53124069c..163364124691 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -138,6 +138,9 @@ teql_destroy(struct Qdisc *sch) struct teql_sched_data *dat = qdisc_priv(sch); struct teql_master *master = dat->m; + if (!master) + return; + prev = master->slaves; if (prev) { do { diff --git a/net/sctp/input.c b/net/sctp/input.c index f64d882c8698..3dd900e42b85 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -461,7 +461,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, else { if (!mod_timer(&t->proto_unreach_timer, jiffies + (HZ/20))) - sctp_association_hold(asoc); + sctp_transport_hold(t); } } else { struct net *net = sock_net(sk); @@ -470,7 +470,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, "encountered!\n", __func__); if (del_timer(&t->proto_unreach_timer)) - sctp_association_put(asoc); + sctp_transport_put(t); sctp_do_sm(net, SCTP_EVENT_T_OTHER, SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 736d8ca9821b..4cc573924493 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -655,8 +655,8 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) if (!(type & IPV6_ADDR_UNICAST)) return 0; - return sp->inet.freebind || net->ipv6.sysctl.ip_nonlocal_bind || - ipv6_chk_addr(net, in6, NULL, 0); + return ipv6_can_nonlocal_bind(net, &sp->inet) || + ipv6_chk_addr(net, in6, NULL, 0); } /* This function checks if the address is a valid address to be used for @@ -945,8 +945,7 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) net = sock_net(&opt->inet.sk); rcu_read_lock(); dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); - if (!dev || !(opt->inet.freebind || - net->ipv6.sysctl.ip_nonlocal_bind || + if (!dev || !(ipv6_can_nonlocal_bind(net, &opt->inet) || ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0))) { rcu_read_unlock(); diff --git a/net/sctp/proc.c b/net/sctp/proc.c index a644292f9faf..84f79ac4b984 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c @@ -230,6 +230,12 @@ static void sctp_transport_seq_stop(struct seq_file *seq, void *v) { struct sctp_ht_iter *iter = seq->private; + if (v && v != SEQ_START_TOKEN) { + struct sctp_transport *transport = v; + + sctp_transport_put(transport); + } + sctp_transport_walk_stop(&iter->hti); } @@ -237,6 +243,12 @@ static void *sctp_transport_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sctp_ht_iter *iter = seq->private; + if (v && v != SEQ_START_TOKEN) { + struct sctp_transport *transport = v; + + sctp_transport_put(transport); + } + ++*pos; return sctp_transport_get_next(seq_file_net(seq), &iter->hti); @@ -292,8 +304,6 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) sk->sk_rcvbuf); seq_printf(seq, "\n"); - sctp_transport_put(transport); - return 0; } @@ -369,8 +379,6 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "\n"); } - sctp_transport_put(transport); - return 0; } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index af054f38341b..de42580afc81 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -1442,10 +1442,10 @@ static __init int sctp_init(void) * The methodology is similar to that of the tcp hash tables. * Though not identical. Start by getting a goal size */ - if (totalram_pages >= (128 * 1024)) - goal = totalram_pages >> (22 - PAGE_SHIFT); + if (totalram_pages() >= (128 * 1024)) + goal = totalram_pages() >> (22 - PAGE_SHIFT); else - goal = totalram_pages >> (24 - PAGE_SHIFT); + goal = totalram_pages() >> (24 - PAGE_SHIFT); /* Then compute the page order for said goal */ order = get_order(goal); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index bb4f1d0da153..2a94240eac36 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -434,7 +434,7 @@ void sctp_generate_proto_unreach_event(struct timer_list *t) /* Try again later. */ if (!mod_timer(&transport->proto_unreach_timer, jiffies + (HZ/20))) - sctp_association_hold(asoc); + sctp_transport_hold(transport); goto out_unlock; } @@ -450,7 +450,7 @@ void sctp_generate_proto_unreach_event(struct timer_list *t) out_unlock: bh_unlock_sock(sk); - sctp_association_put(asoc); + sctp_transport_put(transport); } /* Handle the timeout of the RE-CONFIG timer. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4a2873f70b37..656bd1532883 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1569,11 +1569,9 @@ static void sctp_close(struct sock *sk, long timeout) /* Supposedly, no process has access to the socket, but * the net layers still may. - * Also, sctp_destroy_sock() needs to be called with addr_wq_lock - * held and that should be grabbed before socket lock. */ - spin_lock_bh(&net->sctp.addr_wq_lock); - bh_lock_sock_nested(sk); + local_bh_disable(); + bh_lock_sock(sk); /* Hold the sock, since sk_common_release() will put sock_put() * and we have just a little more cleanup. @@ -1582,7 +1580,7 @@ static void sctp_close(struct sock *sk, long timeout) sk_common_release(sk); bh_unlock_sock(sk); - spin_unlock_bh(&net->sctp.addr_wq_lock); + local_bh_enable(); sock_put(sk); @@ -4776,9 +4774,6 @@ static int sctp_init_sock(struct sock *sk) sk_sockets_allocated_inc(sk); sock_prot_inuse_add(net, sk->sk_prot, 1); - /* Nothing can fail after this block, otherwise - * sctp_destroy_sock() will be called without addr_wq_lock held - */ if (net->sctp.default_auto_asconf) { spin_lock(&sock_net(sk)->sctp.addr_wq_lock); list_add_tail(&sp->auto_asconf_list, @@ -4813,7 +4808,9 @@ static void sctp_destroy_sock(struct sock *sk) if (sp->do_auto_asconf) { sp->do_auto_asconf = 0; + spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock); list_del(&sp->auto_asconf_list); + spin_unlock_bh(&sock_net(sk)->sctp.addr_wq_lock); } sctp_endpoint_free(sp->ep); local_bh_disable(); diff --git a/net/sctp/transport.c b/net/sctp/transport.c index c0d55ed62d2e..78302e547b2b 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -148,7 +148,7 @@ void sctp_transport_free(struct sctp_transport *transport) /* Delete the ICMP proto unreachable timer if it's active. */ if (del_timer(&transport->proto_unreach_timer)) - sctp_association_put(transport->asoc); + sctp_transport_put(transport); sctp_transport_put(transport); } diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index 8391c2785550..7404f02702a1 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c @@ -184,7 +184,7 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, scope_id = dev->ifindex; dev_put(dev); } else { - if (kstrtou32(p, 10, &scope_id) == 0) { + if (kstrtou32(p, 10, &scope_id) != 0) { kfree(p); return 0; } diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8cb7d812ccb8..e61c48c1b37d 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -53,6 +53,7 @@ #include #include +#include "auth_gss_internal.h" #include "../netns.h" static const struct rpc_authops authgss_ops; @@ -147,35 +148,6 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) clear_bit(RPCAUTH_CRED_NEW, &cred->cr_flags); } -static const void * -simple_get_bytes(const void *p, const void *end, void *res, size_t len) -{ - const void *q = (const void *)((const char *)p + len); - if (unlikely(q > end || q < p)) - return ERR_PTR(-EFAULT); - memcpy(res, p, len); - return q; -} - -static inline const void * -simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest) -{ - const void *q; - unsigned int len; - - p = simple_get_bytes(p, end, &len, sizeof(len)); - if (IS_ERR(p)) - return p; - q = (const void *)((const char *)p + len); - if (unlikely(q > end || q < p)) - return ERR_PTR(-EFAULT); - dest->data = kmemdup(p, len, GFP_NOFS); - if (unlikely(dest->data == NULL)) - return ERR_PTR(-ENOMEM); - dest->len = len; - return q; -} - static struct gss_cl_ctx * gss_cred_get_ctx(struct rpc_cred *cred) { diff --git a/net/sunrpc/auth_gss/auth_gss_internal.h b/net/sunrpc/auth_gss/auth_gss_internal.h new file mode 100644 index 000000000000..f6d9631bd9d0 --- /dev/null +++ b/net/sunrpc/auth_gss/auth_gss_internal.h @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * linux/net/sunrpc/auth_gss/auth_gss_internal.h + * + * Internal definitions for RPCSEC_GSS client authentication + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + */ +#include +#include +#include + +static inline const void * +simple_get_bytes(const void *p, const void *end, void *res, size_t len) +{ + const void *q = (const void *)((const char *)p + len); + if (unlikely(q > end || q < p)) + return ERR_PTR(-EFAULT); + memcpy(res, p, len); + return q; +} + +static inline const void * +simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest) +{ + const void *q; + unsigned int len; + + p = simple_get_bytes(p, end, &len, sizeof(len)); + if (IS_ERR(p)) + return p; + q = (const void *)((const char *)p + len); + if (unlikely(q > end || q < p)) + return ERR_PTR(-EFAULT); + if (len) { + dest->data = kmemdup(p, len, GFP_NOFS); + if (unlikely(dest->data == NULL)) + return ERR_PTR(-ENOMEM); + } else + dest->data = NULL; + dest->len = len; + return q; +} diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 7f0424dfa8f6..4e0255b74da5 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -46,6 +46,8 @@ #include #include +#include "auth_gss_internal.h" + #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) # define RPCDBG_FACILITY RPCDBG_AUTH #endif @@ -187,35 +189,6 @@ get_gss_krb5_enctype(int etype) return NULL; } -static const void * -simple_get_bytes(const void *p, const void *end, void *res, int len) -{ - const void *q = (const void *)((const char *)p + len); - if (unlikely(q > end || q < p)) - return ERR_PTR(-EFAULT); - memcpy(res, p, len); - return q; -} - -static const void * -simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) -{ - const void *q; - unsigned int len; - - p = simple_get_bytes(p, end, &len, sizeof(len)); - if (IS_ERR(p)) - return p; - q = (const void *)((const char *)p + len); - if (unlikely(q > end || q < p)) - return ERR_PTR(-EFAULT); - res->data = kmemdup(p, len, GFP_NOFS); - if (unlikely(res->data == NULL)) - return ERR_PTR(-ENOMEM); - res->len = len; - return q; -} - static inline const void * get_key(const void *p, const void *end, struct krb5_ctx *ctx, struct crypto_sync_skcipher **res) diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index ab086081be9c..a85d78d2bdb7 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -1766,11 +1766,14 @@ static int svcauth_gss_release(struct svc_rqst *rqstp) { struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data; - struct rpc_gss_wire_cred *gc = &gsd->clcred; + struct rpc_gss_wire_cred *gc; struct xdr_buf *resbuf = &rqstp->rq_res; int stat = -EINVAL; struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id); + if (!gsd) + goto out; + gc = &gsd->clcred; if (gc->gc_proc != RPC_GSS_PROC_DATA) goto out; /* Release can be called twice, but we only wrap once. */ @@ -1811,10 +1814,10 @@ svcauth_gss_release(struct svc_rqst *rqstp) if (rqstp->rq_cred.cr_group_info) put_group_info(rqstp->rq_cred.cr_group_info); rqstp->rq_cred.cr_group_info = NULL; - if (gsd->rsci) + if (gsd && gsd->rsci) { cache_put(&gsd->rsci->h, sn->rsc_cache); - gsd->rsci = NULL; - + gsd->rsci = NULL; + } return stat; } diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index d65f8d35de87..11d393c04772 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1330,7 +1330,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) sendit: if (svc_authorise(rqstp)) - goto close; + goto close_xprt; return 1; /* Caller can now send it */ dropit: @@ -1339,6 +1339,8 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) return 0; close: + svc_authorise(rqstp); +close_xprt: if (rqstp->rq_xprt && test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags)) svc_close_xprt(rqstp->rq_xprt); dprintk("svc: svc_process close\n"); @@ -1347,7 +1349,7 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) err_short_len: svc_printk(rqstp, "short len %zd, dropping request\n", argv->iov_len); - goto close; + goto close_xprt; err_bad_rpc: serv->sv_stats->rpcbadfmt++; diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 709c082dc905..4b56b949a463 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -1052,7 +1052,7 @@ static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, st struct svc_xprt *xprt; int ret = 0; - spin_lock(&serv->sv_lock); + spin_lock_bh(&serv->sv_lock); list_for_each_entry(xprt, xprt_list, xpt_list) { if (xprt->xpt_net != net) continue; @@ -1060,7 +1060,7 @@ static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, st set_bit(XPT_CLOSE, &xprt->xpt_flags); svc_xprt_enqueue(xprt); } - spin_unlock(&serv->sv_lock); + spin_unlock_bh(&serv->sv_lock); return ret; } diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 5e7c13aa66d0..9c4235ce5789 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -143,31 +143,64 @@ int xprt_unregister_transport(struct xprt_class *transport) } EXPORT_SYMBOL_GPL(xprt_unregister_transport); +static void +xprt_class_release(const struct xprt_class *t) +{ + module_put(t->owner); +} + +static const struct xprt_class * +xprt_class_find_by_netid_locked(const char *netid) +{ + const struct xprt_class *t; + unsigned int i; + + list_for_each_entry(t, &xprt_list, list) { + for (i = 0; t->netid[i][0] != '\0'; i++) { + if (strcmp(t->netid[i], netid) != 0) + continue; + if (!try_module_get(t->owner)) + continue; + return t; + } + } + return NULL; +} + +static const struct xprt_class * +xprt_class_find_by_netid(const char *netid) +{ + const struct xprt_class *t; + + spin_lock(&xprt_list_lock); + t = xprt_class_find_by_netid_locked(netid); + if (!t) { + spin_unlock(&xprt_list_lock); + request_module("rpc%s", netid); + spin_lock(&xprt_list_lock); + t = xprt_class_find_by_netid_locked(netid); + } + spin_unlock(&xprt_list_lock); + return t; +} + /** * xprt_load_transport - load a transport implementation - * @transport_name: transport to load + * @netid: transport to load * * Returns: * 0: transport successfully loaded * -ENOENT: transport module not available */ -int xprt_load_transport(const char *transport_name) +int xprt_load_transport(const char *netid) { - struct xprt_class *t; - int result; + const struct xprt_class *t; - result = 0; - spin_lock(&xprt_list_lock); - list_for_each_entry(t, &xprt_list, list) { - if (strcmp(t->name, transport_name) == 0) { - spin_unlock(&xprt_list_lock); - goto out; - } - } - spin_unlock(&xprt_list_lock); - result = request_module("xprt%s", transport_name); -out: - return result; + t = xprt_class_find_by_netid(netid); + if (!t) + return -ENOENT; + xprt_class_release(t); + return 0; } EXPORT_SYMBOL_GPL(xprt_load_transport); diff --git a/net/sunrpc/xprtrdma/module.c b/net/sunrpc/xprtrdma/module.c index 620327c01302..45c5b41ac8dc 100644 --- a/net/sunrpc/xprtrdma/module.c +++ b/net/sunrpc/xprtrdma/module.c @@ -24,6 +24,7 @@ MODULE_DESCRIPTION("RPC/RDMA Transport"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS("svcrdma"); MODULE_ALIAS("xprtrdma"); +MODULE_ALIAS("rpcrdma6"); static void __exit rpc_rdma_cleanup(void) { diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index d183d4aee822..cf2272a90f13 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c @@ -308,9 +308,9 @@ xprt_setup_rdma_bc(struct xprt_create *args) xprt->timeout = &xprt_rdma_bc_timeout; xprt_set_bound(xprt); xprt_set_connected(xprt); - xprt->bind_timeout = RPCRDMA_BIND_TO; - xprt->reestablish_timeout = RPCRDMA_INIT_REEST_TO; - xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO; + xprt->bind_timeout = 0; + xprt->reestablish_timeout = 0; + xprt->idle_timeout = 0; xprt->prot = XPRT_TRANSPORT_BC_RDMA; xprt->tsh_size = 0; diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index f56f36b4d742..fdd14908eacb 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -854,6 +854,7 @@ static struct xprt_class xprt_rdma = { .owner = THIS_MODULE, .ident = XPRT_TRANSPORT_RDMA, .setup = xprt_setup_rdma, + .netid = { "rdma", "rdma6", "" }, }; void xprt_rdma_cleanup(void) diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 9dc059dea689..798fbd89ed42 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -3241,6 +3241,7 @@ static struct xprt_class xs_local_transport = { .owner = THIS_MODULE, .ident = XPRT_TRANSPORT_LOCAL, .setup = xs_setup_local, + .netid = { "" }, }; static struct xprt_class xs_udp_transport = { @@ -3249,6 +3250,7 @@ static struct xprt_class xs_udp_transport = { .owner = THIS_MODULE, .ident = XPRT_TRANSPORT_UDP, .setup = xs_setup_udp, + .netid = { "udp", "udp6", "" }, }; static struct xprt_class xs_tcp_transport = { @@ -3257,6 +3259,7 @@ static struct xprt_class xs_tcp_transport = { .owner = THIS_MODULE, .ident = XPRT_TRANSPORT_TCP, .setup = xs_setup_tcp, + .netid = { "tcp", "tcp6", "" }, }; static struct xprt_class xs_bc_tcp_transport = { @@ -3265,6 +3268,7 @@ static struct xprt_class xs_bc_tcp_transport = { .owner = THIS_MODULE, .ident = XPRT_TRANSPORT_BC_TCP, .setup = xs_setup_bc_tcp, + .netid = { "" }, }; /** diff --git a/net/tipc/link.c b/net/tipc/link.c index f756b721f93e..bd28ac7f2195 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -914,9 +914,7 @@ void tipc_link_reset(struct tipc_link *l) int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, struct sk_buff_head *xmitq) { - struct tipc_msg *hdr = buf_msg(skb_peek(list)); unsigned int maxwin = l->window; - int imp = msg_importance(hdr); unsigned int mtu = l->mtu; u16 ack = l->rcv_nxt - 1; u16 seqno = l->snd_nxt; @@ -925,13 +923,20 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list, struct sk_buff_head *backlogq = &l->backlogq; struct sk_buff *skb, *_skb, **tskb; int pkt_cnt = skb_queue_len(list); + struct tipc_msg *hdr; int rc = 0; + int imp; + + if (pkt_cnt <= 0) + return 0; + hdr = buf_msg(skb_peek(list)); if (unlikely(msg_size(hdr) > mtu)) { __skb_queue_purge(list); return -EMSGSIZE; } + imp = msg_importance(hdr); /* Allow oversubscription of one data msg per source at congestion */ if (unlikely(l->backlog[imp].len >= l->backlog[imp].limit)) { if (imp == TIPC_SYSTEM_IMPORTANCE) { diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 16e2af3a00cc..4c35f9893081 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1187,7 +1187,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, spin_lock_bh(&inputq->lock); if (skb_peek(arrvq) == skb) { skb_queue_splice_tail_init(&tmpq, inputq); - kfree_skb(__skb_dequeue(arrvq)); + __skb_dequeue(arrvq); } spin_unlock_bh(&inputq->lock); __skb_queue_purge(&tmpq); diff --git a/net/tipc/topsrv.c b/net/tipc/topsrv.c index ec9a7137d267..1c4733153d74 100644 --- a/net/tipc/topsrv.c +++ b/net/tipc/topsrv.c @@ -671,12 +671,18 @@ static int tipc_topsrv_start(struct net *net) ret = tipc_topsrv_work_start(srv); if (ret < 0) - return ret; + goto err_start; ret = tipc_topsrv_create_listener(srv); if (ret < 0) - tipc_topsrv_work_stop(srv); + goto err_create; + return 0; + +err_create: + tipc_topsrv_work_stop(srv); +err_start: + kfree(srv); return ret; } diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index dd0fc2aa6875..228e3ce48d43 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c @@ -955,6 +955,8 @@ void tls_device_offload_cleanup_rx(struct sock *sk) if (tls_ctx->tx_conf != TLS_HW) { dev_put(netdev); tls_ctx->netdev = NULL; + } else { + set_bit(TLS_RX_DEV_CLOSED, &tls_ctx->flags); } out: up_read(&device_offload_lock); @@ -984,7 +986,8 @@ static int tls_device_down(struct net_device *netdev) if (ctx->tx_conf == TLS_HW) netdev->tlsdev_ops->tls_dev_del(netdev, ctx, TLS_OFFLOAD_CTX_DIR_TX); - if (ctx->rx_conf == TLS_HW) + if (ctx->rx_conf == TLS_HW && + !test_bit(TLS_RX_DEV_CLOSED, &ctx->flags)) netdev->tlsdev_ops->tls_dev_del(netdev, ctx, TLS_OFFLOAD_CTX_DIR_RX); WRITE_ONCE(ctx->netdev, NULL); diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index bbb2da70e870..7d761244a360 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -630,6 +630,12 @@ static struct sk_buff *tls_wait_data(struct sock *sk, int flags, return NULL; } + if (!skb_queue_empty(&sk->sk_receive_queue)) { + __strp_unpause(&ctx->strp); + if (ctx->recv_pkt) + return ctx->recv_pkt; + } + if (sk->sk_shutdown & RCV_SHUTDOWN) return NULL; diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 02374459c417..aceafec612a8 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -628,6 +628,7 @@ struct sock *__vsock_create(struct net *net, vsk->trusted = psk->trusted; vsk->owner = get_cred(psk->owner); vsk->connect_timeout = psk->connect_timeout; + security_sk_clone(parent, sk); } else { vsk->trusted = ns_capable_noaudit(&init_user_ns, CAP_NET_ADMIN); vsk->owner = get_current_cred(); @@ -816,10 +817,12 @@ static int vsock_shutdown(struct socket *sock, int mode) */ sk = sock->sk; + + lock_sock(sk); if (sock->state == SS_UNCONNECTED) { err = -ENOTCONN; if (sk->sk_type == SOCK_STREAM) - return err; + goto out; } else { sock->state = SS_DISCONNECTING; err = 0; @@ -828,10 +831,8 @@ static int vsock_shutdown(struct socket *sock, int mode) /* Receive and send shutdowns are treated alike. */ mode = mode & (RCV_SHUTDOWN | SEND_SHUTDOWN); if (mode) { - lock_sock(sk); sk->sk_shutdown |= mode; sk->sk_state_change(sk); - release_sock(sk); if (sk->sk_type == SOCK_STREAM) { sock_reset_flag(sk, SOCK_DONE); @@ -839,6 +840,8 @@ static int vsock_shutdown(struct socket *sock, int mode) } } +out: + release_sock(sk); return err; } @@ -1107,7 +1110,6 @@ static void vsock_connect_timeout(struct work_struct *work) { struct sock *sk; struct vsock_sock *vsk; - int cancel = 0; vsk = container_of(work, struct vsock_sock, connect_work.work); sk = sk_vsock(vsk); @@ -1118,11 +1120,9 @@ static void vsock_connect_timeout(struct work_struct *work) sk->sk_state = TCP_CLOSE; sk->sk_err = ETIMEDOUT; sk->sk_error_report(sk); - cancel = 1; + vsock_transport_cancel_pkt(vsk); } release_sock(sk); - if (cancel) - vsock_transport_cancel_pkt(vsk); sock_put(sk); } diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c index db6ca51228d2..2bdf36845a5f 100644 --- a/net/vmw_vsock/hyperv_transport.c +++ b/net/vmw_vsock/hyperv_transport.c @@ -443,14 +443,10 @@ static void hvs_shutdown_lock_held(struct hvsock *hvs, int mode) static int hvs_shutdown(struct vsock_sock *vsk, int mode) { - struct sock *sk = sk_vsock(vsk); - if (!(mode & SEND_SHUTDOWN)) return 0; - lock_sock(sk); hvs_shutdown_lock_held(vsk->trans, mode); - release_sock(sk); return 0; } diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 5f8a72d34d31..cbb336f01cf2 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -1033,10 +1033,10 @@ void virtio_transport_recv_pkt(struct virtio_transport *t, vsk = vsock_sk(sk); - space_available = virtio_transport_space_update(sk, pkt); - lock_sock(sk); + space_available = virtio_transport_space_update(sk, pkt); + /* Update CID in case it has changed after a transport reset event */ vsk->local_addr.svm_cid = dst.svm_cid; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2949944eca3c..79ccf1ff0222 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -11665,7 +11665,7 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info) struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; struct nlattr *tb[NUM_NL80211_REKEY_DATA]; - struct cfg80211_gtk_rekey_data rekey_data; + struct cfg80211_gtk_rekey_data rekey_data = {}; int err; if (!info->attrs[NL80211_ATTR_REKEY_DATA]) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 54eec91a5d2c..e279c49ddd5e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -3424,7 +3424,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) power_rule = ®_rule->power_rule; if (reg_rule->flags & NL80211_RRF_AUTO_BW) - snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO", + snprintf(bw, sizeof(bw), "%d KHz, %u KHz AUTO", freq_range->max_bandwidth_khz, reg_get_max_bandwidth(rd, reg_rule)); else diff --git a/net/wireless/sme.c b/net/wireless/sme.c index ae52143d6dca..d5d9d7612cb5 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -530,7 +530,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, cfg80211_sme_free(wdev); } - if (WARN_ON(wdev->conn)) + if (wdev->conn) return -EINPROGRESS; wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); diff --git a/net/wireless/util.c b/net/wireless/util.c index 1e92c8a783be..96e06c574130 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -117,11 +117,13 @@ int ieee80211_freq_khz_to_channel(u32 freq) return (freq - 2407) / 5; else if (freq >= 4910 && freq <= 4980) return (freq - 4000) / 5; - else if (freq < 5940) + else if (freq < 5925) return (freq - 5000) / 5; + else if (freq == 5935) + return 2; else if (freq <= 45000) /* DMG band lower limit */ - /* see 802.11ax D4.1 27.3.22.2 */ - return (freq - 5940) / 5; + /* see 802.11ax D6.1 27.3.23.2 */ + return (freq - 5950) / 5; else if (freq >= 58320 && freq <= 70200) return (freq - 56160) / 2160; else diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c index 69102fda9ebd..76a80a41615b 100644 --- a/net/wireless/wext-core.c +++ b/net/wireless/wext-core.c @@ -896,8 +896,9 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd, int call_commit_handler(struct net_device *dev) { #ifdef CONFIG_WIRELESS_EXT - if ((netif_running(dev)) && - (dev->wireless_handlers->standard[0] != NULL)) + if (netif_running(dev) && + dev->wireless_handlers && + dev->wireless_handlers->standard[0]) /* Call the commit handler on the driver */ return dev->wireless_handlers->standard[0](dev, NULL, NULL, NULL); diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index bd1cbbfe5924..f43d037ea852 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -680,7 +680,8 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) int len, i, rc = 0; if (addr_len != sizeof(struct sockaddr_x25) || - addr->sx25_family != AF_X25) { + addr->sx25_family != AF_X25 || + strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN) { rc = -EINVAL; goto out; } @@ -774,7 +775,8 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, rc = -EINVAL; if (addr_len != sizeof(struct sockaddr_x25) || - addr->sx25_family != AF_X25) + addr->sx25_family != AF_X25 || + strnlen(addr->sx25_addr.x25_addr, X25_ADDR_LEN) == X25_ADDR_LEN) goto out; rc = -ENETUNREACH; @@ -824,7 +826,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, sock->state = SS_CONNECTED; rc = 0; out_put_neigh: - if (rc) { + if (rc && x25->neighbour) { read_lock_bh(&x25_list_lock); x25_neigh_put(x25->neighbour); x25->neighbour = NULL; @@ -1049,6 +1051,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, makex25->lci = lci; makex25->dest_addr = dest_addr; makex25->source_addr = source_addr; + x25_neigh_hold(nb); makex25->neighbour = nb; makex25->facilities = facilities; makex25->dte_facilities= dte_facilities; diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 9ff2ab63e639..6bb0649c028c 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -289,17 +289,17 @@ static int xsk_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len) return (xs->zc) ? xsk_zc_xmit(sk) : xsk_generic_xmit(sk, m, total_len); } -static unsigned int xsk_poll(struct file *file, struct socket *sock, +static __poll_t xsk_poll(struct file *file, struct socket *sock, struct poll_table_struct *wait) { - unsigned int mask = datagram_poll(file, sock, wait); + __poll_t mask = datagram_poll(file, sock, wait); struct sock *sk = sock->sk; struct xdp_sock *xs = xdp_sk(sk); if (xs->rx && !xskq_empty_desc(xs->rx)) - mask |= POLLIN | POLLRDNORM; + mask |= EPOLLIN | EPOLLRDNORM; if (xs->tx && !xskq_full_desc(xs->tx)) - mask |= POLLOUT | POLLWRNORM; + mask |= EPOLLOUT | EPOLLWRNORM; return mask; } diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 0ee13d12782f..fcba8a139f61 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -420,7 +420,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) /* only the first xfrm gets the encap type */ encap_type = 0; - if (async && x->repl->recheck(x, skb, seq)) { + if (x->repl->recheck(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c index 6cc9f6e2dd2b..35a020a70985 100644 --- a/net/xfrm/xfrm_interface.c +++ b/net/xfrm/xfrm_interface.c @@ -300,16 +300,19 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) if (mtu < IPV6_MIN_MTU) mtu = IPV6_MIN_MTU; - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); } else { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); + if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) + goto xmit; + icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); } dst_release(dst); return -EMSGSIZE; } +xmit: xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev))); skb_dst_set(skb, dst); skb->dev = tdev; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 939f3adf075a..e9aea82f370d 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2101,8 +2101,8 @@ struct dst_entry *xfrm_lookup_with_ifid(struct net *net, xflo.flags = flags; /* To accelerate a bit... */ - if ((dst_orig->flags & DST_NOXFRM) || - !net->xfrm.policy_count[XFRM_POLICY_OUT]) + if (!if_id && ((dst_orig->flags & DST_NOXFRM) || + !net->xfrm.policy_count[XFRM_POLICY_OUT])) goto nopol; xdst = xfrm_bundle_lookup(net, fl, family, dir, &xflo, if_id); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index c42df9dcad6e..a41f7c6ed9e1 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -41,7 +41,6 @@ static void xfrm_state_gc_task(struct work_struct *work); */ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; -static __read_mostly seqcount_t xfrm_state_hash_generation = SEQCNT_ZERO(xfrm_state_hash_generation); static struct kmem_cache *xfrm_state_cache __ro_after_init; static DECLARE_WORK(xfrm_state_gc_work, xfrm_state_gc_task); @@ -137,7 +136,7 @@ static void xfrm_hash_resize(struct work_struct *work) } spin_lock_bh(&net->xfrm.xfrm_state_lock); - write_seqcount_begin(&xfrm_state_hash_generation); + write_seqcount_begin(&net->xfrm.xfrm_state_hash_generation); nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; odst = xfrm_state_deref_prot(net->xfrm.state_bydst, net); @@ -153,7 +152,7 @@ static void xfrm_hash_resize(struct work_struct *work) rcu_assign_pointer(net->xfrm.state_byspi, nspi); net->xfrm.state_hmask = nhashmask; - write_seqcount_end(&xfrm_state_hash_generation); + write_seqcount_end(&net->xfrm.xfrm_state_hash_generation); spin_unlock_bh(&net->xfrm.xfrm_state_lock); osize = (ohashmask + 1) * sizeof(struct hlist_head); @@ -965,7 +964,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, to_put = NULL; - sequence = read_seqcount_begin(&xfrm_state_hash_generation); + sequence = read_seqcount_begin(&net->xfrm.xfrm_state_hash_generation); rcu_read_lock(); h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); @@ -1076,7 +1075,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, if (to_put) xfrm_state_put(to_put); - if (read_seqcount_retry(&xfrm_state_hash_generation, sequence)) { + if (read_seqcount_retry(&net->xfrm.xfrm_state_hash_generation, sequence)) { *err = -EAGAIN; if (x) { xfrm_state_put(x); @@ -1825,6 +1824,7 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) int err = -ENOENT; __be32 minspi = htonl(low); __be32 maxspi = htonl(high); + __be32 newspi = 0; u32 mark = x->mark.v & x->mark.m; spin_lock_bh(&x->lock); @@ -1843,21 +1843,22 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) xfrm_state_put(x0); goto unlock; } - x->id.spi = minspi; + newspi = minspi; } else { u32 spi = 0; for (h = 0; h < high-low+1; h++) { spi = low + prandom_u32()%(high-low+1); x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); if (x0 == NULL) { - x->id.spi = htonl(spi); + newspi = htonl(spi); break; } xfrm_state_put(x0); } } - if (x->id.spi) { + if (newspi) { spin_lock_bh(&net->xfrm.xfrm_state_lock); + x->id.spi = newspi; h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); hlist_add_head_rcu(&x->byspi, net->xfrm.state_byspi + h); spin_unlock_bh(&net->xfrm.xfrm_state_lock); @@ -2476,6 +2477,7 @@ int __net_init xfrm_state_init(struct net *net) net->xfrm.state_num = 0; INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); spin_lock_init(&net->xfrm.xfrm_state_lock); + seqcount_init(&net->xfrm.xfrm_state_hash_generation); return 0; out_byspi: diff --git a/samples/bpf/lwt_len_hist.sh b/samples/bpf/lwt_len_hist.sh old mode 100644 new mode 100755 index 090b96eaf7f7..0eda9754f50b --- a/samples/bpf/lwt_len_hist.sh +++ b/samples/bpf/lwt_len_hist.sh @@ -8,6 +8,8 @@ VETH1=tst_lwt1b TRACE_ROOT=/sys/kernel/debug/tracing function cleanup { + # To reset saved histogram, remove pinned map + rm /sys/fs/bpf/tc/globals/lwt_len_hist_map ip route del 192.168.253.2/32 dev $VETH0 2> /dev/null ip link del $VETH0 2> /dev/null ip link del $VETH1 2> /dev/null diff --git a/samples/bpf/test_lwt_bpf.sh b/samples/bpf/test_lwt_bpf.sh old mode 100644 new mode 100755 diff --git a/scripts/Makefile b/scripts/Makefile index b3447edcb718..51403cac79b7 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -10,6 +10,9 @@ HOST_EXTRACFLAGS += -I$(srctree)/tools/include +CRYPTO_LIBS = $(shell pkg-config --libs libcrypto 2> /dev/null || echo -lcrypto) +CRYPTO_CFLAGS = $(shell pkg-config --cflags libcrypto 2> /dev/null) + hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c hostprogs-$(CONFIG_KALLSYMS) += kallsyms hostprogs-$(CONFIG_LOGO) += pnmtologo @@ -23,8 +26,10 @@ hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include -HOSTLDLIBS_sign-file = -lcrypto -HOSTLDLIBS_extract-cert = -lcrypto +HOSTCFLAGS_sign-file.o = $(CRYPTO_CFLAGS) +HOSTLDLIBS_sign-file = $(CRYPTO_LIBS) +HOSTCFLAGS_extract-cert.o = $(CRYPTO_CFLAGS) +HOSTLDLIBS_extract-cert = $(CRYPTO_LIBS) always := $(hostprogs-y) $(hostprogs-m) diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 862a11c0ca10..de7e9ad09a58 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -328,7 +328,7 @@ endef # List module undefined symbols (or empty line if not enabled) ifdef CONFIG_TRIM_UNUSED_KSYMS -cmd_undef_syms = $(NM) $@ | sed -n 's/^ *U //p' | xargs echo +cmd_undef_syms = $(NM) $@ | sed -n 's/^ *U //p' | sort -u | xargs echo else cmd_undef_syms = echo endif diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 0c3c273bb1d7..7eea543f10bf 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -255,6 +255,9 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ # --------------------------------------------------------------------------- DTC ?= $(objtree)/scripts/dtc/dtc +# Silence warnings +DTC_FLAGS += -q + # Disable noisy checks by default ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),) DTC_FLAGS += -Wno-unit_address_vs_reg @@ -273,7 +276,8 @@ endif ifneq ($(findstring 2,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),) DTC_FLAGS += -Wnode_name_chars_strict \ - -Wproperty_name_chars_strict + -Wproperty_name_chars_strict \ + -Winterrupt_provider endif DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh index 4d1adf1c9827..2b7d431fd83c 100755 --- a/scripts/adjust_autoksyms.sh +++ b/scripts/adjust_autoksyms.sh @@ -42,6 +42,17 @@ esac # Generate a new symbol list file $CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file" +ksym_wl=/dev/null +if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then + # Use 'eval' to expand the whitelist path and check if it is relative + eval ksym_wl="$CONFIG_UNUSED_KSYMS_WHITELIST" + [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" + if [ ! -f "$ksym_wl" ]; then + echo "ERROR: '$ksym_wl' whitelist file not found" >&2 + exit 1 + fi +fi + # Extract changes between old and new list and touch corresponding # dependency files. changed=$( diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8e11362b8374..92c8f0f86ab2 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4198,7 +4198,7 @@ sub process { $fix) { fix_delete_line($fixlinenr, $rawline); my $fixed_line = $rawline; - $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/; + $fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/; my $line1 = $1; my $line2 = $2; fix_insert_line($fixlinenr, ltrim($line1)); diff --git a/scripts/depmod.sh b/scripts/depmod.sh index e083bcae343f..3643b4f896ed 100755 --- a/scripts/depmod.sh +++ b/scripts/depmod.sh @@ -15,6 +15,8 @@ if ! test -r System.map ; then exit 0 fi +# legacy behavior: "depmod" in /sbin, no /sbin in PATH +PATH="$PATH:/sbin" if [ -z $(command -v $DEPMOD) ]; then echo "Warning: 'make modules_install' requires $DEPMOD. Please install it." >&2 echo "This is probably in the kmod package." >&2 diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 28631ed596ab..377d05fa0cf5 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -13,6 +13,13 @@ dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o # Source files need to get at the userspace version of libfdt_env.h to compile HOST_EXTRACFLAGS := -I$(src)/libfdt +ifeq ($(wildcard /usr/include/yaml.h),) +HOST_EXTRACFLAGS += -DNO_YAML +else +dtc-objs += yamltree.o +HOSTLDLIBS_dtc := -lyaml +endif + # Generated files need one more search path to include headers in source tree HOSTCFLAGS_dtc-lexer.lex.o := -I$(src) HOSTCFLAGS_dtc-parser.tab.o := -I$(src) diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc index bece49b35535..9c467b096f03 100644 --- a/scripts/dtc/Makefile.dtc +++ b/scripts/dtc/Makefile.dtc @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-or-later # Makefile.dtc # # This is not a complete Makefile of itself. Instead, it is designed to @@ -14,5 +15,9 @@ DTC_SRCS = \ treesource.c \ util.c +ifneq ($(NO_YAML),1) +DTC_SRCS += yamltree.c +endif + DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o) diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index a2cc1036c915..b7955dbd71ca 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -1,24 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2007. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" +#include "srcpos.h" #ifdef TRACE_CHECKS #define TRACE(c, ...) \ @@ -78,23 +64,56 @@ static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); + char *str = NULL; + struct srcpos *pos = NULL; + char *file_str; + + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) + return; - if ((c->warn && (quiet < 1)) - || (c->error && (quiet < 2))) { - fprintf(stderr, "%s: %s (%s): ", - strcmp(dti->outname, "-") ? dti->outname : "", + if (prop && prop->srcpos) + pos = prop->srcpos; + else if (node && node->srcpos) + pos = node->srcpos; + + if (pos) { + file_str = srcpos_string(pos); + xasprintf(&str, "%s", file_str); + free(file_str); + } else if (streq(dti->outname, "-")) { + xasprintf(&str, ""); + } else { + xasprintf(&str, "%s", dti->outname); + } + + xasprintf_append(&str, ": %s (%s): ", (c->error) ? "ERROR" : "Warning", c->name); - if (node) { - fprintf(stderr, "%s", node->fullpath); - if (prop) - fprintf(stderr, ":%s", prop->name); - fputs(": ", stderr); - } - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); + + if (node) { + if (prop) + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); + else + xasprintf_append(&str, "%s: ", node->fullpath); } + + va_start(ap, fmt); + xavsprintf_append(&str, fmt, ap); va_end(ap); + + xasprintf_append(&str, "\n"); + + if (!prop && pos) { + pos = node->srcpos; + while (pos->next) { + pos = pos->next; + + file_str = srcpos_string(pos); + xasprintf_append(&str, " also defined at %s\n", file_str); + free(file_str); + } + } + + fputs(str, stderr); } #define FAIL(c, dti, node, ...) \ @@ -333,7 +352,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); } else { if (unitname[0]) - FAIL(c, dti, node, "node has a unit name, but no reg property"); + FAIL(c, dti, node, "node has a unit name, but no reg or ranges property"); } } WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); @@ -626,6 +645,8 @@ ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names); static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti, struct node *node) { + if (generate_symbols && node->labels) + return; if (node->omit_if_unused && !node->is_referenced) delete_node(node); } @@ -670,6 +691,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti, return; for_each_property(node, prop) { + if (streq(prop->name, "phandle") + || streq(prop->name, "linux,phandle")) { + continue; + } + if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)", prop->val.val); @@ -739,13 +765,15 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, { struct property *prop; int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; + const char *ranges = c->data; - prop = get_property(node, "ranges"); + prop = get_property(node, ranges); if (!prop) return; if (!node->parent) { - FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property"); + FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property", + ranges); return; } @@ -757,23 +785,24 @@ static void check_ranges_format(struct check *c, struct dt_info *dti, if (prop->val.len == 0) { if (p_addr_cells != c_addr_cells) - FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " "#address-cells (%d) differs from %s (%d)", - c_addr_cells, node->parent->fullpath, + ranges, c_addr_cells, node->parent->fullpath, p_addr_cells); if (p_size_cells != c_size_cells) - FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " "#size-cells (%d) differs from %s (%d)", - c_size_cells, node->parent->fullpath, + ranges, c_size_cells, node->parent->fullpath, p_size_cells); } else if ((prop->val.len % entrylen) != 0) { - FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) " + FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) " "(parent #address-cells == %d, child #address-cells == %d, " - "#size-cells == %d)", prop->val.len, + "#size-cells == %d)", ranges, prop->val.len, p_addr_cells, c_addr_cells, c_size_cells); } } -WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); +WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells); +WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells); static const struct bus_type pci_bus = { .name = "PCI", @@ -910,7 +939,7 @@ static bool node_is_compatible(struct node *node, const char *compat) for (str = prop->val.val, end = str + prop->val.len; str < end; str += strnlen(str, end - str) + 1) { - if (strprefixeq(str, end - str, compat)) + if (streq(str, compat)) return true; } return false; @@ -921,7 +950,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct if (node_is_compatible(node, "simple-bus")) node->bus = &simple_bus; } -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, + &addr_size_cells, &compatible_is_string_list); static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) { @@ -962,6 +992,159 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no } WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); +static const struct bus_type i2c_bus = { + .name = "i2c-bus", +}; + +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + if (strprefixeq(node->name, node->basenamelen, "i2c-bus") || + strprefixeq(node->name, node->basenamelen, "i2c-arb")) { + node->bus = &i2c_bus; + } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { + struct node *child; + for_each_child(node, child) { + if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) + return; + } + node->bus = &i2c_bus; + } else + return; + + if (!node->children) + return; + + if (node_addr_cells(node) != 1) + FAIL(c, dti, node, "incorrect #address-cells for I2C bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for I2C bus"); + +} +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); + +#define I2C_OWN_SLAVE_ADDRESS (1U << 30) +#define I2C_TEN_BIT_ADDRESS (1U << 31) + +static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[17]; + uint32_t reg = 0; + int len; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &i2c_bus)) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + /* Ignore I2C_OWN_SLAVE_ADDRESS */ + reg &= ~I2C_OWN_SLAVE_ADDRESS; + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", + unit_addr); + + for (len = prop->val.len; len > 0; len -= 4) { + reg = fdt32_to_cpu(*(cells++)); + /* Ignore I2C_OWN_SLAVE_ADDRESS */ + reg &= ~I2C_OWN_SLAVE_ADDRESS; + + if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)) + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", + reg); + else if (reg > 0x7f) + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property", + reg); + } +} +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); + +static const struct bus_type spi_bus = { + .name = "spi-bus", +}; + +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) +{ + int spi_addr_cells = 1; + + if (strprefixeq(node->name, node->basenamelen, "spi")) { + node->bus = &spi_bus; + } else { + /* Try to detect SPI buses which don't have proper node name */ + struct node *child; + + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) + return; + + for_each_child(node, child) { + struct property *prop; + for_each_property(child, prop) { + if (strprefixeq(prop->name, 4, "spi-")) { + node->bus = &spi_bus; + break; + } + } + if (node->bus == &spi_bus) + break; + } + + if (node->bus == &spi_bus && get_property(node, "reg")) + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); + } + if (node->bus != &spi_bus || !node->children) + return; + + if (get_property(node, "spi-slave")) + spi_addr_cells = 0; + if (node_addr_cells(node) != spi_addr_cells) + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); + if (node_size_cells(node) != 0) + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); + +} +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); + +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) +{ + struct property *prop; + const char *unitname = get_unitname(node); + char unit_addr[9]; + uint32_t reg = 0; + cell_t *cells = NULL; + + if (!node->parent || (node->parent->bus != &spi_bus)) + return; + + if (get_property(node->parent, "spi-slave")) + return; + + prop = get_property(node, "reg"); + if (prop) + cells = (cell_t *)prop->val.val; + + if (!cells) { + FAIL(c, dti, node, "missing or empty reg property"); + return; + } + + reg = fdt32_to_cpu(*cells); + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); + if (!streq(unitname, unit_addr)) + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", + unit_addr); +} +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); + static void check_unit_address_format(struct check *c, struct dt_info *dti, struct node *node) { @@ -1034,8 +1217,24 @@ static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *d } WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); -static void check_unique_unit_address(struct check *c, struct dt_info *dti, - struct node *node) +static bool node_is_disabled(struct node *node) +{ + struct property *prop; + + prop = get_property(node, "status"); + if (prop) { + char *str = prop->val.val; + if (streq("disabled", str)) + return true; + } + + return false; +} + +static void check_unique_unit_address_common(struct check *c, + struct dt_info *dti, + struct node *node, + bool disable_check) { struct node *childa; @@ -1052,18 +1251,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti, if (!strlen(addr_a)) continue; + if (disable_check && node_is_disabled(childa)) + continue; + for_each_child(node, childb) { const char *addr_b = get_unitname(childb); if (childa == childb) break; + if (disable_check && node_is_disabled(childb)) + continue; + if (streq(addr_a, addr_b)) FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); } } } + +static void check_unique_unit_address(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, false); +} WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, + struct node *node) +{ + check_unique_unit_address_common(c, dti, node, true); +} +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, + NULL, false, false, &avoid_default_addr_size); + static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node) @@ -1338,6 +1557,28 @@ static bool node_is_interrupt_provider(struct node *node) return false; } + +static void check_interrupt_provider(struct check *c, + struct dt_info *dti, + struct node *node) +{ + struct property *prop; + + if (!node_is_interrupt_provider(node)) + return; + + prop = get_property(node, "#interrupt-cells"); + if (!prop) + FAIL(c, dti, node, + "Missing #interrupt-cells in interrupt provider"); + + prop = get_property(node, "#address-cells"); + if (!prop) + FAIL(c, dti, node, + "Missing #address-cells in interrupt provider"); +} +WARNING(interrupt_provider, check_interrupt_provider, NULL); + static void check_interrupts_property(struct check *c, struct dt_info *dti, struct node *node) @@ -1364,10 +1605,14 @@ static void check_interrupts_property(struct check *c, prop = get_property(parent, "interrupt-parent"); if (prop) { phandle = propval_cell(prop); - /* Give up if this is an overlay with external references */ - if ((phandle == 0 || phandle == -1) && - (dti->dtsflags & DTSF_PLUGIN)) + if ((phandle == 0) || (phandle == -1)) { + /* Give up if this is an overlay with + * external references */ + if (dti->dtsflags & DTSF_PLUGIN) return; + FAIL_PROP(c, dti, parent, prop, "Invalid phandle"); + continue; + } irq_node = get_node_by_phandle(root, phandle); if (!irq_node) { @@ -1391,7 +1636,7 @@ static void check_interrupts_property(struct check *c, prop = get_property(irq_node, "#interrupt-cells"); if (!prop) { - FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent"); + /* We warn about that already in another test. */ return; } @@ -1536,7 +1781,7 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti, return; if (!strprefixeq(node->name, node->basenamelen, "endpoint")) - FAIL(c, dti, node, "graph endpont node name should be 'endpoint'"); + FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'"); check_graph_reg(c, dti, node); @@ -1570,7 +1815,7 @@ static struct check *check_table[] = { &property_name_chars_strict, &node_name_chars_strict, - &addr_size_cells, ®_format, &ranges_format, + &addr_size_cells, ®_format, &ranges_format, &dma_ranges_format, &unit_address_vs_reg, &unit_address_format, @@ -1582,9 +1827,16 @@ static struct check *check_table[] = { &simple_bus_bridge, &simple_bus_reg, + &i2c_bus_bridge, + &i2c_bus_reg, + + &spi_bus_bridge, + &spi_bus_reg, + &avoid_default_addr_size, &avoid_unnecessary_addr_size, &unique_unit_address, + &unique_unit_address_if_enabled, &obsolete_chosen_interrupt_controller, &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, @@ -1608,6 +1860,7 @@ static struct check *check_table[] = { &deprecated_gpio_property, &gpios_property, &interrupts_property, + &interrupt_provider, &alias_paths, diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c index aa37a16c8891..0a43b6de3264 100644 --- a/scripts/dtc/data.c +++ b/scripts/dtc/data.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" @@ -74,7 +59,8 @@ struct data data_copy_escape_string(const char *s, int len) struct data d; char *q; - d = data_grow_for(empty_data, len + 1); + d = data_add_marker(empty_data, TYPE_STRING, NULL); + d = data_grow_for(d, len + 1); q = d.val; while (i < len) { @@ -94,6 +80,7 @@ struct data data_copy_file(FILE *f, size_t maxlen) { struct data d = empty_data; + d = data_add_marker(d, TYPE_NONE, NULL); while (!feof(f) && (d.len < maxlen)) { size_t chunksize, ret; diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l index d3694d6cf202..b3b7270300de 100644 --- a/scripts/dtc/dtc-lexer.l +++ b/scripts/dtc/dtc-lexer.l @@ -1,21 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ %option noyywrap nounput noinput never-interactive @@ -212,14 +197,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...); <*>\&{LABEL} { /* label reference */ DPRINT("Ref: %s\n", yytext+1); yylval.labelref = xstrdup(yytext+1); - return DT_REF; + return DT_LABEL_REF; } <*>"&{/"{PATHCHAR}*\} { /* new-style path reference */ yytext[yyleng-1] = '\0'; DPRINT("Ref: %s\n", yytext+2); yylval.labelref = xstrdup(yytext+2); - return DT_REF; + return DT_PATH_REF; } [0-9a-fA-F]{2} { diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 011a5b25539a..40dcf4f149da 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -1,22 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ +%locations + %{ #include #include @@ -32,6 +19,8 @@ extern void yyerror(char const *s); treesource_error = true; \ } while (0) +#define YYERROR_CALL(msg) yyerror(msg) + extern struct dt_info *parser_output; extern bool treesource_error; %} @@ -70,7 +59,8 @@ extern bool treesource_error; %token DT_BYTE %token DT_STRING %token DT_LABEL -%token DT_REF +%token DT_LABEL_REF +%token DT_PATH_REF %token DT_INCBIN %type propdata @@ -83,6 +73,7 @@ extern bool treesource_error; %type bytestring %type propdef %type proplist +%type dt_ref %type devicetree %type nodedef @@ -158,6 +149,8 @@ memreserve: } ; +dt_ref: DT_LABEL_REF | DT_PATH_REF; + devicetree: '/' nodedef { @@ -167,7 +160,7 @@ devicetree: { $$ = merge_nodes($1, $3); } - | DT_REF nodedef + | dt_ref nodedef { /* * We rely on the rule being always: @@ -176,9 +169,12 @@ devicetree: */ if (!($-1 & DTSF_PLUGIN)) ERROR(&@2, "Label or path %s not found", $1); - $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1); + $$ = add_orphan_node( + name_node(build_node(NULL, NULL, NULL), + ""), + $2, $1); } - | devicetree DT_LABEL DT_REF nodedef + | devicetree DT_LABEL dt_ref nodedef { struct node *target = get_node_by_ref($1, $3); @@ -189,7 +185,7 @@ devicetree: ERROR(&@3, "Label or path %s not found", $3); $$ = $1; } - | devicetree DT_REF nodedef + | devicetree DT_PATH_REF nodedef { /* * We rely on the rule being always: @@ -208,7 +204,26 @@ devicetree: } $$ = $1; } - | devicetree DT_DEL_NODE DT_REF ';' + | devicetree DT_LABEL_REF nodedef + { + struct node *target = get_node_by_ref($1, $2); + + if (target) { + merge_nodes(target, $3); + } else { + /* + * We rely on the rule being always: + * versioninfo plugindecl memreserves devicetree + * so $-1 is what we want (plugindecl) + */ + if ($-1 & DTSF_PLUGIN) + add_orphan_node($1, $3, $2); + else + ERROR(&@2, "Label or path %s not found", $2); + } + $$ = $1; + } + | devicetree DT_DEL_NODE dt_ref ';' { struct node *target = get_node_by_ref($1, $3); @@ -220,7 +235,7 @@ devicetree: $$ = $1; } - | devicetree DT_OMIT_NO_REF DT_REF ';' + | devicetree DT_OMIT_NO_REF dt_ref ';' { struct node *target = get_node_by_ref($1, $3); @@ -237,7 +252,7 @@ devicetree: nodedef: '{' proplist subnodes '}' ';' { - $$ = build_node($2, $3); + $$ = build_node($2, $3, &@$); } ; @@ -255,11 +270,11 @@ proplist: propdef: DT_PROPNODENAME '=' propdata ';' { - $$ = build_property($1, $3); + $$ = build_property($1, $3, &@$); } | DT_PROPNODENAME ';' { - $$ = build_property($1, empty_data); + $$ = build_property($1, empty_data, &@$); } | DT_DEL_PROP DT_PROPNODENAME ';' { @@ -285,8 +300,9 @@ propdata: { $$ = data_merge($1, $3); } - | propdataprefix DT_REF + | propdataprefix dt_ref { + $1 = data_add_marker($1, TYPE_STRING, $2); $$ = data_add_marker($1, REF_PATH, $2); } | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')' @@ -340,22 +356,27 @@ arrayprefix: DT_BITS DT_LITERAL '<' { unsigned long long bits; + enum markertype type = TYPE_UINT32; bits = $2; - if ((bits != 8) && (bits != 16) && - (bits != 32) && (bits != 64)) { + switch (bits) { + case 8: type = TYPE_UINT8; break; + case 16: type = TYPE_UINT16; break; + case 32: type = TYPE_UINT32; break; + case 64: type = TYPE_UINT64; break; + default: ERROR(&@2, "Array elements must be" " 8, 16, 32 or 64-bits"); bits = 32; } - $$.data = empty_data; + $$.data = data_add_marker(empty_data, type, NULL); $$.bits = bits; } | '<' { - $$.data = empty_data; + $$.data = data_add_marker(empty_data, TYPE_UINT32, NULL); $$.bits = 32; } | arrayprefix integer_prim @@ -377,7 +398,7 @@ arrayprefix: $$.data = data_append_integer($1.data, $2, $1.bits); } - | arrayprefix DT_REF + | arrayprefix dt_ref { uint64_t val = ~0ULL >> (64 - $1.bits); @@ -499,7 +520,7 @@ integer_unary: bytestring: /* empty */ { - $$ = empty_data; + $$ = data_add_marker(empty_data, TYPE_UINT8, NULL); } | bytestring DT_BYTE { @@ -534,7 +555,7 @@ subnode: } | DT_DEL_NODE DT_PROPNODENAME ';' { - $$ = name_node(build_node_delete(), $2); + $$ = name_node(build_node_delete(&@$), $2); } | DT_OMIT_NO_REF subnode { diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index c36994e6eac5..35e97aa3ea54 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include @@ -35,6 +20,8 @@ int phandle_format = PHANDLE_EPAPR; /* Use linux,phandle or phandle properties * int generate_symbols; /* enable symbols & fixup support */ int generate_fixups; /* suppress generation of fixups on symbol support */ int auto_label_aliases; /* auto generate labels -> aliases */ +int annotate; /* Level of annotation: 1 for input source location + >1 for full input source location. */ static int is_power_of_2(int x) { @@ -60,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix) /* Usage related data. */ static const char usage_synopsis[] = "dtc [options] "; -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv"; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@AThv"; static struct option const usage_long_opts[] = { {"quiet", no_argument, NULL, 'q'}, {"in-format", a_argument, NULL, 'I'}, @@ -81,6 +68,7 @@ static struct option const usage_long_opts[] = { {"error", a_argument, NULL, 'E'}, {"symbols", no_argument, NULL, '@'}, {"auto-alias", no_argument, NULL, 'A'}, + {"annotate", no_argument, NULL, 'T'}, {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'v'}, {NULL, no_argument, NULL, 0x0}, @@ -95,6 +83,9 @@ static const char * const usage_opts_help[] = { "\n\tOutput formats are:\n" "\t\tdts - device tree source text\n" "\t\tdtb - device tree blob\n" +#ifndef NO_YAML + "\t\tyaml - device tree encoded as YAML\n" +#endif "\t\tasm - assembler source", "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)", "\n\tOutput dependency file", @@ -114,6 +105,7 @@ static const char * const usage_opts_help[] = { "\n\tEnable/disable errors (prefix with \"no-\")", "\n\tEnable generation of symbols", "\n\tEnable auto-alias of labels", + "\n\tAnnotate output .dts with input source file and line (-T -T for more details)", "\n\tPrint this help and exit", "\n\tPrint version and exit", NULL, @@ -128,6 +120,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback) return fallback; if (!strcasecmp(s, ".dts")) return "dts"; + if (!strcasecmp(s, ".yaml")) + return "yaml"; if (!strcasecmp(s, ".dtb")) return "dtb"; return fallback; @@ -259,6 +253,9 @@ int main(int argc, char *argv[]) case 'A': auto_label_aliases = 1; break; + case 'T': + annotate++; + break; case 'h': usage(NULL); @@ -266,6 +263,9 @@ int main(int argc, char *argv[]) usage("unknown option"); } } +#if 1 + if (!quiet) quiet++; +#endif if (argc > (optind+1)) usage("missing files"); @@ -297,6 +297,8 @@ int main(int argc, char *argv[]) outform = "dts"; } } + if (annotate && (!streq(inform, "dts") || !streq(outform, "dts"))) + die("--annotate requires -I dts -O dts\n"); if (streq(inform, "dts")) dti = dt_from_source(arg); else if (streq(inform, "fs")) @@ -350,6 +352,12 @@ int main(int argc, char *argv[]) if (streq(outform, "dts")) { dt_to_source(outf, dti); +#ifndef NO_YAML + } else if (streq(outform, "yaml")) { + if (!streq(inform, "dts")) + die("YAML output format requires dts input format\n"); + dt_to_yaml(outf, dti); +#endif } else if (streq(outform, "dtb")) { dt_to_blob(outf, dti, outversion); } else if (streq(outform, "asm")) { diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index 6d667701ab6a..a08f4159cd03 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -1,24 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef DTC_H #define DTC_H /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include @@ -58,6 +43,7 @@ extern int phandle_format; /* Use linux,phandle or phandle properties */ extern int generate_symbols; /* generate symbols for nodes with labels */ extern int generate_fixups; /* generate fixups */ extern int auto_label_aliases; /* auto generate labels -> aliases */ +extern int annotate; /* annotate .dts with input source location */ #define PHANDLE_LEGACY 0x1 #define PHANDLE_EPAPR 0x2 @@ -65,6 +51,37 @@ extern int auto_label_aliases; /* auto generate labels -> aliases */ typedef uint32_t cell_t; +static inline uint16_t dtb_ld16(const void *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint16_t)bp[0] << 8) + | bp[1]; +} + +static inline uint32_t dtb_ld32(const void *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +static inline uint64_t dtb_ld64(const void *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; +} #define streq(a, b) (strcmp((a), (b)) == 0) #define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0) @@ -74,10 +91,17 @@ typedef uint32_t cell_t; /* Data blobs */ enum markertype { + TYPE_NONE, REF_PHANDLE, REF_PATH, LABEL, + TYPE_UINT8, + TYPE_UINT16, + TYPE_UINT32, + TYPE_UINT64, + TYPE_STRING, }; +extern const char *markername(enum markertype markertype); struct marker { enum markertype type; @@ -101,6 +125,8 @@ struct data { for_each_marker(m) \ if ((m)->type == (t)) +size_t type_marker_length(struct marker *m); + void data_free(struct data d); struct data data_grow_for(struct data d, int xlen); @@ -149,6 +175,7 @@ struct property { struct property *next; struct label *labels; + struct srcpos *srcpos; }; struct node { @@ -168,6 +195,7 @@ struct node { struct label *labels; const struct bus_type *bus; + struct srcpos *srcpos; bool omit_if_unused, is_referenced; }; @@ -196,13 +224,15 @@ struct node { void add_label(struct label **labels, char *label); void delete_labels(struct label **labels); -struct property *build_property(char *name, struct data val); +struct property *build_property(char *name, struct data val, + struct srcpos *srcpos); struct property *build_property_delete(char *name); struct property *chain_property(struct property *first, struct property *list); struct property *reverse_properties(struct property *first); -struct node *build_node(struct property *proplist, struct node *children); -struct node *build_node_delete(void); +struct node *build_node(struct property *proplist, struct node *children, + struct srcpos *srcpos); +struct node *build_node_delete(struct srcpos *srcpos); struct node *name_node(struct node *node, char *name); struct node *omit_node_if_unused(struct node *node); struct node *reference_node(struct node *node); @@ -217,7 +247,8 @@ void add_child(struct node *parent, struct node *child); void delete_node_by_name(struct node *parent, char *name); void delete_node(struct node *node); void append_to_property(struct node *node, - char *name, const void *data, int len); + char *name, const void *data, int len, + enum markertype type); const char *get_unitname(struct node *node); struct property *get_property(struct node *node, const char *propname); @@ -290,6 +321,10 @@ struct dt_info *dt_from_blob(const char *fname); void dt_to_source(FILE *f, struct dt_info *dti); struct dt_info *dt_from_source(const char *f); +/* YAML source */ + +void dt_to_yaml(FILE *f, struct dt_info *dti); + /* FS trees */ struct dt_info *dt_from_fs(const char *dirname); diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c index 8d268fb785db..07f10d2b5d79 100644 --- a/scripts/dtc/flattree.c +++ b/scripts/dtc/flattree.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" @@ -171,7 +156,7 @@ static void asm_emit_data(void *e, struct data d) emit_offset_label(f, m->ref, m->offset); while ((d.len - off) >= sizeof(uint32_t)) { - asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off)))); + asm_emit_cell(e, dtb_ld32(d.val + off)); off += sizeof(uint32_t); } @@ -393,7 +378,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version) padlen = 0; if (quiet < 1) fprintf(stderr, - "Warning: blob size %d >= minimum size %d\n", + "Warning: blob size %"PRIu32" >= minimum size %d\n", fdt32_to_cpu(fdt.totalsize), minsize); } } @@ -525,7 +510,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version) fprintf(f, "/* Memory reserve map from source file */\n"); /* - * Use .long on high and low halfs of u64s to avoid .quad + * Use .long on high and low halves of u64s to avoid .quad * as it appears .quad isn't available in some assemblers. */ for (re = dti->reservelist; re; re = re->next) { @@ -692,7 +677,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf, val = flat_read_data(dtbuf, proplen); - return build_property(name, val); + return build_property(name, val, NULL); } @@ -750,7 +735,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf, char *flatname; uint32_t val; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); flatname = flat_read_string(dtbuf); diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c index ae7d06c3c492..5e59594ab301 100644 --- a/scripts/dtc/fstree.c +++ b/scripts/dtc/fstree.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" @@ -34,7 +19,7 @@ static struct node *read_fstree(const char *dirname) if (!d) die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno)); - tree = build_node(NULL, NULL); + tree = build_node(NULL, NULL, NULL); while ((de = readdir(d)) != NULL) { char *tmpname; @@ -45,7 +30,7 @@ static struct node *read_fstree(const char *dirname) tmpname = join_path(dirname, de->d_name); - if (lstat(tmpname, &st) < 0) + if (stat(tmpname, &st) < 0) die("stat(%s): %s\n", tmpname, strerror(errno)); if (S_ISREG(st.st_mode)) { @@ -60,7 +45,8 @@ static struct node *read_fstree(const char *dirname) } else { prop = build_property(xstrdup(de->d_name), data_copy_file(pfile, - st.st_size)); + st.st_size), + NULL); add_property(tree, prop); fclose(pfile); } diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt index 098b3f36e668..e54639738c8e 100644 --- a/scripts/dtc/libfdt/Makefile.libfdt +++ b/scripts/dtc/libfdt/Makefile.libfdt @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) # Makefile.libfdt # # This is not a complete Makefile of itself. Instead, it is designed to @@ -9,3 +10,9 @@ LIBFDT_VERSION = version.lds LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ fdt_addresses.c fdt_overlay.c LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) +LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) + +libfdt_clean: + @$(VECHO) CLEAN "(libfdt)" + rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) + rm -f $(LIBFDT_dir)/$(LIBFDT_soname) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 9af0733d1837..c28fcc115771 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -55,35 +10,124 @@ #include "libfdt_internal.h" -int fdt_check_header(const void *fdt) +/* + * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks + * that the given buffer contains what appears to be a flattened + * device tree with sane information in its header. + */ +int32_t fdt_ro_probe_(const void *fdt) { + uint32_t totalsize = fdt_totalsize(fdt); + + if (can_assume(VALID_DTB)) + return totalsize; + if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; + if (!can_assume(LATEST)) { + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE; } else { return -FDT_ERR_BADMAGIC; } - if (fdt_off_dt_struct(fdt) > (UINT_MAX - fdt_size_dt_struct(fdt))) - return FDT_ERR_BADOFFSET; + if (totalsize < INT32_MAX) + return totalsize; + else + return -FDT_ERR_TRUNCATED; +} + +static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) +{ + return (off >= hdrsize) && (off <= totalsize); +} + +static int check_block_(uint32_t hdrsize, uint32_t totalsize, + uint32_t base, uint32_t size) +{ + if (!check_off_(hdrsize, totalsize, base)) + return 0; /* block start out of bounds */ + if ((base + size) < base) + return 0; /* overflow */ + if (!check_off_(hdrsize, totalsize, base + size)) + return 0; /* block end out of bounds */ + return 1; +} + +size_t fdt_header_size_(uint32_t version) +{ + if (version <= 1) + return FDT_V1_SIZE; + else if (version <= 2) + return FDT_V2_SIZE; + else if (version <= 3) + return FDT_V3_SIZE; + else if (version <= 16) + return FDT_V16_SIZE; + else + return FDT_V17_SIZE; +} + +size_t fdt_header_size(const void *fdt) +{ + return can_assume(LATEST) ? FDT_V17_SIZE : + fdt_header_size_(fdt_version(fdt)); +} + +int fdt_check_header(const void *fdt) +{ + size_t hdrsize; + + if (fdt_magic(fdt) != FDT_MAGIC) + return -FDT_ERR_BADMAGIC; + if (!can_assume(LATEST)) { + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + } + hdrsize = fdt_header_size(fdt); + if (!can_assume(VALID_DTB)) { + + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; - if (fdt_off_dt_strings(fdt) > (UINT_MAX - fdt_size_dt_strings(fdt))) - return FDT_ERR_BADOFFSET; + /* Bounds check memrsv block */ + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_mem_rsvmap(fdt))) + return -FDT_ERR_TRUNCATED; + } - if ((fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt)) - > fdt_totalsize(fdt)) - return FDT_ERR_BADOFFSET; + if (!can_assume(VALID_DTB)) { + /* Bounds check structure block */ + if (!can_assume(LATEST) && fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } - if ((fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)) - > fdt_totalsize(fdt)) - return FDT_ERR_BADOFFSET; + /* Bounds check strings block */ + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt))) + return -FDT_ERR_TRUNCATED; + } return 0; } @@ -92,12 +136,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { unsigned absoffset = offset + fdt_off_dt_struct(fdt); - if ((absoffset < offset) - || ((absoffset + len) < absoffset) - || (absoffset + len) > fdt_totalsize(fdt)) - return NULL; + if (!can_assume(VALID_INPUT)) + if ((absoffset < offset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; - if (fdt_version(fdt) >= 0x11) + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) if (((offset + len) < offset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; @@ -114,7 +159,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) + if (!can_assume(VALID_DTB) && !tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; @@ -126,18 +171,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); - if (!p) + if (!can_assume(VALID_DTB) && !p) return FDT_END; /* premature end */ break; case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) + if (!can_assume(VALID_DTB) && !lenp) return FDT_END; /* premature end */ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + fdt32_to_cpu(*lenp); - if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + if (!can_assume(LATEST) && + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) offset += 4; break; @@ -160,6 +206,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) int fdt_check_node_offset_(const void *fdt, int offset) { + if (can_assume(VALID_INPUT)) + return offset; if ((offset < 0) || (offset % FDT_TAGSIZE) || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) return -FDT_ERR_BADOFFSET; @@ -258,7 +306,7 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h index 74961f9026d1..f2e68807f277 100644 --- a/scripts/dtc/libfdt/fdt.h +++ b/scripts/dtc/libfdt/fdt.h @@ -1,55 +1,10 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef FDT_H #define FDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __ASSEMBLY__ diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c index eff4dbcc729d..9a82cd0ba2f9 100644 --- a/scripts/dtc/libfdt/fdt_addresses.c +++ b/scripts/dtc/libfdt/fdt_addresses.c @@ -1,52 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2014 David Gibson - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright (C) 2018 embedded brains GmbH */ #include "libfdt_env.h" @@ -55,42 +11,91 @@ #include "libfdt_internal.h" -int fdt_address_cells(const void *fdt, int nodeoffset) +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) { - const fdt32_t *ac; - int val; + const fdt32_t *c; + uint32_t val; int len; - ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); - if (!ac) - return 2; + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) + return len; - if (len != sizeof(*ac)) + if (len != sizeof(*c)) return -FDT_ERR_BADNCELLS; - val = fdt32_to_cpu(*ac); - if ((val <= 0) || (val > FDT_MAX_NCELLS)) + val = fdt32_to_cpu(*c); + if (val > FDT_MAX_NCELLS) return -FDT_ERR_BADNCELLS; + return (int)val; +} + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; + if (val == -FDT_ERR_NOTFOUND) + return 2; return val; } int fdt_size_cells(const void *fdt, int nodeoffset) { - const fdt32_t *sc; int val; - int len; - sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); - if (!sc) - return 2; + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; +} + +/* This function assumes that [address|size]_cells is 1 or 2 */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size) +{ + int addr_cells, size_cells, ret; + uint8_t data[sizeof(fdt64_t) * 2], *prop; - if (len != sizeof(*sc)) + ret = fdt_address_cells(fdt, parent); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, parent); + if (ret < 0) + return ret; + size_cells = ret; + + /* check validity of address */ + prop = data; + if (addr_cells == 1) { + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)addr); + } else if (addr_cells == 2) { + fdt64_st(prop, addr); + } else { return -FDT_ERR_BADNCELLS; + } - val = fdt32_to_cpu(*sc); - if ((val < 0) || (val > FDT_MAX_NCELLS)) + /* check validity of size */ + prop += addr_cells * sizeof(fdt32_t); + if (size_cells == 1) { + if (size > UINT32_MAX) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)size); + } else if (size_cells == 2) { + fdt64_st(prop, size); + } else { return -FDT_ERR_BADNCELLS; + } - return val; + return fdt_appendprop(fdt, nodeoffset, name, data, + (addr_cells + size_cells) * sizeof(fdt32_t)); } diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c index f2ae9b77c285..49d54d44b8e7 100644 --- a/scripts/dtc/libfdt/fdt_empty_tree.c +++ b/scripts/dtc/libfdt/fdt_empty_tree.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2012 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index bf75388ec9a2..b310e49a698e 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -1,53 +1,8 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2016 Free Electrons * Copyright (C) 2016 NextThing Co. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -93,11 +48,11 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) * @pathp: pointer which receives the path of the target (or NULL) * * overlay_get_target() retrieves the target offset in the base - * device tree of a fragment, no matter how the actual targetting is + * device tree of a fragment, no matter how the actual targeting is * done (through a phandle or a path) * * returns: - * the targetted node offset in the base device tree + * the targeted node offset in the base device tree * Negative error code on error */ static int overlay_get_target(const void *fdt, const void *fdto, @@ -697,7 +652,7 @@ static int get_path_len(const void *fdt, int nodeoffset) int len = 0, namelen; const char *name; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); for (;;) { name = fdt_get_name(fdt, nodeoffset, &namelen); @@ -778,26 +733,36 @@ static int overlay_symbol_update(void *fdt, void *fdto) /* keep end marker to avoid strlen() */ e = path + path_len; - /* format: //__overlay__/ */ - if (*path != '/') return -FDT_ERR_BADVALUE; /* get fragment name first */ s = strchr(path + 1, '/'); - if (!s) - return -FDT_ERR_BADOVERLAY; + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } frag_name = path + 1; frag_name_len = s - path - 1; /* verify format; safe since "s" lies in \0 terminated prop */ len = sizeof("/__overlay__/") - 1; - if ((e - s) < len || memcmp(s, "/__overlay__/", len)) - return -FDT_ERR_BADOVERLAY; - - rel_path = s + len; - rel_path_len = e - rel_path; + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* //__overlay__/ */ + rel_path = s + len; + rel_path_len = e - rel_path - 1; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* //__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } /* find the fragment index in which the symbol lies */ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, @@ -863,11 +828,15 @@ static int overlay_symbol_update(void *fdt, void *fdto) int fdt_overlay_apply(void *fdt, void *fdto) { - uint32_t delta = fdt_get_max_phandle(fdt); + uint32_t delta; int ret; - FDT_CHECK_HEADER(fdt); - FDT_CHECK_HEADER(fdto); + FDT_RO_PROBE(fdt); + FDT_RO_PROBE(fdto); + + ret = fdt_find_max_phandle(fdt, &delta); + if (ret) + goto err; ret = overlay_adjust_local_phandles(fdto, delta); if (ret) diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index dfb3236da388..e03570a56eb5 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -76,60 +31,169 @@ static int fdt_nodename_eq_(const void *fdt, int offset, return 0; } +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) +{ + int32_t totalsize; + uint32_t absoffset; + size_t len; + int err; + const char *s, *n; + + if (can_assume(VALID_INPUT)) { + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + + if (lenp) + *lenp = strlen(s); + return s; + } + totalsize = fdt_ro_probe_(fdt); + err = totalsize; + if (totalsize < 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + absoffset = stroffset + fdt_off_dt_strings(fdt); + if (absoffset >= totalsize) + goto fail; + len = totalsize - absoffset; + + if (fdt_magic(fdt) == FDT_MAGIC) { + if (stroffset < 0) + goto fail; + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { + if (stroffset >= fdt_size_dt_strings(fdt)) + goto fail; + if ((fdt_size_dt_strings(fdt) - stroffset) < len) + len = fdt_size_dt_strings(fdt) - stroffset; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + if ((stroffset >= 0) + || (stroffset < -fdt_size_dt_strings(fdt))) + goto fail; + if ((-stroffset) < len) + len = -stroffset; + } else { + err = -FDT_ERR_INTERNAL; + goto fail; + } + + s = (const char *)fdt + absoffset; + n = memchr(s, '\0', len); + if (!n) { + /* missing terminating NULL */ + err = -FDT_ERR_TRUNCATED; + goto fail; + } + + if (lenp) + *lenp = n - s; + return s; + +fail: + if (lenp) + *lenp = err; + return NULL; +} + const char *fdt_string(const void *fdt, int stroffset) { - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + return fdt_get_string(fdt, stroffset, NULL); } static int fdt_string_eq_(const void *fdt, int stroffset, const char *s, int len) { - const char *p = fdt_string(fdt, stroffset); + int slen; + const char *p = fdt_get_string(fdt, stroffset, &slen); - return (strlen(p) == len) && (memcmp(p, s, len) == 0); + return p && (slen == len) && (memcmp(p, s, len) == 0); } -uint32_t fdt_get_max_phandle(const void *fdt) +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) { - uint32_t max_phandle = 0; - int offset; + uint32_t max = 0; + int offset = -1; - for (offset = fdt_next_node(fdt, -1, NULL);; - offset = fdt_next_node(fdt, offset, NULL)) { - uint32_t phandle; + while (true) { + uint32_t value; - if (offset == -FDT_ERR_NOTFOUND) - return max_phandle; + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; - if (offset < 0) - return (uint32_t)-1; + return offset; + } - phandle = fdt_get_phandle(fdt, offset); - if (phandle == (uint32_t)-1) - continue; + value = fdt_get_phandle(fdt, offset); - if (phandle > max_phandle) - max_phandle = phandle; + if (value > max) + max = value; } + if (phandle) + *phandle = max; + return 0; } +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max; + int err; + + err = fdt_find_max_phandle(fdt, &max); + if (err < 0) + return err; + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) +{ + int offset = n * sizeof(struct fdt_reserve_entry); + int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + + if (!can_assume(VALID_INPUT)) { + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - + sizeof(struct fdt_reserve_entry)) + return NULL; + } + return fdt_mem_rsv_(fdt, n); +} + int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { - FDT_CHECK_HEADER(fdt); - *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); - *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); + const struct fdt_reserve_entry *re; + + FDT_RO_PROBE(fdt); + re = fdt_mem_rsv(fdt, n); + if (!can_assume(VALID_INPUT) && !re) + return -FDT_ERR_BADOFFSET; + + *address = fdt64_ld(&re->address); + *size = fdt64_ld(&re->size); return 0; } int fdt_num_mem_rsv(const void *fdt) { - int i = 0; + int i; + const struct fdt_reserve_entry *re; - while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) - i++; - return i; + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { + if (fdt64_ld(&re->size) == 0) + return i; + } + return -FDT_ERR_TRUNCATED; } static int nextprop_(const void *fdt, int offset) @@ -161,7 +225,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, { int depth; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); for (depth = 0; (offset >= 0) && (depth >= 0); @@ -187,7 +251,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) const char *p = path; int offset = 0; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* see if we have an alias */ if (*path != '/') { @@ -237,13 +301,13 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *nameptr; int err; - if (((err = fdt_check_header(fdt)) != 0) + if (((err = fdt_ro_probe_(fdt)) < 0) || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; nameptr = nh->name; - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { /* * For old FDT versions, match the naming conventions of V16: * give only the leaf name (after all /). The actual tree @@ -294,7 +358,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, int err; const struct fdt_property *prop; - if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (!can_assume(VALID_INPUT) && + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; @@ -303,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, prop = fdt_offset_ptr_(fdt, offset); if (lenp) - *lenp = fdt32_to_cpu(prop->len); + *lenp = fdt32_ld(&prop->len); return prop; } @@ -315,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; @@ -336,11 +401,12 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; - if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!can_assume(LIBFDT_FLAWLESS) && !prop) { offset = -FDT_ERR_INTERNAL; break; } - if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff), + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), name, namelen)) { if (poffset) *poffset = offset; @@ -361,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, { /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; @@ -392,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, return NULL; /* Handle realignment */ - if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && - fdt32_to_cpu(prop->len) >= 8) + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -406,12 +472,27 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, prop = fdt_get_property_by_offset_(fdt, offset, lenp); if (!prop) return NULL; - if (namep) - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + if (namep) { + const char *name; + int namelen; + + if (!can_assume(VALID_INPUT)) { + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } else { + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); + } + } /* Handle realignment */ - if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && - fdt32_to_cpu(prop->len) >= 8) + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -436,7 +517,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return 0; } - return fdt32_to_cpu(*php); + return fdt32_ld(php); } const char *fdt_get_alias_namelen(const void *fdt, @@ -462,7 +543,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) int offset, depth, namelen; const char *name; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; @@ -514,7 +595,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; @@ -536,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, } } - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; + if (!can_assume(VALID_INPUT)) { + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + } return offset; /* error from fdt_next_node() */ } @@ -551,7 +634,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset) err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; + return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : + -FDT_ERR_INTERNAL; return nodedepth; } @@ -573,7 +657,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const void *val; int len; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't @@ -599,7 +683,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in @@ -752,7 +836,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, { int offset, err; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 26d5755a97d3..93e4a2b56348 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -67,29 +22,31 @@ static int fdt_blocks_misordered_(const void *fdt, (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); } -static int fdt_rw_check_header_(void *fdt) +static int fdt_rw_probe_(void *fdt) { - FDT_CHECK_HEADER(fdt); + if (can_assume(VALID_DTB)) + return 0; + FDT_RO_PROBE(fdt); - if (fdt_version(fdt) < 17) + if (!can_assume(LATEST) && fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) + if (!can_assume(LATEST) && fdt_version(fdt) > 17) fdt_set_version(fdt, 17); return 0; } -#define FDT_RW_CHECK_HEADER(fdt) \ +#define FDT_RW_PROBE(fdt) \ { \ int err_; \ - if ((err_ = fdt_rw_check_header_(fdt)) != 0) \ + if ((err_ = fdt_rw_probe_(fdt)) != 0) \ return err_; \ } -static inline int fdt_data_size_(void *fdt) +static inline unsigned int fdt_data_size_(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } @@ -97,15 +54,16 @@ static inline int fdt_data_size_(void *fdt) static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + fdt_data_size_(fdt); + unsigned int dsize = fdt_data_size_(fdt); + size_t soff = p - (char *)fdt; - if (((p + oldlen) < p) || ((p + oldlen) > end)) + if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + if ((p < (char *)fdt) || (dsize + newlen < oldlen)) return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); return 0; } @@ -136,6 +94,14 @@ static int fdt_splice_struct_(void *fdt, void *p, return 0; } +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int newlen = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); +} + static int fdt_splice_string_(void *fdt, int newlen) { void *p = (char *)fdt @@ -149,7 +115,16 @@ static int fdt_splice_string_(void *fdt, int newlen) return 0; } -static int fdt_find_add_string_(void *fdt, const char *s) +/** + * fdt_find_add_string_() - Find or allocate a string + * + * @fdt: pointer to the device tree to check/adjust + * @s: string to find/add + * @allocated: Set to 0 if the string was found, 1 if not found and so + * allocated. Ignored if can_assume(NO_ROLLBACK) + * @return offset of string in the string table (whether found or added) + */ +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); const char *p; @@ -157,6 +132,9 @@ static int fdt_find_add_string_(void *fdt, const char *s) int len = strlen(s) + 1; int err; + if (!can_assume(NO_ROLLBACK)) + *allocated = 0; + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) /* found it */ @@ -167,6 +145,9 @@ static int fdt_find_add_string_(void *fdt, const char *s) if (err) return err; + if (!can_assume(NO_ROLLBACK)) + *allocated = 1; + memcpy(new, s, len); return (new - strtab); } @@ -176,7 +157,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) struct fdt_reserve_entry *re; int err; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); err = fdt_splice_mem_rsv_(fdt, re, 0, 1); @@ -192,7 +173,7 @@ int fdt_del_mem_rsv(void *fdt, int n) { struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; @@ -225,11 +206,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, int nextoffset; int namestroff; int err; + int allocated; if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) return nextoffset; - namestroff = fdt_find_add_string_(fdt, name); + namestroff = fdt_find_add_string_(fdt, name, &allocated); if (namestroff < 0) return namestroff; @@ -237,8 +219,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, proplen = sizeof(**prop) + FDT_TAGALIGN(len); err = fdt_splice_struct_(fdt, *prop, 0, proplen); - if (err) + if (err) { + /* Delete the string if we failed to add it */ + if (!can_assume(NO_ROLLBACK) && allocated) + fdt_del_last_string_(fdt, name); return err; + } (*prop)->tag = cpu_to_fdt32(FDT_PROP); (*prop)->nameoff = cpu_to_fdt32(namestroff); @@ -252,7 +238,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) int oldlen, newlen; int err; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) @@ -275,7 +261,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, struct fdt_property *prop; int err; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) @@ -308,7 +294,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, struct fdt_property *prop; int err, oldlen, newlen; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (prop) { @@ -334,7 +320,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) struct fdt_property *prop; int len, proplen; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (!prop) @@ -354,7 +340,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, uint32_t tag; fdt32_t *endtag; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) @@ -394,7 +380,7 @@ int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) @@ -407,7 +393,7 @@ int fdt_del_node(void *fdt, int nodeoffset) static void fdt_packblocks_(const char *old, char *new, int mem_rsv_size, int struct_size) { - uint32_t mem_rsv_off, struct_off, strings_off; + int mem_rsv_off, struct_off, strings_off; mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); struct_off = mem_rsv_off + mem_rsv_size; @@ -435,12 +421,12 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) const char *fdtend = fdtstart + fdt_totalsize(fdt); char *tmp; - FDT_CHECK_HEADER(fdt); + FDT_RO_PROBE(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - if (fdt_version(fdt) >= 17) { + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { struct_size = fdt_size_dt_struct(fdt); } else { struct_size = 0; @@ -450,7 +436,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) return struct_size; } - if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { + if (can_assume(LIBFDT_ORDER) || + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) @@ -494,7 +481,7 @@ int fdt_pack(void *fdt) { int mem_rsv_size; - FDT_RW_CHECK_HEADER(fdt); + FDT_RW_PROBE(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c index 9677a1887e57..768db66eada5 100644 --- a/scripts/dtc/libfdt/fdt_strerror.c +++ b/scripts/dtc/libfdt/fdt_strerror.c @@ -1,51 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -82,6 +38,7 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_BADVALUE), FDT_ERRTABENT(FDT_ERR_BADOVERLAY), FDT_ERRTABENT(FDT_ERR_NOPHANDLES), + FDT_ERRTABENT(FDT_ERR_BADFLAGS), }; #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c index 6d33cc29d022..94ce4bb91a00 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" @@ -55,21 +10,87 @@ #include "libfdt_internal.h" -static int fdt_sw_check_header_(void *fdt) +static int fdt_sw_probe_(void *fdt) { - if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; - /* FIXME: should check more details about the header state */ + if (!can_assume(VALID_INPUT)) { + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + } + return 0; } -#define FDT_SW_CHECK_HEADER(fdt) \ +#define FDT_SW_PROBE(fdt) \ { \ int err; \ - if ((err = fdt_sw_check_header_(fdt)) != 0) \ + if ((err = fdt_sw_probe_(fdt)) != 0) \ return err; \ } +/* 'memrsv' state: Initial state after fdt_create() + * + * Allowed functions: + * fdt_add_reservemap_entry() + * fdt_finish_reservemap() [moves to 'struct' state] + */ +static int fdt_sw_probe_memrsv_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_MEMRSV(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ + return err; \ + } + +/* 'struct' state: Enter this state after fdt_finish_reservemap() + * + * Allowed functions: + * fdt_begin_node() + * fdt_end_node() + * fdt_property*() + * fdt_finish() [moves to 'complete' state] + */ +static int fdt_sw_probe_struct_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (!can_assume(VALID_INPUT) && + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_STRUCT(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ + return err; \ + } + +static inline uint32_t sw_flags(void *fdt) +{ + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ + return fdt_last_comp_version(fdt); +} + +/* 'complete' state: Enter this state after fdt_finish() + * + * Allowed functions: none + */ + static void *fdt_grab_space_(void *fdt, size_t len) { int offset = fdt_size_dt_struct(fdt); @@ -85,38 +106,59 @@ static void *fdt_grab_space_(void *fdt, size_t len) return fdt_offset_ptr_w_(fdt, offset); } -int fdt_create(void *buf, int bufsize) +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) { + const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); void *fdt = buf; - if (bufsize < sizeof(struct fdt_header)) + if (bufsize < hdrsize) return -FDT_ERR_NOSPACE; + if (flags & ~FDT_CREATE_FLAGS_ALL) + return -FDT_ERR_BADFLAGS; + memset(buf, 0, bufsize); + /* + * magic and last_comp_version keep intermediate state during the fdt + * creation process, which is replaced with the proper FDT format by + * fdt_finish(). + * + * flags should be accessed with sw_flags(). + */ fdt_set_magic(fdt, FDT_SW_MAGIC); fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, flags); + fdt_set_totalsize(fdt, bufsize); - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry))); + fdt_set_off_mem_rsvmap(fdt, hdrsize); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, bufsize); + fdt_set_off_dt_strings(fdt, 0); return 0; } +int fdt_create(void *buf, int bufsize) +{ + return fdt_create_with_flags(buf, bufsize, 0); +} + int fdt_resize(void *fdt, void *buf, int bufsize) { size_t headsize, tailsize; char *oldtail, *newtail; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE(fdt); - headsize = fdt_off_dt_struct(fdt); + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); + if (!can_assume(VALID_DTB) && + headsize + tailsize > fdt_totalsize(fdt)) + return -FDT_ERR_INTERNAL; + if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; @@ -133,8 +175,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize) memmove(buf, fdt, headsize); } - fdt_set_off_dt_strings(buf, bufsize); fdt_set_totalsize(buf, bufsize); + if (fdt_off_dt_strings(buf)) + fdt_set_off_dt_strings(buf, bufsize); return 0; } @@ -144,10 +187,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) struct fdt_reserve_entry *re; int offset; - FDT_SW_CHECK_HEADER(fdt); - - if (fdt_size_dt_struct(fdt)) - return -FDT_ERR_BADSTATE; + FDT_SW_PROBE_MEMRSV(fdt); offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) @@ -164,16 +204,23 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) int fdt_finish_reservemap(void *fdt) { - return fdt_add_reservemap_entry(fdt, 0, 0); + int err = fdt_add_reservemap_entry(fdt, 0, 0); + + if (err) + return err; + + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); + return 0; } int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; - int namelen = strlen(name) + 1; + int namelen; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); + namelen = strlen(name) + 1; nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; @@ -187,7 +234,7 @@ int fdt_end_node(void *fdt) { fdt32_t *en; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); en = fdt_grab_space_(fdt, FDT_TAGSIZE); if (! en) @@ -197,19 +244,13 @@ int fdt_end_node(void *fdt) return 0; } -static int fdt_find_add_string_(void *fdt, const char *s) +static int fdt_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); - const char *p; int strtabsize = fdt_size_dt_strings(fdt); int len = strlen(s) + 1; int struct_top, offset; - p = fdt_find_string_(strtab - strtabsize, strtabsize, s); - if (p) - return p - strtab; - - /* Add it */ offset = -strtabsize - len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); if (fdt_totalsize(fdt) + offset < struct_top) @@ -220,20 +261,56 @@ static int fdt_find_add_string_(void *fdt, const char *s) return offset; } +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, strtabsize - len); +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + int strtabsize = fdt_size_dt_strings(fdt); + const char *p; + + *allocated = 0; + + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + *allocated = 1; + + return fdt_add_string_(fdt, s); +} + int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) { struct fdt_property *prop; int nameoff; + int allocated; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); - nameoff = fdt_find_add_string_(fdt, name); + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { + allocated = 1; + nameoff = fdt_add_string_(fdt, name); + } else { + nameoff = fdt_find_add_string_(fdt, name, &allocated); + } if (nameoff == 0) return -FDT_ERR_NOSPACE; prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); - if (! prop) + if (! prop) { + if (allocated) + fdt_del_last_string_(fdt, name); return -FDT_ERR_NOSPACE; + } prop->tag = cpu_to_fdt32(FDT_PROP); prop->nameoff = cpu_to_fdt32(nameoff); @@ -262,7 +339,7 @@ int fdt_finish(void *fdt) uint32_t tag; int offset, nextoffset; - FDT_SW_CHECK_HEADER(fdt); + FDT_SW_PROBE_STRUCT(fdt); /* Add terminator */ end = fdt_grab_space_(fdt, sizeof(*end)); @@ -295,6 +372,10 @@ int fdt_finish(void *fdt) /* Finally, adjust the header */ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + + /* And fix up fields that were keeping intermediate state. */ + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_magic(fdt, FDT_MAGIC); + return 0; } diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c index 534c1cbbb2f3..f64139e0b3dc 100644 --- a/scripts/dtc/libfdt/fdt_wip.c +++ b/scripts/dtc/libfdt/fdt_wip.c @@ -1,52 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index 1e27780e1185..fe49b5d78938 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -1,59 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_H #define LIBFDT_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "libfdt_env.h" #include "fdt.h" +#ifdef __cplusplus +extern "C" { +#endif + #define FDT_FIRST_SUPPORTED_VERSION 0x02 #define FDT_LAST_SUPPORTED_VERSION 0x11 @@ -90,8 +49,9 @@ /* Error codes: codes for bad device tree blobs */ #define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: Structure block of the given device tree - * ends without an FDT_END tag. */ + /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly + * terminated (overflows, goes outside allowed bounds, or + * isn't properly terminated). */ #define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device @@ -137,7 +97,15 @@ /* FDT_ERR_NOPHANDLES: The device tree doesn't have any * phandle available anymore without causing an overflow */ -#define FDT_ERR_MAX 17 +#define FDT_ERR_BADFLAGS 18 + /* FDT_ERR_BADFLAGS: The function was passed a flags field that + * contains invalid flags or an invalid combination of flags. */ + +#define FDT_ERR_MAX 18 + +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ /**********************************************************************/ /* Low-level functions (you probably don't need these) */ @@ -153,6 +121,61 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); +/* + * Alignment helpers: + * These helpers access words from a device tree blob. They're + * built to work even with unaligned pointers on platforms (ike + * ARM) that don't like unaligned loads and stores + */ + +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +static inline void fdt32_st(void *property, uint32_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 24; + bp[1] = (value >> 16) & 0xff; + bp[2] = (value >> 8) & 0xff; + bp[3] = value & 0xff; +} + +static inline uint64_t fdt64_ld(const fdt64_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; +} + +static inline void fdt64_st(void *property, uint64_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 56; + bp[1] = (value >> 48) & 0xff; + bp[2] = (value >> 40) & 0xff; + bp[3] = (value >> 32) & 0xff; + bp[4] = (value >> 24) & 0xff; + bp[5] = (value >> 16) & 0xff; + bp[6] = (value >> 8) & 0xff; + bp[7] = value & 0xff; +} + /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ @@ -195,7 +218,7 @@ int fdt_next_subnode(const void *fdt, int offset); * ... * } * - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) { + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { * Error handling * } * @@ -213,7 +236,7 @@ int fdt_next_subnode(const void *fdt, int offset); /* General functions */ /**********************************************************************/ #define fdt_get_header(fdt, field) \ - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) @@ -244,18 +267,32 @@ fdt_set_hdr_(size_dt_struct); #undef fdt_set_hdr_ /** - * fdt_check_header - sanity check a device tree or possible device tree + * fdt_header_size - return the size of the tree's header + * @fdt: pointer to a flattened device tree + */ +size_t fdt_header_size(const void *fdt); + +/** + * fdt_header_size_ - internal function which takes a version number + */ +size_t fdt_header_size_(uint32_t version); + +/** + * fdt_check_header - sanity check a device tree header + * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree with sane information in its - * header. + * appears to be a flattened device tree, and that the header contains + * valid information (to the extent that can be determined from the + * header alone). * * returns: * 0, if the buffer appears to contain a valid device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, standard meanings, as above + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings, as above */ int fdt_check_header(const void *fdt); @@ -284,6 +321,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ /**********************************************************************/ +int fdt_check_full(const void *fdt, size_t bufsize); + +/** + * fdt_get_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * @lenp: optional pointer to return the string's length + * + * fdt_get_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt, and optionally also + * returns the string's length in *lenp. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); + /** * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob @@ -294,10 +349,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize); * * returns: * a pointer to the string, on success - * NULL, if stroffset is out of bounds + * NULL, if stroffset is out of bounds, or doesn't point to a valid string */ const char *fdt_string(const void *fdt, int stroffset); +/** + * fdt_find_max_phandle - find and return the highest phandle in a tree + * @fdt: pointer to the device tree blob + * @phandle: return location for the highest phandle value found in the tree + * + * fdt_find_max_phandle() finds the highest phandle value in the given device + * tree. The value returned in @phandle is only valid if the function returns + * success. + * + * returns: + * 0 on success or a negative error code on failure + */ +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); + /** * fdt_get_max_phandle - retrieves the highest phandle in a tree * @fdt: pointer to the device tree blob @@ -306,12 +375,39 @@ const char *fdt_string(const void *fdt, int stroffset); * device tree. This will ignore badly formatted phandles, or phandles * with a value of 0 or -1. * + * This function is deprecated in favour of fdt_find_max_phandle(). + * * returns: * the highest phandle on success * 0, if no phandle was found in the device tree * -1, if an error occurred */ -uint32_t fdt_get_max_phandle(const void *fdt); +static inline uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t phandle; + int err; + + err = fdt_find_max_phandle(fdt, &phandle); + if (err < 0) + return (uint32_t)-1; + + return phandle; +} + +/** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * highest phandle value in the device tree blob) will be returned in the + * @phandle parameter. + * + * Returns: + * 0 on success or a negative error-code on failure + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); /** * fdt_num_mem_rsv - retrieve the number of memory reserve map entries @@ -503,7 +599,7 @@ int fdt_next_property_offset(const void *fdt, int offset); * ... * } * - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) { + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { * Error handling * } * @@ -606,7 +702,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, /** * fdt_getprop_by_offset - retrieve the value of a property at a given offset * @fdt: pointer to the device tree blob - * @ffset: offset of the property to read + * @offset: offset of the property to read * @namep: pointer to a string variable (will be overwritten) or NULL * @lenp: pointer to an integer variable (will be overwritten) or NULL * @@ -1090,7 +1186,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #address-cells property + * 1, if the node has no #size-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, @@ -1297,7 +1393,45 @@ int fdt_nop_node(void *fdt, int nodeoffset); /* Sequential write functions */ /**********************************************************************/ +/* fdt_create_with_flags flags */ +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 + /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property + * names in the fdt. This can result in faster creation times, but + * a larger fdt. */ + +#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) + +/** + * fdt_create_with_flags - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. + * + * fdt_create_with_flags() begins the process of creating a new fdt with + * the sequential write interface. + * + * fdt creation process must end with fdt_finished() to produce a valid fdt. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + * -FDT_ERR_BADFLAGS, flags is not valid + */ +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); + +/** + * fdt_create - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + */ int fdt_create(void *buf, int bufsize); + int fdt_resize(void *fdt, void *buf, int bufsize); int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); int fdt_finish_reservemap(void *fdt); @@ -1313,10 +1447,13 @@ static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) fdt64_t tmp = cpu_to_fdt64(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } + +#ifndef SWIG /* Not available in Python */ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { return fdt_property_u32(fdt, name, val); } +#endif /** * fdt_property_placeholder - add a new property and return a ptr to its value @@ -1765,6 +1902,43 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, #define fdt_appendprop_string(fdt, nodeoffset, name, str) \ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) +/** + * fdt_appendprop_addrrange - append a address range property + * @fdt: pointer to the device tree blob + * @parent: offset of the parent node + * @nodeoffset: offset of the node to add a property at + * @name: name of property + * @addr: start address of a given range + * @size: size of a given range + * + * fdt_appendprop_addrrange() appends an address range value (start + * address and size) to the value of the named property in the given + * node, or creates a new property with that value if it does not + * already exist. + * If "name" is not specified, a default "reg" is used. + * Cell sizes are determined by parent's #address-cells and #size-cells. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain a new property + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size); + /** * fdt_delprop - delete a property * @fdt: pointer to the device tree blob @@ -1899,4 +2073,8 @@ int fdt_overlay_apply(void *fdt, void *fdto); const char *fdt_strerror(int errval); +#ifdef __cplusplus +} +#endif + #endif /* LIBFDT_H */ diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h index bd2474628775..73b6d40450ac 100644 --- a/scripts/dtc/libfdt/libfdt_env.h +++ b/scripts/dtc/libfdt/libfdt_env.h @@ -1,61 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_ENV_H #define LIBFDT_ENV_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. * Copyright 2012 Kim Phillips, Freescale Semiconductor. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include #include #include +#include #ifdef __CHECKER__ #define FDT_FORCE __attribute__((force)) diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h index 7681e192295b..d4e0bd49c037 100644 --- a/scripts/dtc/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt/libfdt_internal.h @@ -1,65 +1,21 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ #ifndef LIBFDT_INTERNAL_H #define LIBFDT_INTERNAL_H /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2006 David Gibson, IBM Corporation. - * - * libfdt is dual licensed: you can use it either under the terms of - * the GPL, or the BSD license, at your option. - * - * a) This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - * - * Alternatively, - * - * b) Redistribution and use in source and binary forms, with or - * without modification, are permitted provided that the following - * conditions are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) -#define FDT_CHECK_HEADER(fdt) \ - { \ - int err_; \ - if ((err_ = fdt_check_header(fdt)) != 0) \ - return err_; \ +int32_t fdt_ro_probe_(const void *fdt); +#define FDT_RO_PROBE(fdt) \ + { \ + int32_t totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ } int fdt_check_node_offset_(const void *fdt, int offset); @@ -92,4 +48,126 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) #define FDT_SW_MAGIC (~FDT_MAGIC) +/**********************************************************************/ +/* Checking controls */ +/**********************************************************************/ + +#ifndef FDT_ASSUME_MASK +#define FDT_ASSUME_MASK 0 +#endif + +/* + * Defines assumptions which can be enabled. Each of these can be enabled + * individually. For maximum safety, don't enable any assumptions! + * + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. + * You should have another method of validating the device tree, such as a + * signature or hash check before using libfdt. + * + * For situations where security is not a concern it may be safe to enable + * ASSUME_SANE. + */ +enum { + /* + * This does essentially no checks. Only the latest device-tree + * version is correctly handled. Inconsistencies or errors in the device + * tree may cause undefined behaviour or crashes. Invalid parameters + * passed to libfdt may do the same. + * + * If an error occurs when modifying the tree it may leave the tree in + * an intermediate (but valid) state. As an example, adding a property + * where there is insufficient space may result in the property name + * being added to the string table even though the property itself is + * not added to the struct section. + * + * Only use this if you have a fully validated device tree with + * the latest supported version and wish to minimise code size. + */ + ASSUME_PERFECT = 0xff, + + /* + * This assumes that the device tree is sane. i.e. header metadata + * and basic hierarchy are correct. + * + * With this assumption enabled, normal device trees produced by libfdt + * and the compiler should be handled safely. Malicious device trees and + * complete garbage may cause libfdt to behave badly or crash. Truncated + * device trees (e.g. those only partially loaded) can also cause + * problems. + * + * Note: Only checks that relate exclusively to the device tree itself + * (not the parameters passed to libfdt) are disabled by this + * assumption. This includes checking headers, tags and the like. + */ + ASSUME_VALID_DTB = 1 << 0, + + /* + * This builds on ASSUME_VALID_DTB and further assumes that libfdt + * functions are called with valid parameters, i.e. not trigger + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any + * extensive checking of parameters and the device tree, making various + * assumptions about correctness. + * + * It doesn't make sense to enable this assumption unless + * ASSUME_VALID_DTB is also enabled. + */ + ASSUME_VALID_INPUT = 1 << 1, + + /* + * This disables checks for device-tree version and removes all code + * which handles older versions. + * + * Only enable this if you know you have a device tree with the latest + * version. + */ + ASSUME_LATEST = 1 << 2, + + /* + * This assumes that it is OK for a failed addition to the device tree, + * due to lack of space or some other problem, to skip any rollback + * steps (such as dropping the property name from the string table). + * This is safe to enable in most circumstances, even though it may + * leave the tree in a sub-optimal state. + */ + ASSUME_NO_ROLLBACK = 1 << 3, + + /* + * This assumes that the device tree components appear in a 'convenient' + * order, i.e. the memory reservation block first, then the structure + * block and finally the string block. + * + * This order is not specified by the device-tree specification, + * but is expected by libfdt. The device-tree compiler always created + * device trees with this order. + * + * This assumption disables a check in fdt_open_into() and removes the + * ability to fix the problem there. This is safe if you know that the + * device tree is correctly ordered. See fdt_blocks_misordered_(). + */ + ASSUME_LIBFDT_ORDER = 1 << 4, + + /* + * This assumes that libfdt itself does not have any internal bugs. It + * drops certain checks that should never be needed unless libfdt has an + * undiscovered bug. + * + * This can generally be considered safe to enable. + */ + ASSUME_LIBFDT_FLAWLESS = 1 << 5, +}; + +/** + * can_assume_() - check if a particular assumption is enabled + * + * @mask: Mask to check (ASSUME_...) + * @return true if that assumption is enabled, else false + */ +static inline bool can_assume_(int mask) +{ + return FDT_ASSUME_MASK & mask; +} + +/** helper macros for checking assumptions */ +#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) + #endif /* LIBFDT_INTERNAL_H */ diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 6e4c367f54b3..032df5878ccc 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -1,24 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" +#include "srcpos.h" /* * Tree building functions @@ -50,7 +36,8 @@ void delete_labels(struct label **labels) label->deleted = 1; } -struct property *build_property(char *name, struct data val) +struct property *build_property(char *name, struct data val, + struct srcpos *srcpos) { struct property *new = xmalloc(sizeof(*new)); @@ -58,6 +45,7 @@ struct property *build_property(char *name, struct data val) new->name = name; new->val = val; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -97,7 +85,8 @@ struct property *reverse_properties(struct property *first) return head; } -struct node *build_node(struct property *proplist, struct node *children) +struct node *build_node(struct property *proplist, struct node *children, + struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); struct node *child; @@ -106,6 +95,7 @@ struct node *build_node(struct property *proplist, struct node *children) new->proplist = reverse_properties(proplist); new->children = children; + new->srcpos = srcpos_copy(srcpos); for_each_child(new, child) { child->parent = new; @@ -114,13 +104,14 @@ struct node *build_node(struct property *proplist, struct node *children) return new; } -struct node *build_node_delete(void) +struct node *build_node_delete(struct srcpos *srcpos) { struct node *new = xmalloc(sizeof(*new)); memset(new, 0, sizeof(*new)); new->deleted = 1; + new->srcpos = srcpos_copy(srcpos); return new; } @@ -183,6 +174,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) old_prop->val = new_prop->val; old_prop->deleted = 0; + free(old_prop->srcpos); + old_prop->srcpos = new_prop->srcpos; free(new_prop); new_prop = NULL; break; @@ -223,6 +216,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node) add_child(old_node, new_child); } + old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos); + /* The new node contents are now merged into the old node. Free * the new node. */ free(new_node); @@ -239,20 +234,21 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) char *name; if (ref[0] == '/') { + d = data_add_marker(d, TYPE_STRING, ref); d = data_append_data(d, ref, strlen(ref) + 1); - p = build_property("target-path", d); + p = build_property("target-path", d, NULL); } else { d = data_add_marker(d, REF_PHANDLE, ref); d = data_append_integer(d, 0xffffffff, 32); - p = build_property("target", d); + p = build_property("target", d, NULL); } xasprintf(&name, "fragment@%u", next_orphan_fragment++); name_node(new_node, "__overlay__"); - node = build_node(p, new_node); + node = build_node(p, new_node, NULL); name_node(node, name); add_child(dt, node); @@ -340,18 +336,21 @@ void delete_node(struct node *node) } void append_to_property(struct node *node, - char *name, const void *data, int len) + char *name, const void *data, int len, + enum markertype type) { struct data d; struct property *p; p = get_property(node, name); if (p) { - d = data_append_data(p->val, data, len); + d = data_add_marker(p->val, type, name); + d = data_append_data(d, data, len); p->val = d; } else { - d = data_append_data(empty_data, data, len); - p = build_property(name, d); + d = data_add_marker(empty_data, type, name); + d = data_append_data(d, data, len); + p = build_property(name, d, NULL); add_property(node, p); } } @@ -527,8 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path) p = strchr(path, '/'); for_each_child(tree, child) { - if (p && (strlen(child->name) == p-path) && - strprefixeq(path, p - path, child->name)) + if (p && strprefixeq(path, p - path, child->name)) return get_node_by_path(child, p+1); else if (!p && streq(path, child->name)) return child; @@ -594,6 +592,7 @@ struct node *get_node_by_ref(struct node *tree, const char *ref) cell_t get_node_phandle(struct node *root, struct node *node) { static cell_t phandle = 1; /* FIXME: ick, static local */ + struct data d = empty_data; if ((node->phandle != 0) && (node->phandle != -1)) return node->phandle; @@ -603,17 +602,16 @@ cell_t get_node_phandle(struct node *root, struct node *node) node->phandle = phandle; + d = data_add_marker(d, TYPE_UINT32, NULL); + d = data_append_cell(d, phandle); + if (!get_property(node, "linux,phandle") && (phandle_format & PHANDLE_LEGACY)) - add_property(node, - build_property("linux,phandle", - data_append_cell(empty_data, phandle))); + add_property(node, build_property("linux,phandle", d, NULL)); if (!get_property(node, "phandle") && (phandle_format & PHANDLE_EPAPR)) - add_property(node, - build_property("phandle", - data_append_cell(empty_data, phandle))); + add_property(node, build_property("phandle", d, NULL)); /* If the node *does* have a phandle property, we must * be dealing with a self-referencing phandle, which will be @@ -787,7 +785,7 @@ static struct node *build_and_name_child_node(struct node *parent, char *name) { struct node *node; - node = build_node(NULL, NULL); + node = build_node(NULL, NULL, NULL); name_node(node, xstrdup(name)); add_child(parent, node); @@ -848,8 +846,9 @@ static void generate_label_tree_internal(struct dt_info *dti, /* insert it */ p = build_property(l->label, - data_copy_mem(node->fullpath, - strlen(node->fullpath) + 1)); + data_copy_escape_string(node->fullpath, + strlen(node->fullpath)), + NULL); add_property(an, p); } @@ -899,7 +898,7 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn, xasprintf(&entry, "%s:%s:%u", node->fullpath, prop->name, m->offset); - append_to_property(fn, m->ref, entry, strlen(entry) + 1); + append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING); free(entry); } @@ -959,7 +958,7 @@ static void add_local_fixup_entry(struct dt_info *dti, char **compp; int i, depth; - /* walk back retreiving depth */ + /* walk back retrieving depth */ depth = 0; for (wn = node; wn; wn = wn->parent) depth++; @@ -982,7 +981,7 @@ static void add_local_fixup_entry(struct dt_info *dti, free(compp); value_32 = cpu_to_fdt32(m->offset); - append_to_property(wn, prop->name, &value_32, sizeof(value_32)); + append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32); } static void generate_local_fixups_tree_internal(struct dt_info *dti, diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index cb6ed0e3e5e4..f5205fb9c1ff 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c @@ -1,20 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #define _GNU_SOURCE @@ -33,6 +19,9 @@ struct search_path { /* This is the list of directories that we search for source files */ static struct search_path *search_path_head, **search_path_tail; +/* Detect infinite include recursion. */ +#define MAX_SRCFILE_DEPTH (100) +static int srcfile_depth; /* = 0 */ static char *get_dirname(const char *path) { @@ -51,11 +40,51 @@ static char *get_dirname(const char *path) FILE *depfile; /* = NULL */ struct srcfile_state *current_srcfile; /* = NULL */ +static char *initial_path; /* = NULL */ +static int initial_pathlen; /* = 0 */ +static bool initial_cpp = true; -/* Detect infinite include recursion. */ -#define MAX_SRCFILE_DEPTH (100) -static int srcfile_depth; /* = 0 */ +static void set_initial_path(char *fname) +{ + int i, len = strlen(fname); + + xasprintf(&initial_path, "%s", fname); + initial_pathlen = 0; + for (i = 0; i != len; i++) + if (initial_path[i] == '/') + initial_pathlen++; +} +static char *shorten_to_initial_path(char *fname) +{ + char *p1, *p2, *prevslash1 = NULL; + int slashes = 0; + + for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) { + if (*p1 != *p2) + break; + if (*p1 == '/') { + prevslash1 = p1; + slashes++; + } + } + p1 = prevslash1 + 1; + if (prevslash1) { + int diff = initial_pathlen - slashes, i, j; + int restlen = strlen(fname) - (p1 - fname); + char *res; + + res = xmalloc((3 * diff) + restlen + 1); + for (i = 0, j = 0; i != diff; i++) { + res[j++] = '.'; + res[j++] = '.'; + res[j++] = '/'; + } + strcpy(res + j, p1); + return res; + } + return NULL; +} /** * Try to open a file in a given directory. @@ -157,6 +186,9 @@ void srcfile_push(const char *fname) srcfile->colno = 1; current_srcfile = srcfile; + + if (srcfile_depth == 1) + set_initial_path(srcfile->name); } bool srcfile_pop(void) @@ -197,18 +229,6 @@ void srcfile_add_search_path(const char *dirname) search_path_tail = &node->next; } -/* - * The empty source position. - */ - -struct srcpos srcpos_empty = { - .first_line = 0, - .first_column = 0, - .last_line = 0, - .last_column = 0, - .file = NULL, -}; - void srcpos_update(struct srcpos *pos, const char *text, int len) { int i; @@ -234,13 +254,35 @@ struct srcpos * srcpos_copy(struct srcpos *pos) { struct srcpos *pos_new; + struct srcfile_state *srcfile_state; + + if (!pos) + return NULL; pos_new = xmalloc(sizeof(struct srcpos)); + assert(pos->next == NULL); memcpy(pos_new, pos, sizeof(struct srcpos)); + /* allocate without free */ + srcfile_state = xmalloc(sizeof(struct srcfile_state)); + memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state)); + pos_new->file = srcfile_state; + return pos_new; } +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail) +{ + struct srcpos *p; + + if (!pos) + return newtail; + + for (p = pos; p->next != NULL; p = p->next); + p->next = newtail; + return pos; +} + char * srcpos_string(struct srcpos *pos) { @@ -266,6 +308,68 @@ srcpos_string(struct srcpos *pos) return pos_str; } +static char * +srcpos_string_comment(struct srcpos *pos, bool first_line, int level) +{ + char *pos_str, *fname, *first, *rest; + bool fresh_fname = false; + + if (!pos) { + if (level > 1) { + xasprintf(&pos_str, ":"); + return pos_str; + } else { + return NULL; + } + } + + if (!pos->file) + fname = ""; + else if (!pos->file->name) + fname = ""; + else if (level > 1) + fname = pos->file->name; + else { + fname = shorten_to_initial_path(pos->file->name); + if (fname) + fresh_fname = true; + else + fname = pos->file->name; + } + + if (level > 1) + xasprintf(&first, "%s:%d:%d-%d:%d", fname, + pos->first_line, pos->first_column, + pos->last_line, pos->last_column); + else + xasprintf(&first, "%s:%d", fname, + first_line ? pos->first_line : pos->last_line); + + if (fresh_fname) + free(fname); + + if (pos->next != NULL) { + rest = srcpos_string_comment(pos->next, first_line, level); + xasprintf(&pos_str, "%s, %s", first, rest); + free(first); + free(rest); + } else { + pos_str = first; + } + + return pos_str; +} + +char *srcpos_string_first(struct srcpos *pos, int level) +{ + return srcpos_string_comment(pos, true, level); +} + +char *srcpos_string_last(struct srcpos *pos, int level) +{ + return srcpos_string_comment(pos, false, level); +} + void srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va) { @@ -294,4 +398,9 @@ void srcpos_set_line(char *f, int l) { current_srcfile->name = f; current_srcfile->lineno = l; + + if (initial_cpp) { + initial_cpp = false; + set_initial_path(f); + } } diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h index 9ded12a3830a..4318d7ad34d9 100644 --- a/scripts/dtc/srcpos.h +++ b/scripts/dtc/srcpos.h @@ -1,20 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #ifndef SRCPOS_H @@ -74,6 +60,7 @@ struct srcpos { int last_line; int last_column; struct srcfile_state *file; + struct srcpos *next; }; #define YYLTYPE struct srcpos @@ -93,19 +80,18 @@ struct srcpos { YYRHSLOC(Rhs, 0).last_column; \ (Current).file = YYRHSLOC (Rhs, 0).file; \ } \ + (Current).next = NULL; \ } while (0) -/* - * Fictional source position used for IR nodes that are - * created without otherwise knowing a true source position. - * For example,constant definitions from the command line. - */ -extern struct srcpos srcpos_empty; - extern void srcpos_update(struct srcpos *pos, const char *text, int len); extern struct srcpos *srcpos_copy(struct srcpos *pos); +extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos, + struct srcpos *old_srcpos); extern char *srcpos_string(struct srcpos *pos); +extern char *srcpos_string_first(struct srcpos *pos, int level); +extern char *srcpos_string_last(struct srcpos *pos, int level); + extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix, const char *fmt, va_list va); diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c index 2461a3d068a0..061ba8c9c5e8 100644 --- a/scripts/dtc/treesource.c +++ b/scripts/dtc/treesource.c @@ -1,21 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright David Gibson , IBM Corporation. 2005. - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include "dtc.h" @@ -61,24 +46,18 @@ static bool isstring(char c) || strchr("\a\b\t\n\v\f\r", c)); } -static void write_propval_string(FILE *f, struct data val) +static void write_propval_string(FILE *f, const char *s, size_t len) { - const char *str = val.val; - int i; - struct marker *m = val.markers; - - assert(str[val.len-1] == '\0'); + const char *end = s + len - 1; - while (m && (m->offset == 0)) { - if (m->type == LABEL) - fprintf(f, "%s: ", m->ref); - m = m->next; - } - fprintf(f, "\""); + if (!len) + return; - for (i = 0; i < (val.len-1); i++) { - char c = str[i]; + assert(*end == '\0'); + fprintf(f, "\""); + while (s < end) { + char c = *s++; switch (c) { case '\a': fprintf(f, "\\a"); @@ -108,91 +87,80 @@ static void write_propval_string(FILE *f, struct data val) fprintf(f, "\\\""); break; case '\0': - fprintf(f, "\", "); - while (m && (m->offset <= (i + 1))) { - if (m->type == LABEL) { - assert(m->offset == (i+1)); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } - fprintf(f, "\""); + fprintf(f, "\\0"); break; default: if (isprint((unsigned char)c)) fprintf(f, "%c", c); else - fprintf(f, "\\x%02hhx", c); + fprintf(f, "\\x%02"PRIx8, c); } } fprintf(f, "\""); - - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } } -static void write_propval_cells(FILE *f, struct data val) +static void write_propval_int(FILE *f, const char *p, size_t len, size_t width) { - void *propend = val.val + val.len; - fdt32_t *cp = (fdt32_t *)val.val; - struct marker *m = val.markers; - - fprintf(f, "<"); - for (;;) { - while (m && (m->offset <= ((char *)cp - val.val))) { - if (m->type == LABEL) { - assert(m->offset == ((char *)cp - val.val)); - fprintf(f, "%s: ", m->ref); - } - m = m->next; - } + const char *end = p + len; + assert(len % width == 0); - fprintf(f, "0x%x", fdt32_to_cpu(*cp++)); - if ((void *)cp >= propend) + for (; p < end; p += width) { + switch (width) { + case 1: + fprintf(f, "%02"PRIx8, *(const uint8_t*)p); + break; + case 2: + fprintf(f, "0x%02"PRIx16, dtb_ld16(p)); break; - fprintf(f, " "); + case 4: + fprintf(f, "0x%02"PRIx32, dtb_ld32(p)); + break; + case 8: + fprintf(f, "0x%02"PRIx64, dtb_ld64(p)); + break; + } + if (p + width < end) + fputc(' ', f); } +} - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } - fprintf(f, ">"); +static bool has_data_type_information(struct marker *m) +{ + return m->type >= TYPE_UINT8; } -static void write_propval_bytes(FILE *f, struct data val) +static struct marker *next_type_marker(struct marker *m) { - void *propend = val.val + val.len; - const char *bp = val.val; - struct marker *m = val.markers; - - fprintf(f, "["); - for (;;) { - while (m && (m->offset == (bp-val.val))) { - if (m->type == LABEL) - fprintf(f, "%s: ", m->ref); - m = m->next; - } + while (m && !has_data_type_information(m)) + m = m->next; + return m; +} - fprintf(f, "%02hhx", (unsigned char)(*bp++)); - if ((const void *)bp >= propend) - break; - fprintf(f, " "); - } +size_t type_marker_length(struct marker *m) +{ + struct marker *next = next_type_marker(m->next); - /* Wrap up any labels at the end of the value */ - for_each_marker_of_type(m, LABEL) { - assert (m->offset == val.len); - fprintf(f, " %s:", m->ref); - } - fprintf(f, "]"); + if (next) + return next->offset - m->offset; + return 0; } -static void write_propval(FILE *f, struct property *prop) +static const char *delim_start[] = { + [TYPE_UINT8] = "[", + [TYPE_UINT16] = "/bits/ 16 <", + [TYPE_UINT32] = "<", + [TYPE_UINT64] = "/bits/ 64 <", + [TYPE_STRING] = "", +}; +static const char *delim_end[] = { + [TYPE_UINT8] = "]", + [TYPE_UINT16] = ">", + [TYPE_UINT32] = ">", + [TYPE_UINT64] = ">", + [TYPE_STRING] = "", +}; + +static enum markertype guess_value_type(struct property *prop) { int len = prop->val.len; const char *p = prop->val.val; @@ -201,11 +169,6 @@ static void write_propval(FILE *f, struct property *prop) int nnotstringlbl = 0, nnotcelllbl = 0; int i; - if (len == 0) { - fprintf(f, ";\n"); - return; - } - for (i = 0; i < len; i++) { if (! isstring(p[i])) nnotstring++; @@ -220,17 +183,99 @@ static void write_propval(FILE *f, struct property *prop) nnotcelllbl++; } - fprintf(f, " = "); - if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul)) + if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul)) && (nnotstringlbl == 0)) { - write_propval_string(f, prop->val); + return TYPE_STRING; } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) { - write_propval_cells(f, prop->val); - } else { - write_propval_bytes(f, prop->val); + return TYPE_UINT32; + } + + return TYPE_UINT8; +} + +static void write_propval(FILE *f, struct property *prop) +{ + size_t len = prop->val.len; + struct marker *m = prop->val.markers; + struct marker dummy_marker; + enum markertype emit_type = TYPE_NONE; + char *srcstr; + + if (len == 0) { + fprintf(f, ";"); + if (annotate) { + srcstr = srcpos_string_first(prop->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); + return; } - fprintf(f, ";\n"); + fprintf(f, " ="); + + if (!next_type_marker(m)) { + /* data type information missing, need to guess */ + dummy_marker.type = guess_value_type(prop); + dummy_marker.next = prop->val.markers; + dummy_marker.offset = 0; + dummy_marker.ref = NULL; + m = &dummy_marker; + } + + for_each_marker(m) { + size_t chunk_len = (m->next ? m->next->offset : len) - m->offset; + size_t data_len = type_marker_length(m) ? : len - m->offset; + const char *p = &prop->val.val[m->offset]; + + if (has_data_type_information(m)) { + emit_type = m->type; + fprintf(f, " %s", delim_start[emit_type]); + } else if (m->type == LABEL) + fprintf(f, " %s:", m->ref); + else if (m->offset) + fputc(' ', f); + + if (emit_type == TYPE_NONE) { + assert(chunk_len == 0); + continue; + } + + switch(emit_type) { + case TYPE_UINT16: + write_propval_int(f, p, chunk_len, 2); + break; + case TYPE_UINT32: + write_propval_int(f, p, chunk_len, 4); + break; + case TYPE_UINT64: + write_propval_int(f, p, chunk_len, 8); + break; + case TYPE_STRING: + write_propval_string(f, p, chunk_len); + break; + default: + write_propval_int(f, p, chunk_len, 1); + } + + if (chunk_len == data_len) { + size_t pos = m->offset + chunk_len; + fprintf(f, pos == len ? "%s" : "%s,", + delim_end[emit_type] ? : ""); + emit_type = TYPE_NONE; + } + } + fprintf(f, ";"); + if (annotate) { + srcstr = srcpos_string_first(prop->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); } static void write_tree_source_node(FILE *f, struct node *tree, int level) @@ -238,14 +283,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) struct property *prop; struct node *child; struct label *l; + char *srcstr; write_prefix(f, level); for_each_label(tree->labels, l) fprintf(f, "%s: ", l->label); if (tree->name && (*tree->name)) - fprintf(f, "%s {\n", tree->name); + fprintf(f, "%s {", tree->name); else - fprintf(f, "/ {\n"); + fprintf(f, "/ {"); + + if (annotate) { + srcstr = srcpos_string_first(tree->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); for_each_property(tree, prop) { write_prefix(f, level+1); @@ -259,10 +314,17 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level) write_tree_source_node(f, child, level+1); } write_prefix(f, level); - fprintf(f, "};\n"); + fprintf(f, "};"); + if (annotate) { + srcstr = srcpos_string_last(tree->srcpos, annotate); + if (srcstr) { + fprintf(f, " /* %s */", srcstr); + free(srcstr); + } + } + fprintf(f, "\n"); } - void dt_to_source(FILE *f, struct dt_info *dti) { struct reserve_info *re; @@ -281,4 +343,3 @@ void dt_to_source(FILE *f, struct dt_info *dti) write_tree_source_node(f, dti->dt, 0); } - diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh index 1a009fd195d0..7dd29a0362b8 100755 --- a/scripts/dtc/update-dtc-source.sh +++ b/scripts/dtc/update-dtc-source.sh @@ -32,7 +32,7 @@ DTC_UPSTREAM_PATH=`pwd`/../dtc DTC_LINUX_PATH=`pwd`/scripts/dtc DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ - srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \ + srcpos.h treesource.c util.c util.h version_gen.h yamltree.c Makefile.dtc \ dtc-lexer.l dtc-parser.y" LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \ diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 9953c32a0244..40274fb79236 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -1,24 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. * * util_is_printable_string contributed by * Pantelis Antoniou - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #include @@ -27,6 +13,7 @@ #include #include #include +#include #include #include @@ -46,36 +33,54 @@ char *xstrdup(const char *s) return d; } -/* based in part from (3) vsnprintf */ -int xasprintf(char **strp, const char *fmt, ...) +int xavsprintf_append(char **strp, const char *fmt, va_list ap) { - int n, size = 128; /* start with 128 bytes */ + int n, size = 0; /* start with 128 bytes */ char *p; - va_list ap; + va_list ap_copy; - /* initial pointer is NULL making the fist realloc to be malloc */ - p = NULL; - while (1) { - p = xrealloc(p, size); + p = *strp; + if (p) + size = strlen(p); - /* Try to print in the allocated space. */ - va_start(ap, fmt); - n = vsnprintf(p, size, fmt, ap); - va_end(ap); + va_copy(ap_copy, ap); + n = vsnprintf(NULL, 0, fmt, ap_copy) + 1; + va_end(ap_copy); + + p = xrealloc(p, size + n); + + n = vsnprintf(p + size, n, fmt, ap); - /* If that worked, return the string. */ - if (n > -1 && n < size) - break; - /* Else try again with more space. */ - if (n > -1) /* glibc 2.1 */ - size = n + 1; /* precisely what is needed */ - else /* glibc 2.0 */ - size *= 2; /* twice the old size */ - } *strp = p; return strlen(p); } +int xasprintf_append(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + + va_start(ap, fmt); + n = xavsprintf_append(strp, fmt, ap); + va_end(ap); + + return n; +} + +int xasprintf(char **strp, const char *fmt, ...) +{ + int n; + va_list ap; + + *strp = NULL; + + va_start(ap, fmt); + n = xavsprintf_append(strp, fmt, ap); + va_end(ap); + + return n; +} + char *join_path(const char *path, const char *name) { int lenp = strlen(path); @@ -227,11 +232,11 @@ char get_escape_char(const char *s, int *i) return val; } -int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) +int utilfdt_read_err(const char *filename, char **buffp, size_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; - off_t bufsize = 1024, offset = 0; + size_t bufsize = 1024, offset = 0; int ret = 0; *buffp = NULL; @@ -264,20 +269,15 @@ int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) free(buf); else *buffp = buf; - *len = bufsize; + if (len) + *len = bufsize; return ret; } -int utilfdt_read_err(const char *filename, char **buffp) -{ - off_t len; - return utilfdt_read_err_len(filename, buffp, &len); -} - -char *utilfdt_read_len(const char *filename, off_t *len) +char *utilfdt_read(const char *filename, size_t *len) { char *buff; - int ret = utilfdt_read_err_len(filename, &buff, len); + int ret = utilfdt_read_err(filename, &buff, len); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, @@ -288,12 +288,6 @@ char *utilfdt_read_len(const char *filename, off_t *len) return buff; } -char *utilfdt_read(const char *filename) -{ - off_t len; - return utilfdt_read_len(filename, &len); -} - int utilfdt_write_err(const char *filename, const void *blob) { int fd = 1; /* assume stdout */ @@ -400,7 +394,7 @@ void utilfdt_print_data(const char *data, int len) printf(" = <"); for (i = 0, len /= 4; i < len; i++) - printf("0x%08x%s", fdt32_to_cpu(cell[i]), + printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]), i < (len - 1) ? " " : ""); printf(">"); } else { diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index 66fba8ea709b..5a4172dd0f84 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef UTIL_H #define UTIL_H @@ -8,25 +9,14 @@ /* * Copyright 2011 The Chromium Authors, All Rights Reserved. * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA */ #ifdef __GNUC__ +#ifdef __clang__ #define PRINTF(i, j) __attribute__((format (printf, i, j))) +#else +#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j))) +#endif #define NORETURN __attribute__((noreturn)) #else #define PRINTF(i, j) @@ -72,6 +62,8 @@ static inline void *xrealloc(void *p, size_t len) extern char *xstrdup(const char *s); extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...); +extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...); +extern int xavsprintf_append(char **strp, const char *fmt, va_list ap); extern char *join_path(const char *path, const char *name); /** @@ -98,16 +90,10 @@ char get_escape_char(const char *s, int *i); * stderr. * * @param filename The filename to read, or - for stdin - * @return Pointer to allocated buffer containing fdt, or NULL on error - */ -char *utilfdt_read(const char *filename); - -/** - * Like utilfdt_read(), but also passes back the size of the file read. - * * @param len If non-NULL, the amount of data we managed to read + * @return Pointer to allocated buffer containing fdt, or NULL on error */ -char *utilfdt_read_len(const char *filename, off_t *len); +char *utilfdt_read(const char *filename, size_t *len); /** * Read a device tree file into a buffer. Does not report errors, but only @@ -116,23 +102,17 @@ char *utilfdt_read_len(const char *filename, off_t *len); * * @param filename The filename to read, or - for stdin * @param buffp Returns pointer to buffer containing fdt - * @return 0 if ok, else an errno value representing the error - */ -int utilfdt_read_err(const char *filename, char **buffp); - -/** - * Like utilfdt_read_err(), but also passes back the size of the file read. - * * @param len If non-NULL, the amount of data we managed to read + * @return 0 if ok, else an errno value representing the error */ -int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); +int utilfdt_read_err(const char *filename, char **buffp, size_t *len); /** * Write a device tree buffer to a file. This will report any errors on * stderr. * * @param filename The filename to write, or - for stdout - * @param blob Poiner to buffer containing fdt + * @param blob Pointer to buffer containing fdt * @return 0 if ok, -1 on error */ int utilfdt_write(const char *filename, const void *blob); @@ -143,7 +123,7 @@ int utilfdt_write(const char *filename, const void *blob); * an error message for the user. * * @param filename The filename to write, or - for stdout - * @param blob Poiner to buffer containing fdt + * @param blob Pointer to buffer containing fdt * @return 0 if ok, else an errno value representing the error */ int utilfdt_write_err(const char *filename, const void *blob); diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index b00f14ff7a17..0714799446f8 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.6-g84e414b0" +#define DTC_VERSION "DTC 1.6.0-g9d7888cb" diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c new file mode 100644 index 000000000000..261561f3c5cb --- /dev/null +++ b/scripts/dtc/yamltree.c @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * (C) Copyright Linaro, Ltd. 2018 + * (C) Copyright Arm Holdings. 2017 + * (C) Copyright David Gibson , IBM Corporation. 2005. + */ + +#include +#include +#include "dtc.h" +#include "srcpos.h" + +char *yaml_error_name[] = { + [YAML_NO_ERROR] = "no error", + [YAML_MEMORY_ERROR] = "memory error", + [YAML_READER_ERROR] = "reader error", + [YAML_SCANNER_ERROR] = "scanner error", + [YAML_PARSER_ERROR] = "parser error", + [YAML_COMPOSER_ERROR] = "composer error", + [YAML_WRITER_ERROR] = "writer error", + [YAML_EMITTER_ERROR] = "emitter error", +}; + +#define yaml_emitter_emit_or_die(emitter, event) ( \ +{ \ + if (!yaml_emitter_emit(emitter, event)) \ + die("yaml '%s': %s in %s, line %i\n", \ + yaml_error_name[(emitter)->error], \ + (emitter)->problem, __func__, __LINE__); \ +}) + +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width) +{ + yaml_event_t event; + void *tag; + int off, start_offset = markers->offset; + + switch(width) { + case 1: tag = "!u8"; break; + case 2: tag = "!u16"; break; + case 4: tag = "!u32"; break; + case 8: tag = "!u64"; break; + default: + die("Invalid width %i", width); + } + assert(len % width == 0); + + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for (off = 0; off < len; off += width) { + char buf[32]; + struct marker *m; + bool is_phandle = false; + + switch(width) { + case 1: + sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off)); + break; + case 2: + sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off)); + break; + case 4: + sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off)); + m = markers; + is_phandle = false; + for_each_marker_of_type(m, REF_PHANDLE) { + if (m->offset == (start_offset + off)) { + is_phandle = true; + break; + } + } + break; + case 8: + sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off)); + break; + } + + if (is_phandle) + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t*)"!phandle", (yaml_char_t *)buf, + strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE); + else + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf, + strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + } + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + +static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len) +{ + yaml_event_t event; + int i; + + assert(str[len-1] == '\0'); + + /* Make sure the entire string is in the lower 7-bit ascii range */ + for (i = 0; i < len; i++) + assert(isascii(str[i])); + + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str, + len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); +} + +static void yaml_propval(yaml_emitter_t *emitter, struct property *prop) +{ + yaml_event_t event; + int len = prop->val.len; + struct marker *m = prop->val.markers; + + /* Emit the property name */ + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name, + strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + /* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */ + if (len == 0) { + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_BOOL_TAG, + (yaml_char_t*)"true", + strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + return; + } + + if (!m) + die("No markers present in property '%s' value\n", prop->name); + + yaml_sequence_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + /* Ensure we have a type marker before any phandle */ + for_each_marker(m) { + int last_offset = 0; + struct marker *type_m; + + if (m->type >= TYPE_UINT8) + last_offset = m->offset; + + if (!(m->next && m->next->type == REF_PHANDLE && + last_offset < m->next->offset)) + continue; + + type_m = xmalloc(sizeof(*type_m)); + type_m->offset = m->next->offset; + type_m->type = TYPE_UINT32; + type_m->ref = NULL; + type_m->next = m->next; + m->next = type_m; + } + + m = prop->val.markers; + for_each_marker(m) { + int chunk_len; + char *data = &prop->val.val[m->offset]; + + if (m->type < TYPE_UINT8) + continue; + + chunk_len = type_marker_length(m) ? : len; + assert(chunk_len > 0); + len -= chunk_len; + + switch(m->type) { + case TYPE_UINT16: + yaml_propval_int(emitter, m, data, chunk_len, 2); + break; + case TYPE_UINT32: + yaml_propval_int(emitter, m, data, chunk_len, 4); + break; + case TYPE_UINT64: + yaml_propval_int(emitter, m, data, chunk_len, 8); + break; + case TYPE_STRING: + yaml_propval_string(emitter, data, chunk_len); + break; + default: + yaml_propval_int(emitter, m, data, chunk_len, 1); + break; + } + } + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + + +static void yaml_tree(struct node *tree, yaml_emitter_t *emitter) +{ + struct property *prop; + struct node *child; + yaml_event_t event; + + if (tree->deleted) + return; + + yaml_mapping_start_event_initialize(&event, NULL, + (yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + + for_each_property(tree, prop) + yaml_propval(emitter, prop); + + /* Loop over all the children, emitting them into the map */ + for_each_child(tree, child) { + yaml_scalar_event_initialize(&event, NULL, + (yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name, + strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE); + yaml_emitter_emit_or_die(emitter, &event); + yaml_tree(child, emitter); + } + + yaml_mapping_end_event_initialize(&event); + yaml_emitter_emit_or_die(emitter, &event); +} + +void dt_to_yaml(FILE *f, struct dt_info *dti) +{ + yaml_emitter_t emitter; + yaml_event_t event; + + yaml_emitter_initialize(&emitter); + yaml_emitter_set_output_file(&emitter, f); + yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_tree(dti->dt, &emitter); + + yaml_sequence_end_event_initialize(&event); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_document_end_event_initialize(&event, 0); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_stream_end_event_initialize(&event); + yaml_emitter_emit_or_die(&emitter, &event); + + yaml_emitter_delete(&emitter); +} diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 846dde7accca..3c88af58092b 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -24,7 +24,7 @@ if [ -n "$CONFIG_UNUSED_KSYMS_WHITELIST" ]; then # Use 'eval' to expand the whitelist path and check if it is relative eval ksym_wl="$CONFIG_UNUSED_KSYMS_WHITELIST" [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" - if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then + if [ ! -f "$ksym_wl" ]; then echo "ERROR: '$ksym_wl' whitelist file not found" >&2 exit 1 fi diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 4b2711c23f4e..c0c18d1bac86 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -28,7 +28,7 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) #endif -#define KSYM_NAME_LEN 128 +#define KSYM_NAME_LEN 256 struct sym_entry { unsigned long long addr; diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c index 5ca2df790d3c..389814b02d06 100644 --- a/scripts/kconfig/preprocess.c +++ b/scripts/kconfig/preprocess.c @@ -111,7 +111,7 @@ static char *do_error_if(int argc, char *argv[]) if (!strcmp(argv[0], "y")) pperror("%s", argv[1]); - return NULL; + return xstrdup(""); } static char *do_filename(int argc, char *argv[]) diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index 929196065232..a073837a3fd4 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -401,7 +401,7 @@ static uint32_t (*w2)(uint16_t); static int is_mcounted_section_name(char const *const txtname) { - return strcmp(".text", txtname) == 0 || + return strncmp(".text", txtname, 5) == 0 || strcmp(".init.text", txtname) == 0 || strcmp(".ref.text", txtname) == 0 || strcmp(".sched.text", txtname) == 0 || diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index f599031260d5..9a8fe8ea6b03 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -142,6 +142,11 @@ ".text.unlikely" => 1, ); +# Acceptable section-prefixes to record. +my %text_section_prefixes = ( + ".text." => 1, +); + # Note: we are nice to C-programmers here, thus we skip the '||='-idiom. $objdump = 'objdump' if (!$objdump); $objcopy = 'objcopy' if (!$objcopy); @@ -263,7 +268,11 @@ sub check_objcopy # force flags for this arch $ld .= " -m shlelf_linux"; - $objcopy .= " -O elf32-sh-linux"; + if ($endian eq "big") { + $objcopy .= " -O elf32-shbig-linux"; + } else { + $objcopy .= " -O elf32-sh-linux"; + } } elsif ($arch eq "powerpc") { my $ldemulation; @@ -519,6 +528,14 @@ sub update_funcs # Only record text sections that we know are safe $read_function = defined($text_sections{$1}); + if (!$read_function) { + foreach my $prefix (keys %text_section_prefixes) { + if (substr($1, 0, length $prefix) eq $prefix) { + $read_function = 1; + last; + } + } + } # print out any recorded offsets update_funcs(); diff --git a/scripts/setlocalversion b/scripts/setlocalversion index c2e8455b3aeb..e02959536644 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -204,15 +204,6 @@ res="${res}${CONFIG_LOCALVERSION}${LOCALVERSION}" if test "$CONFIG_LOCALVERSION_AUTO" = "y"; then # full scm version string res="$res$(scm_version)" -else - # append a plus sign if the repository is not in a clean - # annotated or signed tagged state (as git describe only - # looks at signed or annotated tags - git tag -a/-s) and - # LOCALVERSION= is not specified - if test "${LOCALVERSION+set}" != "set"; then - scm=$(scm_version --short) - res="$res${scm:++}" - fi fi echo "$res" diff --git a/security/commoncap.c b/security/commoncap.c index b43f5ef2c677..b0e7cba705c2 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -381,10 +381,11 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, { int size, ret; kuid_t kroot; + u32 nsmagic, magic; uid_t root, mappedroot; char *tmpbuf = NULL; struct vfs_cap_data *cap; - struct vfs_ns_cap_data *nscap; + struct vfs_ns_cap_data *nscap = NULL; struct dentry *dentry; struct user_namespace *fs_ns; @@ -406,46 +407,61 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, fs_ns = inode->i_sb->s_user_ns; cap = (struct vfs_cap_data *) tmpbuf; if (is_v2header((size_t) ret, cap)) { - /* If this is sizeof(vfs_cap_data) then we're ok with the - * on-disk value, so return that. */ - if (alloc) - *buffer = tmpbuf; - else - kfree(tmpbuf); - return ret; - } else if (!is_v3header((size_t) ret, cap)) { - kfree(tmpbuf); - return -EINVAL; + root = 0; + } else if (is_v3header((size_t) ret, cap)) { + nscap = (struct vfs_ns_cap_data *) tmpbuf; + root = le32_to_cpu(nscap->rootid); + } else { + size = -EINVAL; + goto out_free; } - nscap = (struct vfs_ns_cap_data *) tmpbuf; - root = le32_to_cpu(nscap->rootid); kroot = make_kuid(fs_ns, root); /* If the root kuid maps to a valid uid in current ns, then return * this as a nscap. */ mappedroot = from_kuid(current_user_ns(), kroot); if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) { + size = sizeof(struct vfs_ns_cap_data); if (alloc) { - *buffer = tmpbuf; + if (!nscap) { + /* v2 -> v3 conversion */ + nscap = kzalloc(size, GFP_ATOMIC); + if (!nscap) { + size = -ENOMEM; + goto out_free; + } + nsmagic = VFS_CAP_REVISION_3; + magic = le32_to_cpu(cap->magic_etc); + if (magic & VFS_CAP_FLAGS_EFFECTIVE) + nsmagic |= VFS_CAP_FLAGS_EFFECTIVE; + memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32); + nscap->magic_etc = cpu_to_le32(nsmagic); + } else { + /* use allocated v3 buffer */ + tmpbuf = NULL; + } nscap->rootid = cpu_to_le32(mappedroot); - } else - kfree(tmpbuf); - return size; + *buffer = nscap; + } + goto out_free; } if (!rootid_owns_currentns(kroot)) { - kfree(tmpbuf); - return -EOPNOTSUPP; + size = -EOVERFLOW; + goto out_free; } /* This comes from a parent namespace. Return as a v2 capability */ size = sizeof(struct vfs_cap_data); if (alloc) { - *buffer = kmalloc(size, GFP_ATOMIC); - if (*buffer) { - struct vfs_cap_data *cap = *buffer; - __le32 nsmagic, magic; + if (nscap) { + /* v3 -> v2 conversion */ + cap = kzalloc(size, GFP_ATOMIC); + if (!cap) { + size = -ENOMEM; + goto out_free; + } magic = VFS_CAP_REVISION_2; nsmagic = le32_to_cpu(nscap->magic_etc); if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE) @@ -453,9 +469,12 @@ int cap_inode_getsecurity(struct inode *inode, const char *name, void **buffer, memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32); cap->magic_etc = cpu_to_le32(magic); } else { - size = -ENOMEM; + /* use unconverted v2 */ + tmpbuf = NULL; } + *buffer = cap; } +out_free: kfree(tmpbuf); return size; } diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index f4f3de5f06ca..f0b244989734 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -415,7 +415,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) loff_t i_size; int rc; struct file *f = file; - bool new_file_instance = false, modified_mode = false; + bool new_file_instance = false; /* * For consistency, fail file's opened with the O_DIRECT flag on @@ -433,18 +433,10 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL); flags |= O_RDONLY; f = dentry_open(&file->f_path, flags, file->f_cred); - if (IS_ERR(f)) { - /* - * Cannot open the file again, lets modify f_mode - * of original and continue - */ - pr_info_ratelimited("Unable to reopen file for reading.\n"); - f = file; - f->f_mode |= FMODE_READ; - modified_mode = true; - } else { - new_file_instance = true; - } + if (IS_ERR(f)) + return PTR_ERR(f); + + new_file_instance = true; } i_size = i_size_read(file_inode(f)); @@ -459,8 +451,6 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) out: if (new_file_instance) fput(f); - else if (modified_mode) - f->f_mode &= ~FMODE_READ; return rc; } @@ -651,7 +641,7 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, return calc_buffer_shash(buf, len, hash); } -static void __init ima_pcrread(int idx, u8 *pcr) +static void ima_pcrread(int idx, u8 *pcr) { if (!ima_tpm_chip) return; diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 16bd18747cfa..c49f05471de7 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -106,7 +106,7 @@ void ima_add_kexec_buffer(struct kimage *image) kexec_segment_size = ALIGN(ima_get_binary_runtime_size() + PAGE_SIZE / 2, PAGE_SIZE); if ((kexec_segment_size == ULONG_MAX) || - ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages / 2)) { + ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages() / 2)) { pr_err("Binary measurement list too large.\n"); return; } @@ -124,6 +124,7 @@ void ima_add_kexec_buffer(struct kimage *image) ret = kexec_add_buffer(&kbuf); if (ret) { pr_err("Error passing over kexec measurement buffer.\n"); + vfree(kexec_buffer); return; } @@ -133,6 +134,8 @@ void ima_add_kexec_buffer(struct kimage *image) return; } + image->ima_buffer = kexec_buffer; + pr_debug("kexec measurement buffer for the loaded kernel at 0x%lx.\n", kbuf.mem); } diff --git a/security/integrity/ima/ima_mok.c b/security/integrity/ima/ima_mok.c index 073ddc9bce5b..3e7a1523663b 100644 --- a/security/integrity/ima/ima_mok.c +++ b/security/integrity/ima/ima_mok.c @@ -43,13 +43,12 @@ __init int ima_mok_init(void) (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH, - KEY_ALLOC_NOT_IN_QUOTA, + KEY_ALLOC_NOT_IN_QUOTA | + KEY_ALLOC_SET_KEEP, restriction, NULL); if (IS_ERR(ima_blacklist_keyring)) panic("Can't allocate IMA blacklist keyring."); - - set_bit(KEY_FLAG_KEEP, &ima_blacklist_keyring->flags); return 0; } device_initcall(ima_mok_init); diff --git a/security/keys/key.c b/security/keys/key.c index d5fa8c4fc554..d3ebc0533e3a 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -305,6 +305,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->flags |= 1 << KEY_FLAG_BUILTIN; if (flags & KEY_ALLOC_UID_KEYRING) key->flags |= 1 << KEY_FLAG_UID_KEYRING; + if (flags & KEY_ALLOC_SET_KEEP) + key->flags |= 1 << KEY_FLAG_KEEP; #ifdef KEY_DEBUGGING key->magic = KEY_DEBUG_MAGIC; diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 09545c42977e..9179a5bbf998 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -796,7 +796,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, case Opt_migratable: if (*args[0].from == '0') pay->migratable = 0; - else + else if (*args[0].from != '1') return -EINVAL; break; case Opt_pcrlock: diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 33028c098ef3..d6fea68d22ad 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -277,7 +277,9 @@ static void dump_common_audit_data(struct audit_buffer *ab, struct inode *inode; audit_log_format(ab, " name="); + spin_lock(&a->u.dentry->d_lock); audit_log_untrustedstring(ab, a->u.dentry->d_name.name); + spin_unlock(&a->u.dentry->d_lock); inode = d_backing_inode(a->u.dentry); if (inode) { @@ -295,8 +297,9 @@ static void dump_common_audit_data(struct audit_buffer *ab, dentry = d_find_alias(inode); if (dentry) { audit_log_format(ab, " name="); - audit_log_untrustedstring(ab, - dentry->d_name.name); + spin_lock(&dentry->d_lock); + audit_log_untrustedstring(ab, dentry->d_name.name); + spin_unlock(&dentry->d_lock); dput(dentry); } audit_log_format(ab, " dev="); diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 8297e48a283d..2728517339a1 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig @@ -1,6 +1,6 @@ config SECURITY_SELINUX bool "NSA SELinux Support" - depends on SECURITY_NETWORK && AUDIT && NET && INET + depends on SECURITY_NETWORK && NET && INET select NETWORK_SECMARK default n help diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 6c7702071c04..308a0c771d64 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -771,6 +771,10 @@ noinline int slow_avc_audit(struct selinux_state *state, struct common_audit_data stack_data; struct selinux_audit_data sad; + /* Only log permissive=1 messages for SECURITY_SELINUX_DEVELOP */ + if (denied && !result) + return 0; + if (!a) { a = &stack_data; a->type = LSM_AUDIT_DATA_NONE; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 305890cab97b..15284c59102f 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -100,7 +100,7 @@ #include "audit.h" #include "avc_ss.h" -struct selinux_state selinux_state __rticdata; +struct selinux_state selinux_state; /* SECMARK reference count */ static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0); @@ -1553,6 +1553,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent u16 sclass; struct dentry *dentry; #define INITCONTEXTLEN 255 + char context_onstack[INITCONTEXTLEN + 1]; char *context = NULL; unsigned len = 0; int rc = 0; @@ -1619,21 +1620,14 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent * inode_doinit with a dentry, before these inodes could * be used again by userspace. */ - goto out; + goto out_invalid; } len = INITCONTEXTLEN; - context = kmalloc(len+1, GFP_NOFS); - if (!context) { - rc = -ENOMEM; - dput(dentry); - goto out; - } + context = context_onstack; context[len] = '\0'; rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len); if (rc == -ERANGE) { - kfree(context); - /* Need a larger buffer. Query for the right size. */ rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0); if (rc < 0) { @@ -1656,7 +1650,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent pr_warn("SELinux: %s: getxattr returned " "%d for dev=%s ino=%ld\n", __func__, -rc, inode->i_sb->s_id, inode->i_ino); - kfree(context); + if (context != context_onstack) + kfree(context); goto out; } /* Map ENODATA to the default file SID */ @@ -1681,13 +1676,15 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent "returned %d for dev=%s ino=%ld\n", __func__, context, -rc, dev, ino); } - kfree(context); + if (context != context_onstack) + kfree(context); /* Leave with the unlabeled SID */ rc = 0; break; } } - kfree(context); + if (context != context_onstack) + kfree(context); break; case SECURITY_FS_USE_TASK: sid = task_sid; @@ -1735,7 +1732,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent * could be used again by userspace. */ if (!dentry) - goto out; + goto out_invalid; rc = selinux_genfs_get_sid(dentry, sclass, sbsec->flags, &sid); dput(dentry); @@ -1748,11 +1745,10 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent out: spin_lock(&isec->lock); if (isec->initialized == LABEL_PENDING) { - if (!sid || rc) { + if (rc) { isec->initialized = LABEL_INVALID; goto out_unlock; } - isec->initialized = LABEL_INITIALIZED; isec->sid = sid; } @@ -1760,6 +1756,15 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent out_unlock: spin_unlock(&isec->lock); return rc; + +out_invalid: + spin_lock(&isec->lock); + if (isec->initialized == LABEL_PENDING) { + isec->initialized = LABEL_INVALID; + isec->sid = sid; + } + spin_unlock(&isec->lock); + return 0; } /* Convert a Linux signal to an access vector. */ @@ -5213,17 +5218,15 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff * static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) { - struct sk_security_struct *sksec; - - sksec = kzalloc(sizeof(*sksec), priority); - if (!sksec) - return -ENOMEM; + struct sk_security_struct *sksec = sk->sk_security; +#ifdef CONFIG_NETLABEL + memset(sksec, 0, offsetof(struct sk_security_struct, sid)); +#endif sksec->peer_sid = SECINITSID_UNLABELED; sksec->sid = SECINITSID_UNLABELED; sksec->sclass = SECCLASS_SOCKET; selinux_netlbl_sk_security_reset(sksec); - sk->sk_security = sksec; return 0; } @@ -5232,14 +5235,12 @@ static void selinux_sk_free_security(struct sock *sk) { struct sk_security_struct *sksec = sk->sk_security; - sk->sk_security = NULL; selinux_netlbl_sk_security_free(sksec); - kfree(sksec); } static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) { - struct sk_security_struct *sksec = sk->sk_security; + const struct sk_security_struct *sksec = sk->sk_security; struct sk_security_struct *newsksec = newsk->sk_security; newsksec->sid = sksec->sid; diff --git a/security/selinux/ibpkey.c b/security/selinux/ibpkey.c index 0a4b89d48297..cb05ae28ce00 100644 --- a/security/selinux/ibpkey.c +++ b/security/selinux/ibpkey.c @@ -161,8 +161,10 @@ static int sel_ib_pkey_sid_slow(u64 subnet_prefix, u16 pkey_num, u32 *sid) * is valid, it just won't be added to the cache. */ new = kzalloc(sizeof(*new), GFP_ATOMIC); - if (!new) + if (!new) { + ret = -ENOMEM; goto out; + } new->psec.subnet_prefix = subnet_prefix; new->psec.pkey = pkey_num; diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 25b69dc17d1b..c43cd13d8064 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -116,26 +116,6 @@ struct netport_security_struct { u8 protocol; /* transport protocol */ }; -struct sk_security_struct { -#ifdef CONFIG_NETLABEL - enum { /* NetLabel state */ - NLBL_UNSET = 0, - NLBL_REQUIRE, - NLBL_LABELED, - NLBL_REQSKB, - NLBL_CONNLABELED, - } nlbl_state; - struct netlbl_lsm_secattr *nlbl_secattr; /* NetLabel sec attributes */ -#endif - u32 sid; /* SID of this object */ - u32 peer_sid; /* SID of peer */ - u16 sclass; /* sock security class */ - enum { /* SCTP association state */ - SCTP_ASSOC_UNSET = 0, - SCTP_ASSOC_SET, - } sctp_assoc_state; -}; - struct tun_security_struct { u32 sid; /* SID for the tun device sockets */ }; diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index 6fd9954e1c08..127975238422 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -114,7 +114,7 @@ static struct netlbl_lsm_secattr *selinux_netlbl_sock_getattr( const struct sock *sk, u32 sid) { - struct sk_security_struct *sksec = sk->sk_security; + const struct sk_security_struct *sksec = sk->sk_security; struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr; if (secattr == NULL) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index f6bc78aba75a..ec18f43decd6 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -815,6 +815,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; struct selinux_state *state = fsi->state; char *scon = NULL, *tcon = NULL; + char scon_onstack[256], tcon_onstack[256]; u32 ssid, tsid; u16 tclass; struct av_decision avd; @@ -826,15 +827,22 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) if (length) goto out; - length = -ENOMEM; - scon = kzalloc(size + 1, GFP_KERNEL); - if (!scon) - goto out; + if (size + 1 > ARRAY_SIZE(scon_onstack)) { + length = -ENOMEM; + scon = kzalloc(size + 1, GFP_KERNEL); + if (!scon) + goto out; - length = -ENOMEM; - tcon = kzalloc(size + 1, GFP_KERNEL); - if (!tcon) - goto out; + length = -ENOMEM; + tcon = kzalloc(size + 1, GFP_KERNEL); + if (!tcon) + goto out; + } else { + scon = scon_onstack; + tcon = tcon_onstack; + memset(scon_onstack, 0, size + 1); + memset(tcon_onstack, 0, size + 1); + } length = -EINVAL; if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) @@ -856,8 +864,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) avd.auditallow, avd.auditdeny, avd.seqno, avd.flags); out: - kfree(tcon); - kfree(scon); + if (scon != scon_onstack) { + kfree(tcon); + kfree(scon); + } return length; } diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index accd3846f1e3..4f8c1a272df0 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -1191,7 +1191,7 @@ static ssize_t smk_write_net4addr(struct file *file, const char __user *buf, return -EPERM; if (*ppos != 0) return -EINVAL; - if (count < SMK_NETLBLADDRMIN) + if (count < SMK_NETLBLADDRMIN || count > PAGE_SIZE - 1) return -EINVAL; data = memdup_user_nul(buf, count); @@ -1451,7 +1451,7 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, return -EPERM; if (*ppos != 0) return -EINVAL; - if (count < SMK_NETLBLADDRMIN) + if (count < SMK_NETLBLADDRMIN || count > PAGE_SIZE - 1) return -EINVAL; data = memdup_user_nul(buf, count); @@ -1858,6 +1858,10 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; + /* Enough data must be present */ + if (count == 0 || count > PAGE_SIZE) + return -EINVAL; + data = memdup_user_nul(buf, count); if (IS_ERR(data)) return PTR_ERR(data); @@ -2029,6 +2033,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; + if (count > PAGE_SIZE) + return -EINVAL; + data = memdup_user_nul(buf, count); if (IS_ERR(data)) return PTR_ERR(data); @@ -2116,6 +2123,9 @@ static ssize_t smk_write_unconfined(struct file *file, const char __user *buf, if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; + if (count > PAGE_SIZE) + return -EINVAL; + data = memdup_user_nul(buf, count); if (IS_ERR(data)) return PTR_ERR(data); @@ -2669,6 +2679,10 @@ static ssize_t smk_write_syslog(struct file *file, const char __user *buf, if (!smack_privileged(CAP_MAC_ADMIN)) return -EPERM; + /* Enough data must be present */ + if (count == 0 || count > PAGE_SIZE) + return -EINVAL; + data = memdup_user_nul(buf, count); if (IS_ERR(data)) return PTR_ERR(data); @@ -2761,10 +2775,13 @@ static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, return -EPERM; /* + * No partial write. * Enough data must be present. */ if (*ppos != 0) return -EINVAL; + if (count == 0 || count > PAGE_SIZE) + return -EINVAL; data = memdup_user_nul(buf, count); if (IS_ERR(data)) diff --git a/sound/core/control.c b/sound/core/control.c index d1312f14d78f..9cec0e8c9d53 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1388,7 +1388,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, unlock: up_write(&card->controls_rwsem); - return 0; + return err; } static int snd_ctl_elem_add_user(struct snd_ctl_file *file, diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c index 507fd5210c1c..ee150f8988a9 100644 --- a/sound/core/control_compat.c +++ b/sound/core/control_compat.c @@ -94,55 +94,52 @@ struct snd_ctl_elem_info32 { static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, struct snd_ctl_elem_info32 __user *data32) { - struct snd_ctl_elem_info *data; + struct snd_ctl_elem_info data; int err; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (! data) - return -ENOMEM; - + memset(&data, 0, sizeof(data)); err = -EFAULT; /* copy id */ - if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) + if (copy_from_user(&data.id, &data32->id, sizeof(data.id))) goto error; /* we need to copy the item index. * hope this doesn't break anything.. */ - if (get_user(data->value.enumerated.item, &data32->value.enumerated.item)) + if (get_user(data.value.enumerated.item, &data32->value.enumerated.item)) goto error; err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0); if (err < 0) goto error; - err = snd_ctl_elem_info(ctl, data); + err = snd_ctl_elem_info(ctl, &data); if (err < 0) goto error; /* restore info to 32bit */ err = -EFAULT; /* id, type, access, count */ - if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) || - copy_to_user(&data32->type, &data->type, 3 * sizeof(u32))) + if (copy_to_user(&data32->id, &data.id, sizeof(data.id)) || + copy_to_user(&data32->type, &data.type, 3 * sizeof(u32))) goto error; - if (put_user(data->owner, &data32->owner)) + if (put_user(data.owner, &data32->owner)) goto error; - switch (data->type) { + switch (data.type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: case SNDRV_CTL_ELEM_TYPE_INTEGER: - if (put_user(data->value.integer.min, &data32->value.integer.min) || - put_user(data->value.integer.max, &data32->value.integer.max) || - put_user(data->value.integer.step, &data32->value.integer.step)) + if (put_user(data.value.integer.min, &data32->value.integer.min) || + put_user(data.value.integer.max, &data32->value.integer.max) || + put_user(data.value.integer.step, &data32->value.integer.step)) goto error; break; case SNDRV_CTL_ELEM_TYPE_INTEGER64: if (copy_to_user(&data32->value.integer64, - &data->value.integer64, - sizeof(data->value.integer64))) + &data.value.integer64, + sizeof(data.value.integer64))) goto error; break; case SNDRV_CTL_ELEM_TYPE_ENUMERATED: if (copy_to_user(&data32->value.enumerated, - &data->value.enumerated, - sizeof(data->value.enumerated))) + &data.value.enumerated, + sizeof(data.value.enumerated))) goto error; break; default: @@ -150,7 +147,6 @@ static int snd_ctl_elem_info_compat(struct snd_ctl_file *ctl, } err = 0; error: - kfree(data); return err; } @@ -187,7 +183,7 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, int *countp) { struct snd_kcontrol *kctl; - struct snd_ctl_elem_info *info; + struct snd_ctl_elem_info info; int err; down_read(&card->controls_rwsem); @@ -196,19 +192,13 @@ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id, up_read(&card->controls_rwsem); return -ENOENT; } - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) { - up_read(&card->controls_rwsem); - return -ENOMEM; - } - info->id = *id; - err = kctl->info(kctl, info); + info = (typeof(info)){ .id = *id }; + err = kctl->info(kctl, &info); up_read(&card->controls_rwsem); if (err >= 0) { - err = info->type; - *countp = info->count; + err = info.type; + *countp = info.count; } - kfree(info); return err; } @@ -301,14 +291,11 @@ static int copy_ctl_value_to_user(void __user *userdata, static int ctl_elem_read_user(struct snd_card *card, void __user *userdata, void __user *valuep) { - struct snd_ctl_elem_value *data; + struct snd_ctl_elem_value data; int err, type, count; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - err = copy_ctl_value_from_user(card, data, userdata, valuep, + memset(&data, 0, sizeof(data)); + err = copy_ctl_value_from_user(card, &data, userdata, valuep, &type, &count); if (err < 0) goto error; @@ -316,27 +303,23 @@ static int ctl_elem_read_user(struct snd_card *card, err = snd_power_wait(card, SNDRV_CTL_POWER_D0); if (err < 0) goto error; - err = snd_ctl_elem_read(card, data); + err = snd_ctl_elem_read(card, &data); if (err < 0) goto error; - err = copy_ctl_value_to_user(userdata, valuep, data, type, count); + err = copy_ctl_value_to_user(userdata, valuep, &data, type, count); error: - kfree(data); return err; } static int ctl_elem_write_user(struct snd_ctl_file *file, void __user *userdata, void __user *valuep) { - struct snd_ctl_elem_value *data; + struct snd_ctl_elem_value data; struct snd_card *card = file->card; int err, type, count; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - err = copy_ctl_value_from_user(card, data, userdata, valuep, + memset(&data, 0, sizeof(data)); + err = copy_ctl_value_from_user(card, &data, userdata, valuep, &type, &count); if (err < 0) goto error; @@ -344,12 +327,11 @@ static int ctl_elem_write_user(struct snd_ctl_file *file, err = snd_power_wait(card, SNDRV_CTL_POWER_D0); if (err < 0) goto error; - err = snd_ctl_elem_write(card, file, data); + err = snd_ctl_elem_write(card, file, &data); if (err < 0) goto error; - err = copy_ctl_value_to_user(userdata, valuep, data, type, count); + err = copy_ctl_value_to_user(userdata, valuep, &data, type, count); error: - kfree(data); return err; } @@ -384,48 +366,44 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file, struct snd_ctl_elem_info32 __user *data32, int replace) { - struct snd_ctl_elem_info *data; + struct snd_ctl_elem_info data; int err; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (! data) - return -ENOMEM; - + memset(&data, 0, sizeof(data)); err = -EFAULT; /* id, type, access, count */ \ - if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || - copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) + if (copy_from_user(&data.id, &data32->id, sizeof(data.id)) || + copy_from_user(&data.type, &data32->type, 3 * sizeof(u32))) goto error; - if (get_user(data->owner, &data32->owner)) + if (get_user(data.owner, &data32->owner)) goto error; - switch (data->type) { + switch (data.type) { case SNDRV_CTL_ELEM_TYPE_BOOLEAN: case SNDRV_CTL_ELEM_TYPE_INTEGER: - if (get_user(data->value.integer.min, &data32->value.integer.min) || - get_user(data->value.integer.max, &data32->value.integer.max) || - get_user(data->value.integer.step, &data32->value.integer.step)) + if (get_user(data.value.integer.min, &data32->value.integer.min) || + get_user(data.value.integer.max, &data32->value.integer.max) || + get_user(data.value.integer.step, &data32->value.integer.step)) goto error; break; case SNDRV_CTL_ELEM_TYPE_INTEGER64: - if (copy_from_user(&data->value.integer64, + if (copy_from_user(&data.value.integer64, &data32->value.integer64, - sizeof(data->value.integer64))) + sizeof(data.value.integer64))) goto error; break; case SNDRV_CTL_ELEM_TYPE_ENUMERATED: - if (copy_from_user(&data->value.enumerated, + if (copy_from_user(&data.value.enumerated, &data32->value.enumerated, - sizeof(data->value.enumerated))) + sizeof(data.value.enumerated))) goto error; - data->value.enumerated.names_ptr = - (uintptr_t)compat_ptr(data->value.enumerated.names_ptr); + data.value.enumerated.names_ptr = + (uintptr_t)compat_ptr(data.value.enumerated.names_ptr); break; default: break; } - err = snd_ctl_elem_add(file, data, replace); + err = snd_ctl_elem_add(file, &data, replace); error: - kfree(data); return err; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 41abb8bd466a..2a286167460f 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -708,6 +708,8 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, oss_buffer_size = snd_pcm_plug_client_size(substream, snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; + if (!oss_buffer_size) + return -EINVAL; oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); if (atomic_read(&substream->mmap_count)) { if (oss_buffer_size > runtime->oss.mmap_bytes) @@ -743,17 +745,21 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream, min_period_size = snd_pcm_plug_client_size(substream, snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); - min_period_size *= oss_frame_size; - min_period_size = roundup_pow_of_two(min_period_size); - if (oss_period_size < min_period_size) - oss_period_size = min_period_size; + if (min_period_size) { + min_period_size *= oss_frame_size; + min_period_size = roundup_pow_of_two(min_period_size); + if (oss_period_size < min_period_size) + oss_period_size = min_period_size; + } max_period_size = snd_pcm_plug_client_size(substream, snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); - max_period_size *= oss_frame_size; - max_period_size = rounddown_pow_of_two(max_period_size); - if (oss_period_size > max_period_size) - oss_period_size = max_period_size; + if (max_period_size) { + max_period_size *= oss_frame_size; + max_period_size = rounddown_pow_of_two(max_period_size); + if (oss_period_size > max_period_size) + oss_period_size = max_period_size; + } oss_periods = oss_buffer_size / oss_period_size; @@ -1949,11 +1955,15 @@ static int snd_pcm_oss_set_subdivide(struct snd_pcm_oss_file *pcm_oss_file, int static int snd_pcm_oss_set_fragment1(struct snd_pcm_substream *substream, unsigned int val) { struct snd_pcm_runtime *runtime; + int fragshift; runtime = substream->runtime; if (runtime->oss.subdivision || runtime->oss.fragshift) return -EINVAL; - runtime->oss.fragshift = val & 0xffff; + fragshift = val & 0xffff; + if (fragshift >= 31) + return -EINVAL; + runtime->oss.fragshift = fragshift; runtime->oss.maxfrags = (val >> 16) & 0xffff; if (runtime->oss.fragshift < 4) /* < 16 */ runtime->oss.fragshift = 4; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ab173b4a8076..9895c59c1632 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -755,8 +755,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, runtime->boundary *= 2; /* clear the buffer for avoiding possible kernel info leaks */ - if (runtime->dma_area && !substream->ops->copy_user) - memset(runtime->dma_area, 0, runtime->dma_bytes); + if (runtime->dma_area && !substream->ops->copy_user) { + size_t size = runtime->dma_bytes; + + if (runtime->info & SNDRV_PCM_INFO_MMAP) + size = PAGE_ALIGN(size); + memset(runtime->dma_area, 0, size); + } snd_pcm_timer_resolution_change(substream); snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 9b26973fe697..f4f855d7a791 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -87,11 +87,21 @@ static inline unsigned short snd_rawmidi_file_flags(struct file *file) } } -static inline int snd_rawmidi_ready(struct snd_rawmidi_substream *substream) +static inline bool __snd_rawmidi_ready(struct snd_rawmidi_runtime *runtime) +{ + return runtime->avail >= runtime->avail_min; +} + +static bool snd_rawmidi_ready(struct snd_rawmidi_substream *substream) { struct snd_rawmidi_runtime *runtime = substream->runtime; + unsigned long flags; + bool ready; - return runtime->avail >= runtime->avail_min; + spin_lock_irqsave(&runtime->lock, flags); + ready = __snd_rawmidi_ready(runtime); + spin_unlock_irqrestore(&runtime->lock, flags); + return ready; } static inline int snd_rawmidi_ready_append(struct snd_rawmidi_substream *substream, @@ -960,7 +970,7 @@ int snd_rawmidi_receive(struct snd_rawmidi_substream *substream, if (result > 0) { if (runtime->event) schedule_work(&runtime->event_work); - else if (snd_rawmidi_ready(substream)) + else if (__snd_rawmidi_ready(runtime)) wake_up(&runtime->sleep); } spin_unlock_irqrestore(&runtime->lock, flags); @@ -1039,7 +1049,7 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun result = 0; while (count > 0) { spin_lock_irq(&runtime->lock); - while (!snd_rawmidi_ready(substream)) { + while (!__snd_rawmidi_ready(runtime)) { wait_queue_entry_t wait; if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) { @@ -1056,9 +1066,11 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; - if (!runtime->avail) - return result > 0 ? result : -EIO; spin_lock_irq(&runtime->lock); + if (!runtime->avail) { + spin_unlock_irq(&runtime->lock); + return result > 0 ? result : -EIO; + } } spin_unlock_irq(&runtime->lock); count1 = snd_rawmidi_kernel_read1(substream, @@ -1196,7 +1208,7 @@ int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int coun runtime->avail += count; substream->bytes += count; if (count > 0) { - if (runtime->drain || snd_rawmidi_ready(substream)) + if (runtime->drain || __snd_rawmidi_ready(runtime)) wake_up(&runtime->sleep); } return count; @@ -1363,9 +1375,11 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; - if (!runtime->avail && !timeout) - return result > 0 ? result : -EIO; spin_lock_irq(&runtime->lock); + if (!runtime->avail && !timeout) { + spin_unlock_irq(&runtime->lock); + return result > 0 ? result : -EIO; + } } spin_unlock_irq(&runtime->lock); count1 = snd_rawmidi_kernel_write1(substream, buf, NULL, count); @@ -1445,6 +1459,7 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *substream; struct snd_rawmidi_runtime *runtime; + unsigned long buffer_size, avail, xruns; rmidi = entry->private_data; snd_iprintf(buffer, "%s\n\n", rmidi->name); @@ -1463,13 +1478,16 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, " Owner PID : %d\n", pid_vnr(substream->pid)); runtime = substream->runtime; + spin_lock_irq(&runtime->lock); + buffer_size = runtime->buffer_size; + avail = runtime->avail; + spin_unlock_irq(&runtime->lock); snd_iprintf(buffer, " Mode : %s\n" " Buffer size : %lu\n" " Avail : %lu\n", runtime->oss ? "OSS compatible" : "native", - (unsigned long) runtime->buffer_size, - (unsigned long) runtime->avail); + buffer_size, avail); } } } @@ -1487,13 +1505,16 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry, " Owner PID : %d\n", pid_vnr(substream->pid)); runtime = substream->runtime; + spin_lock_irq(&runtime->lock); + buffer_size = runtime->buffer_size; + avail = runtime->avail; + xruns = runtime->xruns; + spin_unlock_irq(&runtime->lock); snd_iprintf(buffer, " Buffer size : %lu\n" " Avail : %lu\n" " Overruns : %lu\n", - (unsigned long) runtime->buffer_size, - (unsigned long) runtime->avail, - (unsigned long) runtime->xruns); + buffer_size, avail, xruns); } } } diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c index c93945917235..247b68790a52 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -624,7 +624,8 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in if (info->is_midi) { struct midi_info minf; - snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf); + if (snd_seq_oss_midi_make_info(dp, info->midi_mapped, &minf)) + return -ENXIO; inf->synth_type = SYNTH_TYPE_MIDI; inf->synth_subtype = 0; inf->nr_voices = 16; diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h index e006fc8e3a36..6b634cfb42ed 100644 --- a/sound/core/seq/seq_queue.h +++ b/sound/core/seq/seq_queue.h @@ -40,10 +40,10 @@ struct snd_seq_queue { struct snd_seq_timer *timer; /* time keeper for this queue */ int owner; /* client that 'owns' the timer */ - unsigned int locked:1, /* timer is only accesibble by owner if set */ - klocked:1, /* kernel lock (after START) */ - check_again:1, - check_blocked:1; + bool locked; /* timer is only accesibble by owner if set */ + bool klocked; /* kernel lock (after START) */ + bool check_again; /* concurrent access happened during check */ + bool check_blocked; /* queue being checked */ unsigned int flags; /* status flags */ unsigned int info_flags; /* info for sync */ diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 1e34e6381baa..3c65e52b014c 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -1047,6 +1047,14 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) return -ENOMEM; kctl->id.device = dev; kctl->id.subdevice = substr; + + /* Add the control before copying the id so that + * the numid field of the id is set in the copy. + */ + err = snd_ctl_add(card, kctl); + if (err < 0) + return err; + switch (idx) { case ACTIVE_IDX: setup->active_id = kctl->id; @@ -1063,9 +1071,6 @@ static int loopback_mixer_new(struct loopback *loopback, int notify) default: break; } - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; } } } diff --git a/sound/firewire/fireface/ff-transaction.c b/sound/firewire/fireface/ff-transaction.c index 332b29f8ed75..47280ae50682 100644 --- a/sound/firewire/fireface/ff-transaction.c +++ b/sound/firewire/fireface/ff-transaction.c @@ -99,7 +99,7 @@ static void transmit_midi_msg(struct snd_ff *ff, unsigned int port) /* Set interval to next transaction. */ ff->next_ktime[port] = ktime_add_ns(ktime_get(), - len * 8 * NSEC_PER_SEC / 31250); + len * 8 * (NSEC_PER_SEC / 31250)); ff->rx_bytes[port] = len; /* diff --git a/sound/firewire/fireworks/fireworks_transaction.c b/sound/firewire/fireworks/fireworks_transaction.c index 36a08ba51ec7..58674a711132 100644 --- a/sound/firewire/fireworks/fireworks_transaction.c +++ b/sound/firewire/fireworks/fireworks_transaction.c @@ -124,7 +124,7 @@ copy_resp_to_buf(struct snd_efw *efw, void *data, size_t length, int *rcode) t = (struct snd_efw_transaction *)data; length = min_t(size_t, be32_to_cpu(t->length) * sizeof(u32), length); - spin_lock_irq(&efw->lock); + spin_lock(&efw->lock); if (efw->push_ptr < efw->pull_ptr) capacity = (unsigned int)(efw->pull_ptr - efw->push_ptr); @@ -191,7 +191,7 @@ handle_resp_for_user(struct fw_card *card, int generation, int source, copy_resp_to_buf(efw, data, length, rcode); end: - spin_unlock_irq(&instances_lock); + spin_unlock(&instances_lock); } static void diff --git a/sound/firewire/tascam/tascam-transaction.c b/sound/firewire/tascam/tascam-transaction.c index 2ad692dd4b13..92f7e74d5847 100644 --- a/sound/firewire/tascam/tascam-transaction.c +++ b/sound/firewire/tascam/tascam-transaction.c @@ -210,7 +210,7 @@ static void midi_port_work(struct work_struct *work) /* Set interval to next transaction. */ port->next_ktime = ktime_add_ns(ktime_get(), - port->consume_bytes * 8 * NSEC_PER_SEC / 31250); + port->consume_bytes * 8 * (NSEC_PER_SEC / 31250)); /* Start this transaction. */ port->idling = false; diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index 84b44cdae28a..b96abebcfd1a 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -156,6 +156,8 @@ struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus, return NULL; if (bus->idx != bus_idx) return NULL; + if (addr < 0 || addr > 31) + return NULL; list_for_each_entry(hlink, &bus->hlink_list, list) { for (i = 0; i < HDA_MAX_CODECS; i++) { diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 3c966fafc754..6c9ab602212e 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c @@ -995,7 +995,7 @@ static int daio_mgr_dao_init(void *blk, unsigned int idx, unsigned int conf) if (idx < 4) { /* S/PDIF output */ - switch ((conf & 0x7)) { + switch ((conf & 0xf)) { case 1: set_field(&ctl->txctl[idx], ATXCTL_NUC, 0); break; diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index c175b2cf63f7..66010d0774b4 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -46,6 +46,10 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev) if (codec->bus->shutdown) return; + /* ignore unsol events during system suspend/resume */ + if (codec->core.dev.power.power_state.event != PM_EVENT_ON) + return; + if (codec->patch_ops.unsol_event) codec->patch_ops.unsol_event(codec, ev); } diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index dbeb62362f1c..7f1e763ccca8 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1782,7 +1782,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) return -EBUSY; /* OK, let it free */ - snd_hdac_device_unregister(&codec->core); + device_release_driver(hda_codec_dev(codec)); /* allow device access again */ snd_hda_unlock_devices(bus); diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 8198d2e53b7d..0c5d41e5d146 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -624,13 +624,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream) 20, 178000000); - /* by some reason, the playback stream stalls on PulseAudio with - * tsched=1 when a capture stream triggers. Until we figure out the - * real cause, disable tsched mode by telling the PCM info flag. - */ - if (chip->driver_caps & AZX_DCAPS_AMD_WORKAROUND) - runtime->hw.info |= SNDRV_PCM_INFO_BATCH; - if (chip->align_buffer_size) /* constrain buffer sizes to be multiple of 128 bytes. This is more efficient in terms of memory diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 97adb7e340f9..b9f7b23ae378 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -1376,16 +1376,20 @@ static int try_assign_dacs(struct hda_codec *codec, int num_outs, struct nid_path *path; hda_nid_t pin = pins[i]; - path = snd_hda_get_path_from_idx(codec, path_idx[i]); - if (path) { - badness += assign_out_path_ctls(codec, path); - continue; + if (!spec->obey_preferred_dacs) { + path = snd_hda_get_path_from_idx(codec, path_idx[i]); + if (path) { + badness += assign_out_path_ctls(codec, path); + continue; + } } dacs[i] = get_preferred_dac(codec, pin); if (dacs[i]) { if (is_dac_already_used(codec, dacs[i])) badness += bad->shared_primary; + } else if (spec->obey_preferred_dacs) { + badness += BAD_NO_PRIMARY_DAC; } if (!dacs[i]) @@ -4025,7 +4029,7 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec, spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE; spec->micmute_led.capture = 0; - spec->micmute_led.led_value = 0; + spec->micmute_led.led_value = -1; spec->micmute_led.old_hook = spec->cap_sync_hook; spec->micmute_led.update = hook; spec->cap_sync_hook = update_micmute_led; diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 8933c0f64cc4..2ccdd92c8c7f 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -240,6 +240,7 @@ struct hda_gen_spec { unsigned int power_down_unused:1; /* power down unused widgets */ unsigned int dac_min_mute:1; /* minimal = mute for DACs */ unsigned int suppress_vmaster:1; /* don't create vmaster kctls */ + unsigned int obey_preferred_dacs:1; /* obey preferred_dacs assignment */ /* other internal flags */ unsigned int no_analog:1; /* digital I/O only */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index d43245937db7..2cd8bfd5293b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2328,8 +2328,6 @@ static struct snd_pci_quirk power_save_blacklist[] = { SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0), /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0), - /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */ - SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0), /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0), /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */ diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 6535155e992d..25a4c2d580da 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -138,7 +138,7 @@ static int reconfig_codec(struct hda_codec *codec) "The codec is being used, can't reconfigure.\n"); goto error; } - err = snd_hda_codec_configure(codec); + err = device_reprobe(hda_codec_dev(codec)); if (err < 0) goto error; err = snd_card_register(codec->card); diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index c9f3c002bd55..004a7772bb5d 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -106,7 +106,7 @@ enum { }; /* Strings for Input Source Enum Control */ -static const char *const in_src_str[3] = {"Rear Mic", "Line", "Front Mic" }; +static const char *const in_src_str[3] = { "Microphone", "Line In", "Front Microphone" }; #define IN_SRC_NUM_OF_INPUTS 3 enum { REAR_MIC, diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 78bb96263bc2..7d471ecc1ca0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1088,6 +1088,7 @@ static int patch_conexant_auto(struct hda_codec *codec) static const struct hda_device_id snd_hda_id_conexant[] = { HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto), + HDA_CODEC_ENTRY(0x14f120d0, "CX11970", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto), HDA_CODEC_ENTRY(0x14f15051, "CX20561 (Hermosa)", patch_conexant_auto), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 708efb9b4387..d21a4eb1ca49 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1955,20 +1955,23 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, int pinctl; int err = 0; + mutex_lock(&spec->pcm_lock); if (hinfo->nid) { pcm_idx = hinfo_to_pcm_index(codec, hinfo); - if (snd_BUG_ON(pcm_idx < 0)) - return -EINVAL; + if (snd_BUG_ON(pcm_idx < 0)) { + err = -EINVAL; + goto unlock; + } cvt_idx = cvt_nid_to_cvt_index(codec, hinfo->nid); - if (snd_BUG_ON(cvt_idx < 0)) - return -EINVAL; + if (snd_BUG_ON(cvt_idx < 0)) { + err = -EINVAL; + goto unlock; + } per_cvt = get_cvt(spec, cvt_idx); - snd_BUG_ON(!per_cvt->assigned); per_cvt->assigned = 0; hinfo->nid = 0; - mutex_lock(&spec->pcm_lock); snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); @@ -1996,10 +1999,11 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_pin->setup = false; per_pin->channels = 0; mutex_unlock(&per_pin->lock); - unlock: - mutex_unlock(&spec->pcm_lock); } +unlock: + mutex_unlock(&spec->pcm_lock); + return err; } @@ -2322,6 +2326,18 @@ static void generic_hdmi_free(struct hda_codec *codec) } #ifdef CONFIG_PM +static int generic_hdmi_suspend(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + int pin_idx; + + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); + cancel_delayed_work_sync(&per_pin->work); + } + return 0; +} + static int generic_hdmi_resume(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; @@ -2345,6 +2361,7 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = { .build_controls = generic_hdmi_build_controls, .unsol_event = hdmi_unsol_event, #ifdef CONFIG_PM + .suspend = generic_hdmi_suspend, .resume = generic_hdmi_resume, #endif }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 382a8d179eb0..f456e5f67824 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -439,6 +439,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) alc_update_coef_idx(codec, 0x7, 1<<5, 0); break; case 0x10ec0892: + case 0x10ec0897: alc_update_coef_idx(codec, 0x7, 1<<5, 0); break; case 0x10ec0899: @@ -1879,6 +1880,7 @@ enum { ALC889_FIXUP_FRONT_HP_NO_PRESENCE, ALC889_FIXUP_VAIO_TT, ALC888_FIXUP_EEE1601, + ALC886_FIXUP_EAPD, ALC882_FIXUP_EAPD, ALC883_FIXUP_EAPD, ALC883_FIXUP_ACER_EAPD, @@ -2212,6 +2214,15 @@ static const struct hda_fixup alc882_fixups[] = { { } } }, + [ALC886_FIXUP_EAPD] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* change to EAPD mode */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 }, + { } + } + }, [ALC882_FIXUP_EAPD] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -2484,27 +2495,40 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD), + SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD), SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE), SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1458, 0xa0ce, "Gigabyte X570 Aorus Xtreme", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x11f7, "MSI-GE63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1228, "MSI-GP63", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1462, 0x1229, "MSI-GP73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1275, "MSI-GL63", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x1293, "MSI-GP65", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD), + SND_PCI_QUIRK(0x1462, 0xcc34, "MSI Godlike X570", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS), SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3), SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX), SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x9506, "Clevo P955HQ", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x950A, "Clevo P955H[PR]", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e3, "Clevo P955[ER]T", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e4, "Clevo P955ER", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e5, "Clevo P955EE6", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x95e6, "Clevo P950R[CDF]", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x96e1, "Clevo P960[ER][CDFN]-K", ALC1220_FIXUP_CLEVO_P950), SND_PCI_QUIRK(0x1558, 0x97e1, "Clevo P970[ER][CDFN]", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x97e2, "Clevo P970RC-M", ALC1220_FIXUP_CLEVO_P950), + SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x65d1, "Clevo PB51[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x65d2, "Clevo PB51R[CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x65e1, "Clevo PB51[ED][DF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x67d1, "Clevo PB71[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), - SND_PCI_QUIRK(0x1558, 0x50d3, "Clevo PC50[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), + SND_PCI_QUIRK(0x1558, 0x67e1, "Clevo PB71[DE][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170", ALC1220_FIXUP_CLEVO_PB51ED_PINS), SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD), @@ -4846,7 +4870,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) case 0x10ec0274: case 0x10ec0294: alc_process_coef_fw(codec, coef0274); - msleep(80); + msleep(850); val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x00f0) == 0x00f0; break; @@ -5030,6 +5054,7 @@ static void alc_update_headset_jack_cb(struct hda_codec *codec, struct alc_spec *spec = codec->spec; spec->current_headset_type = ALC_HEADSET_TYPE_UNKNOWN; snd_hda_gen_hp_automute(codec, jack); + alc_update_headset_mode(codec); } static void alc_probe_headset_mode(struct hda_codec *codec) @@ -5762,6 +5787,7 @@ enum { ALC221_FIXUP_HP_FRONT_MIC, ALC292_FIXUP_TPT460, ALC298_FIXUP_SPK_VOLUME, + ALC298_FIXUP_LENOVO_SPK_VOLUME, ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER, ALC269_FIXUP_ATIV_BOOK_8, ALC221_FIXUP_HP_MIC_NO_PRESENCE, @@ -6533,6 +6559,10 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, }, + [ALC298_FIXUP_LENOVO_SPK_VOLUME] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc298_fixup_speaker_volume, + }, [ALC295_FIXUP_DISABLE_DAC3] = { .type = HDA_FIXUP_FUNC, .v.func = alc295_fixup_disable_dac3, @@ -7058,6 +7088,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x820d, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8256, "HP", ALC221_FIXUP_HP_FRONT_MIC), SND_PCI_QUIRK(0x103c, 0x827e, "HP x360", ALC295_FIXUP_HP_X360), + SND_PCI_QUIRK(0x103c, 0x827f, "HP x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), @@ -7072,6 +7103,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1290, "ASUS X441SA", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x12a0, "ASUS X441UV", ALC233_FIXUP_EAPD_COEF_AND_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x12f0, "ASUS X541UV", ALC256_FIXUP_ASUS_MIC), @@ -7088,6 +7120,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), @@ -7114,11 +7147,51 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x152d, 0x1082, "Quanta NL3", ALC269_FIXUP_LIFEBOOK), + SND_PCI_QUIRK(0x1558, 0x1323, "Clevo N130ZU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1401, "Clevo L140[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1403, "Clevo N140CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x1404, "Clevo N150CU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x14a1, "Clevo L141MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4018, "Clevo NV40M[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4019, "Clevo NV40MZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x4020, "Clevo NV40MB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40a1, "Clevo NL40GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40c1, "Clevo NL40[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x40d1, "Clevo NL41DU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50a3, "Clevo NJ51GU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b3, "Clevo NK50S[BEZ]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b6, "Clevo NK50S5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8535, "Clevo NH50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8536, "Clevo NH79D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8550, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8551, "System76 Gazelle (gaze14)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1558, 0x8560, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1558, 0x8561, "System76 Gazelle (gaze14)", ALC269_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x1558, 0x8562, "Clevo NH[5|7][0-9]RZ[Q]", ALC269_FIXUP_DMIC), + SND_PCI_QUIRK(0x1558, 0x8668, "Clevo NP50B[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8680, "Clevo NJ50LU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8686, "Clevo NH50[CZ]U", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8a20, "Clevo NH55DCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS), SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), @@ -7166,6 +7239,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), @@ -7729,6 +7803,9 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x13, 0x90a60140}), + SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_HPE, + {0x17, 0x90170110}, + {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC, {0x14, 0x90170110}, {0x1b, 0x90a70130}, @@ -9114,6 +9191,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0888, "ALC888", patch_alc882), HDA_CODEC_ENTRY(0x10ec0889, "ALC889", patch_alc882), HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662), + HDA_CODEC_ENTRY(0x10ec0897, "ALC897", patch_alc662), HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882), HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882), HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882), diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 6b9617aee0e6..0046ea78abd2 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -126,6 +126,7 @@ static struct via_spec *via_new_spec(struct hda_codec *codec) spec->codec_type = VT1708S; spec->gen.indep_hp = 1; spec->gen.keep_eapd_on = 1; + spec->gen.dac_min_mute = 1; spec->gen.pcm_playback_hook = via_playback_pcm_hook; spec->gen.add_stereo_mix_input = HDA_HINT_STEREO_MIX_AUTO; codec->power_save_node = 1; @@ -1015,6 +1016,7 @@ static const struct hda_verb vt1802_init_verbs[] = { enum { VIA_FIXUP_INTMIC_BOOST, VIA_FIXUP_ASUS_G75, + VIA_FIXUP_POWER_SAVE, }; static void via_fixup_intmic_boost(struct hda_codec *codec, @@ -1024,6 +1026,13 @@ static void via_fixup_intmic_boost(struct hda_codec *codec, override_mic_boost(codec, 0x30, 0, 2, 40); } +static void via_fixup_power_save(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) + codec->power_save_node = 0; +} + static const struct hda_fixup via_fixups[] = { [VIA_FIXUP_INTMIC_BOOST] = { .type = HDA_FIXUP_FUNC, @@ -1038,11 +1047,16 @@ static const struct hda_fixup via_fixups[] = { { } } }, + [VIA_FIXUP_POWER_SAVE] = { + .type = HDA_FIXUP_FUNC, + .v.func = via_fixup_power_save, + }, }; static const struct snd_pci_quirk vt2002p_fixups[] = { SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75), SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST), + SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE), {} }; diff --git a/sound/pci/mixart/mixart_core.c b/sound/pci/mixart/mixart_core.c index 71776bfe0485..5a956f8bfa9e 100644 --- a/sound/pci/mixart/mixart_core.c +++ b/sound/pci/mixart/mixart_core.c @@ -83,7 +83,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, unsigned int i; #endif - mutex_lock(&mgr->msg_lock); err = 0; /* copy message descriptor from miXart to driver */ @@ -132,8 +131,6 @@ static int get_msg(struct mixart_mgr *mgr, struct mixart_msg *resp, writel_be(headptr, MIXART_MEM(mgr, MSG_OUTBOUND_FREE_HEAD)); _clean_exit: - mutex_unlock(&mgr->msg_lock); - return err; } @@ -271,7 +268,9 @@ int snd_mixart_send_msg(struct mixart_mgr *mgr, struct mixart_msg *request, int resp.data = resp_data; resp.size = max_resp_size; + mutex_lock(&mgr->msg_lock); err = get_msg(mgr, &resp, msg_frame); + mutex_unlock(&mgr->msg_lock); if( request->message_id != resp.message_id ) dev_err(&mgr->pci->dev, "RESPONSE ERROR!\n"); diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 3bd57c02e6fd..0b35b84abb61 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -642,6 +642,7 @@ static const struct of_device_id ak4458_of_match[] = { { .compatible = "asahi-kasei,ak4458", }, { }, }; +MODULE_DEVICE_TABLE(of, ak4458_of_match); static struct i2c_driver ak4458_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 448bb90c9c8e..73c418517f8d 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -396,6 +396,7 @@ static const struct of_device_id ak5558_i2c_dt_ids[] = { { .compatible = "asahi-kasei,ak5558"}, { } }; +MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids); static struct i2c_driver ak5558_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/cpcap.c b/sound/soc/codecs/cpcap.c index d7f05b384f1f..1902689c5ea2 100644 --- a/sound/soc/codecs/cpcap.c +++ b/sound/soc/codecs/cpcap.c @@ -1263,12 +1263,12 @@ static int cpcap_voice_hw_params(struct snd_pcm_substream *substream, if (direction == SNDRV_PCM_STREAM_CAPTURE) { mask = 0x0000; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT0; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT1; - mask |= CPCAP_BIT_MIC1_RX_TIMESLOT2; - mask |= CPCAP_BIT_MIC2_TIMESLOT0; - mask |= CPCAP_BIT_MIC2_TIMESLOT1; - mask |= CPCAP_BIT_MIC2_TIMESLOT2; + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0); + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT1); + mask |= BIT(CPCAP_BIT_MIC1_RX_TIMESLOT2); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT0); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT1); + mask |= BIT(CPCAP_BIT_MIC2_TIMESLOT2); val = 0x0000; if (channels >= 2) val = BIT(CPCAP_BIT_MIC1_RX_TIMESLOT0); diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 651329bf9743..fddfd227a9c0 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -405,7 +405,7 @@ static const struct regmap_config cs42l42_regmap = { }; static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false); -static DECLARE_TLV_DB_SCALE(mixer_tlv, -6200, 100, false); +static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true); static const char * const cs42l42_hpf_freq_text[] = { "1.86Hz", "120Hz", "235Hz", "466Hz" @@ -462,7 +462,7 @@ static const struct snd_kcontrol_new cs42l42_snd_controls[] = { CS42L42_DAC_HPF_EN_SHIFT, true, false), SOC_DOUBLE_R_TLV("Mixer Volume", CS42L42_MIXER_CHA_VOL, CS42L42_MIXER_CHB_VOL, CS42L42_MIXER_CH_VOL_SHIFT, - 0x3e, 1, mixer_tlv) + 0x3f, 1, mixer_tlv) }; static int cs42l42_hpdrv_evt(struct snd_soc_dapm_widget *w, @@ -695,24 +695,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component) CS42L42_CLK_OASRC_SEL_MASK, CS42L42_CLK_OASRC_SEL_12 << CS42L42_CLK_OASRC_SEL_SHIFT); - /* channel 1 on low LRCLK, 32 bit */ - snd_soc_component_update_bits(component, - CS42L42_ASP_RX_DAI0_CH1_AP_RES, - CS42L42_ASP_RX_CH_AP_MASK | - CS42L42_ASP_RX_CH_RES_MASK, - (CS42L42_ASP_RX_CH_AP_LOW << - CS42L42_ASP_RX_CH_AP_SHIFT) | - (CS42L42_ASP_RX_CH_RES_32 << - CS42L42_ASP_RX_CH_RES_SHIFT)); - /* Channel 2 on high LRCLK, 32 bit */ - snd_soc_component_update_bits(component, - CS42L42_ASP_RX_DAI0_CH2_AP_RES, - CS42L42_ASP_RX_CH_AP_MASK | - CS42L42_ASP_RX_CH_RES_MASK, - (CS42L42_ASP_RX_CH_AP_HI << - CS42L42_ASP_RX_CH_AP_SHIFT) | - (CS42L42_ASP_RX_CH_RES_32 << - CS42L42_ASP_RX_CH_RES_SHIFT)); if (pll_ratio_table[i].mclk_src_sel == 0) { /* Pass the clock straight through */ snd_soc_component_update_bits(component, @@ -801,27 +783,23 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* Bitclock/frame inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: + asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT; break; case SND_SOC_DAIFMT_NB_IF: - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_LCPOL_IN_SHIFT; + asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT; + asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT; break; case SND_SOC_DAIFMT_IB_NF: - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_SCPOL_IN_DAC_SHIFT; break; case SND_SOC_DAIFMT_IB_IF: - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_LCPOL_IN_SHIFT; - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_SCPOL_IN_DAC_SHIFT; + asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT; break; } - snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, - CS42L42_ASP_MODE_MASK | - CS42L42_ASP_SCPOL_IN_DAC_MASK | - CS42L42_ASP_LCPOL_IN_MASK, asp_cfg_val); + snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, CS42L42_ASP_MODE_MASK | + CS42L42_ASP_SCPOL_MASK | + CS42L42_ASP_LCPOL_MASK, + asp_cfg_val); return 0; } @@ -832,14 +810,29 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); - int retval; + unsigned int width = (params_width(params) / 8) - 1; + unsigned int val = 0; cs42l42->srate = params_rate(params); - cs42l42->swidth = params_width(params); - retval = cs42l42_pll_config(component); + switch(substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + val |= width << CS42L42_ASP_RX_CH_RES_SHIFT; + /* channel 1 on low LRCLK */ + snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH1_AP_RES, + CS42L42_ASP_RX_CH_AP_MASK | + CS42L42_ASP_RX_CH_RES_MASK, val); + /* Channel 2 on high LRCLK */ + val |= CS42L42_ASP_RX_CH_AP_HI << CS42L42_ASP_RX_CH_AP_SHIFT; + snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES, + CS42L42_ASP_RX_CH_AP_MASK | + CS42L42_ASP_RX_CH_RES_MASK, val); + break; + default: + break; + } - return retval; + return cs42l42_pll_config(component); } static int cs42l42_set_sysclk(struct snd_soc_dai *dai, @@ -904,9 +897,9 @@ static int cs42l42_digital_mute(struct snd_soc_dai *dai, int mute) return 0; } -#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) +#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE ) static const struct snd_soc_dai_ops cs42l42_ops = { @@ -1807,7 +1800,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, dev_dbg(&i2c_client->dev, "Found reset GPIO\n"); gpiod_set_value_cansleep(cs42l42->reset_gpio, 1); } - mdelay(3); + usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); /* Request IRQ */ ret = devm_request_threaded_irq(&i2c_client->dev, @@ -1932,6 +1925,7 @@ static int cs42l42_runtime_resume(struct device *dev) } gpiod_set_value_cansleep(cs42l42->reset_gpio, 1); + usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); regcache_cache_only(cs42l42->regmap, false); regcache_sync(cs42l42->regmap); diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 09b0a93203ef..bcaf4f22408d 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -262,11 +262,12 @@ #define CS42L42_ASP_SLAVE_MODE 0x00 #define CS42L42_ASP_MODE_SHIFT 4 #define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT) -#define CS42L42_ASP_SCPOL_IN_DAC_SHIFT 2 -#define CS42L42_ASP_SCPOL_IN_DAC_MASK (1 << CS42L42_ASP_SCPOL_IN_DAC_SHIFT) -#define CS42L42_ASP_LCPOL_IN_SHIFT 0 -#define CS42L42_ASP_LCPOL_IN_MASK (1 << CS42L42_ASP_LCPOL_IN_SHIFT) -#define CS42L42_ASP_POL_INV 1 +#define CS42L42_ASP_SCPOL_SHIFT 2 +#define CS42L42_ASP_SCPOL_MASK (3 << CS42L42_ASP_SCPOL_SHIFT) +#define CS42L42_ASP_SCPOL_NOR 3 +#define CS42L42_ASP_LCPOL_SHIFT 0 +#define CS42L42_ASP_LCPOL_MASK (3 << CS42L42_ASP_LCPOL_SHIFT) +#define CS42L42_ASP_LCPOL_INV 3 #define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08) #define CS42L42_ASP_STP_SHIFT 4 @@ -743,6 +744,7 @@ #define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16) #define CS42L42_NUM_SUPPLIES 5 +#define CS42L42_BOOT_TIME_US 3000 static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = { "VA", @@ -760,7 +762,6 @@ struct cs42l42_private { struct completion pdn_done; u32 sclk; u32 srate; - u32 swidth; u8 plug_state; u8 hs_type; u8 ts_inv; diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index a5c8736fad77..04f89b751304 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1260,6 +1260,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L56 Device ID (%X). Expected %X\n", devid, CS42L56_DEVID); + ret = -EINVAL; goto err_enable; } alpha_rev = reg & CS42L56_AREV_MASK; @@ -1317,7 +1318,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client, ret = devm_snd_soc_register_component(&i2c_client->dev, &soc_component_dev_cs42l56, &cs42l56_dai, 1); if (ret < 0) - return ret; + goto err_enable; return 0; diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 9ebe77c3784a..57130edaf3ab 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -56,13 +56,8 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv, 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0), 2, 2, TLV_DB_SCALE_ITEM(250, 0, 0), 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), - 4, 4, TLV_DB_SCALE_ITEM(700, 0, 0), - 5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0), - 6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0), - 7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0), - 8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0), - 9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0), - 10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0), + 4, 7, TLV_DB_SCALE_ITEM(700, 300, 0), + 8, 10, TLV_DB_SCALE_ITEM(1800, 300, 0), ); static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv, diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 974e1a449172..63e19a6a9790 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -342,9 +342,9 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 985852fd9723..318a4c9b380f 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -288,9 +288,9 @@ static bool rt5651_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 1c1a521c73cb..b331b3ba61a9 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3466,12 +3466,17 @@ static int rt5659_set_component_sysclk(struct snd_soc_component *component, int { struct rt5659_priv *rt5659 = snd_soc_component_get_drvdata(component); unsigned int reg_val = 0; + int ret; if (freq == rt5659->sysclk && clk_id == rt5659->sysclk_src) return 0; switch (clk_id) { case RT5659_SCLK_S_MCLK: + ret = clk_set_rate(rt5659->mclk, freq); + if (ret) + return ret; + reg_val |= RT5659_SCLK_SRC_MCLK; break; case RT5659_SCLK_S_PLL1: diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 7c0a06b487f7..17255e9683f5 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -71,7 +71,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f }, { SGTL5000_DAP_MAIN_CHAN, 0x8000 }, { SGTL5000_DAP_MIX_CHAN, 0x0000 }, - { SGTL5000_DAP_AVC_CTRL, 0x0510 }, + { SGTL5000_DAP_AVC_CTRL, 0x5100 }, { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 }, { SGTL5000_DAP_AVC_ATTACK, 0x0028 }, { SGTL5000_DAP_AVC_DECAY, 0x0050 }, diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index c4c00297ada6..88e869d16714 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -710,7 +710,13 @@ int wm8960_configure_pll(struct snd_soc_component *component, int freq_in, best_freq_out = -EINVAL; *sysclk_idx = *dac_idx = *bclk_idx = -1; - for (i = 0; i < ARRAY_SIZE(sysclk_divs); ++i) { + /* + * From Datasheet, the PLL performs best when f2 is between + * 90MHz and 100MHz, the desired sysclk output is 11.2896MHz + * or 12.288MHz, then sysclkdiv = 2 is the best choice. + * So search sysclk_divs from 2 to 1 other than from 1 to 2. + */ + for (i = ARRAY_SIZE(sysclk_divs) - 1; i >= 0; --i) { if (sysclk_divs[i] == -1) continue; for (j = 0; j < ARRAY_SIZE(dac_divs); ++j) { diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index df5b36b8fc5a..bb6a95be8726 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1180,6 +1180,8 @@ static int wm8997_probe(struct platform_device *pdev) goto err_spk_irqs; } + return ret; + err_spk_irqs: arizona_free_spk_irqs(arizona); diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index 61294c787f27..17dc5780ab68 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1378,7 +1378,7 @@ static int wm8998_probe(struct platform_device *pdev) ret = arizona_init_spk_irqs(arizona); if (ret < 0) - return ret; + goto err_pm_disable; ret = devm_snd_soc_register_component(&pdev->dev, &soc_component_dev_wm8998, @@ -1393,6 +1393,8 @@ static int wm8998_probe(struct platform_device *pdev) err_spk_irqs: arizona_free_spk_irqs(arizona); +err_pm_disable: + pm_runtime_disable(&pdev->dev); return ret; } diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index b114fc7b2a95..02c557e1f779 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -1379,7 +1379,7 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); if (!ctl_work) { ret = -ENOMEM; - goto err_ctl_cache; + goto err_list_del; } ctl_work->dsp = dsp; @@ -1389,7 +1389,8 @@ static int wm_adsp_create_control(struct wm_adsp *dsp, return 0; -err_ctl_cache: +err_list_del: + list_del(&ctl->list); kfree(ctl->cache); err_ctl_name: kfree(ctl->name); diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index ff96db91f818..baa76337c33f 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -497,11 +497,13 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, ESAI_SAICR_SYNC, esai_priv->synchronous ? ESAI_SAICR_SYNC : 0); - /* Set a default slot number -- 2 */ + /* Set slots count */ regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR, - ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2)); + ESAI_xCCR_xDC_MASK, + ESAI_xCCR_xDC(esai_priv->slots)); regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR, - ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(2)); + ESAI_xCCR_xDC_MASK, + ESAI_xCCR_xDC(esai_priv->slots)); } return 0; diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 0e2bdad373d6..d6a1573b457a 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -873,6 +873,7 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream *substream, static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) { u32 strcr = 0, scr = 0, stcr, srcr, mask; + unsigned int slots; ssi->dai_fmt = fmt; @@ -904,10 +905,11 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) return -EINVAL; } + slots = ssi->slots ? : 2; regmap_update_bits(ssi->regs, REG_SSI_STCCR, - SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2)); + SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots)); regmap_update_bits(ssi->regs, REG_SSI_SRCCR, - SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2)); + SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots)); /* Data on rising edge of bclk, frame low, 1clk before data */ strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS; diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index 0572c3c96450..be773101d876 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -508,14 +508,14 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { .channels_min = SST_STEREO, .channels_max = SST_STEREO, .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, + .formats = SNDRV_PCM_FMTBIT_S16_LE, }, .capture = { .stream_name = "Headset Capture", .channels_min = 1, .channels_max = 2, .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, + .formats = SNDRV_PCM_FMTBIT_S16_LE, }, }, { @@ -526,7 +526,7 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { .channels_min = SST_STEREO, .channels_max = SST_STEREO, .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, - .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE, + .formats = SNDRV_PCM_FMTBIT_S16_LE, }, }, { diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index ec630127ef2f..d63d99776384 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -409,6 +409,19 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { /* Acer One 10 S1002 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "One S1002"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF2 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -431,6 +444,18 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "ARCHOS 140 CESIUM"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), @@ -510,6 +535,16 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_MONO_SPEAKER | BYT_RT5640_MCLK_EN), }, + { /* Estar Beauty HD MID 7316R */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Estar"), + DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"), + }, + .driver_data = (void *)(BYTCR_INPUT_DEFAULTS | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -746,6 +781,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF2 | BYT_RT5640_MCLK_EN), }, + { /* Voyo Winpad A15 */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + /* Above strings are too generic, also match on BIOS date */ + DMI_MATCH(DMI_BIOS_DATE, "11/20/2014"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_MCLK_EN), + }, { /* Catch-all for generic Insyde tablets, must be last */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Insyde"), diff --git a/sound/soc/intel/boards/haswell.c b/sound/soc/intel/boards/haswell.c index a4022983a7ce..67eb4a446c3c 100644 --- a/sound/soc/intel/boards/haswell.c +++ b/sound/soc/intel/boards/haswell.c @@ -198,6 +198,7 @@ static struct platform_driver haswell_audio = { .probe = haswell_audio_probe, .driver = { .name = "haswell-audio", + .pm = &snd_soc_pm_ops, }, }; diff --git a/sound/soc/intel/skylake/cnl-sst.c b/sound/soc/intel/skylake/cnl-sst.c index 245df1067ba8..7b429c0fb4e5 100644 --- a/sound/soc/intel/skylake/cnl-sst.c +++ b/sound/soc/intel/skylake/cnl-sst.c @@ -212,6 +212,7 @@ static int cnl_set_dsp_D0(struct sst_dsp *ctx, unsigned int core_id) "dsp boot timeout, status=%#x error=%#x\n", sst_dsp_shim_read(ctx, CNL_ADSP_FW_STATUS), sst_dsp_shim_read(ctx, CNL_ADSP_ERROR_CODE)); + ret = -ETIMEDOUT; goto err; } } else { diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index e099c0505b76..2c6b0ac97c68 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c @@ -318,10 +318,14 @@ static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, switch (clk_id) { case JZ4740_I2S_CLKSRC_EXT: parent = clk_get(NULL, "ext"); + if (IS_ERR(parent)) + return PTR_ERR(parent); clk_set_parent(i2s->clk_i2s, parent); break; case JZ4740_I2S_CLKSRC_PLL: parent = clk_get(NULL, "pll half"); + if (IS_ERR(parent)) + return PTR_ERR(parent); clk_set_parent(i2s->clk_i2s, parent); ret = clk_set_rate(i2s->clk_i2s, freq); break; diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig index 8af8bc358a90..19fd4d583b86 100644 --- a/sound/soc/meson/Kconfig +++ b/sound/soc/meson/Kconfig @@ -1,5 +1,5 @@ menu "ASoC support for Amlogic platforms" - depends on ARCH_MESON || COMPILE_TEST + depends on ARCH_MESON || (COMPILE_TEST && COMMON_CLK) config SND_MESON_AXG_FIFO tristate diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 5c055d8de8c7..01cc551a8e3f 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -459,8 +459,20 @@ static int axg_tdm_iface_set_bias_level(struct snd_soc_component *component, return ret; } +static const struct snd_soc_dapm_widget axg_tdm_iface_dapm_widgets[] = { + SND_SOC_DAPM_SIGGEN("Playback Signal"), +}; + +static const struct snd_soc_dapm_route axg_tdm_iface_dapm_routes[] = { + { "Loopback", NULL, "Playback Signal" }, +}; + static const struct snd_soc_component_driver axg_tdm_iface_component_drv = { - .set_bias_level = axg_tdm_iface_set_bias_level, + .dapm_widgets = axg_tdm_iface_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(axg_tdm_iface_dapm_widgets), + .dapm_routes = axg_tdm_iface_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(axg_tdm_iface_dapm_routes), + .set_bias_level = axg_tdm_iface_set_bias_level, }; static const struct of_device_id axg_tdm_iface_of_match[] = { diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 2f2967247789..1d06e2b7bb63 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -81,8 +81,10 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) else dma_ch = 0; - if (dma_ch < 0) + if (dma_ch < 0) { + kfree(data); return dma_ch; + } drvdata->substream[dma_ch] = substream; @@ -103,6 +105,7 @@ static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream) ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) { + kfree(data); dev_err(soc_runtime->dev, "setting constraints failed: %d\n", ret); return -EINVAL; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 4e21ce136e3e..f6987d9dd7ec 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2465,6 +2465,7 @@ void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w) enum snd_soc_dapm_direction dir; list_del(&w->list); + list_del(&w->dirty); /* * remove source and sink paths associated to this widget. * While removing the path, remove reference to it from both diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b4949bc343dc..23bd5e928ec1 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2581,6 +2581,7 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_DRAIN: ret = dpcm_dai_trigger_fe_be(substream, cmd, true); break; case SNDRV_PCM_TRIGGER_STOP: @@ -2598,6 +2599,7 @@ static int dpcm_fe_dai_do_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_DRAIN: ret = dpcm_dai_trigger_fe_be(substream, cmd, false); break; case SNDRV_PCM_TRIGGER_STOP: diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 9a3cb7704810..16e8f74288a5 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1235,6 +1235,7 @@ static struct snd_soc_card *sun4i_codec_create_card(struct device *dev) return ERR_PTR(-ENOMEM); card->dev = dev; + card->owner = THIS_MODULE; card->name = "sun4i-codec"; card->dapm_widgets = sun4i_codec_card_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(sun4i_codec_card_dapm_widgets); @@ -1267,6 +1268,7 @@ static struct snd_soc_card *sun6i_codec_create_card(struct device *dev) return ERR_PTR(-ENOMEM); card->dev = dev; + card->owner = THIS_MODULE; card->name = "A31 Audio Codec"; card->dapm_widgets = sun6i_codec_card_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets); @@ -1320,6 +1322,7 @@ static struct snd_soc_card *sun8i_a23_codec_create_card(struct device *dev) return ERR_PTR(-ENOMEM); card->dev = dev; + card->owner = THIS_MODULE; card->name = "A23 Audio Codec"; card->dapm_widgets = sun6i_codec_card_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets); @@ -1358,6 +1361,7 @@ static struct snd_soc_card *sun8i_h3_codec_create_card(struct device *dev) return ERR_PTR(-ENOMEM); card->dev = dev; + card->owner = THIS_MODULE; card->name = "H3 Audio Codec"; card->dapm_widgets = sun6i_codec_card_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets); @@ -1396,6 +1400,7 @@ static struct snd_soc_card *sun8i_v3s_codec_create_card(struct device *dev) return ERR_PTR(-ENOMEM); card->dev = dev; + card->owner = THIS_MODULE; card->name = "V3s Audio Codec"; card->dapm_widgets = sun6i_codec_card_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets); diff --git a/sound/usb/clock.c b/sound/usb/clock.c index bfe5540030b8..54818658d021 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -508,6 +508,12 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface, } crate = data[0] | (data[1] << 8) | (data[2] << 16); + if (!crate) { + dev_info(&dev->dev, "failed to read current rate; disabling the check\n"); + chip->sample_rate_read_error = 3; /* three strikes, see above */ + return 0; + } + if (crate != rate) { dev_warn(&dev->dev, "current rate %d is different from the runtime rate %d\n", crate, rate); // runtime->rate = crate; diff --git a/sound/usb/format.c b/sound/usb/format.c index c8207b52c651..a3daf93c565a 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -53,6 +53,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, case UAC_VERSION_1: default: { struct uac_format_type_i_discrete_descriptor *fmt = _fmt; + if (format >= 64) + return 0; /* invalid format */ sample_width = fmt->bBitResolution; sample_bytes = fmt->bSubframeSize; format = 1ULL << format; diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 137e1e8718d6..26548f760bc1 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -1890,6 +1890,8 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi, ms_ep = find_usb_ms_endpoint_descriptor(hostep); if (!ms_ep) continue; + if (ms_ep->bNumEmbMIDIJack > 0x10) + continue; if (usb_endpoint_dir_out(ep)) { if (endpoints[epidx].out_ep) { if (++epidx >= MIDI_MAX_ENDPOINTS) { @@ -2142,6 +2144,8 @@ static int snd_usbmidi_detect_roland(struct snd_usb_midi *umidi, cs_desc[1] == USB_DT_CS_INTERFACE && cs_desc[2] == 0xf1 && cs_desc[3] == 0x02) { + if (cs_desc[4] > 0x10 || cs_desc[5] > 0x10) + continue; endpoint->in_cables = (1 << cs_desc[4]) - 1; endpoint->out_cables = (1 << cs_desc[5]) - 1; return snd_usbmidi_detect_endpoints(umidi, endpoint, 1); diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c index 26ed23b18b77..7db3032e723a 100644 --- a/sound/usb/mixer_us16x08.c +++ b/sound/usb/mixer_us16x08.c @@ -617,7 +617,7 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol, static int snd_us16x08_meter_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - uinfo->count = 1; + uinfo->count = 34; uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->value.integer.max = 0x7FFF; uinfo->value.integer.min = 0; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 94e52495888d..d775217b8289 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -2006,7 +2006,7 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs) { struct snd_pcm *pcm = subs->stream->pcm; struct snd_pcm_substream *s = pcm->streams[subs->direction].substream; - struct device *dev = subs->dev->bus->controller; + struct device *dev = subs->dev->bus->sysdev; if (!snd_usb_use_vmalloc) snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 49fe37ad8cb5..195431673339 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1183,6 +1183,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip) case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */ case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */ case USB_ID(0x2912, 0x30c8): /* Audioengine D1 */ + case USB_ID(0x413c, 0xa506): /* Dell AE515 sound bar */ return true; } @@ -1335,13 +1336,21 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) msleep(20); - /* Zoom R16/24, Logitech H650e/H570e, Jabra 550a, Kingston HyperX - * needs a tiny delay here, otherwise requests like get/set - * frequency return as failed despite actually succeeding. + /* + * Plantronics headsets (C320, C320-M, etc) need a delay to avoid + * random microhpone failures. + */ + if (USB_ID_VENDOR(chip->usb_id) == 0x047f && + (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) + msleep(20); + + /* Zoom R16/24, many Logitech(at least H650e/H570e/BCC950), + * Jabra 550a, Kingston HyperX needs a tiny delay here, + * otherwise requests like get/set frequency return + * as failed despite actually succeeding. */ if ((chip->usb_id == USB_ID(0x1686, 0x00dd) || - chip->usb_id == USB_ID(0x046d, 0x0a46) || - chip->usb_id == USB_ID(0x046d, 0x0a56) || + USB_ID_VENDOR(chip->usb_id) == 0x046d || /* Logitech */ chip->usb_id == USB_ID(0x0b0e, 0x0349) || chip->usb_id == USB_ID(0x0951, 0x16ad)) && (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) @@ -1462,6 +1471,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip, case 0x25ce: /* Mytek devices */ case 0x278b: /* Rotel? */ case 0x292b: /* Gustard/Ess based devices */ + case 0x2972: /* FiiO devices */ case 0x2ab6: /* T+A devices */ case 0x3353: /* Khadas devices */ case 0x3842: /* EVGA */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index c414dffa55f0..9c00119f73a1 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -202,16 +202,16 @@ static int usb_chmap_ctl_get(struct snd_kcontrol *kcontrol, struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); struct snd_usb_substream *subs = info->private_data; struct snd_pcm_chmap_elem *chmap = NULL; - int i; + int i = 0; - memset(ucontrol->value.integer.value, 0, - sizeof(ucontrol->value.integer.value)); if (subs->cur_audiofmt) chmap = subs->cur_audiofmt->chmap; if (chmap) { for (i = 0; i < chmap->channels; i++) ucontrol->value.integer.value[i] = chmap->map[i]; } + for (; i < subs->channels_max; i++) + ucontrol->value.integer.value[i] = 0; return 0; } diff --git a/techpack/audio/asoc/Kbuild b/techpack/audio/asoc/Kbuild index a0d8de1f66e7..08c40b0598ed 100644 --- a/techpack/audio/asoc/Kbuild +++ b/techpack/audio/asoc/Kbuild @@ -286,6 +286,3 @@ machine_dlkm-y := $(MACHINE_OBJS) obj-$(CONFIG_SND_SOC_CPE) += cpe_lsm_dlkm.o cpe_lsm_dlkm-y := $(CPE_LSM_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/Kbuild b/techpack/audio/asoc/codecs/Kbuild index 5bd3ffe19f3b..b407165a23cb 100644 --- a/techpack/audio/asoc/codecs/Kbuild +++ b/techpack/audio/asoc/codecs/Kbuild @@ -268,6 +268,3 @@ mbhc_dlkm-y := $(MBHC_OBJS) obj-$(CONFIG_SND_SOC_MSM_HDMI_CODEC_RX) += hdmi_dlkm.o hdmi_dlkm-y := $(HDMICODEC_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/aqt1000/Kbuild b/techpack/audio/asoc/codecs/aqt1000/Kbuild index d83955f0ad37..c7f8b895c6c6 100644 --- a/techpack/audio/asoc/codecs/aqt1000/Kbuild +++ b/techpack/audio/asoc/codecs/aqt1000/Kbuild @@ -115,6 +115,3 @@ endif # Module information used by KBuild framework obj-$(CONFIG_SND_SOC_AQT1000) += aqt1000_cdc_dlkm.o aqt1000_cdc_dlkm-y := $(AQT1000_CDC_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/bolero/Kbuild b/techpack/audio/asoc/codecs/bolero/Kbuild index 15e5dc576da3..9042ebfa8e1e 100644 --- a/techpack/audio/asoc/codecs/bolero/Kbuild +++ b/techpack/audio/asoc/codecs/bolero/Kbuild @@ -154,6 +154,3 @@ tx_macro_dlkm-y := $(TX_OBJS) obj-$(CONFIG_RX_MACRO) += rx_macro_dlkm.o rx_macro_dlkm-y := $(RX_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/cs35l41/Android.mk b/techpack/audio/asoc/codecs/cs35l41/Android.mk index a7335db8cee2..3c41717cef13 100755 --- a/techpack/audio/asoc/codecs/cs35l41/Android.mk +++ b/techpack/audio/asoc/codecs/cs35l41/Android.mk @@ -50,7 +50,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := $(AUDIO_CHIPSET)_cs35l41.ko LOCAL_MODULE_KBUILD_NAME := cs35l41_dlkm.ko LOCAL_MODULE_TAGS := optional -LOCAL_MODULE_DEBUG_ENABLE := true +LOCAL_MODULE_DEBUG_ENABLE := false LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) include $(DLKM_DIR)/AndroidKernelModule.mk ########################################################### diff --git a/techpack/audio/asoc/codecs/cs35l41/Kbuild b/techpack/audio/asoc/codecs/cs35l41/Kbuild index 68101c8354b1..a2f15951d9b0 100755 --- a/techpack/audio/asoc/codecs/cs35l41/Kbuild +++ b/techpack/audio/asoc/codecs/cs35l41/Kbuild @@ -47,8 +47,8 @@ endif # As per target team, build is done as follows: # Defconfig : build with default flags -# Slub : defconfig + CONFIG_SLUB_DEBUG := y + -# CONFIG_SLUB_DEBUG_ON := y + CONFIG_PAGE_POISONING := y +# Slub : defconfig + CONFIG_SLUB_DEBUG := n + +# CONFIG_SLUB_DEBUG_ON := n + CONFIG_PAGE_POISONING := y # Perf : Using appropriate msmXXXX-perf_defconfig # # Shipment builds (user variants) should not have any debug feature @@ -77,7 +77,6 @@ ifdef CONFIG_SND_SOC_CS35L41 CS35L41_OBJS += cs35l41-i2c.o CS35L41_OBJS += cs35l41-tables.o CS35L41_OBJS += wm_adsp.o - CS35L41_OBJS += send_data_to_xlog.o endif LINUX_INC += -Iinclude/linux diff --git a/techpack/audio/asoc/codecs/cs35l41/cs35l41.c b/techpack/audio/asoc/codecs/cs35l41/cs35l41.c index 39c394634e26..43abc1c83bae 100755 --- a/techpack/audio/asoc/codecs/cs35l41/cs35l41.c +++ b/techpack/audio/asoc/codecs/cs35l41/cs35l41.c @@ -12,7 +12,6 @@ * published by the Free Software Foundation. * */ -#define DEBUG #include #include #include @@ -796,7 +795,6 @@ static irqreturn_t cs35l41_irq(int irq, void *data) unsigned int status[4]; unsigned int masks[4]; unsigned int i; - char reason[] = "DSP"; dev_info(cs35l41->dev, "step into cs35l41 irq handler\n"); for (i = 0; i < ARRAY_SIZE(status); i++) { @@ -922,7 +920,6 @@ static irqreturn_t cs35l41_irq(int irq, void *data) //regmap_write(cs35l41->regmap, CS35L41_AMP_OUT_MUTE, // 1 << CS35L41_AMP_MUTE_SHIFT); cs35l41->dc_current_cnt++; - send_DC_data_to_xlog((int)cs35l41->dc_current_cnt, reason); dev_crit(cs35l41->dev, "DC current detected"); } diff --git a/techpack/audio/asoc/codecs/csra66x0/Kbuild b/techpack/audio/asoc/codecs/csra66x0/Kbuild index ef599622dd25..fe77d62718f8 100644 --- a/techpack/audio/asoc/codecs/csra66x0/Kbuild +++ b/techpack/audio/asoc/codecs/csra66x0/Kbuild @@ -100,6 +100,3 @@ endif # Module information used by KBuild framework obj-$(CONFIG_SND_SOC_CSRA66X0) += csra66x0_dlkm.o csra66x0_dlkm-y := $(CSRA66X0_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/ep92/Kbuild b/techpack/audio/asoc/codecs/ep92/Kbuild index fc46a72f775d..ee4db7f39caf 100644 --- a/techpack/audio/asoc/codecs/ep92/Kbuild +++ b/techpack/audio/asoc/codecs/ep92/Kbuild @@ -101,6 +101,3 @@ endif # Module information used by KBuild framework obj-$(CONFIG_SND_SOC_EP92) += ep92_dlkm.o ep92_dlkm-y := $(EP92_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/rouleur/Kbuild b/techpack/audio/asoc/codecs/rouleur/Kbuild index b59bcb1194ef..97965788b5e6 100644 --- a/techpack/audio/asoc/codecs/rouleur/Kbuild +++ b/techpack/audio/asoc/codecs/rouleur/Kbuild @@ -115,6 +115,3 @@ rouleur_slave_dlkm-y := $(ROULEUR_SLAVE_OBJS) obj-$(CONFIG_PM2250_SPMI) += pm2250_spmi_dlkm.o pm2250_spmi_dlkm-y := $(PM2250_SPMI_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/wcd934x/Kbuild b/techpack/audio/asoc/codecs/wcd934x/Kbuild index d372ed762cef..404cc8dca141 100644 --- a/techpack/audio/asoc/codecs/wcd934x/Kbuild +++ b/techpack/audio/asoc/codecs/wcd934x/Kbuild @@ -121,6 +121,3 @@ endif # Module information used by KBuild framework obj-$(CONFIG_SND_SOC_WCD934X) += wcd934x_dlkm.o wcd934x_dlkm-y := $(WCD934X_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/wcd937x/Kbuild b/techpack/audio/asoc/codecs/wcd937x/Kbuild index 5bbbad7cbdf5..b81fed3efd34 100644 --- a/techpack/audio/asoc/codecs/wcd937x/Kbuild +++ b/techpack/audio/asoc/codecs/wcd937x/Kbuild @@ -123,6 +123,3 @@ wcd937x_dlkm-y := $(WCD937X_OBJS) obj-$(CONFIG_SND_SOC_WCD937X_SLAVE) += wcd937x_slave_dlkm.o wcd937x_slave_dlkm-y := $(WCD937X_SLAVE_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/wcd938x/Kbuild b/techpack/audio/asoc/codecs/wcd938x/Kbuild index 3dfe142bcfc2..bc5284355db2 100644 --- a/techpack/audio/asoc/codecs/wcd938x/Kbuild +++ b/techpack/audio/asoc/codecs/wcd938x/Kbuild @@ -111,6 +111,3 @@ wcd938x_dlkm-y := $(WCD938X_OBJS) obj-$(CONFIG_SND_SOC_WCD938X_SLAVE) += wcd938x_slave_dlkm.o wcd938x_slave_dlkm-y := $(WCD938X_SLAVE_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/codecs/wsa883x/Kbuild b/techpack/audio/asoc/codecs/wsa883x/Kbuild index ac608b46c6a3..a7013e40ea4a 100644 --- a/techpack/audio/asoc/codecs/wsa883x/Kbuild +++ b/techpack/audio/asoc/codecs/wsa883x/Kbuild @@ -102,6 +102,3 @@ endif # Module information used by KBuild framework obj-$(CONFIG_SND_SOC_WSA883X) += wsa883x_dlkm.o wsa883x_dlkm-y := $(WSA883X_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/asoc/kona.c b/techpack/audio/asoc/kona.c index c847be1c89bd..94fcaf5b9c1f 100644 --- a/techpack/audio/asoc/kona.c +++ b/techpack/audio/asoc/kona.c @@ -5055,15 +5055,10 @@ static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream, static int msm_fe_qos_prepare(struct snd_pcm_substream *substream) { - cpumask_t mask; - if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); - cpumask_clear(&mask); - cpumask_set_cpu(1, &mask); /* affine to core 1 */ - cpumask_set_cpu(2, &mask); /* affine to core 2 */ - cpumask_copy(&substream->latency_pm_qos_req.cpus_affine, &mask); + atomic_set(&substream->latency_pm_qos_req.cpus_affine, BIT(1) | BIT(2)); substream->latency_pm_qos_req.type = PM_QOS_REQ_AFFINE_CORES; diff --git a/techpack/audio/dsp/Kbuild b/techpack/audio/dsp/Kbuild index 840cddac6e63..8f91124dcdcf 100644 --- a/techpack/audio/dsp/Kbuild +++ b/techpack/audio/dsp/Kbuild @@ -283,6 +283,3 @@ q6_pdr_dlkm-y := $(QDSP6_PDR_OBJS) obj-$(CONFIG_MSM_QDSP6_NOTIFIER) += q6_notifier_dlkm.o q6_notifier_dlkm-y := $(QDSP6_NOTIFIER_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/dsp/codecs/Kbuild b/techpack/audio/dsp/codecs/Kbuild index 808bfe22a076..6a6a3da96ccc 100644 --- a/techpack/audio/dsp/codecs/Kbuild +++ b/techpack/audio/dsp/codecs/Kbuild @@ -161,6 +161,3 @@ endif # Module information used by KBuild framework obj-$(CONFIG_MSM_QDSP6V2_CODECS) += native_dlkm.o native_dlkm-y := $(NATIVE_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/dsp/q6afe.c b/techpack/audio/dsp/q6afe.c index 645c4799f9bf..38d0b20f8995 100644 --- a/techpack/audio/dsp/q6afe.c +++ b/techpack/audio/dsp/q6afe.c @@ -2934,7 +2934,7 @@ static int afe_send_hw_delay(u16 port_id, u32 rate) __func__, port_id, ret); fail_cmd: - pr_info("%s: port_id 0x%x rate %u delay_usec %d status %d\n", + pr_debug("%s: port_id 0x%x rate %u delay_usec %d status %d\n", __func__, port_id, rate, delay_entry.delay_usec, ret); return ret; } @@ -2958,7 +2958,7 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port( /* Skip cal_block if it is already marked stale */ if (cal_utils_is_cal_stale(cal_block)) continue; - pr_info("%s: port id: 0x%x, dev_acdb_id: %d\n", __func__, + pr_debug("%s: port id: 0x%x, dev_acdb_id: %d\n", __func__, port_id, this_afe.dev_acdb_id[afe_port_index]); path = ((afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE)); @@ -2968,14 +2968,14 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port( if (this_afe.dev_acdb_id[afe_port_index] > 0) { if (afe_top->acdb_id == this_afe.dev_acdb_id[afe_port_index]) { - pr_info("%s: top_id:%x acdb_id:%d afe_port_id:0x%x\n", + pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:0x%x\n", __func__, afe_top->topology, afe_top->acdb_id, q6audio_get_port_id(port_id)); return cal_block; } } else { - pr_info("%s: top_id:%x acdb_id:%d afe_port:0x%x\n", + pr_debug("%s: top_id:%x acdb_id:%d afe_port:0x%x\n", __func__, afe_top->topology, afe_top->acdb_id, q6audio_get_port_id(port_id)); return cal_block; @@ -3032,7 +3032,7 @@ static int afe_get_cal_topology_id(u16 port_id, u32 *topology_id, *topology_id = (u32)afe_top_info->topology; cal_utils_mark_cal_used(cal_block); - pr_info("%s: port_id = 0x%x acdb_id = %d topology_id = 0x%x cal_type_index=%d ret=%d\n", + pr_debug("%s: port_id = 0x%x acdb_id = %d topology_id = 0x%x cal_type_index=%d ret=%d\n", __func__, port_id, afe_top_info->acdb_id, afe_top_info->topology, cal_type_index, ret); unlock: @@ -3091,7 +3091,7 @@ static int afe_send_port_topology_id(u16 port_id) this_afe.topology[index] = topology_id; rtac_update_afe_topology(port_id); done: - pr_info("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n", + pr_debug("%s: AFE set topology id 0x%x enable for port 0x%x ret %d\n", __func__, topology_id, port_id, ret); return ret; @@ -3328,7 +3328,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id) struct audio_cal_info_afe *afe_cal_info = NULL; int afe_port_index = q6audio_get_port_index(port_id); - pr_info("%s: cal_index %d port_id 0x%x port_index %d\n", __func__, + pr_debug("%s: cal_index %d port_id 0x%x port_index %d\n", __func__, cal_index, port_id, afe_port_index); if (afe_port_index < 0) { pr_err("%s: Error getting AFE port index %d\n", @@ -3340,7 +3340,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id) &this_afe.cal_data[cal_index]->cal_blocks) { cal_block = list_entry(ptr, struct cal_block_data, list); afe_cal_info = cal_block->cal_info; - pr_info("%s: acdb_id %d dev_acdb_id %d sample_rate %d afe_sample_rates %d\n", + pr_debug("%s: acdb_id %d dev_acdb_id %d sample_rate %d afe_sample_rates %d\n", __func__, afe_cal_info->acdb_id, this_afe.dev_acdb_id[afe_port_index], afe_cal_info->sample_rate, @@ -3349,7 +3349,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id) this_afe.dev_acdb_id[afe_port_index]) && (afe_cal_info->sample_rate == this_afe.afe_sample_rates[afe_port_index])) { - pr_info("%s: cal block is a match, size is %zd\n", + pr_debug("%s: cal block is a match, size is %zd\n", __func__, cal_block->cal_data.size); goto exit; } @@ -3367,7 +3367,7 @@ static int send_afe_cal_type(int cal_index, int port_id) int ret; int afe_port_index = q6audio_get_port_index(port_id); - pr_info("%s: cal_index is %d\n", __func__, cal_index); + pr_debug("%s: cal_index is %d\n", __func__, cal_index); if (this_afe.cal_data[cal_index] == NULL) { pr_warn("%s: cal_index %d not allocated!\n", @@ -3384,7 +3384,7 @@ static int send_afe_cal_type(int cal_index, int port_id) } mutex_lock(&this_afe.cal_data[cal_index]->lock); - pr_info("%s: dev_acdb_id[%d] is %d\n", + pr_debug("%s: dev_acdb_id[%d] is %d\n", __func__, afe_port_index, this_afe.dev_acdb_id[afe_port_index]); if (((cal_index == AFE_COMMON_RX_CAL) || @@ -3402,7 +3402,7 @@ static int send_afe_cal_type(int cal_index, int port_id) goto unlock; } - pr_info("%s: Sending cal_index cal %d\n", __func__, cal_index); + pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index); ret = remap_cal_data(cal_block, cal_index); if (ret) { @@ -5357,7 +5357,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config, port_id = VIRTUAL_ID_TO_PORTID(port_id); } - pr_info("%s: port id: 0x%x\n", __func__, port_id); + pr_debug("%s: port id: 0x%x\n", __func__, port_id); index = q6audio_get_port_index(port_id); if (index < 0 || index >= AFE_MAX_PORTS) { diff --git a/techpack/audio/ipc/Kbuild b/techpack/audio/ipc/Kbuild index 755d6d8eacd5..d63930a06391 100644 --- a/techpack/audio/ipc/Kbuild +++ b/techpack/audio/ipc/Kbuild @@ -190,6 +190,3 @@ apr_dlkm-y := $(APRV_GLINK) obj-$(CONFIG_WCD_DSP_GLINK) += wglink_dlkm.o wglink_dlkm-y := $(WDSP_GLINK) - -# inject some build related information -CDEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/soc/Kbuild b/techpack/audio/soc/Kbuild index 4fedbddcf460..d7d0c32a52fb 100644 --- a/techpack/audio/soc/Kbuild +++ b/techpack/audio/soc/Kbuild @@ -211,6 +211,3 @@ swr_ctrl_dlkm-y := $(SWR_CTRL_OBJS) obj-$(CONFIG_WCD_SPI_AC) += wcd_spi_acc_ctl_dlkm.o wcd_spi_acc_ctl_dlkm-y := $(WCD_SPI_ACC_CTL_OBJS) - -# inject some build related information -DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\" diff --git a/techpack/audio/soc/pinctrl-lpi.c b/techpack/audio/soc/pinctrl-lpi.c index 3258b10f18e8..1c9d5881cb54 100644 --- a/techpack/audio/soc/pinctrl-lpi.c +++ b/techpack/audio/soc/pinctrl-lpi.c @@ -953,7 +953,17 @@ static struct platform_driver lpi_pinctrl_driver = { .remove = lpi_pinctrl_remove, }; -module_platform_driver(lpi_pinctrl_driver); +static int __init lpi_init(void) +{ + return platform_driver_register(&lpi_pinctrl_driver); +} +late_initcall(lpi_init); + +static void __exit lpi_exit(void) +{ + platform_driver_unregister(&lpi_pinctrl_driver); +} +module_exit(lpi_exit); MODULE_DESCRIPTION("QTI LPI GPIO pin control driver"); MODULE_LICENSE("GPL v2"); diff --git a/techpack/camera/drivers/cam_icp/hfi.c b/techpack/camera/drivers/cam_icp/hfi.c index 89a95aca62e1..fdbaa11cee56 100644 --- a/techpack/camera/drivers/cam_icp/hfi.c +++ b/techpack/camera/drivers/cam_icp/hfi.c @@ -674,10 +674,6 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len, icp_base + HFI_REG_IO2_REGION_SIZE); - CAM_INFO(CAM_HFI, "Resume IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]", - hfi_mem->io_mem.iova, hfi_mem->io_mem.len, - hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len); - return rc; } diff --git a/techpack/camera/drivers/cam_isp/cam_isp_context.c b/techpack/camera/drivers/cam_isp/cam_isp_context.c index 63a46f2216c3..067363f32e2e 100644 --- a/techpack/camera/drivers/cam_isp/cam_isp_context.c +++ b/techpack/camera/drivers/cam_isp/cam_isp_context.c @@ -1137,13 +1137,6 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id); - if (ctx_isp->frame_id == 1) - CAM_INFO(CAM_ISP, - "First SOF in EPCR ctx:%d frame_id:%lld next substate %s", - ctx->ctx_id, ctx_isp->frame_id, - __cam_isp_ctx_substate_val_to_type( - ctx_isp->substate_activated)); - CAM_DBG(CAM_ISP, "SOF in epoch ctx:%d frame_id:%lld next substate:%s", ctx->ctx_id, ctx_isp->frame_id, __cam_isp_ctx_substate_val_to_type( diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 76b94263fa9f..d9b23643783b 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -2794,10 +2794,6 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) acquire_hw_info->num_inputs; getnstimeofday64(&ife_ctx->ts); - CAM_INFO(CAM_ISP, - "Acquire HW success with total_pix: %u total_rdi: %u is_dual: %u in ctx: %u", - total_pix_port, total_rdi_port, - ife_ctx->is_dual, ife_ctx->ctx_index); cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); @@ -4211,9 +4207,6 @@ static int cam_ife_mgr_release_hw(void *hw_mgr_priv, ctx->epoch_cnt[i] = 0; } - CAM_INFO(CAM_ISP, "Release HW success ctx id: %u", - ctx->ctx_index); - memset(&ctx->ts, 0, sizeof(struct timespec64)); cam_ife_hw_mgr_put_ctx(&hw_mgr->free_ctx_list, &ctx); return rc; diff --git a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c index 53933b9afad0..dade7d7e149d 100644 --- a/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c +++ b/techpack/camera/drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver3.c @@ -3595,7 +3595,6 @@ static int cam_vfe_bus_ver3_init_hw(void *hw_priv, } /* no clock gating at bus input */ - CAM_INFO(CAM_ISP, "Overriding clock gating at bus input"); cam_io_w_mb(0x3FFFFFF, bus_priv->common_data.mem_base + bus_priv->common_data.common_reg->cgc_ovd); diff --git a/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c index 34055db2863e..43b5032b95d0 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.c @@ -665,6 +665,9 @@ static int cam_res_mgr_probe(struct platform_device *pdev) { int rc = 0; + if (cam_res) + return 0; + cam_res = kzalloc(sizeof(*cam_res), GFP_KERNEL); if (!cam_res) return -ENOMEM; diff --git a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c index c16ad5b39a20..0d92bb79b23f 100644 --- a/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c +++ b/techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c @@ -709,12 +709,6 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, goto free_power_settings; } - CAM_INFO(CAM_SENSOR, - "Probe success,slot:%d,slave_addr:0x%x,sensor_id:0x%x", - s_ctrl->soc_info.index, - s_ctrl->sensordata->slave_info.sensor_slave_addr, - s_ctrl->sensordata->slave_info.sensor_id); - rc = cam_sensor_power_down(s_ctrl); if (rc < 0) { CAM_ERR(CAM_SENSOR, "fail in Sensor Power Down"); @@ -783,10 +777,6 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; s_ctrl->last_flush_req = 0; - CAM_INFO(CAM_SENSOR, - "CAM_ACQUIRE_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", - s_ctrl->sensordata->slave_info.sensor_id, - s_ctrl->sensordata->slave_info.sensor_slave_addr); } break; case CAM_RELEASE_DEV: { @@ -853,10 +843,6 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, s_ctrl->bridge_intf.session_hdl = -1; s_ctrl->sensor_state = CAM_SENSOR_INIT; - CAM_INFO(CAM_SENSOR, - "CAM_RELEASE_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", - s_ctrl->sensordata->slave_info.sensor_id, - s_ctrl->sensordata->slave_info.sensor_slave_addr); s_ctrl->streamon_count = 0; s_ctrl->streamoff_count = 0; s_ctrl->last_flush_req = 0; @@ -895,10 +881,6 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, } } s_ctrl->sensor_state = CAM_SENSOR_START; - CAM_INFO(CAM_SENSOR, - "CAM_START_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", - s_ctrl->sensordata->slave_info.sensor_id, - s_ctrl->sensordata->slave_info.sensor_slave_addr); } break; case CAM_STOP_DEV: { @@ -923,10 +905,6 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl, cam_sensor_release_per_frame_resource(s_ctrl); s_ctrl->last_flush_req = 0; s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE; - CAM_INFO(CAM_SENSOR, - "CAM_STOP_DEV Success, sensor_id:0x%x,sensor_slave_addr:0x%x", - s_ctrl->sensordata->slave_info.sensor_id, - s_ctrl->sensordata->slave_info.sensor_slave_addr); } break; case CAM_CONFIG_DEV: { diff --git a/techpack/camera/drivers/cam_smmu/cam_smmu_api.c b/techpack/camera/drivers/cam_smmu/cam_smmu_api.c index 4ab25ea73681..f8fe5c7d60d5 100644 --- a/techpack/camera/drivers/cam_smmu/cam_smmu_api.c +++ b/techpack/camera/drivers/cam_smmu/cam_smmu_api.c @@ -178,6 +178,8 @@ struct cam_dma_buff_info { struct cam_sec_buff_info { struct dma_buf *buf; + struct dma_buf_attachment *attach; + struct sg_table *table; enum dma_data_direction dir; int ref_count; dma_addr_t paddr; @@ -2506,6 +2508,8 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, mapping_info->dir = dma_dir; mapping_info->ref_count = 1; mapping_info->buf = dmabuf; + mapping_info->attach = attach; + mapping_info->table = table; CAM_DBG(CAM_SMMU, "idx=%d, ion_fd=%d, dev=%pK, paddr=%pK, len=%u", idx, ion_fd, @@ -2515,14 +2519,13 @@ static int cam_smmu_map_stage2_buffer_and_add_to_list(int idx, int ion_fd, /* add to the list */ list_add(&mapping_info->list, &iommu_cb_set.cb_info[idx].smmu_buf_list); - return 0; - err_unmap_sg: dma_buf_unmap_attachment(attach, table, dma_dir); err_detach: dma_buf_detach(dmabuf, attach); err_put: - dma_buf_put(dmabuf); + if (rc) + dma_buf_put(dmabuf); err_out: return rc; } @@ -2610,6 +2613,9 @@ static int cam_smmu_secure_unmap_buf_and_remove_from_list( CAM_ERR(CAM_SMMU, "Error: List doesn't exist"); return -EINVAL; } + dma_buf_unmap_attachment(mapping_info->attach, mapping_info->table, + mapping_info->dir); + dma_buf_detach(mapping_info->buf, mapping_info->attach); dma_buf_put(mapping_info->buf); list_del_init(&mapping_info->list); diff --git a/techpack/camera/drivers/cam_sync/cam_sync.c b/techpack/camera/drivers/cam_sync/cam_sync.c index 9099e2a91088..153529e59571 100644 --- a/techpack/camera/drivers/cam_sync/cam_sync.c +++ b/techpack/camera/drivers/cam_sync/cam_sync.c @@ -17,6 +17,7 @@ #include #endif struct sync_device *sync_dev; +static struct kmem_cache *kmem_payload_pool; /* * Flag to determine whether to enqueue cb of a @@ -604,7 +605,7 @@ static int cam_sync_handle_register_user_payload( if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) return -EINVAL; - user_payload_kernel = kzalloc(sizeof(*user_payload_kernel), GFP_KERNEL); + user_payload_kernel = kmem_cache_zalloc(kmem_payload_pool, GFP_KERNEL); if (!user_payload_kernel) return -ENOMEM; @@ -620,7 +621,7 @@ static int cam_sync_handle_register_user_payload( "Error: accessing an uninitialized sync obj = %d", sync_obj); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); - kfree(user_payload_kernel); + kmem_cache_free(kmem_payload_pool, user_payload_kernel); return -EINVAL; } @@ -634,7 +635,7 @@ static int cam_sync_handle_register_user_payload( CAM_SYNC_USER_PAYLOAD_SIZE * sizeof(__u64)); spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); - kfree(user_payload_kernel); + kmem_cache_free(kmem_payload_pool, user_payload_kernel); return 0; } @@ -648,7 +649,7 @@ static int cam_sync_handle_register_user_payload( user_payload_kernel->payload_data[1]) { spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]); - kfree(user_payload_kernel); + kmem_cache_free(kmem_payload_pool, user_payload_kernel); return -EALREADY; } } @@ -703,7 +704,7 @@ static int cam_sync_handle_deregister_user_payload( user_payload_kernel->payload_data[1] == userpayload_info.payload[1]) { list_del_init(&user_payload_kernel->list); - kfree(user_payload_kernel); + kmem_cache_free(kmem_payload_pool, user_payload_kernel); } } @@ -1138,6 +1139,8 @@ static int __init cam_sync_init(void) { int rc; + kmem_payload_pool = KMEM_CACHE(sync_user_payload, SLAB_HWCACHE_ALIGN | SLAB_PANIC); + rc = platform_device_register(&cam_sync_device); if (rc) return -ENODEV; @@ -1154,6 +1157,8 @@ static void __exit cam_sync_exit(void) platform_driver_unregister(&cam_sync_driver); platform_device_unregister(&cam_sync_device); kfree(sync_dev); + + kmem_cache_destroy(kmem_payload_pool); } module_init(cam_sync_init); diff --git a/techpack/camera/drivers/cam_utils/Makefile b/techpack/camera/drivers/cam_utils/Makefile index e17c2f50bb95..6b1710b7dfde 100644 --- a/techpack/camera/drivers/cam_utils/Makefile +++ b/techpack/camera/drivers/cam_utils/Makefile @@ -5,5 +5,5 @@ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_core/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_req_mgr/ ccflags-y += -I$(srctree)/techpack/camera/drivers/cam_smmu/ -obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_debug_util.o cam_trace.o cam_common_util.o +obj-$(CONFIG_SPECTRA_CAMERA) += cam_soc_util.o cam_io_util.o cam_packet_util.o cam_trace.o cam_common_util.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_cx_ipeak.o diff --git a/techpack/camera/drivers/cam_utils/cam_debug_util.h b/techpack/camera/drivers/cam_utils/cam_debug_util.h index 181a1558a904..caf95d1dcb41 100644 --- a/techpack/camera/drivers/cam_utils/cam_debug_util.h +++ b/techpack/camera/drivers/cam_utils/cam_debug_util.h @@ -55,8 +55,10 @@ * @fmt : Formatted string which needs to be print in the log * */ -void cam_debug_log(unsigned int module_id, const char *func, const int line, - const char *fmt, ...); +static inline void cam_debug_log(unsigned int module_id, const char *func, + const int line, const char *fmt, ...) +{ +} /* * cam_get_module_name() @@ -65,7 +67,10 @@ void cam_debug_log(unsigned int module_id, const char *func, const int line, * * @module_id : Module ID which is using this function */ -const char *cam_get_module_name(unsigned int module_id); +static inline const char *cam_get_module_name(unsigned int module_id) +{ + return NULL; +} /* * CAM_ERR @@ -75,9 +80,9 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_ERR(__module, fmt, args...) \ - pr_info("CAM_ERR: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_ERR(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) + /* * CAM_WARN * @brief : This Macro will print warning logs @@ -86,9 +91,9 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_WARN(__module, fmt, args...) \ - pr_info("CAM_WARN: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_WARN(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) + /* * CAM_INFO * @brief : This Macro will print Information logs @@ -97,9 +102,8 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_INFO(__module, fmt, args...) \ - pr_info("CAM_INFO: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_INFO(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) /* * CAM_INFO_RATE_LIMIT @@ -109,9 +113,8 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_INFO_RATE_LIMIT(__module, fmt, args...) \ - pr_info_ratelimited("CAM_INFO: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_INFO_RATE_LIMIT(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) /* * CAM_DBG @@ -121,16 +124,16 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_DBG(__module, fmt, args...) \ +#define CAM_DBG(__module, fmt, args...) \ cam_debug_log(__module, __func__, __LINE__, fmt, ##args) /* * CAM_ERR_RATE_LIMIT * @brief : This Macro will print error print logs with ratelimit */ -#define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ - pr_info_ratelimited("CAM_ERR: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_ERR_RATE_LIMIT(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) + /* * CAM_WARN_RATE_LIMIT * @brief : This Macro will print warning logs with ratelimit @@ -139,9 +142,8 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_WARN_RATE_LIMIT(__module, fmt, args...) \ - pr_info_ratelimited("CAM_WARN: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, __LINE__, ##args) +#define CAM_WARN_RATE_LIMIT(__module, fmt, args...) \ + cam_debug_log(__module, __func__, __LINE__, fmt, ##args) /* * CAM_WARN_RATE_LIMIT_CUSTOM @@ -153,17 +155,7 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_WARN_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ - ({ \ - static DEFINE_RATELIMIT_STATE(_rs, \ - (interval * HZ), \ - burst); \ - if (__ratelimit(&_rs)) \ - pr_info( \ - "CAM_WARN: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, \ - __LINE__, ##args); \ - }) +#define CAM_WARN_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) /* * CAM_INFO_RATE_LIMIT_CUSTOM @@ -175,17 +167,7 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_INFO_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ - ({ \ - static DEFINE_RATELIMIT_STATE(_rs, \ - (interval * HZ), \ - burst); \ - if (__ratelimit(&_rs)) \ - pr_info( \ - "CAM_INFO: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, \ - __LINE__, ##args); \ - }) +#define CAM_INFO_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) /* * CAM_ERR_RATE_LIMIT_CUSTOM @@ -197,16 +179,6 @@ const char *cam_get_module_name(unsigned int module_id); * @fmt : Formatted string which needs to be print in log * @args : Arguments which needs to be print in log */ -#define CAM_ERR_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) \ - ({ \ - static DEFINE_RATELIMIT_STATE(_rs, \ - (interval * HZ), \ - burst); \ - if (__ratelimit(&_rs)) \ - pr_info( \ - "CAM_ERR: %s: %s: %d " fmt "\n", \ - cam_get_module_name(__module), __func__, \ - __LINE__, ##args); \ - }) +#define CAM_ERR_RATE_LIMIT_CUSTOM(__module, interval, burst, fmt, args...) #endif /* _CAM_DEBUG_UTIL_H_ */ diff --git a/techpack/display/config/konadisp.conf b/techpack/display/config/konadisp.conf index dbbf3c847dbb..a6cfc5499d19 100644 --- a/techpack/display/config/konadisp.conf +++ b/techpack/display/config/konadisp.conf @@ -6,8 +6,9 @@ export CONFIG_DRM_MSM_DP=y export CONFIG_QCOM_MDSS_DP_PLL=y export CONFIG_DSI_PARSER=y export CONFIG_DRM_SDE_WB=y -export CONFIG_DRM_MSM_REGISTER_LOGGING=y +export CONFIG_DRM_MSM_REGISTER_LOGGING=n +export CONFIG_DRM_SDE_EVTLOG_DEBUG=n export CONFIG_QCOM_MDSS_PLL=y export CONFIG_MSM_SDE_ROTATOR=y -export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y +export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=n export CONFIG_DRM_SDE_RSC=y diff --git a/techpack/display/config/konadispconf.h b/techpack/display/config/konadispconf.h index 690d4ec79f41..4998bacccbdf 100644 --- a/techpack/display/config/konadispconf.h +++ b/techpack/display/config/konadispconf.h @@ -11,10 +11,10 @@ #define CONFIG_QCOM_MDSS_DP_PLL 1 #define CONFIG_DSI_PARSER 1 #define CONFIG_DRM_SDE_WB 1 -#define CONFIG_DRM_MSM_REGISTER_LOGGING 1 -#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1 +#define CONFIG_DRM_MSM_REGISTER_LOGGING 0 +#define CONFIG_DRM_SDE_EVTLOG_DEBUG 0 #define CONFIG_QCOM_MDSS_PLL 1 #define CONFIG_MSM_SDE_ROTATOR 1 -#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1 +#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 0 #define CONFIG_DRM_SDE_RSC 1 diff --git a/techpack/display/config/saipdisp.conf b/techpack/display/config/saipdisp.conf index dbbf3c847dbb..b225d21642ec 100644 --- a/techpack/display/config/saipdisp.conf +++ b/techpack/display/config/saipdisp.conf @@ -2,12 +2,9 @@ export CONFIG_DRM_MSM=y export CONFIG_DRM_MSM_SDE=y export CONFIG_SYNC_FILE=y export CONFIG_DRM_MSM_DSI=y -export CONFIG_DRM_MSM_DP=y export CONFIG_QCOM_MDSS_DP_PLL=y export CONFIG_DSI_PARSER=y export CONFIG_DRM_SDE_WB=y -export CONFIG_DRM_MSM_REGISTER_LOGGING=y export CONFIG_QCOM_MDSS_PLL=y export CONFIG_MSM_SDE_ROTATOR=y -export CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y export CONFIG_DRM_SDE_RSC=y diff --git a/techpack/display/config/saipdispconf.h b/techpack/display/config/saipdispconf.h index 049024839701..f3e3d1773232 100644 --- a/techpack/display/config/saipdispconf.h +++ b/techpack/display/config/saipdispconf.h @@ -7,13 +7,9 @@ #define CONFIG_DRM_MSM_SDE 1 #define CONFIG_SYNC_FILE 1 #define CONFIG_DRM_MSM_DSI 1 -#define CONFIG_DRM_MSM_DP 1 #define CONFIG_QCOM_MDSS_DP_PLL 1 #define CONFIG_DSI_PARSER 1 #define CONFIG_DRM_SDE_WB 1 -#define CONFIG_DRM_MSM_REGISTER_LOGGING 1 -#define CONFIG_DRM_SDE_EVTLOG_DEBUG 1 #define CONFIG_QCOM_MDSS_PLL 1 #define CONFIG_MSM_SDE_ROTATOR 1 -#define CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG 1 #define CONFIG_DRM_SDE_RSC 1 diff --git a/techpack/display/msm/dsi/dsi_defs.h b/techpack/display/msm/dsi/dsi_defs.h index fc1e6cb139f7..2330b400e13b 100644 --- a/techpack/display/msm/dsi/dsi_defs.h +++ b/techpack/display/msm/dsi/dsi_defs.h @@ -45,9 +45,9 @@ (index < MAX_DSI_CTRLS_PER_DISPLAY); index++) #define DSI_WARN(fmt, ...) DRM_WARN("[msm-dsi-warn]: "fmt, ##__VA_ARGS__) -#define DSI_ERR(fmt, ...) DRM_DEV_ERROR(NULL, "[msm-dsi-error]: " fmt, \ +#define DSI_ERR(fmt, ...) DRM_DEV_DEBUG(NULL, "[msm-dsi-error]: " fmt, \ ##__VA_ARGS__) -#define DSI_INFO(fmt, ...) DRM_DEV_INFO(NULL, "[msm-dsi-info]: "fmt, \ +#define DSI_INFO(fmt, ...) DRM_DEV_DEBUG(NULL, "[msm-dsi-info]: "fmt, \ ##__VA_ARGS__) #define DSI_DEBUG(fmt, ...) DRM_DEV_DEBUG(NULL, "[msm-dsi-debug]: "fmt, \ ##__VA_ARGS__) diff --git a/techpack/display/msm/dsi/dsi_display.c b/techpack/display/msm/dsi/dsi_display.c index 413eeefaf906..a614939bb754 100644 --- a/techpack/display/msm/dsi/dsi_display.c +++ b/techpack/display/msm/dsi/dsi_display.c @@ -48,6 +48,8 @@ static const struct of_device_id dsi_display_dt_match[] = { {} }; +static unsigned int cur_refresh_rate = 60; + static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display, u32 mask, bool enable) { @@ -7703,6 +7705,11 @@ int dsi_display_pre_commit(void *display, return rc; } +unsigned int dsi_panel_get_refresh_rate(void) +{ + return READ_ONCE(cur_refresh_rate); +} + int dsi_display_enable(struct dsi_display *display) { int rc = 0; @@ -7772,6 +7779,7 @@ int dsi_display_enable(struct dsi_display *display) mutex_lock(&display->display_lock); mode = display->panel->cur_mode; + WRITE_ONCE(cur_refresh_rate, mode->timing.refresh_rate); if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) { rc = dsi_panel_post_switch(display->panel); diff --git a/techpack/display/msm/msm_atomic.c b/techpack/display/msm/msm_atomic.c index 6c80d242e001..887c07ac3789 100644 --- a/techpack/display/msm/msm_atomic.c +++ b/techpack/display/msm/msm_atomic.c @@ -116,18 +116,6 @@ static inline bool _msm_seamless_for_conn(struct drm_connector *connector, /* clear specified crtcs (no longer pending update) */ static void commit_destroy(struct msm_commit *c) { - struct msm_drm_private *priv = c->dev->dev_private; - uint32_t crtc_mask = c->crtc_mask; - uint32_t plane_mask = c->plane_mask; - - /* End_atomic */ - spin_lock(&priv->pending_crtcs_event.lock); - DBG("end: %08x", crtc_mask); - priv->pending_crtcs &= ~crtc_mask; - priv->pending_planes &= ~plane_mask; - wake_up_all_locked(&priv->pending_crtcs_event); - spin_unlock(&priv->pending_crtcs_event.lock); - if (c->nonblock) kfree(c); } @@ -469,6 +457,16 @@ static void msm_atomic_helper_commit_modeset_enables(struct drm_device *dev, SDE_ATRACE_END("msm_enable"); } +static void complete_commit_cleanup(struct kthread_work *work) +{ + struct msm_commit *c = container_of(work, typeof(*c), commit_work); + struct drm_atomic_state *state = c->state; + + drm_atomic_state_put(state); + + commit_destroy(c); +} + int msm_atomic_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { @@ -505,6 +503,8 @@ static void complete_commit(struct msm_commit *c) struct drm_device *dev = state->dev; struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; + uint32_t crtc_mask = c->crtc_mask; + uint32_t plane_mask = c->plane_mask; drm_atomic_helper_wait_for_fences(dev, state, false); @@ -536,35 +536,43 @@ static void complete_commit(struct msm_commit *c) kms->funcs->complete_commit(kms, state); - drm_atomic_state_put(state); - priv->complete_commit_time = ktime_get()/1000; complete_time_generate_event(dev); - commit_destroy(c); + /* End_atomic */ + spin_lock(&priv->pending_crtcs_event.lock); + DBG("end: %08x", crtc_mask); + priv->pending_crtcs &= ~crtc_mask; + priv->pending_planes &= ~plane_mask; + wake_up_all_locked(&priv->pending_crtcs_event); + spin_unlock(&priv->pending_crtcs_event.lock); } static void _msm_drm_commit_work_cb(struct kthread_work *work) { - struct msm_commit *commit = NULL; + struct msm_commit *c = container_of(work, typeof(*c), commit_work); + struct drm_atomic_state *state = c->state; + struct drm_device *dev = state->dev; + struct msm_drm_private *priv = dev->dev_private; ktime_t start, end; s64 duration; - if (!work) { - DRM_ERROR("%s: Invalid commit work data!\n", __func__); - return; - } - - commit = container_of(work, struct msm_commit, commit_work); - start = ktime_get(); frame_stat_collector(0, COMMIT_START_TS); SDE_ATRACE_BEGIN("complete_commit"); - complete_commit(commit); + complete_commit(c); SDE_ATRACE_END("complete_commit"); + if (c->nonblock) { + /* Offload the cleanup onto little CPUs */ + kthread_init_work(&c->commit_work, complete_commit_cleanup); + kthread_queue_work(&priv->clean_thread.worker, &c->commit_work); + } else { + complete_commit_cleanup(&c->commit_work); + } + end = ktime_get(); duration = ktime_to_ns(ktime_sub(end, start)); frame_stat_collector(duration, COMMIT_END_TS); @@ -643,6 +651,7 @@ static void msm_atomic_commit_dispatch(struct drm_device *dev, * ensure that SW and HW state don't get out of sync. */ complete_commit(commit); + complete_commit_cleanup(&commit->commit_work); } else if (!nonblock) { kthread_flush_work(&commit->commit_work); } @@ -732,6 +741,10 @@ int msm_atomic_commit(struct drm_device *dev, * mark our set of crtc's as busy: */ + if (!atomic_cmpxchg_acquire(&priv->pm_req_set, 1, 0)) + pm_qos_update_request(&priv->pm_irq_req, 100); + mod_delayed_work(system_unbound_wq, &priv->pm_unreq_dwork, HZ / 10); + /* Start Atomic */ spin_lock(&priv->pending_crtcs_event.lock); ret = wait_event_interruptible_locked(priv->pending_crtcs_event, diff --git a/techpack/display/msm/msm_drv.c b/techpack/display/msm/msm_drv.c index 274b2df4ff8f..c1eef6785282 100644 --- a/techpack/display/msm/msm_drv.c +++ b/techpack/display/msm/msm_drv.c @@ -371,6 +371,8 @@ static int msm_drm_uninit(struct device *dev) } } + kthread_stop(priv->clean_thread.thread); + drm_kms_helper_poll_fini(ddev); drm_mode_config_cleanup(ddev); @@ -547,6 +549,11 @@ static int msm_drm_display_thread_create(struct sched_param param, { int i, ret = 0; + kthread_init_worker(&priv->clean_thread.worker); + priv->clean_thread.thread = kthread_run_perf_critical(cpu_lp_mask, + kthread_worker_fn, &priv->clean_thread.worker, "drm_cleanup"); + BUG_ON(IS_ERR(priv->clean_thread.thread)); + /** * this priority was found during empiric testing to have appropriate * realtime scheduling to process display updates and interact with @@ -560,7 +567,8 @@ static int msm_drm_display_thread_create(struct sched_param param, kthread_init_worker(&priv->disp_thread[i].worker); priv->disp_thread[i].dev = ddev; priv->disp_thread[i].thread = - kthread_run(kthread_worker_fn, + kthread_run_perf_critical(cpu_prime_mask, + kthread_worker_fn, &priv->disp_thread[i].worker, "crtc_commit:%d", priv->disp_thread[i].crtc_id); ret = sched_setscheduler(priv->disp_thread[i].thread, @@ -579,7 +587,8 @@ static int msm_drm_display_thread_create(struct sched_param param, kthread_init_worker(&priv->event_thread[i].worker); priv->event_thread[i].dev = ddev; priv->event_thread[i].thread = - kthread_run(kthread_worker_fn, + kthread_run_perf_critical(cpu_prime_mask, + kthread_worker_fn, &priv->event_thread[i].worker, "crtc_event:%d", priv->event_thread[i].crtc_id); /** @@ -626,8 +635,8 @@ static int msm_drm_display_thread_create(struct sched_param param, * other important events. */ kthread_init_worker(&priv->pp_event_worker); - priv->pp_event_thread = kthread_run(kthread_worker_fn, - &priv->pp_event_worker, "pp_event"); + priv->pp_event_thread = kthread_run_perf_critical(cpu_prime_mask, + kthread_worker_fn, &priv->pp_event_worker, "pp_event"); ret = sched_setscheduler(priv->pp_event_thread, SCHED_FIFO, ¶m); @@ -698,6 +707,16 @@ static struct msm_kms *_msm_drm_init_helper(struct msm_drm_private *priv, return kms; } +static void msm_drm_pm_unreq(struct work_struct *work) +{ + struct msm_drm_private *priv = container_of(to_delayed_work(work), + typeof(*priv), + pm_unreq_dwork); + + pm_qos_update_request(&priv->pm_irq_req, PM_QOS_DEFAULT_VALUE); + atomic_set_release(&priv->pm_req_set, 0); +} + static int msm_drm_init(struct device *dev, struct drm_driver *drv) { struct platform_device *pdev = to_platform_device(dev); @@ -736,6 +755,9 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) INIT_LIST_HEAD(&priv->client_event_list); INIT_LIST_HEAD(&priv->inactive_list); + priv->pm_req_set = (atomic_t)ATOMIC_INIT(0); + INIT_DELAYED_WORK(&priv->pm_unreq_dwork, msm_drm_pm_unreq); + ret = sde_power_resource_init(pdev, &priv->phandle); if (ret) { pr_err("sde power resource init failed\n"); @@ -1079,8 +1101,13 @@ static void msm_irq_preinstall(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; + struct sde_kms *sde_kms = to_sde_kms(kms); BUG_ON(!kms); kms->funcs->irq_preinstall(kms); + priv->pm_irq_req.type = PM_QOS_REQ_AFFINE_IRQ; + priv->pm_irq_req.irq = sde_kms->irq_num; + pm_qos_add_request(&priv->pm_irq_req, PM_QOS_CPU_DMA_LATENCY, + PM_QOS_DEFAULT_VALUE); } static int msm_irq_postinstall(struct drm_device *dev) @@ -1097,6 +1124,8 @@ static void msm_irq_uninstall(struct drm_device *dev) struct msm_kms *kms = priv->kms; BUG_ON(!kms); kms->funcs->irq_uninstall(kms); + flush_delayed_work(&priv->pm_unreq_dwork); + pm_qos_remove_request(&priv->pm_irq_req); } static int msm_enable_vblank(struct drm_device *dev, unsigned int pipe) diff --git a/techpack/display/msm/msm_drv.h b/techpack/display/msm/msm_drv.h index a08cdcea42f0..3d1dea28a0c1 100644 --- a/techpack/display/msm/msm_drv.h +++ b/techpack/display/msm/msm_drv.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -649,6 +650,11 @@ struct msm_drm_private { struct msm_drm_thread disp_thread[MAX_CRTCS]; struct msm_drm_thread event_thread[MAX_CRTCS]; + struct { + struct task_struct *thread; + struct kthread_worker worker; + } clean_thread; + struct task_struct *pp_event_thread; struct kthread_worker pp_event_worker; @@ -703,6 +709,10 @@ struct msm_drm_private { /* update the flag when msm driver receives shutdown notification */ bool shutdown_in_progress; ktime_t complete_commit_time; + + struct pm_qos_request pm_irq_req; + struct delayed_work pm_unreq_dwork; + atomic_t pm_req_set; }; /* get struct msm_kms * from drm_device * */ diff --git a/techpack/display/msm/sde/sde_core_irq.c b/techpack/display/msm/sde/sde_core_irq.c index 5ee1865be632..727da5d016e4 100644 --- a/techpack/display/msm/sde/sde_core_irq.c +++ b/techpack/display/msm/sde/sde_core_irq.c @@ -628,15 +628,6 @@ int sde_core_irq_domain_fini(struct sde_kms *sde_kms) irqreturn_t sde_core_irq(struct sde_kms *sde_kms) { - /* - * Read interrupt status from all sources. Interrupt status are - * stored within hw_intr. - * Function will also clear the interrupt status after reading. - * Individual interrupt status bit will only get stored if it - * is enabled. - */ - sde_kms->hw_intr->ops.get_interrupt_statuses(sde_kms->hw_intr); - /* * Dispatch to HW driver to handle interrupt lookup that is being * fired. When matching interrupt is located, HW driver will call to diff --git a/techpack/display/msm/sde/sde_crtc.c b/techpack/display/msm/sde/sde_crtc.c index b7fded00181a..818cf21d858c 100644 --- a/techpack/display/msm/sde/sde_crtc.c +++ b/techpack/display/msm/sde/sde_crtc.c @@ -1339,7 +1339,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_plane_state *state; struct sde_crtc_state *cstate; struct sde_plane_state *pstate = NULL; - struct plane_state *pstates = NULL; + struct plane_state pstates[SDE_PSTATES_MAX]; struct sde_format *format; struct sde_hw_ctl *ctl; struct sde_hw_mixer *lm; @@ -1359,10 +1359,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, lm = mixer->hw_lm; stage_cfg = &sde_crtc->stage_cfg; cstate = to_sde_crtc_state(crtc->state); - pstates = kcalloc(SDE_PSTATES_MAX, - sizeof(struct plane_state), GFP_KERNEL); - if (!pstates) - return; drm_atomic_crtc_for_each_plane(plane, crtc) { state = plane->state; @@ -1395,7 +1391,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, format = to_sde_format(msm_framebuffer_format(pstate->base.fb)); if (!format) { SDE_ERROR("invalid format\n"); - goto end; + return; } if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) @@ -1455,9 +1451,6 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, } _sde_crtc_program_lm_output_roi(crtc); - -end: - kfree(pstates); } static void _sde_crtc_swap_mixers_for_right_partial_update( @@ -3676,8 +3669,6 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc, } sde_crtc->play_count++; - sde_vbif_clear_errors(sde_kms); - if (is_error) { _sde_crtc_remove_pipe_flush(crtc); _sde_crtc_blend_setup(crtc, old_state, false); @@ -4766,11 +4757,11 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, { struct drm_device *dev; struct sde_crtc *sde_crtc; - struct plane_state *pstates = NULL; + struct plane_state pstates[SDE_PSTATES_MAX]; struct sde_crtc_state *cstate; struct drm_display_mode *mode; int rc = 0; - struct sde_multirect_plane_states *multirect_plane = NULL; + struct sde_multirect_plane_states multirect_plane[SDE_MULTIRECT_PLANE_MAX]; struct drm_connector *conn; struct drm_connector_list_iter conn_iter; @@ -4789,18 +4780,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, goto end; } - pstates = kcalloc(SDE_PSTATES_MAX, - sizeof(struct plane_state), GFP_KERNEL); - - multirect_plane = kcalloc(SDE_MULTIRECT_PLANE_MAX, - sizeof(struct sde_multirect_plane_states), - GFP_KERNEL); - - if (!pstates || !multirect_plane) { - rc = -ENOMEM; - goto end; - } - mode = &state->adjusted_mode; SDE_DEBUG("%s: check", sde_crtc->name); @@ -4850,8 +4829,6 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc, } end: - kfree(pstates); - kfree(multirect_plane); return rc; } diff --git a/techpack/display/msm/sde/sde_encoder.c b/techpack/display/msm/sde/sde_encoder.c index 027ba5750bc6..b90542b51319 100644 --- a/techpack/display/msm/sde/sde_encoder.c +++ b/techpack/display/msm/sde/sde_encoder.c @@ -236,7 +236,6 @@ enum sde_enc_rc_states { * @recovery_events_enabled: status of hw recovery feature enable by client * @elevated_ahb_vote: increase AHB bus speed for the first frame * after power collapse - * @pm_qos_cpu_req: pm_qos request for cpu frequency * @mode_info: stores the current mode and should be used * only in commit phase */ @@ -303,7 +302,6 @@ struct sde_encoder_virt { bool recovery_events_enabled; bool elevated_ahb_vote; - struct pm_qos_request pm_qos_cpu_req; struct msm_mode_info mode_info; }; @@ -325,44 +323,6 @@ void sde_encoder_uidle_enable(struct drm_encoder *drm_enc, bool enable) } } -static void _sde_encoder_pm_qos_add_request(struct drm_encoder *drm_enc, - struct sde_kms *sde_kms) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - struct pm_qos_request *req; - u32 cpu_mask; - u32 cpu_dma_latency; - int cpu; - - if (!sde_kms->catalog || !sde_kms->catalog->perf.cpu_mask) - return; - - cpu_mask = sde_kms->catalog->perf.cpu_mask; - cpu_dma_latency = sde_kms->catalog->perf.cpu_dma_latency; - - req = &sde_enc->pm_qos_cpu_req; - req->type = PM_QOS_REQ_AFFINE_CORES; - cpumask_empty(&req->cpus_affine); - for_each_possible_cpu(cpu) { - if ((1 << cpu) & cpu_mask) - cpumask_set_cpu(cpu, &req->cpus_affine); - } - pm_qos_add_request(req, PM_QOS_CPU_DMA_LATENCY, cpu_dma_latency); - - SDE_EVT32_VERBOSE(DRMID(drm_enc), cpu_mask, cpu_dma_latency); -} - -static void _sde_encoder_pm_qos_remove_request(struct drm_encoder *drm_enc, - struct sde_kms *sde_kms) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - - if (!sde_kms->catalog || !sde_kms->catalog->perf.cpu_mask) - return; - - pm_qos_remove_request(&sde_enc->pm_qos_cpu_req); -} - static bool _sde_encoder_is_autorefresh_enabled( struct sde_encoder_virt *sde_enc) { @@ -2216,13 +2176,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, /* enable all the irq */ _sde_encoder_irq_control(drm_enc, true); - if (is_cmd_mode) - _sde_encoder_pm_qos_add_request(drm_enc, sde_kms); - } else { - if (is_cmd_mode) - _sde_encoder_pm_qos_remove_request(drm_enc, sde_kms); - /* disable all the irq */ _sde_encoder_irq_control(drm_enc, false); @@ -5018,7 +4972,7 @@ void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc, if (phys && phys->hw_intf && phys->hw_pp && phys->hw_intf->ops.get_vsync_info) { ret = phys->hw_intf->ops.get_vsync_info( - phys->hw_intf, &info[i]); + phys->hw_intf, &info[i], true); if (!ret) { info[i].pp_idx = phys->hw_pp->idx - PINGPONG_0; info[i].intf_idx = phys->hw_intf->idx - INTF_0; diff --git a/techpack/display/msm/sde/sde_encoder_phys_cmd.c b/techpack/display/msm/sde/sde_encoder_phys_cmd.c index 9d35c5ca6265..51efc4f05da4 100644 --- a/techpack/display/msm/sde/sde_encoder_phys_cmd.c +++ b/techpack/display/msm/sde/sde_encoder_phys_cmd.c @@ -612,9 +612,9 @@ static int _sde_encoder_phys_cmd_poll_write_pointer_started( } if (phys_enc->has_intf_te) - ret = hw_intf->ops.get_vsync_info(hw_intf, &info); + ret = hw_intf->ops.get_vsync_info(hw_intf, &info, false); else - ret = hw_pp->ops.get_vsync_info(hw_pp, &info); + ret = hw_pp->ops.get_vsync_info(hw_pp, &info, false); if (ret) return ret; @@ -663,13 +663,13 @@ static bool _sde_encoder_phys_cmd_is_ongoing_pptx( if (!hw_intf || !hw_intf->ops.get_vsync_info) return false; - hw_intf->ops.get_vsync_info(hw_intf, &info); + hw_intf->ops.get_vsync_info(hw_intf, &info, true); } else { hw_pp = phys_enc->hw_pp; if (!hw_pp || !hw_pp->ops.get_vsync_info) return false; - hw_pp->ops.get_vsync_info(hw_pp, &info); + hw_pp->ops.get_vsync_info(hw_pp, &info, true); } SDE_EVT32(DRMID(phys_enc->parent), @@ -1181,12 +1181,20 @@ static void sde_encoder_phys_cmd_enable(struct sde_encoder_phys *phys_enc) static bool sde_encoder_phys_cmd_is_autorefresh_enabled( struct sde_encoder_phys *phys_enc) { + struct sde_encoder_phys_cmd *cmd_enc; struct sde_hw_pingpong *hw_pp; struct sde_hw_intf *hw_intf; struct sde_hw_autorefresh cfg; int ret; - if (!phys_enc || !phys_enc->hw_pp || !phys_enc->hw_intf) + if (!phys_enc) + return false; + + cmd_enc = to_sde_encoder_phys_cmd(phys_enc); + if (!cmd_enc->autorefresh.cfg.enable) + return false; + + if (!phys_enc->hw_pp || !phys_enc->hw_intf) return false; if (!sde_encoder_phys_cmd_is_master(phys_enc)) @@ -1279,14 +1287,14 @@ static int sde_encoder_phys_cmd_get_write_line_count( if (!hw_intf->ops.get_vsync_info) return -EINVAL; - if (hw_intf->ops.get_vsync_info(hw_intf, &info)) + if (hw_intf->ops.get_vsync_info(hw_intf, &info, true)) return -EINVAL; } else { hw_pp = phys_enc->hw_pp; if (!hw_pp->ops.get_vsync_info) return -EINVAL; - if (hw_pp->ops.get_vsync_info(hw_pp, &info)) + if (hw_pp->ops.get_vsync_info(hw_pp, &info, true)) return -EINVAL; } diff --git a/techpack/display/msm/sde/sde_hw_catalog.c b/techpack/display/msm/sde/sde_hw_catalog.c index ad7aa05e1eb7..75b9bbba29d4 100644 --- a/techpack/display/msm/sde/sde_hw_catalog.c +++ b/techpack/display/msm/sde/sde_hw_catalog.c @@ -1612,6 +1612,7 @@ static int sde_sspp_parse_dt(struct device_node *np, sde_cfg->mdp[j].clk_ctrls[sspp->clk_ctrl].bit_off = PROP_BITVALUE_ACCESS(prop_value, SSPP_CLK_CTRL, i, 1); + sde_cfg->mdp[j].clk_ctrls[sspp->clk_ctrl].val = -1; } SDE_DEBUG( @@ -2125,6 +2126,7 @@ static int sde_wb_parse_dt(struct device_node *np, struct sde_mdss_cfg *sde_cfg) sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].bit_off = PROP_BITVALUE_ACCESS(prop_value, WB_CLK_CTRL, i, 1); + sde_cfg->mdp[j].clk_ctrls[wb->clk_ctrl].val = -1; } wb->format_list = sde_cfg->wb_formats; @@ -3579,6 +3581,7 @@ static int sde_parse_reg_dma_dt(struct device_node *np, sde_cfg->mdp[i].clk_ctrls[sde_cfg->dma_cfg.clk_ctrl].bit_off = PROP_BITVALUE_ACCESS(prop_value, REG_DMA_CLK_CTRL, 0, 1); + sde_cfg->mdp[i].clk_ctrls[sde_cfg->dma_cfg.clk_ctrl].val = -1; } end: diff --git a/techpack/display/msm/sde/sde_hw_catalog.h b/techpack/display/msm/sde/sde_hw_catalog.h index bed02d96fbde..d827e129baf6 100644 --- a/techpack/display/msm/sde/sde_hw_catalog.h +++ b/techpack/display/msm/sde/sde_hw_catalog.h @@ -720,10 +720,12 @@ enum sde_clk_ctrl_type { /* struct sde_clk_ctrl_reg : Clock control register * @reg_off: register offset * @bit_off: bit offset + * @val: current bit value */ struct sde_clk_ctrl_reg { u32 reg_off; u32 bit_off; + int val; }; /* struct sde_mdp_cfg : MDP TOP-BLK instance info diff --git a/techpack/display/msm/sde/sde_hw_color_proc_v4.c b/techpack/display/msm/sde/sde_hw_color_proc_v4.c index f266683a96ea..427650756bb7 100644 --- a/techpack/display/msm/sde/sde_hw_color_proc_v4.c +++ b/techpack/display/msm/sde/sde_hw_color_proc_v4.c @@ -1,11 +1,29 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, Pal Zoltan Illes (tbalden) - kcal rgb */ +#include #include #include "sde_hw_color_proc_common_v4.h" #include "sde_hw_color_proc_v4.h" +static unsigned short kcal_red = 256; +static unsigned short kcal_green = 256; +static unsigned short kcal_blue = 256; +static unsigned short kcal_hue = 0; +static unsigned short kcal_sat = 255; +static unsigned short kcal_val = 255; +static unsigned short kcal_cont = 255; + +module_param(kcal_red, short, 0644); +module_param(kcal_green, short, 0644); +module_param(kcal_blue, short, 0644); +module_param(kcal_hue, short, 0644); +module_param(kcal_sat, short, 0644); +module_param(kcal_val, short, 0644); +module_param(kcal_cont, short, 0644); + static int sde_write_3d_gamut(struct sde_hw_blk_reg_map *hw, struct drm_msm_3d_gamut *payload, u32 base, u32 *opcode, u32 pipe, u32 scale_tbl_a_len, @@ -203,13 +221,22 @@ void sde_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg) struct drm_msm_pcc *pcc_cfg; struct drm_msm_pcc_coeff *coeffs = NULL; int i = 0; + int kcal_min = 20; u32 base = 0; + u32 opcode = 0, local_opcode = 0; if (!ctx || !cfg) { DRM_ERROR("invalid param ctx %pK cfg %pK\n", ctx, cfg); return; } + if (kcal_red < kcal_min) + kcal_red = kcal_min; + if (kcal_green < kcal_min) + kcal_green = kcal_min; + if (kcal_blue < kcal_min) + kcal_blue = kcal_min; + if (!hw_cfg->payload) { DRM_DEBUG_DRIVER("disable pcc feature\n"); SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->pcc.base, 0); @@ -223,7 +250,6 @@ void sde_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg) } pcc_cfg = hw_cfg->payload; - for (i = 0; i < PCC_NUM_PLANES; i++) { base = ctx->cap->sblk->pcc.base + (i * sizeof(u32)); switch (i) { @@ -260,15 +286,48 @@ void sde_setup_dspp_pccv4(struct sde_hw_dspp *ctx, void *cfg) } SDE_REG_WRITE(&ctx->hw, base + PCC_C_OFF, coeffs->c); - SDE_REG_WRITE(&ctx->hw, base + PCC_R_OFF, coeffs->r); - SDE_REG_WRITE(&ctx->hw, base + PCC_G_OFF, coeffs->g); - SDE_REG_WRITE(&ctx->hw, base + PCC_B_OFF, coeffs->b); + + // RED + SDE_REG_WRITE(&ctx->hw, base + PCC_R_OFF, + i == 0 ? (coeffs->r * kcal_red) / 256 : coeffs->r); + // GREEN + SDE_REG_WRITE(&ctx->hw, base + PCC_G_OFF, + i == 1 ? (coeffs->g * kcal_green) / 256 : coeffs->g); + // BLUE + SDE_REG_WRITE(&ctx->hw, base + PCC_B_OFF, + i == 2 ? (coeffs->b * kcal_blue) / 256 : coeffs->b); + SDE_REG_WRITE(&ctx->hw, base + PCC_RG_OFF, coeffs->rg); SDE_REG_WRITE(&ctx->hw, base + PCC_RB_OFF, coeffs->rb); SDE_REG_WRITE(&ctx->hw, base + PCC_GB_OFF, coeffs->gb); SDE_REG_WRITE(&ctx->hw, base + PCC_RGB_OFF, coeffs->rgb); } + opcode = SDE_REG_READ(&ctx->hw, ctx->cap->sblk->hsic.base); + + // HUE + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->hsic.base + PA_HUE_OFF, + kcal_hue & PA_HUE_MASK); + local_opcode |= PA_HUE_EN; + + // SATURATION + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->hsic.base + PA_SAT_OFF, + kcal_sat & PA_SAT_MASK); + local_opcode |= PA_SAT_EN; + + // VALUE + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->hsic.base + PA_VAL_OFF, + kcal_val & PA_VAL_MASK); + local_opcode |= PA_VAL_EN; + + // CONTRAST + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->hsic.base + PA_CONT_OFF, + kcal_cont & PA_CONT_MASK); + local_opcode |= PA_CONT_EN; + + opcode |= (local_opcode | PA_EN); + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->hsic.base, opcode); + SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->pcc.base, PCC_EN); } diff --git a/techpack/display/msm/sde/sde_hw_dspp.c b/techpack/display/msm/sde/sde_hw_dspp.c index 5b66b83be806..d7f09de83866 100644 --- a/techpack/display/msm/sde/sde_hw_dspp.c +++ b/techpack/display/msm/sde/sde_hw_dspp.c @@ -57,7 +57,7 @@ static void dspp_pcc(struct sde_hw_dspp *c) c->ops.setup_pcc = sde_setup_dspp_pcc_v1_7; else if (c->cap->sblk->pcc.version == (SDE_COLOR_PROCESS_VER(0x4, 0x0))) { - ret = reg_dmav1_init_dspp_op_v4(SDE_DSPP_PCC, c->idx); + ret = 1; // reg_dmav1_init_dspp_op_v4(SDE_DSPP_PCC, c->idx); use the sde one instead, with correct hsic settings possibilities if (!ret) c->ops.setup_pcc = reg_dmav1_setup_dspp_pccv4; else diff --git a/techpack/display/msm/sde/sde_hw_interrupts.c b/techpack/display/msm/sde/sde_hw_interrupts.c index 5616d1f28631..b545ab677922 100644 --- a/techpack/display/msm/sde/sde_hw_interrupts.c +++ b/techpack/display/msm/sde/sde_hw_interrupts.c @@ -608,8 +608,6 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, */ spin_lock_irqsave(&intr->irq_lock, irq_flags); for (reg_idx = 0; reg_idx < intr->sde_irq_size; reg_idx++) { - irq_status = intr->save_irq_status[reg_idx]; - /* get the global offset in 'sde_irq_map' */ sde_irq_idx = intr->sde_irq_tbl[reg_idx].sde_irq_idx; if (sde_irq_idx < 0) @@ -626,6 +624,9 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, end_idx > intr->sde_irq_map_size) continue; + irq_status = SDE_REG_READ(&intr->hw, + intr->sde_irq_tbl[reg_idx].status_off); + /* * Search through matching intr status from irq map. * start_idx and end_idx defined the search range in @@ -648,8 +649,9 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, if (cbfunc) cbfunc(arg, irq_idx); else - intr->ops.clear_intr_status_nolock( - intr, irq_idx); + SDE_REG_WRITE(&intr->hw, + intr->sde_irq_tbl[reg_idx].clr_off, + intr->sde_irq_map[irq_idx].irq_mask); /* * When callback finish, clear the irq_status @@ -700,9 +702,6 @@ static int sde_hw_intr_enable_irq_nolock(struct sde_hw_intr *intr, int irq_idx) /* Enabling interrupts with the new mask */ SDE_REG_WRITE(&intr->hw, reg->en_off, cache_irq_mask); - /* ensure register write goes through */ - wmb(); - intr->cache_irq_mask[reg_idx] = cache_irq_mask; } @@ -818,40 +817,6 @@ static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr, return 0; } -static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr) -{ - int i; - u32 enable_mask; - unsigned long irq_flags; - - if (!intr) - return; - - spin_lock_irqsave(&intr->irq_lock, irq_flags); - for (i = 0; i < intr->sde_irq_size; i++) { - /* Read interrupt status */ - intr->save_irq_status[i] = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[i].status_off); - - /* Read enable mask */ - enable_mask = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[i].en_off); - - /* and clear the interrupt */ - if (intr->save_irq_status[i]) - SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[i].clr_off, - intr->save_irq_status[i]); - - /* Finally update IRQ status based on enable mask */ - intr->save_irq_status[i] &= enable_mask; - } - - /* ensure register writes go through */ - wmb(); - - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); -} - static void sde_hw_intr_clear_intr_status_force_mask(struct sde_hw_intr *intr, int irq_idx, u32 irq_mask) { @@ -908,12 +873,20 @@ static void sde_hw_intr_clear_interrupt_status(struct sde_hw_intr *intr, int irq_idx) { unsigned long irq_flags; + int reg_idx; if (!intr) return; + reg_idx = intr->sde_irq_map[irq_idx].reg_idx; + if (reg_idx < 0 || reg_idx > intr->sde_irq_size) { + pr_err("invalid irq reg:%d irq:%d\n", reg_idx, irq_idx); + return; + } + spin_lock_irqsave(&intr->irq_lock, irq_flags); - sde_hw_intr_clear_intr_status_nolock(intr, irq_idx); + SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, + intr->sde_irq_map[irq_idx].irq_mask); spin_unlock_irqrestore(&intr->irq_lock, irq_flags); } @@ -980,9 +953,6 @@ static u32 sde_hw_intr_get_interrupt_status(struct sde_hw_intr *intr, SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, intr_status); - /* ensure register writes go through */ - wmb(); - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); return intr_status; @@ -1028,7 +998,6 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops) ops->disable_all_irqs = sde_hw_intr_disable_irqs; ops->get_valid_interrupts = sde_hw_intr_get_valid_interrupts; ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources; - ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses; ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status; ops->clear_intr_status_nolock = sde_hw_intr_clear_intr_status_nolock; ops->clear_intr_status_force_mask = @@ -1193,7 +1162,6 @@ void sde_hw_intr_destroy(struct sde_hw_intr *intr) kfree(intr->sde_irq_tbl); kfree(intr->sde_irq_map); kfree(intr->cache_irq_mask); - kfree(intr->save_irq_status); kfree(intr); } } @@ -1480,13 +1448,6 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, goto exit; } - intr->save_irq_status = kcalloc(intr->sde_irq_size, - sizeof(*intr->save_irq_status), GFP_KERNEL); - if (intr->save_irq_status == NULL) { - ret = -ENOMEM; - goto exit; - } - spin_lock_init(&intr->irq_lock); exit: diff --git a/techpack/display/msm/sde/sde_hw_interrupts.h b/techpack/display/msm/sde/sde_hw_interrupts.h index 2be78655cc04..bc162999326c 100644 --- a/techpack/display/msm/sde/sde_hw_interrupts.h +++ b/techpack/display/msm/sde/sde_hw_interrupts.h @@ -177,14 +177,6 @@ struct sde_hw_intr_ops { void (*cbfunc)(void *arg, int irq_idx), void *arg); - /** - * get_interrupt_statuses - Gets and store value from all interrupt - * status registers that are currently fired. - * @intr: HW interrupt handle - */ - void (*get_interrupt_statuses)( - struct sde_hw_intr *intr); - /** * clear_interrupt_status - Clears HW interrupt status based on given * lookup IRQ index. @@ -281,7 +273,6 @@ struct sde_hw_intr_ops { * @hw: virtual address mapping * @ops: function pointer mapping for IRQ handling * @cache_irq_mask: array of IRQ enable masks reg storage created during init - * @save_irq_status: array of IRQ status reg storage created during init * @irq_lock: spinlock for accessing IRQ resources * @sde_irq_size: total number of elements of the sde_irq_tbl * @sde_irq_tbl: table with the registesrs offsets of the sde interrupts @@ -293,7 +284,6 @@ struct sde_hw_intr { struct sde_hw_blk_reg_map hw; struct sde_hw_intr_ops ops; u32 *cache_irq_mask; - u32 *save_irq_status; u32 sde_irq_size; struct sde_intr_reg *sde_irq_tbl; u32 sde_irq_map_size; diff --git a/techpack/display/msm/sde/sde_hw_intf.c b/techpack/display/msm/sde/sde_hw_intf.c index f6ac49701657..08b51b2dd9ae 100644 --- a/techpack/display/msm/sde/sde_hw_intf.c +++ b/techpack/display/msm/sde/sde_hw_intf.c @@ -610,7 +610,7 @@ static int sde_hw_intf_connect_external_te(struct sde_hw_intf *intf, } static int sde_hw_intf_get_vsync_info(struct sde_hw_intf *intf, - struct sde_hw_pp_vsync_info *info) + struct sde_hw_pp_vsync_info *info, bool wr_ptr_only) { struct sde_hw_blk_reg_map *c = &intf->hw; u32 val; @@ -620,12 +620,14 @@ static int sde_hw_intf_get_vsync_info(struct sde_hw_intf *intf, c = &intf->hw; - val = SDE_REG_READ(c, INTF_TEAR_VSYNC_INIT_VAL); - info->rd_ptr_init_val = val & 0xffff; + if (!wr_ptr_only) { + val = SDE_REG_READ(c, INTF_TEAR_VSYNC_INIT_VAL); + info->rd_ptr_init_val = val & 0xffff; - val = SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL); - info->rd_ptr_frame_count = (val & 0xffff0000) >> 16; - info->rd_ptr_line_count = val & 0xffff; + val = SDE_REG_READ(c, INTF_TEAR_INT_COUNT_VAL); + info->rd_ptr_frame_count = (val & 0xffff0000) >> 16; + info->rd_ptr_line_count = val & 0xffff; + } val = SDE_REG_READ(c, INTF_TEAR_LINE_COUNT); info->wr_ptr_line_count = val & 0xffff; diff --git a/techpack/display/msm/sde/sde_hw_intf.h b/techpack/display/msm/sde/sde_hw_intf.h index 403ac6b286b1..0327fb800aa3 100644 --- a/techpack/display/msm/sde/sde_hw_intf.h +++ b/techpack/display/msm/sde/sde_hw_intf.h @@ -140,7 +140,7 @@ struct sde_hw_intf_ops { * line_count */ int (*get_vsync_info)(struct sde_hw_intf *intf, - struct sde_hw_pp_vsync_info *info); + struct sde_hw_pp_vsync_info *info, bool wr_ptr_only); /** * configure and enable the autorefresh config diff --git a/techpack/display/msm/sde/sde_hw_lm.c b/techpack/display/msm/sde/sde_hw_lm.c index 3be559bc1011..6f2448c8c00b 100644 --- a/techpack/display/msm/sde/sde_hw_lm.c +++ b/techpack/display/msm/sde/sde_hw_lm.c @@ -173,8 +173,16 @@ static void sde_hw_lm_clear_dim_layer(struct sde_hw_mixer *ctx) int stage_off, i; u32 reset = BIT(16), val; + if (!ctx->dim.enabled) + return; + + ctx->dim.enabled = false; reset = ~reset; for (i = SDE_STAGE_0; i <= sblk->maxblendstages; i++) { + if (!ctx->dim.stage[i]) + continue; + + ctx->dim.stage[i] = false; stage_off = _stage_offset(ctx, i); if (WARN_ON(stage_off < 0)) return; @@ -205,6 +213,8 @@ static void sde_hw_lm_setup_dim_layer(struct sde_hw_mixer *ctx, return; } + ctx->dim.enabled = true; + ctx->dim.stage[dim_layer->stage] = true; alpha = dim_layer->color_fill.color_3 & 0xFF; val = ((dim_layer->color_fill.color_1 << 2) & 0xFFF) << 16 | ((dim_layer->color_fill.color_0 << 2) & 0xFFF); diff --git a/techpack/display/msm/sde/sde_hw_lm.h b/techpack/display/msm/sde/sde_hw_lm.h index 07574d3f656d..4687c350189b 100644 --- a/techpack/display/msm/sde/sde_hw_lm.h +++ b/techpack/display/msm/sde/sde_hw_lm.h @@ -98,6 +98,11 @@ struct sde_hw_mixer { /* store mixer info specific to display */ struct sde_hw_mixer_cfg cfg; + + struct { + bool enabled; + bool stage[SDE_STAGE_MAX]; + } dim; }; /** diff --git a/techpack/display/msm/sde/sde_hw_pingpong.c b/techpack/display/msm/sde/sde_hw_pingpong.c index 0d44b21e2c3c..50ec3639eb48 100644 --- a/techpack/display/msm/sde/sde_hw_pingpong.c +++ b/techpack/display/msm/sde/sde_hw_pingpong.c @@ -398,7 +398,7 @@ static int sde_hw_pp_connect_external_te(struct sde_hw_pingpong *pp, } static int sde_hw_pp_get_vsync_info(struct sde_hw_pingpong *pp, - struct sde_hw_pp_vsync_info *info) + struct sde_hw_pp_vsync_info *info, bool wr_ptr_only) { struct sde_hw_blk_reg_map *c; u32 val; @@ -407,12 +407,14 @@ static int sde_hw_pp_get_vsync_info(struct sde_hw_pingpong *pp, return -EINVAL; c = &pp->hw; - val = SDE_REG_READ(c, PP_VSYNC_INIT_VAL); - info->rd_ptr_init_val = val & 0xffff; + if (!wr_ptr_only) { + val = SDE_REG_READ(c, PP_VSYNC_INIT_VAL); + info->rd_ptr_init_val = val & 0xffff; - val = SDE_REG_READ(c, PP_INT_COUNT_VAL); - info->rd_ptr_frame_count = (val & 0xffff0000) >> 16; - info->rd_ptr_line_count = val & 0xffff; + val = SDE_REG_READ(c, PP_INT_COUNT_VAL); + info->rd_ptr_frame_count = (val & 0xffff0000) >> 16; + info->rd_ptr_line_count = val & 0xffff; + } val = SDE_REG_READ(c, PP_LINE_COUNT); info->wr_ptr_line_count = val & 0xffff; diff --git a/techpack/display/msm/sde/sde_hw_pingpong.h b/techpack/display/msm/sde/sde_hw_pingpong.h index 102cfc03afe8..b18e060d509f 100644 --- a/techpack/display/msm/sde/sde_hw_pingpong.h +++ b/techpack/display/msm/sde/sde_hw_pingpong.h @@ -65,7 +65,7 @@ struct sde_hw_pingpong_ops { * line_count */ int (*get_vsync_info)(struct sde_hw_pingpong *pp, - struct sde_hw_pp_vsync_info *info); + struct sde_hw_pp_vsync_info *info, bool wr_ptr_only); /** * configure and enable the autorefresh config diff --git a/techpack/display/msm/sde/sde_hw_top.c b/techpack/display/msm/sde/sde_hw_top.c index d01ab8f1c18b..9325c805dfe6 100644 --- a/techpack/display/msm/sde/sde_hw_top.c +++ b/techpack/display/msm/sde/sde_hw_top.c @@ -179,6 +179,7 @@ static void sde_hw_setup_cdm_output(struct sde_hw_mdp *mdp, static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp, enum sde_clk_ctrl_type clk_ctrl, bool enable) { + struct sde_clk_ctrl_reg *ctrl_reg; struct sde_hw_blk_reg_map *c; u32 reg_off, bit_off; u32 reg_val, new_val; @@ -192,8 +193,12 @@ static bool sde_hw_setup_clk_force_ctrl(struct sde_hw_mdp *mdp, if (clk_ctrl <= SDE_CLK_CTRL_NONE || clk_ctrl >= SDE_CLK_CTRL_MAX) return false; - reg_off = mdp->caps->clk_ctrls[clk_ctrl].reg_off; - bit_off = mdp->caps->clk_ctrls[clk_ctrl].bit_off; + ctrl_reg = (struct sde_clk_ctrl_reg *)&mdp->caps->clk_ctrls[clk_ctrl]; + if (cmpxchg(&ctrl_reg->val, !enable, enable) == enable) + return enable; + + reg_off = ctrl_reg->reg_off; + bit_off = ctrl_reg->bit_off; reg_val = SDE_REG_READ(c, reg_off); diff --git a/techpack/display/msm/sde/sde_hw_util.c b/techpack/display/msm/sde/sde_hw_util.c index ff4b5dfd08f0..47e54f12388f 100644 --- a/techpack/display/msm/sde/sde_hw_util.c +++ b/techpack/display/msm/sde/sde_hw_util.c @@ -72,10 +72,6 @@ void sde_reg_write(struct sde_hw_blk_reg_map *c, u32 val, const char *name) { - /* don't need to mutex protect this */ - if (c->log_mask & sde_hw_util_log_mask) - SDE_DEBUG_DRIVER("[%s:0x%X] <= 0x%X\n", - name, c->blk_off + reg_off, val); writel_relaxed(val, c->base_off + c->blk_off + reg_off); } diff --git a/techpack/display/msm/sde/sde_kms.c b/techpack/display/msm/sde/sde_kms.c index 4a54599f73e8..b1a4ac0936c2 100644 --- a/techpack/display/msm/sde/sde_kms.c +++ b/techpack/display/msm/sde/sde_kms.c @@ -3217,67 +3217,35 @@ void sde_kms_update_pm_qos_irq_request(struct sde_kms *sde_kms, { struct msm_drm_private *priv; + if (!sde_kms->irq_num) + return; + priv = sde_kms->dev->dev_private; if (!skip_lock) mutex_lock(&priv->phandle.phandle_lock); if (enable) { - struct pm_qos_request *req; - u32 cpu_irq_latency; - - req = &sde_kms->pm_qos_irq_req; - req->type = PM_QOS_REQ_AFFINE_CORES; - req->cpus_affine = sde_kms->irq_cpu_mask; - cpu_irq_latency = sde_kms->catalog->perf.cpu_irq_latency; + u32 cpu_irq_latency = sde_kms->catalog->perf.cpu_irq_latency; + struct pm_qos_request *req = &sde_kms->pm_qos_irq_req; - if (pm_qos_request_active(req)) + if (pm_qos_request_active(req)) { pm_qos_update_request(req, cpu_irq_latency); - else if (!cpumask_empty(&req->cpus_affine)) { - /** If request is not active yet and mask is not empty - * then it needs to be added initially - */ + } else { + req->type = PM_QOS_REQ_AFFINE_IRQ; + req->irq = sde_kms->irq_num; pm_qos_add_request(req, PM_QOS_CPU_DMA_LATENCY, - cpu_irq_latency); + cpu_irq_latency); } } else if (!enable && pm_qos_request_active(&sde_kms->pm_qos_irq_req)) { pm_qos_update_request(&sde_kms->pm_qos_irq_req, PM_QOS_DEFAULT_VALUE); } - sde_kms->pm_qos_irq_req_en = enable; - if (!skip_lock) mutex_unlock(&priv->phandle.phandle_lock); } -static void sde_kms_irq_affinity_notify( - struct irq_affinity_notify *affinity_notify, - const cpumask_t *mask) -{ - struct msm_drm_private *priv; - struct sde_kms *sde_kms = container_of(affinity_notify, - struct sde_kms, affinity_notify); - - if (!sde_kms || !sde_kms->dev || !sde_kms->dev->dev_private) - return; - - priv = sde_kms->dev->dev_private; - - mutex_lock(&priv->phandle.phandle_lock); - - // save irq cpu mask - sde_kms->irq_cpu_mask = *mask; - - // request vote with updated irq cpu mask - if (sde_kms->pm_qos_irq_req_en) - sde_kms_update_pm_qos_irq_request(sde_kms, true, true); - - mutex_unlock(&priv->phandle.phandle_lock); -} - -static void sde_kms_irq_affinity_release(struct kref *ref) {} - static void sde_kms_handle_power_event(u32 event_type, void *usr) { struct sde_kms *sde_kms = usr; @@ -3768,7 +3736,7 @@ static int sde_kms_hw_init(struct msm_kms *kms) struct drm_device *dev; struct msm_drm_private *priv; struct platform_device *platformdev; - int i, irq_num, rc = -EINVAL; + int i, rc = -EINVAL; if (!kms) { SDE_ERROR("invalid kms\n"); @@ -3843,13 +3811,6 @@ static int sde_kms_hw_init(struct msm_kms *kms) pm_runtime_put_sync(sde_kms->dev->dev); } - sde_kms->affinity_notify.notify = sde_kms_irq_affinity_notify; - sde_kms->affinity_notify.release = sde_kms_irq_affinity_release; - - irq_num = platform_get_irq(to_platform_device(sde_kms->dev->dev), 0); - SDE_DEBUG("Registering for notification of irq_num: %d\n", irq_num); - irq_set_affinity_notifier(irq_num, &sde_kms->affinity_notify); - return 0; hw_init_err: diff --git a/techpack/display/msm/sde/sde_kms.h b/techpack/display/msm/sde/sde_kms.h index a9f56f7a342a..88ecdc4f8b91 100644 --- a/techpack/display/msm/sde/sde_kms.h +++ b/techpack/display/msm/sde/sde_kms.h @@ -48,36 +48,21 @@ * @fmt: Pointer to format string */ #define SDE_DEBUG(fmt, ...) \ - do { \ - if (unlikely(drm_debug & DRM_UT_KMS)) \ - DRM_DEBUG(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) + no_printk(fmt, ##__VA_ARGS__) /** * SDE_INFO - macro for kms/plane/crtc/encoder/connector logs * @fmt: Pointer to format string */ #define SDE_INFO(fmt, ...) \ - do { \ - if (unlikely(drm_debug & DRM_UT_KMS)) \ - DRM_INFO(fmt, ##__VA_ARGS__); \ - else \ - pr_info(fmt, ##__VA_ARGS__); \ - } while (0) + no_printk(fmt, ##__VA_ARGS__) /** * SDE_DEBUG_DRIVER - macro for hardware driver logging * @fmt: Pointer to format string */ #define SDE_DEBUG_DRIVER(fmt, ...) \ - do { \ - if (unlikely(drm_debug & DRM_UT_DRIVER)) \ - DRM_ERROR(fmt, ##__VA_ARGS__); \ - else \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) + no_printk(fmt, ##__VA_ARGS__) #define SDE_ERROR(fmt, ...) pr_err("[sde error]" fmt, ##__VA_ARGS__) @@ -298,10 +283,7 @@ struct sde_kms { bool first_kickoff; bool qdss_enabled; - cpumask_t irq_cpu_mask; struct pm_qos_request pm_qos_irq_req; - struct irq_affinity_notify affinity_notify; - bool pm_qos_irq_req_en; }; /** diff --git a/techpack/display/rotator/sde_rotator_base.c b/techpack/display/rotator/sde_rotator_base.c index 3cf850753aca..d22de798d6c4 100644 --- a/techpack/display/rotator/sde_rotator_base.c +++ b/techpack/display/rotator/sde_rotator_base.c @@ -791,14 +791,6 @@ static int sde_mdp_parse_dt_misc(struct platform_device *pdev, sde_mdp_parse_inline_rot_lut_setting(pdev, mdata); - rc = of_property_read_u32(pdev->dev.of_node, - "qcom,mdss-rot-qos-cpu-mask", &data); - mdata->rot_pm_qos_cpu_mask = (!rc ? data : 0); - - rc = of_property_read_u32(pdev->dev.of_node, - "qcom,mdss-rot-qos-cpu-dma-latency", &data); - mdata->rot_pm_qos_cpu_dma_latency = (!rc ? data : 0); - mdata->mdp_base = mdata->sde_io.base + SDE_MDP_OFFSET; return 0; diff --git a/techpack/display/rotator/sde_rotator_base.h b/techpack/display/rotator/sde_rotator_base.h index bdb319dc28a9..bac436f72c5d 100644 --- a/techpack/display/rotator/sde_rotator_base.h +++ b/techpack/display/rotator/sde_rotator_base.h @@ -18,7 +18,6 @@ #include "sde_rotator_io_util.h" #include "sde_rotator_smmu.h" #include "sde_rotator_formats.h" -#include /* HW Revisions for different targets */ #define SDE_GET_MAJOR_REV(rev) ((rev) >> 28) @@ -262,11 +261,6 @@ struct sde_rot_data_type { u32 vbif_xin_id[MAX_XIN]; - struct pm_qos_request pm_qos_rot_cpu_req; - u32 rot_pm_qos_cpu_count; - u32 rot_pm_qos_cpu_mask; - u32 rot_pm_qos_cpu_dma_latency; - u32 vbif_memtype_count; u32 *vbif_memtype; diff --git a/techpack/display/rotator/sde_rotator_core.c b/techpack/display/rotator/sde_rotator_core.c index cad29dfa58b1..e80be7ef216b 100644 --- a/techpack/display/rotator/sde_rotator_core.c +++ b/techpack/display/rotator/sde_rotator_core.c @@ -3228,8 +3228,6 @@ int sde_rotator_core_init(struct sde_rot_mgr **pmgr, goto error_hw_init; } - sde_rotator_pm_qos_add(mdata); - ret = sde_rotator_init_queue(mgr); if (ret) { SDEROT_ERR("fail to init queue\n"); diff --git a/techpack/display/rotator/sde_rotator_dev.c b/techpack/display/rotator/sde_rotator_dev.c index bdb9c57376ce..6a000a4db789 100644 --- a/techpack/display/rotator/sde_rotator_dev.c +++ b/techpack/display/rotator/sde_rotator_dev.c @@ -48,15 +48,8 @@ #define SDE_ROTATOR_DEGREE_180 180 #define SDE_ROTATOR_DEGREE_90 90 -/* Inline rotator qos request */ -#define SDE_ROTATOR_ADD_REQUEST 1 -#define SDE_ROTATOR_REMOVE_REQUEST 0 - - static void sde_rotator_submit_handler(struct kthread_work *work); static void sde_rotator_retire_handler(struct kthread_work *work); -static void sde_rotator_pm_qos_request(struct sde_rotator_device *rot_dev, - bool add_request); #ifdef CONFIG_COMPAT static long sde_rotator_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg); @@ -1001,8 +994,6 @@ struct sde_rotator_ctx *sde_rotator_ctx_open( SDEDEV_DBG(ctx->rot_dev->dev, "timeline is not available\n"); sde_rot_mgr_lock(rot_dev->mgr); - sde_rotator_pm_qos_request(rot_dev, - SDE_ROTATOR_ADD_REQUEST); ret = sde_rotator_session_open(rot_dev->mgr, &ctx->private, ctx->session_id, &ctx->work_queue); if (ret < 0) { @@ -1127,8 +1118,6 @@ static int sde_rotator_ctx_release(struct sde_rotator_ctx *ctx, } SDEDEV_DBG(rot_dev->dev, "release session s:%d\n", session_id); sde_rot_mgr_lock(rot_dev->mgr); - sde_rotator_pm_qos_request(rot_dev, - SDE_ROTATOR_REMOVE_REQUEST); sde_rotator_session_close(rot_dev->mgr, ctx->private, session_id); sde_rot_mgr_unlock(rot_dev->mgr); SDEDEV_DBG(rot_dev->dev, "release retire work s:%d\n", session_id); @@ -1243,104 +1232,6 @@ static bool sde_rotator_is_request_retired(struct sde_rotator_request *request) return retire_delta >= 0; } -static void sde_rotator_pm_qos_remove(struct sde_rot_data_type *rot_mdata) -{ - struct pm_qos_request *req; - u32 cpu_mask; - - if (!rot_mdata) { - SDEROT_DBG("invalid rot device or context\n"); - return; - } - - cpu_mask = rot_mdata->rot_pm_qos_cpu_mask; - - if (!cpu_mask) - return; - - req = &rot_mdata->pm_qos_rot_cpu_req; - pm_qos_remove_request(req); -} - -void sde_rotator_pm_qos_add(struct sde_rot_data_type *rot_mdata) -{ - struct pm_qos_request *req; - u32 cpu_mask; - int cpu; - - if (!rot_mdata) { - SDEROT_DBG("invalid rot device or context\n"); - return; - } - - cpu_mask = rot_mdata->rot_pm_qos_cpu_mask; - - if (!cpu_mask) - return; - - req = &rot_mdata->pm_qos_rot_cpu_req; - req->type = PM_QOS_REQ_AFFINE_CORES; - cpumask_empty(&req->cpus_affine); - for_each_possible_cpu(cpu) { - if ((1 << cpu) & cpu_mask) - cpumask_set_cpu(cpu, &req->cpus_affine); - } - pm_qos_add_request(req, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - - SDEROT_DBG("rotator pmqos add mask %x latency %x\n", - rot_mdata->rot_pm_qos_cpu_mask, - rot_mdata->rot_pm_qos_cpu_dma_latency); -} - -static void sde_rotator_pm_qos_request(struct sde_rotator_device *rot_dev, - bool add_request) -{ - u32 cpu_mask; - u32 cpu_dma_latency; - bool changed = false; - - if (!rot_dev) { - SDEROT_DBG("invalid rot device or context\n"); - return; - } - - cpu_mask = rot_dev->mdata->rot_pm_qos_cpu_mask; - cpu_dma_latency = rot_dev->mdata->rot_pm_qos_cpu_dma_latency; - - if (!cpu_mask) - return; - - if (add_request) { - if (rot_dev->mdata->rot_pm_qos_cpu_count == 0) - changed = true; - rot_dev->mdata->rot_pm_qos_cpu_count++; - } else { - if (rot_dev->mdata->rot_pm_qos_cpu_count != 0) { - rot_dev->mdata->rot_pm_qos_cpu_count--; - if (rot_dev->mdata->rot_pm_qos_cpu_count == 0) - changed = true; - } else { - SDEROT_DBG("%s: ref_count is not balanced\n", - __func__); - } - } - - if (!changed) - return; - - SDEROT_EVTLOG(add_request, cpu_mask, cpu_dma_latency); - - if (!add_request) { - pm_qos_update_request(&rot_dev->mdata->pm_qos_rot_cpu_req, - PM_QOS_DEFAULT_VALUE); - return; - } - - pm_qos_update_request(&rot_dev->mdata->pm_qos_rot_cpu_req, - cpu_dma_latency); -} - /* * sde_rotator_inline_open - open inline rotator session * @pdev: Pointer to rotator platform device @@ -3651,6 +3542,8 @@ static int sde_rotator_probe(struct platform_device *pdev) rot_dev->kthread_free[i] = true; } + device_enable_async_suspend(&pdev->dev); + SDEDEV_INFO(&pdev->dev, "SDE v4l2 rotator probe success\n"); return 0; @@ -3689,7 +3582,6 @@ static int sde_rotator_remove(struct platform_device *pdev) return 0; } - sde_rotator_pm_qos_remove(rot_dev->mdata); for (i = MAX_ROT_OPEN_SESSION - 1; i >= 0; i--) kthread_stop(rot_dev->rot_thread[i]); sde_rotator_destroy_debugfs(rot_dev->debugfs_root); diff --git a/techpack/display/rotator/sde_rotator_dev.h b/techpack/display/rotator/sde_rotator_dev.h index 711d8d87b80b..86b1fcc2d4bc 100644 --- a/techpack/display/rotator/sde_rotator_dev.h +++ b/techpack/display/rotator/sde_rotator_dev.h @@ -253,6 +253,4 @@ struct sde_rot_mgr *sde_rot_mgr_from_device(struct device *dev) return ((struct sde_rotator_device *) dev_get_drvdata(dev))->mgr; } -void sde_rotator_pm_qos_add(struct sde_rot_data_type *rot_mdata); - #endif /* __SDE_ROTATOR_DEV_H__ */ diff --git a/techpack/video/msm/vidc/msm_vidc.c b/techpack/video/msm/vidc/msm_vidc.c index cbb46852cbb9..ca71e8dfc422 100644 --- a/techpack/video/msm/vidc/msm_vidc.c +++ b/techpack/video/msm/vidc/msm_vidc.c @@ -1447,7 +1447,7 @@ void *msm_vidc_open(int core_id, int session_type) goto err_invalid_sid; } - pr_info(VIDC_DBG_TAG "Opening video instance: %pK, %d\n", + pr_debug(VIDC_DBG_TAG "Opening video instance: %pK, %d\n", "high", inst->sid, get_codec_name(inst->sid), inst, session_type); mutex_init(&inst->sync_lock); @@ -1717,7 +1717,7 @@ int msm_vidc_destroy(struct msm_vidc_inst *inst) msm_vidc_debugfs_deinit_inst(inst); - pr_info(VIDC_DBG_TAG "Closed video instance: %pK\n", + pr_debug(VIDC_DBG_TAG "Closed video instance: %pK\n", "high", inst->sid, get_codec_name(inst->sid), inst); put_sid(inst->sid); diff --git a/techpack/video/msm/vidc/msm_vidc_common.c b/techpack/video/msm/vidc/msm_vidc_common.c index 21adfe4d560e..b1d1557fab5b 100644 --- a/techpack/video/msm/vidc/msm_vidc_common.c +++ b/techpack/video/msm/vidc/msm_vidc_common.c @@ -5812,7 +5812,7 @@ static u32 msm_comm_get_memory_limit(struct msm_vidc_core *core) memory_limits_tbl = core->resources.mem_limit_tbl; memory_limits_tbl_size = core->resources.memory_limit_table_size; - memory_limit_mbytes = ((u64)totalram_pages * PAGE_SIZE) >> 20; + memory_limit_mbytes = ((u64)totalram_pages() * PAGE_SIZE) >> 20; for (i = memory_limits_tbl_size - 1; i >= 0; i--) { memory_size = memory_limits_tbl[i].ddr_size; memory_limit = memory_limits_tbl[i].mem_limit; diff --git a/techpack/video/msm/vidc/msm_vidc_debug.c b/techpack/video/msm/vidc/msm_vidc_debug.c index e803269aa6bd..8e6fd72a30b3 100644 --- a/techpack/video/msm/vidc/msm_vidc_debug.c +++ b/techpack/video/msm/vidc/msm_vidc_debug.c @@ -10,8 +10,7 @@ #include "vidc_hfi_api.h" #include -int msm_vidc_debug = VIDC_ERR | VIDC_PRINTK | - FW_ERROR | FW_FATAL | FW_FTRACE; +int msm_vidc_debug = 0; EXPORT_SYMBOL(msm_vidc_debug); bool msm_vidc_lossless_encode = !true; diff --git a/techpack/video/msm/vidc/msm_vidc_platform.c b/techpack/video/msm/vidc/msm_vidc_platform.c index 56f8d0e08e57..8d27ca4d3437 100644 --- a/techpack/video/msm/vidc/msm_vidc_platform.c +++ b/techpack/video/msm/vidc/msm_vidc_platform.c @@ -1327,7 +1327,7 @@ static struct msm_vidc_common_data kona_common_data[] = { }, { .key = "qcom,decode-batching", - .value = 1, + .value = 0, }, { .key = "qcom,batch-timeout", diff --git a/tools/arch/ia64/include/asm/barrier.h b/tools/arch/ia64/include/asm/barrier.h index d808ee0e77b5..90f8bbd9aede 100644 --- a/tools/arch/ia64/include/asm/barrier.h +++ b/tools/arch/ia64/include/asm/barrier.h @@ -39,9 +39,6 @@ * sequential memory pages only. */ -/* XXX From arch/ia64/include/uapi/asm/gcc_intrin.h */ -#define ia64_mf() asm volatile ("mf" ::: "memory") - #define mb() ia64_mf() #define rmb() mb() #define wmb() mb() diff --git a/tools/build/Makefile b/tools/build/Makefile index 727050c40f09..8a55378e8b7c 100644 --- a/tools/build/Makefile +++ b/tools/build/Makefile @@ -15,10 +15,6 @@ endef $(call allow-override,CC,$(CROSS_COMPILE)gcc) $(call allow-override,LD,$(CROSS_COMPILE)ld) -HOSTCC ?= gcc -HOSTLD ?= ld -HOSTAR ?= ar - export HOSTCC HOSTLD HOSTAR ifeq ($(V),1) diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index 7c17f17ea2cd..7f91b6013ddc 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -31,8 +31,11 @@ FEATURE_TESTS_BASIC := \ backtrace \ dwarf \ dwarf_getlocations \ + eventfd \ fortify-source \ sync-compare-and-swap \ + get_current_dir_name \ + gettid \ glibc \ gtk2 \ gtk2-infobar \ diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index c4845b66b9ba..6df574750bc9 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -5,8 +5,10 @@ FILES= \ test-bionic.bin \ test-dwarf.bin \ test-dwarf_getlocations.bin \ + test-eventfd.bin \ test-fortify-source.bin \ test-sync-compare-and-swap.bin \ + test-get_current_dir_name.bin \ test-glibc.bin \ test-gtk2.bin \ test-gtk2-infobar.bin \ @@ -52,6 +54,7 @@ FILES= \ test-get_cpuid.bin \ test-sdt.bin \ test-cxx.bin \ + test-gettid.bin \ test-jvmti.bin \ test-sched_getcpu.bin \ test-setns.bin \ @@ -99,6 +102,12 @@ $(OUTPUT)test-bionic.bin: $(OUTPUT)test-libelf.bin: $(BUILD) -lelf +$(OUTPUT)test-eventfd.bin: + $(BUILD) + +$(OUTPUT)test-get_current_dir_name.bin: + $(BUILD) + $(OUTPUT)test-glibc.bin: $(BUILD) @@ -254,6 +263,9 @@ $(OUTPUT)test-sdt.bin: $(OUTPUT)test-cxx.bin: $(BUILDXX) -std=gnu++11 +$(OUTPUT)test-gettid.bin: + $(BUILD) + $(OUTPUT)test-jvmti.bin: $(BUILD) diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c index 8dc20a61341f..8282bbe547c4 100644 --- a/tools/build/feature/test-all.c +++ b/tools/build/feature/test-all.c @@ -34,6 +34,14 @@ # include "test-libelf-mmap.c" #undef main +#define main main_test_get_current_dir_name +# include "test-get_current_dir_name.c" +#undef main + +#define main main_test_gettid +# include "test-gettid.c" +#undef main + #define main main_test_glibc # include "test-glibc.c" #undef main @@ -46,6 +54,10 @@ # include "test-dwarf_getlocations.c" #undef main +#define main main_test_eventfd +# include "test-eventfd.c" +#undef main + #define main main_test_libelf_getphdrnum # include "test-libelf-getphdrnum.c" #undef main @@ -174,9 +186,12 @@ int main(int argc, char *argv[]) main_test_hello(); main_test_libelf(); main_test_libelf_mmap(); + main_test_get_current_dir_name(); + main_test_gettid(); main_test_glibc(); main_test_dwarf(); main_test_dwarf_getlocations(); + main_test_eventfd(); main_test_libelf_getphdrnum(); main_test_libelf_gelf_getnote(); main_test_libelf_getshdrstrndx(); diff --git a/tools/build/feature/test-eventfd.c b/tools/build/feature/test-eventfd.c new file mode 100644 index 000000000000..f4de7ef00ccb --- /dev/null +++ b/tools/build/feature/test-eventfd.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo + +#include + +int main(void) +{ + return eventfd(0, EFD_NONBLOCK); +} diff --git a/tools/build/feature/test-get_current_dir_name.c b/tools/build/feature/test-get_current_dir_name.c new file mode 100644 index 000000000000..573000f93212 --- /dev/null +++ b/tools/build/feature/test-get_current_dir_name.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include + +int main(void) +{ + free(get_current_dir_name()); + return 0; +} diff --git a/tools/build/feature/test-gettid.c b/tools/build/feature/test-gettid.c new file mode 100644 index 000000000000..ef24e42d3f1b --- /dev/null +++ b/tools/build/feature/test-gettid.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2019, Red Hat Inc, Arnaldo Carvalho de Melo +#define _GNU_SOURCE +#include + +int main(void) +{ + return gettid(); +} + +#undef _GNU_SOURCE diff --git a/tools/include/linux/kallsyms.h b/tools/include/linux/kallsyms.h index 89ca6fe257cc..4149c3e19889 100644 --- a/tools/include/linux/kallsyms.h +++ b/tools/include/linux/kallsyms.h @@ -6,7 +6,7 @@ #include #include -#define KSYM_NAME_LEN 128 +#define KSYM_NAME_LEN 256 struct module; diff --git a/tools/include/linux/lockdep.h b/tools/include/linux/lockdep.h index e56997288f2b..b497a16548a6 100644 --- a/tools/include/linux/lockdep.h +++ b/tools/include/linux/lockdep.h @@ -47,7 +47,7 @@ static inline int debug_locks_off(void) #define task_pid_nr(tsk) ((tsk)->pid) -#define KSYM_NAME_LEN 128 +#define KSYM_NAME_LEN 256 #define printk(...) dprintf(STDOUT_FILENO, __VA_ARGS__) #define pr_err(format, ...) fprintf (stderr, format, ## __VA_ARGS__) #define pr_warn pr_err diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 13944978ada5..ff52939004e2 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -469,6 +469,8 @@ union bpf_attr { * u64 bpf_ktime_get_ns(void) * Description * Return the time elapsed since system boot, in nanoseconds. + * Does not include time the system was suspended. + * See: clock_gettime(CLOCK_MONOTONIC) * Return * Current *ktime*. * @@ -2141,6 +2143,14 @@ union bpf_attr { * request in the skb. * Return * 0 on success, or a negative error in case of failure. + * + * u64 bpf_ktime_get_boot_ns(void) + * Description + * Return the time elapsed since system boot, in nanoseconds. + * Does include the time the system was suspended. + * See: clock_gettime(CLOCK_BOOTTIME) + * Return + * Current *ktime*. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -2226,7 +2236,49 @@ union bpf_attr { FN(get_current_cgroup_id), \ FN(get_local_storage), \ FN(sk_select_reuseport), \ - FN(skb_ancestor_cgroup_id), + FN(skb_ancestor_cgroup_id), \ + FN(sk_lookup_tcp), \ + FN(sk_lookup_udp), \ + FN(sk_release), \ + FN(map_push_elem), \ + FN(map_pop_elem), \ + FN(map_peek_elem), \ + FN(msg_push_data), \ + FN(msg_pop_data), \ + FN(rc_pointer_rel), \ + FN(spin_lock), \ + FN(spin_unlock), \ + FN(sk_fullsock), \ + FN(tcp_sock), \ + FN(skb_ecn_set_ce), \ + FN(get_listener_sock), \ + FN(skc_lookup_tcp), \ + FN(tcp_check_syncookie), \ + FN(sysctl_get_name), \ + FN(sysctl_get_current_value), \ + FN(sysctl_get_new_value), \ + FN(sysctl_set_new_value), \ + FN(strtol), \ + FN(strtoul), \ + FN(sk_storage_get), \ + FN(sk_storage_delete), \ + FN(send_signal), \ + FN(tcp_gen_syncookie), \ + FN(skb_output), \ + FN(probe_read_user), \ + FN(probe_read_kernel), \ + FN(probe_read_user_str), \ + FN(probe_read_kernel_str), \ + FN(tcp_send_ack), \ + FN(send_signal_thread), \ + FN(jiffies64), \ + FN(read_branch_records), \ + FN(get_ns_current_pid_tgid), \ + FN(xdp_output), \ + FN(get_netns_cookie), \ + FN(get_current_ancestor_cgroup_id), \ + FN(sk_assign), \ + FN(ktime_get_boot_ns), /* integer value in 'imm' field of BPF_CALL instruction selects which helper * function eBPF program intends to call diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index 3624557550a1..6f57d38443c7 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -179,7 +179,7 @@ define do_install if [ ! -d '$(DESTDIR_SQ)$2' ]; then \ $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$2'; \ fi; \ - $(INSTALL) $1 $(if $3,-m $3,) '$(DESTDIR_SQ)$2' + $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2' endef install_lib: all_cmd diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile index baa92279c137..15f32f67cf34 100644 --- a/tools/objtool/Makefile +++ b/tools/objtool/Makefile @@ -7,15 +7,6 @@ ARCH := x86 endif # always use the host compiler -ifneq ($(LLVM),) -HOSTAR ?= llvm-ar -HOSTCC ?= clang -HOSTLD ?= ld.lld -else -HOSTAR ?= ar -HOSTCC ?= gcc -HOSTLD ?= ld -endif AR = $(HOSTAR) CC = $(HOSTCC) LD = $(HOSTLD) diff --git a/tools/objtool/arch/x86/include/asm/insn.h b/tools/objtool/arch/x86/include/asm/insn.h index c2c01f84df75..3e0e18d376d2 100644 --- a/tools/objtool/arch/x86/include/asm/insn.h +++ b/tools/objtool/arch/x86/include/asm/insn.h @@ -208,6 +208,21 @@ static inline int insn_offset_immediate(struct insn *insn) return insn_offset_displacement(insn) + insn->displacement.nbytes; } +/** + * for_each_insn_prefix() -- Iterate prefixes in the instruction + * @insn: Pointer to struct insn. + * @idx: Index storage. + * @prefix: Prefix byte. + * + * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix + * and the index is stored in @idx (note that this @idx is just for a cursor, + * do not change it.) + * Since prefixes.nbytes can be bigger than 4 if some prefixes + * are repeated, it cannot be used for looping over the prefixes. + */ +#define for_each_insn_prefix(insn, idx, prefix) \ + for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++) + #define POP_SS_OPCODE 0x1f #define MOV_SREG_OPCODE 0x8e diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c index b8f3cca8e58b..fbaf85e6d6c6 100644 --- a/tools/objtool/elf.c +++ b/tools/objtool/elf.c @@ -226,8 +226,11 @@ static int read_symbols(struct elf *elf) symtab = find_section_by_name(elf, ".symtab"); if (!symtab) { - WARN("missing symbol table"); - return -1; + /* + * A missing symbol table is actually possible if it's an empty + * .o file. This can happen for thunk_64.o. + */ + return 0; } symbols_nr = symtab->sh.sh_size / symtab->sh.sh_entsize; @@ -363,7 +366,7 @@ static int read_relas(struct elf *elf) if (sec->sh.sh_type != SHT_RELA) continue; - sec->base = find_section_by_name(elf, sec->name + 5); + sec->base = find_section_by_index(elf, sec->sh.sh_info); if (!sec->base) { WARN("can't find base section for rela section %s", sec->name); diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index ae0c5bee8014..a328beb9f505 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -310,6 +310,18 @@ ifndef NO_BIONIC endif endif +ifeq ($(feature-eventfd), 1) + CFLAGS += -DHAVE_EVENTFD +endif + +ifeq ($(feature-get_current_dir_name), 1) + CFLAGS += -DHAVE_GET_CURRENT_DIR_NAME +endif + +ifeq ($(feature-gettid), 1) + CFLAGS += -DHAVE_GETTID +endif + ifdef NO_LIBELF NO_DWARF := 1 NO_DEMANGLE := 1 diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 0be411695379..678aa7feb84d 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -148,10 +148,6 @@ endef LD += $(EXTRA_LDFLAGS) -HOSTCC ?= gcc -HOSTLD ?= ld -HOSTAR ?= ar - PKG_CONFIG = $(CROSS_COMPILE)pkg-config LLVM_CONFIG ?= llvm-config diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 6e0189df2b3b..0cb7f7b731fb 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c @@ -620,7 +620,7 @@ static int report_lock_release_event(struct perf_evsel *evsel, case SEQ_STATE_READ_ACQUIRED: seq->read_count--; BUG_ON(seq->read_count < 0); - if (!seq->read_count) { + if (seq->read_count) { ls->nr_release++; goto end; } diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c index f7eb63cbbc65..88108598d6e9 100644 --- a/tools/perf/jvmti/jvmti_agent.c +++ b/tools/perf/jvmti/jvmti_agent.c @@ -45,10 +45,12 @@ static char jit_path[PATH_MAX]; static void *marker_addr; +#ifndef HAVE_GETTID static inline pid_t gettid(void) { return (pid_t)syscall(__NR_gettid); } +#endif static int get_e_machine(struct jitheader *hdr) { diff --git a/tools/perf/tests/sample-parsing.c b/tools/perf/tests/sample-parsing.c index 0e2d00d69e6e..66e46bc8d6f1 100644 --- a/tools/perf/tests/sample-parsing.c +++ b/tools/perf/tests/sample-parsing.c @@ -173,7 +173,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) .data = {1, 211, 212, 213}, }; u64 regs[64]; - const u64 raw_data[] = {0x123456780a0b0c0dULL, 0x1102030405060708ULL}; + const u32 raw_data[] = {0x12345678, 0x0a0b0c0d, 0x11020304, 0x05060708, 0 }; const u64 data[] = {0x2211443366558877ULL, 0, 0xaabbccddeeff4321ULL}; struct perf_sample sample = { .ip = 101, diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 7efe15b9618d..4eaac6aaaefe 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -10,6 +10,7 @@ libperf-y += evlist.o libperf-y += evsel.o libperf-y += evsel_fprintf.o libperf-y += find_bit.o +libperf-y += get_current_dir_name.o libperf-y += kallsyms.o libperf-y += levenshtein.o libperf-y += llvm-utils.o diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c index 40c93d8158b5..f7c4dcb9d582 100644 --- a/tools/perf/util/auxtrace.c +++ b/tools/perf/util/auxtrace.c @@ -256,10 +256,6 @@ static int auxtrace_queues__queue_buffer(struct auxtrace_queues *queues, queue->set = true; queue->tid = buffer->tid; queue->cpu = buffer->cpu; - } else if (buffer->cpu != queue->cpu || buffer->tid != queue->tid) { - pr_err("auxtrace queue conflict: cpu %d, tid %d vs cpu %d, tid %d\n", - queue->cpu, queue->tid, buffer->cpu, buffer->tid); - return -EINVAL; } buffer->buffer_nr = queues->next_buffer_nr++; diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c index 938def6d0bb9..f540037eb705 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -278,14 +278,12 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, enum cs_etm_sample_type sample_type) { u32 et = 0; - struct int_node *inode = NULL; + int cpu; if (decoder->packet_count >= MAX_BUFFER - 1) return OCSD_RESP_FATAL_SYS_ERR; - /* Search the RB tree for the cpu associated with this traceID */ - inode = intlist__find(traceid_list, trace_chan_id); - if (!inode) + if (cs_etm__get_cpu(trace_chan_id, &cpu) < 0) return OCSD_RESP_FATAL_SYS_ERR; et = decoder->tail; @@ -296,7 +294,7 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, decoder->packet_buffer[et].sample_type = sample_type; decoder->packet_buffer[et].exc = false; decoder->packet_buffer[et].exc_ret = false; - decoder->packet_buffer[et].cpu = *((int *)inode->priv); + decoder->packet_buffer[et].cpu = cpu; decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR; decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR; diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index ad33b99f5d21..3275b8dc9344 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -94,6 +94,20 @@ static int cs_etm__update_queues(struct cs_etm_auxtrace *etm); static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm, pid_t tid, u64 time_); +int cs_etm__get_cpu(u8 trace_chan_id, int *cpu) +{ + struct int_node *inode; + u64 *metadata; + + inode = intlist__find(traceid_list, trace_chan_id); + if (!inode) + return -EINVAL; + + metadata = inode->priv; + *cpu = (int)metadata[CS_ETM_CPU]; + return 0; +} + static void cs_etm__packet_dump(const char *pkt_string) { const char *color = PERF_COLOR_BLUE; @@ -233,7 +247,7 @@ static void cs_etm__free(struct perf_session *session) cs_etm__free_events(session); session->auxtrace = NULL; - /* First remove all traceID/CPU# nodes for the RB tree */ + /* First remove all traceID/metadata nodes for the RB tree */ intlist__for_each_entry_safe(inode, tmp, traceid_list) intlist__remove(traceid_list, inode); /* Then the RB tree itself */ @@ -1319,9 +1333,9 @@ int cs_etm__process_auxtrace_info(union perf_event *event, 0xffffffff); /* - * Create an RB tree for traceID-CPU# tuple. Since the conversion has - * to be made for each packet that gets decoded, optimizing access in - * anything other than a sequential array is worth doing. + * Create an RB tree for traceID-metadata tuple. Since the conversion + * has to be made for each packet that gets decoded, optimizing access + * in anything other than a sequential array is worth doing. */ traceid_list = intlist__new(NULL); if (!traceid_list) { @@ -1387,8 +1401,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event, err = -EINVAL; goto err_free_metadata; } - /* All good, associate the traceID with the CPU# */ - inode->priv = &metadata[j][CS_ETM_CPU]; + /* All good, associate the traceID with the metadata pointer */ + inode->priv = metadata[j]; } /* diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index c7ef97b198c7..97c3152f5bfd 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -66,6 +66,7 @@ static const u64 __perf_cs_etmv4_magic = 0x4040404040404040ULL; #ifdef HAVE_CSTRACE_SUPPORT int cs_etm__process_auxtrace_info(union perf_event *event, struct perf_session *session); +int cs_etm__get_cpu(u8 trace_chan_id, int *cpu); #else static inline int cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused, @@ -73,6 +74,12 @@ cs_etm__process_auxtrace_info(union perf_event *event __maybe_unused, { return -1; } + +static inline int cs_etm__get_cpu(u8 trace_chan_id __maybe_unused, + int *cpu __maybe_unused) +{ + return -1; +} #endif #endif diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index 29e75c051d04..230e94bf7775 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c @@ -332,6 +332,7 @@ bool die_is_func_def(Dwarf_Die *dw_die) int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr) { Dwarf_Addr base, end; + Dwarf_Attribute attr; if (!addr) return -EINVAL; @@ -339,6 +340,13 @@ int die_entrypc(Dwarf_Die *dw_die, Dwarf_Addr *addr) if (dwarf_entrypc(dw_die, addr) == 0) return 0; + /* + * Since the dwarf_ranges() will return 0 if there is no + * DW_AT_ranges attribute, we should check it first. + */ + if (!dwarf_attr(dw_die, DW_AT_ranges, &attr)) + return -ENOENT; + return dwarf_ranges(dw_die, 0, &base, addr, &end) < 0 ? -ENOENT : 0; } diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index aa9c7df120ca..4efc8dac3fff 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -1659,6 +1659,8 @@ int machine__resolve(struct machine *machine, struct addr_location *al, } al->sym = map__find_symbol(al->map, al->addr); + } else if (symbol_conf.dso_list) { + al->filtered |= (1 << HIST_FILTER__DSO); } if (symbol_conf.sym_list && diff --git a/tools/perf/util/expr.y b/tools/perf/util/expr.y index 432b8560cf51..e7bd19c384ae 100644 --- a/tools/perf/util/expr.y +++ b/tools/perf/util/expr.y @@ -10,7 +10,8 @@ #define MAXIDLEN 256 %} -%pure-parser +%define api.pure full + %parse-param { double *final_val } %parse-param { struct parse_ctx *ctx } %parse-param { const char **pp } diff --git a/tools/perf/util/get_current_dir_name.c b/tools/perf/util/get_current_dir_name.c new file mode 100644 index 000000000000..267aa609a582 --- /dev/null +++ b/tools/perf/util/get_current_dir_name.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo +// +#ifndef HAVE_GET_CURRENT_DIR_NAME +#include "util.h" +#include +#include +#include + +/* Android's 'bionic' library, for one, doesn't have this */ + +char *get_current_dir_name(void) +{ + char pwd[PATH_MAX]; + + return getcwd(pwd, sizeof(pwd)) == NULL ? NULL : strdup(pwd); +} +#endif // HAVE_GET_CURRENT_DIR_NAME diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h index 2669c9f748e4..1a01d0a41ab8 100644 --- a/tools/perf/util/intel-pt-decoder/insn.h +++ b/tools/perf/util/intel-pt-decoder/insn.h @@ -208,6 +208,21 @@ static inline int insn_offset_immediate(struct insn *insn) return insn_offset_displacement(insn) + insn->displacement.nbytes; } +/** + * for_each_insn_prefix() -- Iterate prefixes in the instruction + * @insn: Pointer to struct insn. + * @idx: Index storage. + * @prefix: Prefix byte. + * + * Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix + * and the index is stored in @idx (note that this @idx is just for a cursor, + * do not change it.) + * Since prefixes.nbytes can be bigger than 4 if some prefixes + * are repeated, it cannot be used for looping over the prefixes. + */ +#define for_each_insn_prefix(insn, idx, prefix) \ + for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++) + #define POP_SS_OPCODE 0x1f #define MOV_SREG_OPCODE 0x8e diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 6522b6513895..e2f038f84dbc 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1596,6 +1596,9 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder) break; case INTEL_PT_CYC: + intel_pt_calc_cyc_timestamp(decoder); + break; + case INTEL_PT_VMCS: case INTEL_PT_MNT: case INTEL_PT_PAD: diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index d3d3601f41cc..769d11575a7b 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -88,8 +88,7 @@ static inline bool replace_android_lib(const char *filename, char *newfilename) if (!strncmp(filename, "/system/lib/", 12)) { char *ndk, *app; const char *arch; - size_t ndk_length; - size_t app_length; + int ndk_length, app_length; ndk = getenv("NDK_ROOT"); app = getenv("APP_PLATFORM"); @@ -117,8 +116,8 @@ static inline bool replace_android_lib(const char *filename, char *newfilename) if (new_length > PATH_MAX) return false; snprintf(newfilename, new_length, - "%s/platforms/%s/arch-%s/usr/lib/%s", - ndk, app, arch, libname); + "%.*s/platforms/%.*s/arch-%s/usr/lib/%s", + ndk_length, ndk, app_length, app, arch, libname); return true; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index da8fe57691b8..8d7578be708a 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -1,4 +1,4 @@ -%pure-parser +%define api.pure full %parse-param {void *_parse_state} %parse-param {void *scanner} %lex-param {void* scanner} diff --git a/tools/perf/util/parse-regs-options.c b/tools/perf/util/parse-regs-options.c index e6599e290f46..e5ad120e7f69 100644 --- a/tools/perf/util/parse-regs-options.c +++ b/tools/perf/util/parse-regs-options.c @@ -41,7 +41,7 @@ parse_regs(const struct option *opt, const char *str, int unset) } fputc('\n', stderr); /* just printing available regs */ - return -1; + goto error; } for (r = sample_reg_masks; r->name; r++) { if (!strcasecmp(s, r->name)) diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 9569cc06e0a7..2814251df06b 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -1493,7 +1493,6 @@ static void _free_command_line(wchar_t **command_line, int num) static int python_start_script(const char *script, int argc, const char **argv) { struct tables *tables = &tables_global; - PyMODINIT_FUNC (*initfunc)(void); #if PY_MAJOR_VERSION < 3 const char **command_line; #else @@ -1508,20 +1507,18 @@ static int python_start_script(const char *script, int argc, const char **argv) FILE *fp; #if PY_MAJOR_VERSION < 3 - initfunc = initperf_trace_context; command_line = malloc((argc + 1) * sizeof(const char *)); command_line[0] = script; for (i = 1; i < argc + 1; i++) command_line[i] = argv[i - 1]; + PyImport_AppendInittab(name, initperf_trace_context); #else - initfunc = PyInit_perf_trace_context; command_line = malloc((argc + 1) * sizeof(wchar_t *)); command_line[0] = Py_DecodeLocale(script, NULL); for (i = 1; i < argc + 1; i++) command_line[i] = Py_DecodeLocale(argv[i - 1], NULL); + PyImport_AppendInittab(name, PyInit_perf_trace_context); #endif - - PyImport_AppendInittab(name, initfunc); Py_Initialize(); #if PY_MAJOR_VERSION < 3 diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f016d1b330e5..6a2037b52098 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -488,6 +488,7 @@ static void perf_event__mmap2_swap(union perf_event *event, event->mmap2.maj = bswap_32(event->mmap2.maj); event->mmap2.min = bswap_32(event->mmap2.min); event->mmap2.ino = bswap_64(event->mmap2.ino); + event->mmap2.ino_generation = bswap_64(event->mmap2.ino_generation); if (sample_id_all) { void *data = &event->mmap2.filename; diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 5eb1b2469bba..12324325ea0b 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c @@ -381,6 +381,7 @@ static int read_saved_cmdline(struct tep_handle *pevent) pr_debug("error reading saved cmdlines\n"); goto out; } + buf[ret] = '\0'; parse_saved_cmdline(pevent, buf, size); ret = 0; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 8c01b2cfdb1a..2efec9e77753 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -57,6 +57,10 @@ int fetch_kernel_version(unsigned int *puint, const char *perf_tip(const char *dirpath); +#ifndef HAVE_GET_CURRENT_DIR_NAME +char *get_current_dir_name(void); +#endif + #ifndef HAVE_SCHED_GETCPU_SUPPORT int sched_getcpu(void); #endif diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config index fc116c060b98..32ff7baf39df 100644 --- a/tools/power/acpi/Makefile.config +++ b/tools/power/acpi/Makefile.config @@ -57,7 +57,6 @@ INSTALL_SCRIPT = ${INSTALL_PROGRAM} CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- CROSS_COMPILE ?= $(CROSS) LD = $(CC) -HOSTCC = gcc # check if compiler option is supported cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include index 8fc6b1ca47dc..42dbe05b1807 100644 --- a/tools/scripts/Makefile.include +++ b/tools/scripts/Makefile.include @@ -60,6 +60,16 @@ $(call allow-override,LD,$(CROSS_COMPILE)ld) $(call allow-override,CXX,$(CROSS_COMPILE)g++) $(call allow-override,STRIP,$(CROSS_COMPILE)strip) +ifneq ($(LLVM),) +HOSTAR ?= llvm-ar +HOSTCC ?= clang +HOSTLD ?= ld.lld +else +HOSTAR ?= ar +HOSTCC ?= gcc +HOSTLD ?= ld +endif + ifeq ($(CC_NO_CLANG), 1) EXTRA_WARNINGS += -Wstrict-aliasing=3 endif diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index 3118fc0d149b..406401f1acc2 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl @@ -4177,7 +4177,12 @@ sub do_send_mail { $mail_command =~ s/\$SUBJECT/$subject/g; $mail_command =~ s/\$MESSAGE/$message/g; - run_command $mail_command; + my $ret = run_command $mail_command; + if (!$ret && defined($file)) { + # try again without the file + $message .= "\n\n*** FAILED TO SEND LOG ***\n\n"; + do_send_email($subject, $message); + } } sub send_email { diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py index d59642e70f56..2229e55216a9 100755 --- a/tools/testing/selftests/bpf/test_offload.py +++ b/tools/testing/selftests/bpf/test_offload.py @@ -787,6 +787,7 @@ def test_spurios_extack(sim, obj, skip_hw, needle): start_test("Test disabling TC offloads is rejected while filters installed...") ret, _ = sim.set_ethtool_tc_offloads(False, fail=False) fail(ret == 0, "Driver should refuse to disable TC offloads with filters installed...") + sim.set_ethtool_tc_offloads(True) start_test("Test qdisc removal frees things...") sim.tc_flush_filters() diff --git a/tools/testing/selftests/kvm/include/x86.h b/tools/testing/selftests/kvm/include/x86.h index 42c3596815b8..a7667a613bbc 100644 --- a/tools/testing/selftests/kvm/include/x86.h +++ b/tools/testing/selftests/kvm/include/x86.h @@ -59,7 +59,7 @@ enum x86_register { struct desc64 { uint16_t limit0; uint16_t base0; - unsigned base1:8, s:1, type:4, dpl:2, p:1; + unsigned base1:8, type:4, s:1, dpl:2, p:1; unsigned limit1:4, avl:1, l:1, db:1, g:1, base2:8; uint32_t base3; uint32_t zero1; diff --git a/tools/testing/selftests/kvm/lib/x86.c b/tools/testing/selftests/kvm/lib/x86.c index 4d35eba73dc9..800fe36064f9 100644 --- a/tools/testing/selftests/kvm/lib/x86.c +++ b/tools/testing/selftests/kvm/lib/x86.c @@ -449,11 +449,12 @@ static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp) desc->limit0 = segp->limit & 0xFFFF; desc->base0 = segp->base & 0xFFFF; desc->base1 = segp->base >> 16; - desc->s = segp->s; desc->type = segp->type; + desc->s = segp->s; desc->dpl = segp->dpl; desc->p = segp->present; desc->limit1 = segp->limit >> 16; + desc->avl = segp->avl; desc->l = segp->l; desc->db = segp->db; desc->g = segp->g; diff --git a/tools/testing/selftests/net/fib_tests.sh b/tools/testing/selftests/net/fib_tests.sh index 67048f922ff2..a5ba149761bf 100755 --- a/tools/testing/selftests/net/fib_tests.sh +++ b/tools/testing/selftests/net/fib_tests.sh @@ -987,7 +987,6 @@ ipv6_addr_metric_test() check_route6 "2001:db8:104::1 dev dummy2 proto kernel metric 260" log_test $? 0 "Set metric with peer route on local side" - log_test $? 0 "User specified metric on local address" check_route6 "2001:db8:104::2 dev dummy2 proto kernel metric 260" log_test $? 0 "Set metric with peer route on peer side" diff --git a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d_vlan.sh b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d_vlan.sh index 197e769c2ed1..f8cda822c1ce 100755 --- a/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d_vlan.sh +++ b/tools/testing/selftests/net/forwarding/mirror_gre_bridge_1d_vlan.sh @@ -86,11 +86,20 @@ test_ip6gretap() test_gretap_stp() { + # Sometimes after mirror installation, the neighbor's state is not valid. + # The reason is that there is no SW datapath activity related to the + # neighbor for the remote GRE address. Therefore whether the corresponding + # neighbor will be valid is a matter of luck, and the test is thus racy. + # Set the neighbor's state to permanent, so it would be always valid. + ip neigh replace 192.0.2.130 lladdr $(mac_get $h3) \ + nud permanent dev br2 full_test_span_gre_stp gt4 $swp3.555 "mirror to gretap" } test_ip6gretap_stp() { + ip neigh replace 2001:db8:2::2 lladdr $(mac_get $h3) \ + nud permanent dev br2 full_test_span_gre_stp gt6 $swp3.555 "mirror to ip6gretap" } diff --git a/tools/testing/selftests/powerpc/alignment/alignment_handler.c b/tools/testing/selftests/powerpc/alignment/alignment_handler.c index 169a8b9719fb..4f8335e0c985 100644 --- a/tools/testing/selftests/powerpc/alignment/alignment_handler.c +++ b/tools/testing/selftests/powerpc/alignment/alignment_handler.c @@ -384,7 +384,6 @@ int test_alignment_handler_integer(void) LOAD_DFORM_TEST(ldu); LOAD_XFORM_TEST(ldx); LOAD_XFORM_TEST(ldux); - LOAD_DFORM_TEST(lmw); STORE_DFORM_TEST(stb); STORE_XFORM_TEST(stbx); STORE_DFORM_TEST(stbu); @@ -403,7 +402,11 @@ int test_alignment_handler_integer(void) STORE_XFORM_TEST(stdx); STORE_DFORM_TEST(stdu); STORE_XFORM_TEST(stdux); + +#ifdef __BIG_ENDIAN__ + LOAD_DFORM_TEST(lmw); STORE_DFORM_TEST(stmw); +#endif return rc; } diff --git a/tools/testing/selftests/proc/proc-loadavg-001.c b/tools/testing/selftests/proc/proc-loadavg-001.c index fcff7047000d..8edaafc2b92f 100644 --- a/tools/testing/selftests/proc/proc-loadavg-001.c +++ b/tools/testing/selftests/proc/proc-loadavg-001.c @@ -14,7 +14,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Test that /proc/loadavg correctly reports last pid in pid namespace. */ -#define _GNU_SOURCE #include #include #include diff --git a/tools/testing/selftests/proc/proc-self-syscall.c b/tools/testing/selftests/proc/proc-self-syscall.c index 5ab5f4810e43..7b9018fad092 100644 --- a/tools/testing/selftests/proc/proc-self-syscall.c +++ b/tools/testing/selftests/proc/proc-self-syscall.c @@ -13,7 +13,6 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define _GNU_SOURCE #include #include #include diff --git a/tools/testing/selftests/proc/proc-uptime-002.c b/tools/testing/selftests/proc/proc-uptime-002.c index 30e2b7849089..e7ceabed7f51 100644 --- a/tools/testing/selftests/proc/proc-uptime-002.c +++ b/tools/testing/selftests/proc/proc-uptime-002.c @@ -15,7 +15,6 @@ */ // Test that values in /proc/uptime increment monotonically // while shifting across CPUs. -#define _GNU_SOURCE #undef NDEBUG #include #include diff --git a/tools/usb/usbip/libsrc/usbip_host_common.c b/tools/usb/usbip/libsrc/usbip_host_common.c index b0f7489d069d..84d0fa85939e 100644 --- a/tools/usb/usbip/libsrc/usbip_host_common.c +++ b/tools/usb/usbip/libsrc/usbip_host_common.c @@ -35,7 +35,7 @@ #include "list.h" #include "sysfs_utils.h" -struct udev *udev_context; +extern struct udev *udev_context; static int32_t read_attr_usbip_status(struct usbip_usb_device *udev) { diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index 787f7329d1b7..11103b75c596 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -2080,7 +2080,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, * Prevent userspace from creating a memory region outside of the IPA * space addressable by the KVM guest IPA space. */ - if (memslot->base_gfn + memslot->npages >= + if (memslot->base_gfn + memslot->npages > (KVM_PHYS_SIZE >> PAGE_SHIFT)) return -EFAULT; diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index a2a175b08b17..cbb38a0d1b25 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c @@ -226,6 +226,23 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu, return extract_bytes(value, addr & 7, len); } +static unsigned long vgic_uaccess_read_v3r_typer(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len) +{ + unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu); + int target_vcpu_id = vcpu->vcpu_id; + u64 value; + + value = (u64)(mpidr & GENMASK(23, 0)) << 32; + value |= ((target_vcpu_id & 0xffff) << 8); + + if (vgic_has_its(vcpu->kvm)) + value |= GICR_TYPER_PLPIS; + + /* reporting of the Last bit is not supported for userspace */ + return extract_bytes(value, addr & 7, len); +} + static unsigned long vgic_mmio_read_v3r_iidr(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len) { @@ -532,8 +549,9 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = { REGISTER_DESC_WITH_LENGTH(GICR_IIDR, vgic_mmio_read_v3r_iidr, vgic_mmio_write_wi, 4, VGIC_ACCESS_32bit), - REGISTER_DESC_WITH_LENGTH(GICR_TYPER, - vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, 8, + REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_TYPER, + vgic_mmio_read_v3r_typer, vgic_mmio_write_wi, + vgic_uaccess_read_v3r_typer, vgic_mmio_uaccess_write_wi, 8, VGIC_ACCESS_64bit | VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH(GICR_WAKER, vgic_mmio_read_raz, vgic_mmio_write_wi, 4, diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9312c7e750ed..1ecb27b3421a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -412,9 +412,8 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, */ kvm->mmu_notifier_count++; need_tlb_flush = kvm_unmap_hva_range(kvm, start, end, blockable); - need_tlb_flush |= kvm->tlbs_dirty; /* we've to flush the tlb before the pages can be freed */ - if (need_tlb_flush) + if (need_tlb_flush || kvm->tlbs_dirty) kvm_flush_remote_tlbs(kvm); spin_unlock(&kvm->mmu_lock);